Projektdateien hinzufügen.
1
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
81
App.xaml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<Application x:Class="ReSync.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="clr-namespace:ReSync"
|
||||||
|
StartupUri="MainWindow.xaml">
|
||||||
|
<Application.Resources>
|
||||||
|
<Style TargetType="Button" x:Key="ToolbarButton">
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||||
|
<Setter Property="VerticalAlignment" Value="Top"/>
|
||||||
|
<Setter Property="Margin" Value="10"/>
|
||||||
|
<Setter Property="Height" Value="80"/>
|
||||||
|
<Setter Property="MinWidth" Value="80"/>
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border x:Name="border"
|
||||||
|
CornerRadius="5">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter TargetName="border" Property="Background" Value="SkyBlue"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TextBlock" x:Key="FolderPathText">
|
||||||
|
<Setter Property="Width" Value="180"/>
|
||||||
|
<Setter Property="FontSize" Value="14"/>
|
||||||
|
<Setter Property="Margin" Value="5"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="MinHeight" Value="30"/>
|
||||||
|
<Setter Property="Margin" Value="5"/>
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
|
<Setter Property="BorderThickness" Value="2"/>
|
||||||
|
<Setter Property="BorderBrush" Value="Black"/>
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Right"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border x:Name="border"
|
||||||
|
CornerRadius="5"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter TargetName="border" Property="Background" Value="SkyBlue"/>
|
||||||
|
</Trigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="StackPanel" x:Key="StatusElement">
|
||||||
|
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TextBlock" x:Key="HeadingText">
|
||||||
|
<Setter Property="FontSize" Value="24"/>
|
||||||
|
<Setter Property="FontWeight" Value="Bold"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="TextBlock">
|
||||||
|
<Setter Property="FontSize" Value="16"/>
|
||||||
|
<Setter Property="Margin" Value="5"/>
|
||||||
|
</Style>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
13
App.xaml.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Configuration;
|
||||||
|
using System.Data;
|
||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
namespace ReSync;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for App.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
10
AssemblyInfo.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
[assembly:ThemeInfo(
|
||||||
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// or application resource dictionaries)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// app, or any theme specific resource dictionaries)
|
||||||
|
)]
|
||||||
139
BackEnd/DataBaseConnector.cs
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace ReSync
|
||||||
|
{
|
||||||
|
public class DataBaseConnector
|
||||||
|
{
|
||||||
|
private string _dbPath;
|
||||||
|
|
||||||
|
public DataBaseConnector(string dbPath)
|
||||||
|
{
|
||||||
|
_dbPath = dbPath;
|
||||||
|
InitializeDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeDatabase()
|
||||||
|
{
|
||||||
|
// Ensure database file exists
|
||||||
|
if (!File.Exists(_dbPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(_dbPath) ?? "");
|
||||||
|
File.Create(_dbPath).Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open connection and apply schema (CREATE TABLE IF NOT EXISTS ...)
|
||||||
|
using (var connection = new SqliteConnection($"Data Source={_dbPath}"))
|
||||||
|
{
|
||||||
|
connection.Open();
|
||||||
|
|
||||||
|
// Ensure foreign key support is enabled
|
||||||
|
using (var pragma = connection.CreateCommand())
|
||||||
|
{
|
||||||
|
pragma.CommandText = "PRAGMA foreign_keys = ON;";
|
||||||
|
pragma.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
var command = connection.CreateCommand();
|
||||||
|
command.CommandText = @"
|
||||||
|
-- Devices: phones or other sources
|
||||||
|
CREATE TABLE IF NOT EXISTS device (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
uuid TEXT UNIQUE,
|
||||||
|
name TEXT,
|
||||||
|
type TEXT,
|
||||||
|
last_seen INTEGER,
|
||||||
|
metadata TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_device_uuid ON device(uuid);
|
||||||
|
|
||||||
|
-- Media: canonical original files detected (one row per unique original hash)
|
||||||
|
CREATE TABLE IF NOT EXISTS media (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
original_hash TEXT NOT NULL,
|
||||||
|
original_path TEXT,
|
||||||
|
storage_type TEXT,
|
||||||
|
file_name TEXT,
|
||||||
|
mime_type TEXT,
|
||||||
|
size INTEGER,
|
||||||
|
width INTEGER,
|
||||||
|
height INTEGER,
|
||||||
|
duration REAL,
|
||||||
|
created_at INTEGER,
|
||||||
|
modified_at INTEGER,
|
||||||
|
source_device_id INTEGER,
|
||||||
|
note TEXT,
|
||||||
|
UNIQUE(original_hash)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_media_hash ON media(original_hash);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_media_device ON media(source_device_id);
|
||||||
|
|
||||||
|
-- Encoded: one row per encoded variant (phone-optimized copy)
|
||||||
|
CREATE TABLE IF NOT EXISTS encoded (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
media_id INTEGER NOT NULL,
|
||||||
|
encoded_hash TEXT NOT NULL,
|
||||||
|
encoded_path TEXT NOT NULL,
|
||||||
|
codec TEXT,
|
||||||
|
preset TEXT,
|
||||||
|
crf INTEGER,
|
||||||
|
size INTEGER,
|
||||||
|
width INTEGER,
|
||||||
|
height INTEGER,
|
||||||
|
duration REAL,
|
||||||
|
created_at INTEGER,
|
||||||
|
encoder_version TEXT,
|
||||||
|
notes TEXT,
|
||||||
|
FOREIGN KEY(media_id) REFERENCES media(id) ON DELETE CASCADE,
|
||||||
|
UNIQUE(media_id, encoded_hash)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_encoded_media ON encoded(media_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_encoded_hash ON encoded(encoded_hash);
|
||||||
|
|
||||||
|
-- Sync jobs: track sync runs and basic results
|
||||||
|
CREATE TABLE IF NOT EXISTS sync_job (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
started_at INTEGER,
|
||||||
|
finished_at INTEGER,
|
||||||
|
initiated_by TEXT,
|
||||||
|
phone_device_id INTEGER,
|
||||||
|
files_found INTEGER,
|
||||||
|
files_backed_up INTEGER,
|
||||||
|
files_encoded INTEGER,
|
||||||
|
errors INTEGER,
|
||||||
|
notes TEXT,
|
||||||
|
FOREIGN KEY(phone_device_id) REFERENCES device(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_sync_started ON sync_job(started_at);
|
||||||
|
|
||||||
|
-- Duplicate groups: optional helper for UI to store grouped duplicates
|
||||||
|
CREATE TABLE IF NOT EXISTS duplicate_group (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
media_hash TEXT NOT NULL,
|
||||||
|
created_at INTEGER
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_dupgroup_hash ON duplicate_group(media_hash);
|
||||||
|
|
||||||
|
-- Log: operation log for auditing and debugging
|
||||||
|
CREATE TABLE IF NOT EXISTS log (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
ts INTEGER,
|
||||||
|
level TEXT,
|
||||||
|
source TEXT,
|
||||||
|
message TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_log_ts ON log(ts);
|
||||||
|
";
|
||||||
|
|
||||||
|
command.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
BackEnd/FileManager.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
using Blake3;
|
||||||
|
using MediaDevices;
|
||||||
|
|
||||||
|
namespace ReSync
|
||||||
|
{
|
||||||
|
public static class FileManager
|
||||||
|
{
|
||||||
|
static bool cancel = false;
|
||||||
|
public static void ScanMTPDevice(MediaDevice device)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Starting MTP device scan...");
|
||||||
|
Debug.WriteLine(cancel);
|
||||||
|
device.Connect();
|
||||||
|
ListAllFiles(device, "//");
|
||||||
|
|
||||||
|
device.Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ListAllFiles(MediaDevice device, string directory)
|
||||||
|
{
|
||||||
|
if (cancel) return;
|
||||||
|
// Get all subdirectories
|
||||||
|
var dirs = device.GetDirectories(directory);
|
||||||
|
var files = device.GetFiles(directory);
|
||||||
|
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
if (cancel) return;
|
||||||
|
Console.WriteLine(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursively explore directories
|
||||||
|
foreach (var dir in dirs)
|
||||||
|
{
|
||||||
|
if (cancel) return;
|
||||||
|
ListAllFiles(device, dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetFileHash(string filePath)
|
||||||
|
{
|
||||||
|
return "a";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CancelOperation()
|
||||||
|
{
|
||||||
|
cancel = true;
|
||||||
|
Dispatcher.CurrentDispatcher.InvokeAsync(async() =>
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
cancel = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
BackEnd/Logger.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace ReSync
|
||||||
|
{
|
||||||
|
public class Logger
|
||||||
|
{
|
||||||
|
private readonly string _logFilePath;
|
||||||
|
public ObservableCollection<LogEntry> Entries { get; } = new();
|
||||||
|
|
||||||
|
public Logger(string logFilePath)
|
||||||
|
{
|
||||||
|
_logFilePath = logFilePath;
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)!);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(string message, string level = "Info")
|
||||||
|
{
|
||||||
|
var entry = new LogEntry { Message = message, Level = level };
|
||||||
|
App.Current.Dispatcher.Invoke(() => Entries.Add(entry)); // update UI safely
|
||||||
|
|
||||||
|
var line = $"{entry.Timestamp:yyyy-MM-dd HH:mm:ss} [{entry.Level}] {entry.Message}";
|
||||||
|
File.AppendAllText(_logFilePath, line + Environment.NewLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
Entries.Clear();
|
||||||
|
File.WriteAllText(_logFilePath, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LogEntry
|
||||||
|
{
|
||||||
|
public DateTime Timestamp { get; set; } = DateTime.Now;
|
||||||
|
public string Level { get; set; } = "Info";
|
||||||
|
public string Message { get; set; } = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
138
MainWindow.xaml
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
<Window x:Class="ReSync.MainWindow"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:local="clr-namespace:ReSync"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="MainWindow" Height="550" Width="800">
|
||||||
|
<Border Margin="5" BorderBrush="Black" BorderThickness="3" CornerRadius="5">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Image Grid.Row="0" Grid.Column="0" Height="80" HorizontalAlignment="Left" Source="pack://application:,,,/Resources/logo.png"/>
|
||||||
|
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
|
||||||
|
<Button Style="{StaticResource ToolbarButton}" Click="Scan_Phone_Click">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Source="pack://application:,,,/Resources/phone.png" Width="35"/>
|
||||||
|
<TextBlock Text="Scan Phone"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Style="{StaticResource ToolbarButton}" Click="Sync_Files_Click">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Source="pack://application:,,,/Resources/sync.png" Width="35"/>
|
||||||
|
<TextBlock Text="Sync Now"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Style="{StaticResource ToolbarButton}" Click="Settings_Click">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Source="pack://application:,,,/Resources/settings.png" Width="35"/>
|
||||||
|
<TextBlock Text="Settings"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Style="{StaticResource ToolbarButton}" Click="Database_Click">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Source="pack://application:,,,/Resources/database.png" Width="35"/>
|
||||||
|
<TextBlock Text="Database"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Style="{StaticResource ToolbarButton}" Click="Duplicates_Click">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Source="pack://application:,,,/Resources/duplicates.png" Width="35"/>
|
||||||
|
<TextBlock Text="Duplicates"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
<Button Style="{StaticResource ToolbarButton}" Click="Logs_Click">
|
||||||
|
<StackPanel>
|
||||||
|
<Image Source="pack://application:,,,/Resources/logs.png" Width="35"/>
|
||||||
|
<TextBlock Text="Logs"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
</StackPanel><!-- Toolbar End -->
|
||||||
|
<Border BorderBrush="Black" BorderThickness="1.5" Grid.ColumnSpan="2" Grid.Row="1"/>
|
||||||
|
<StackPanel Grid.Row="2" Grid.ColumnSpan="2" Orientation="Horizontal">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="Folders" Style="{StaticResource HeadingText}"/>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="pack://application:,,,/Resources/phone.png" Width="32" Height="32"/>
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="Phone:"/>
|
||||||
|
<ComboBox Width="180" ItemsSource="{Binding DevicesNameList}" SelectedItem="{Binding SelectedDevice, Mode=TwoWay}" Height="35" Margin="5,0,5,0"/>
|
||||||
|
</StackPanel>
|
||||||
|
<Button Content="Refresh" Click="Refresh_Phone_Click" Height="40" Width="68"/>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="pack://application:,,,/Resources/folder.png" Width="32" Height="32"/>
|
||||||
|
<StackPanel Height="66.28">
|
||||||
|
<TextBlock Text="Backup Folder:"/>
|
||||||
|
<TextBlock Text="{Binding BackupFolderPath}" Style="{StaticResource FolderPathText}"/>
|
||||||
|
</StackPanel>
|
||||||
|
<Button Content="Change" Click="Change_Backup_Click" Height="40" Width="68"/>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<Image Source="pack://application:,,,/Resources/folder.png" Width="32" Height="32"/>
|
||||||
|
<StackPanel Height="66.28">
|
||||||
|
<TextBlock Text="Encoded Output Folder:"/>
|
||||||
|
<TextBlock Text="{Binding EncodedOutputFolderPath}" Style="{StaticResource FolderPathText}"/>
|
||||||
|
</StackPanel>
|
||||||
|
<Button Content="Change" Click="Change_Encoded_Click" Height="40" Width="68"/>
|
||||||
|
</StackPanel>
|
||||||
|
<Button Content="Rescan Folder" Click="Rescan_Click"/>
|
||||||
|
</StackPanel>
|
||||||
|
<Border BorderThickness="1.5" BorderBrush="Black" />
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock Text="Status" Style="{StaticResource HeadingText}"/>
|
||||||
|
<StackPanel Orientation="Horizontal" Style="{StaticResource StatusElement}">
|
||||||
|
<TextBlock Text="Phone connected:"/>
|
||||||
|
<TextBlock Text="{Binding PhoneConnected}"/>
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal" Style="{StaticResource StatusElement}">
|
||||||
|
<TextBlock Text="New Files:"/>
|
||||||
|
<TextBlock Text="None" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal" Style="{StaticResource StatusElement}">
|
||||||
|
<TextBlock Text="Backups Pending:"/>
|
||||||
|
<TextBlock Text="None" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal" Style="{StaticResource StatusElement}">
|
||||||
|
<TextBlock Text="Encodings Pending:"/>
|
||||||
|
<TextBlock Text="None" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal" Style="{StaticResource StatusElement}">
|
||||||
|
<TextBlock Text="Last Sync:"/>
|
||||||
|
<TextBlock Text="Never" />
|
||||||
|
</StackPanel>
|
||||||
|
<StackPanel Orientation="Horizontal" Style="{StaticResource StatusElement}">
|
||||||
|
<TextBlock Text="DB Entries:"/>
|
||||||
|
<TextBlock Text="None" />
|
||||||
|
</StackPanel>
|
||||||
|
<Button Click="Start_Click">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<ProgressBar Width="150" Height="15" Margin="5" Value="0" Maximum="100"/>
|
||||||
|
<TextBlock Text="Start Sync" Margin="5"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
<Border BorderBrush="Black" BorderThickness="1.5" Grid.Row="3" Grid.ColumnSpan="2"/>
|
||||||
|
<Grid Grid.Row="4" Grid.ColumnSpan="2">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Text="Idle"/>
|
||||||
|
<Button Content="Pause / Stop" Click="Stop_Click" Margin="5"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Window>
|
||||||
347
MainWindow.xaml.cs
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using System.Windows.Navigation;
|
||||||
|
using System.Windows.Shapes;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using MediaDevices;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
|
||||||
|
namespace ReSync;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for MainWindow.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class MainWindow : Window, INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
#region Variablen
|
||||||
|
private string _phoneFolderPath;
|
||||||
|
private string _backupFolderPath;
|
||||||
|
private string _encodedOutputFolderPath;
|
||||||
|
private string _phoneConnected;
|
||||||
|
private string _newFiles;
|
||||||
|
private string _backupsPending;
|
||||||
|
private string _encodingsPending;
|
||||||
|
private string _lastSync;
|
||||||
|
private string _dbEntries;
|
||||||
|
private List<MediaDevice> _devicesList = new();
|
||||||
|
private List<string> _devicesNameList = new();
|
||||||
|
private string _selectedDevice;
|
||||||
|
private MediaDevice _selectedDeviceObject;
|
||||||
|
|
||||||
|
public List<string> DevicesNameList
|
||||||
|
{
|
||||||
|
get => _devicesNameList;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_devicesNameList != value)
|
||||||
|
{
|
||||||
|
_devicesNameList = value;
|
||||||
|
OnPropertyChanged(nameof(DevicesNameList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public MediaDevice SelectedDeviceObject
|
||||||
|
{
|
||||||
|
get => _selectedDeviceObject;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_selectedDeviceObject != value)
|
||||||
|
{
|
||||||
|
_selectedDeviceObject = value;
|
||||||
|
OnPropertyChanged(nameof(SelectedDeviceObject));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string SelectedDevice
|
||||||
|
{
|
||||||
|
get => _selectedDevice;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_selectedDevice != value)
|
||||||
|
{
|
||||||
|
_selectedDevice = value;
|
||||||
|
OnPropertyChanged(nameof(SelectedDevice));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public List<MediaDevice> DevicesList
|
||||||
|
{
|
||||||
|
get => _devicesList;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_devicesList != value)
|
||||||
|
{
|
||||||
|
_devicesList = value;
|
||||||
|
OnPropertyChanged(nameof(DevicesList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string PhoneFolderPath
|
||||||
|
{
|
||||||
|
get => _phoneFolderPath;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_phoneFolderPath != value)
|
||||||
|
{
|
||||||
|
_phoneFolderPath = value;
|
||||||
|
OnPropertyChanged(nameof(PhoneFolderPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BackupFolderPath
|
||||||
|
{
|
||||||
|
get => _backupFolderPath;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_backupFolderPath != value)
|
||||||
|
{
|
||||||
|
_backupFolderPath = value;
|
||||||
|
OnPropertyChanged(nameof(BackupFolderPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string EncodedOutputFolderPath
|
||||||
|
{
|
||||||
|
get => _encodedOutputFolderPath;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_encodedOutputFolderPath != value)
|
||||||
|
{
|
||||||
|
_encodedOutputFolderPath = value;
|
||||||
|
OnPropertyChanged(nameof(EncodedOutputFolderPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string PhoneConnected
|
||||||
|
{
|
||||||
|
get => _phoneConnected;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_phoneConnected != value)
|
||||||
|
{
|
||||||
|
_phoneConnected = value;
|
||||||
|
OnPropertyChanged(nameof(PhoneConnected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string NewFiles
|
||||||
|
{
|
||||||
|
get => _newFiles;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_newFiles != value)
|
||||||
|
{
|
||||||
|
_newFiles = value;
|
||||||
|
OnPropertyChanged(nameof(NewFiles));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BackupsPending
|
||||||
|
{
|
||||||
|
get => _backupsPending;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_backupsPending != value)
|
||||||
|
{
|
||||||
|
_backupsPending = value;
|
||||||
|
OnPropertyChanged(nameof(BackupsPending));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string EncodingsPending
|
||||||
|
{
|
||||||
|
get => _encodingsPending;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_encodingsPending != value)
|
||||||
|
{
|
||||||
|
_encodingsPending = value;
|
||||||
|
OnPropertyChanged(nameof(EncodingsPending));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string LastSync
|
||||||
|
{
|
||||||
|
get => _lastSync;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_lastSync != value)
|
||||||
|
{
|
||||||
|
_lastSync = value;
|
||||||
|
OnPropertyChanged(nameof(LastSync));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DbEntries
|
||||||
|
{
|
||||||
|
get => _dbEntries;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_dbEntries != value)
|
||||||
|
{
|
||||||
|
_dbEntries = value;
|
||||||
|
OnPropertyChanged(nameof(DbEntries));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
public void repeatingTasks()
|
||||||
|
{
|
||||||
|
Dispatcher.InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
DevicesList = GetDevices();
|
||||||
|
DevicesNameList = DevicesList.Select(d => d.FriendlyName).ToList();
|
||||||
|
if (SelectedDevice != null)
|
||||||
|
{
|
||||||
|
PhoneConnected = "Connected";
|
||||||
|
foreach (var device in DevicesList)
|
||||||
|
{
|
||||||
|
if (device.FriendlyName.Equals(SelectedDevice))
|
||||||
|
{
|
||||||
|
SelectedDeviceObject = device;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PhoneConnected = "Disconnected";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
DataContext = this;
|
||||||
|
PhoneFolderPath = "storage/emulated/0/";
|
||||||
|
BackupFolderPath = "D:/MediaBackup/";
|
||||||
|
EncodedOutputFolderPath = "D:/EncodedForPhone/";
|
||||||
|
PhoneConnected = "Disconnected";
|
||||||
|
NewFiles = "None";
|
||||||
|
BackupsPending = "None";
|
||||||
|
EncodingsPending = "None";
|
||||||
|
LastSync = "Never";
|
||||||
|
DbEntries = "None";
|
||||||
|
DevicesList = GetDevices();
|
||||||
|
SelectedDevice = DevicesList.FirstOrDefault().FriendlyName;
|
||||||
|
repeatingTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MediaDevice> GetDevices()
|
||||||
|
{
|
||||||
|
var devices = MediaDevice.GetDevices();
|
||||||
|
foreach(var device in devices.Select(d => d.FriendlyName).ToList())
|
||||||
|
{
|
||||||
|
Debug.WriteLine(device);
|
||||||
|
}
|
||||||
|
return devices.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Scan_Phone_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Scan Phone button clicked");
|
||||||
|
Dispatcher.InvokeAsync(async () =>
|
||||||
|
{
|
||||||
|
if (SelectedDeviceObject != null)
|
||||||
|
{
|
||||||
|
await Task.Run(() => FileManager.ScanMTPDevice(SelectedDeviceObject));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Sync_Files_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Sync Files button clicked");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Settings_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Settings button clicked");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Database_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Database button clicked");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Duplicates_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Duplicates button clicked");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Logs_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Logs button clicked");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Refresh_Phone_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
DevicesList = GetDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Change_Backup_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Change Backup button clicked");
|
||||||
|
var dialog = new OpenFolderDialog();
|
||||||
|
if (dialog.ShowDialog() == true)
|
||||||
|
{
|
||||||
|
BackupFolderPath = dialog.FolderName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Change_Encoded_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Change Encoded button clicked");
|
||||||
|
var dialog = new OpenFolderDialog();
|
||||||
|
if (dialog.ShowDialog() == true)
|
||||||
|
{
|
||||||
|
EncodedOutputFolderPath = dialog.FolderName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Rescan_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Rescan button clicked");
|
||||||
|
}
|
||||||
|
private void Start_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Start Sync button clicked");
|
||||||
|
}
|
||||||
|
private void Stop_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Pause/Stop button clicked");
|
||||||
|
FileManager.CancelOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
protected void OnPropertyChanged(string propertyName)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
27
ReSync.csproj
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net9.0-windows</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<UseWPF>true</UseWPF>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Include resources (SVG/PNG/etc) so they are embedded and accessible via pack URIs -->
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Resources\*.*" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Frames\**" />
|
||||||
|
<EmbeddedResource Remove="Frames\**" />
|
||||||
|
<None Remove="Frames\**" />
|
||||||
|
<Page Remove="Frames\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Blake3" Version="2.0.0" />
|
||||||
|
<PackageReference Include="MediaDevices" Version="1.10.0" />
|
||||||
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.10" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
24
ReSync.sln
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.5.2.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReSync", "ReSync.csproj", "{F7C05B29-6490-135B-BC0D-5D4BFB6049BE}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{F7C05B29-6490-135B-BC0D-5D4BFB6049BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F7C05B29-6490-135B-BC0D-5D4BFB6049BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F7C05B29-6490-135B-BC0D-5D4BFB6049BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F7C05B29-6490-135B-BC0D-5D4BFB6049BE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {4C1A8D6F-B157-4647-BE2F-15A58F0919CF}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
BIN
Resources/database.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
Resources/duplicates.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
Resources/folder.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
Resources/logo.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
Resources/logs.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
Resources/phone.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
Resources/settings.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
8
Resources/svg/database.svg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4 18V6" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
<path d="M20 6V18" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
<path d="M12 10C16.4183 10 20 8.20914 20 6C20 3.79086 16.4183 2 12 2C7.58172 2 4 3.79086 4 6C4 8.20914 7.58172 10 12 10Z" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
<path opacity="0.5" d="M20 12C20 14.2091 16.4183 16 12 16C7.58172 16 4 14.2091 4 12" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
<path d="M20 18C20 20.2091 16.4183 22 12 22C7.58172 22 4 20.2091 4 18" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 778 B |
7
Resources/svg/duplicates.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M2 13.4375C2 9.66626 2 7.78065 3.17157 6.60907C4.34315 5.4375 6.22876 5.4375 10 5.4375H14C17.7712 5.4375 19.6569 5.4375 20.8284 6.60907C22 7.78065 22 9.66626 22 13.4375C22 17.2087 22 19.0944 20.8284 20.2659C19.6569 21.4375 17.7712 21.4375 14 21.4375H10C6.22876 21.4375 4.34315 21.4375 3.17157 20.2659C2 19.0944 2 17.2087 2 13.4375Z" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
<path opacity="0.5" d="M3.98779 6C4.10022 5.06898 4.33494 4.42559 4.82498 3.93726C5.76553 3 7.27932 3 10.3069 3H13.5181C16.5457 3 18.0595 3 19 3.93726C19.4901 4.42559 19.7248 5.06898 19.8372 6" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
<circle opacity="0.5" cx="17.5" cy="9.9375" r="1.5" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
<path opacity="0.5" d="M2 13.9376L3.75159 12.405C4.66286 11.6077 6.03628 11.6534 6.89249 12.5096L11.1822 16.7993C11.8694 17.4866 12.9512 17.5803 13.7464 17.0214L14.0446 16.8119C15.1888 16.0077 16.7369 16.1009 17.7765 17.0365L21 19.9376" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
6
Resources/svg/folder.svg
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path opacity="0.5" d="M18 10L13 10" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
<path opacity="0.5" d="M10 3H16.5C16.9644 3 17.1966 3 17.3916 3.02567C18.7378 3.2029 19.7971 4.26222 19.9743 5.60842C20 5.80337 20 6.03558 20 6.5" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
<path d="M2 6.94975C2 6.06722 2 5.62595 2.06935 5.25839C2.37464 3.64031 3.64031 2.37464 5.25839 2.06935C5.62595 2 6.06722 2 6.94975 2C7.33642 2 7.52976 2 7.71557 2.01738C8.51665 2.09229 9.27652 2.40704 9.89594 2.92051C10.0396 3.03961 10.1763 3.17633 10.4497 3.44975L11 4C11.8158 4.81578 12.2237 5.22367 12.7121 5.49543C12.9804 5.64471 13.2651 5.7626 13.5604 5.84678C14.0979 6 14.6747 6 15.8284 6H16.2021C18.8345 6 20.1506 6 21.0062 6.76946C21.0849 6.84024 21.1598 6.91514 21.2305 6.99383C22 7.84935 22 9.16554 22 11.7979V14C22 17.7712 22 19.6569 20.8284 20.8284C19.6569 22 17.7712 22 14 22H10C6.22876 22 4.34315 22 3.17157 20.8284C2 19.6569 2 17.7712 2 14V6.94975Z" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
63
Resources/svg/logo.svg
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="400" height="240" viewBox="0 0 400 120" role="img" aria-labelledby="title desc">
|
||||||
|
<title id="title">ReSync logo</title>
|
||||||
|
<desc id="desc">Circular sync icon with two arrows and the ReSync wordmark</desc>
|
||||||
|
|
||||||
|
<!-- Definitions: gradient -->
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="g" x1="0" x2="1" y1="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#00C6FF"/>
|
||||||
|
<stop offset="1" stop-color="#0072FF"/>
|
||||||
|
</linearGradient>
|
||||||
|
|
||||||
|
</defs>
|
||||||
|
|
||||||
|
<!-- Background circle (subtle) -->
|
||||||
|
<circle cx="64" cy="60" r="52" fill="none" stroke="#E9F5FF" stroke-width="2"/>
|
||||||
|
|
||||||
|
<!-- First arc (clockwise) -->
|
||||||
|
<path d="M100 60
|
||||||
|
A36 36 0 0 0 64 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="url(#g)"
|
||||||
|
stroke-width="10"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
vector-effect="non-scaling-stroke"/>
|
||||||
|
|
||||||
|
<!-- Second arc (counter-clockwise) -->
|
||||||
|
<path d="M28 60
|
||||||
|
A36 36 0 0 0 64 96"
|
||||||
|
fill="none"
|
||||||
|
stroke="#00A3FF"
|
||||||
|
stroke-width="10"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
vector-effect="non-scaling-stroke"/>
|
||||||
|
|
||||||
|
<!-- Inner stylized "R" letter as brand mark -->
|
||||||
|
<g transform="translate(44,42)">
|
||||||
|
<path d="M8 36 L8 12 C8 10 10 8 12 8 L20 8 C26 8 30 12 30 18 C30 24 26 28 20 28 L12 28"
|
||||||
|
fill="none" stroke="#004EBD" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M20 28 C24 28 28 30 30 34" fill="none" stroke="#004EBD" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Wordmark: ReSync -->
|
||||||
|
<g transform="translate(130,72)" aria-hidden="true">
|
||||||
|
<text x="0" y="0" font-family="Segoe UI, Roboto, Arial, sans-serif" font-weight="700" font-size="36" fill="#0A2E6C">
|
||||||
|
Re
|
||||||
|
</text>
|
||||||
|
<text x="45" y="0" font-family="Segoe UI, Roboto, Arial, sans-serif" font-weight="700" font-size="36" fill="url(#g)">
|
||||||
|
Sync
|
||||||
|
</text>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
<!-- Optional tagline (comment out if unused) -->
|
||||||
|
<!--
|
||||||
|
<text x="130" y="98" font-family="Segoe UI, Roboto, Arial, sans-serif" font-size="12" fill="#6C7A93">
|
||||||
|
seamless file synchronization
|
||||||
|
</text>
|
||||||
|
-->
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |
5
Resources/svg/logs.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path opacity="0.5" d="M12 8V12L14.5 14.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M5.60414 5.60414L5.07381 5.07381V5.07381L5.60414 5.60414ZM4.33776 6.87052L3.58777 6.87429C3.58984 7.28556 3.92272 7.61844 4.33399 7.62051L4.33776 6.87052ZM6.87954 7.6333C7.29375 7.63539 7.63122 7.30129 7.6333 6.88708C7.63538 6.47287 7.30129 6.1354 6.88708 6.13332L6.87954 7.6333ZM5.07496 4.3212C5.07288 3.90699 4.73541 3.5729 4.3212 3.57498C3.90699 3.57706 3.5729 3.91453 3.57498 4.32874L5.07496 4.3212ZM3.82661 10.7849C3.88286 10.3745 3.59578 9.99627 3.1854 9.94002C2.77503 9.88377 2.39675 10.1708 2.3405 10.5812L3.82661 10.7849ZM18.8622 5.13777C15.042 1.31758 8.86873 1.27889 5.07381 5.07381L6.13447 6.13447C9.33358 2.93536 14.5571 2.95395 17.8016 6.19843L18.8622 5.13777ZM5.13777 18.8622C8.95796 22.6824 15.1313 22.7211 18.9262 18.9262L17.8655 17.8655C14.6664 21.0646 9.44291 21.0461 6.19843 17.8016L5.13777 18.8622ZM18.9262 18.9262C22.7211 15.1313 22.6824 8.95796 18.8622 5.13777L17.8016 6.19843C21.0461 9.44291 21.0646 14.6664 17.8655 17.8655L18.9262 18.9262ZM5.07381 5.07381L3.80743 6.34019L4.86809 7.40085L6.13447 6.13447L5.07381 5.07381ZM4.33399 7.62051L6.87954 7.6333L6.88708 6.13332L4.34153 6.12053L4.33399 7.62051ZM5.08775 6.86675L5.07496 4.3212L3.57498 4.32874L3.58777 6.87429L5.08775 6.86675ZM2.3405 10.5812C1.93907 13.5099 2.87392 16.5984 5.13777 18.8622L6.19843 17.8016C4.27785 15.881 3.48663 13.2652 3.82661 10.7849L2.3405 10.5812Z" fill="#1C274C"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
5
Resources/svg/phone.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M4 10C4 6.22876 4 4.34315 5.17157 3.17157C6.34315 2 8.22876 2 12 2C15.7712 2 17.6569 2 18.8284 3.17157C20 4.34315 20 6.22876 20 10V14C20 17.7712 20 19.6569 18.8284 20.8284C17.6569 22 15.7712 22 12 22C8.22876 22 6.34315 22 5.17157 20.8284C4 19.6569 4 17.7712 4 14V10Z" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
<path opacity="0.5" d="M15 19H9" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 636 B |
5
Resources/svg/settings.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="12" cy="12" r="3" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
<path opacity="0.5" d="M13.7654 2.15224C13.3978 2 12.9319 2 12 2C11.0681 2 10.6022 2 10.2346 2.15224C9.74457 2.35523 9.35522 2.74458 9.15223 3.23463C9.05957 3.45834 9.0233 3.7185 9.00911 4.09799C8.98826 4.65568 8.70226 5.17189 8.21894 5.45093C7.73564 5.72996 7.14559 5.71954 6.65219 5.45876C6.31645 5.2813 6.07301 5.18262 5.83294 5.15102C5.30704 5.08178 4.77518 5.22429 4.35436 5.5472C4.03874 5.78938 3.80577 6.1929 3.33983 6.99993C2.87389 7.80697 2.64092 8.21048 2.58899 8.60491C2.51976 9.1308 2.66227 9.66266 2.98518 10.0835C3.13256 10.2756 3.3397 10.437 3.66119 10.639C4.1338 10.936 4.43789 11.4419 4.43786 12C4.43783 12.5581 4.13375 13.0639 3.66118 13.3608C3.33965 13.5629 3.13248 13.7244 2.98508 13.9165C2.66217 14.3373 2.51966 14.8691 2.5889 15.395C2.64082 15.7894 2.87379 16.193 3.33973 17C3.80568 17.807 4.03865 18.2106 4.35426 18.4527C4.77508 18.7756 5.30694 18.9181 5.83284 18.8489C6.07289 18.8173 6.31632 18.7186 6.65204 18.5412C7.14547 18.2804 7.73556 18.27 8.2189 18.549C8.70224 18.8281 8.98826 19.3443 9.00911 19.9021C9.02331 20.2815 9.05957 20.5417 9.15223 20.7654C9.35522 21.2554 9.74457 21.6448 10.2346 21.8478C10.6022 22 11.0681 22 12 22C12.9319 22 13.3978 22 13.7654 21.8478C14.2554 21.6448 14.6448 21.2554 14.8477 20.7654C14.9404 20.5417 14.9767 20.2815 14.9909 19.902C15.0117 19.3443 15.2977 18.8281 15.781 18.549C16.2643 18.2699 16.8544 18.2804 17.3479 18.5412C17.6836 18.7186 17.927 18.8172 18.167 18.8488C18.6929 18.9181 19.2248 18.7756 19.6456 18.4527C19.9612 18.2105 20.1942 17.807 20.6601 16.9999C21.1261 16.1929 21.3591 15.7894 21.411 15.395C21.4802 14.8691 21.3377 14.3372 21.0148 13.9164C20.8674 13.7243 20.6602 13.5628 20.3387 13.3608C19.8662 13.0639 19.5621 12.558 19.5621 11.9999C19.5621 11.4418 19.8662 10.9361 20.3387 10.6392C20.6603 10.4371 20.8675 10.2757 21.0149 10.0835C21.3378 9.66273 21.4803 9.13087 21.4111 8.60497C21.3592 8.21055 21.1262 7.80703 20.6602 7C20.1943 6.19297 19.9613 5.78945 19.6457 5.54727C19.2249 5.22436 18.693 5.08185 18.1671 5.15109C17.9271 5.18269 17.6837 5.28136 17.3479 5.4588C16.8545 5.71959 16.2644 5.73002 15.7811 5.45096C15.2977 5.17191 15.0117 4.65566 14.9909 4.09794C14.9767 3.71848 14.9404 3.45833 14.8477 3.23463C14.6448 2.74458 14.2554 2.35523 13.7654 2.15224Z" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.5 KiB |
5
Resources/svg/sync.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||||
|
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path opacity="0.5" d="M9.00195 7C9.01406 4.82497 9.11051 3.64706 9.87889 2.87868C10.7576 2 12.1718 2 15.0002 2L16.0002 2C18.8286 2 20.2429 2 21.1215 2.87868C22.0002 3.75736 22.0002 5.17157 22.0002 8L22.0002 16C22.0002 18.8284 22.0002 20.2426 21.1215 21.1213C20.2429 22 18.8286 22 16.0002 22H15.0002C12.1718 22 10.7576 22 9.87889 21.1213C9.11051 20.3529 9.01406 19.175 9.00195 17" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
<path d="M15 12L2 12M2 12L5.5 9M2 12L5.5 15" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 799 B |
BIN
Resources/sync.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |