diff --git a/FreeTubeSyncer/App.axaml b/FreeTubeSyncer/App.axaml index 8c9d9af..d527e69 100644 --- a/FreeTubeSyncer/App.axaml +++ b/FreeTubeSyncer/App.axaml @@ -1,7 +1,9 @@ @@ -11,8 +13,8 @@ - diff --git a/FreeTubeSyncer/App.axaml.cs b/FreeTubeSyncer/App.axaml.cs index 4f96b59..bbfd8ac 100644 --- a/FreeTubeSyncer/App.axaml.cs +++ b/FreeTubeSyncer/App.axaml.cs @@ -8,8 +8,11 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Avalonia; +using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Markup.Xaml; +using Avalonia.Platform; +using Avalonia.Threading; using FreeTubeSyncer.Library; using FreeTubeSyncer.Models; using FreeTubeSyncer.Models.DatabaseModels; @@ -39,13 +42,23 @@ public partial class App : Application private TimeSpan _checkInterval; private DateTime _lastUpdated; + private WindowIcon? _normalTrayIcon; + private WindowIcon? _waitingTrayIcon; + private WindowIcon? _completeTrayIcon; + public event EventHandler? SettingsChanged; public static App GetApp() => (App)App.Current!; public static ClassicDesktopStyleApplicationLifetime GetDesktop() => (ClassicDesktopStyleApplicationLifetime)App.Current!.ApplicationLifetime!; public override void Initialize() { + _normalTrayIcon = new WindowIcon(AssetLoader.Open(new Uri("avares://FreeTubeSyncer/Assets/freetubesyncer.64.png"))); + _waitingTrayIcon = new WindowIcon(AssetLoader.Open(new Uri("avares://FreeTubeSyncer/Assets/awaiting_sync.png"))); + _completeTrayIcon = new WindowIcon(AssetLoader.Open(new Uri("avares://FreeTubeSyncer/Assets/sync_complete.png"))); + var vm = new AppViewModel(); + vm.AppIcon = _normalTrayIcon; AvaloniaXamlLoader.Load(this); + DataContext = vm; } public override void OnFrameworkInitializationCompleted() @@ -159,6 +172,18 @@ public partial class App : Application Log.Information("Log Started."); } + private async Task UpdateSTIconHint(WindowIcon icon, string? hint = null) + { + await Dispatcher.UIThread.InvokeAsync(async () => + { + await _semaphoreSlim.WaitAsync(); + ((AppViewModel)DataContext!).AppIcon = icon; + if (hint != null) ((AppViewModel)DataContext).HintTooltip = hint; + _semaphoreSlim.Release(); + + }); + } + private async Task SyncMonitor() { Log.Information("Sync Monitor Starting Up."); @@ -191,6 +216,11 @@ public partial class App : Application while (_isRunning) { await Task.Delay(100); + + if (_syncers.Any(x => x.IsDirty())) + { + await UpdateSTIconHint(_waitingTrayIcon!, "FreeTube Syncer - Changes waiting to be written..."); + } var sinceLastCheck = DateTime.Now - lastCheck; if (sinceLastCheck.TotalSeconds > _checkInterval.TotalSeconds) @@ -219,6 +249,7 @@ public partial class App : Application if (procs.Length > 0) continue; Log.Information("FreeTube instance closed, and we have writes to make..."); await Task.Delay(1500); + await UpdateSTIconHint(_waitingTrayIcon, "FreeTube Syncer - Syncing data..."); await _semaphoreSlim.WaitAsync(); var syncStart = DateTime.Now; @@ -227,6 +258,12 @@ public partial class App : Application var syncEnd = DateTime.Now - syncStart; _semaphoreSlim.Release(); Log.Information("Sync Completed. Total Time: {EndTime}", syncEnd); + await UpdateSTIconHint(_completeTrayIcon, "FreeTube Syncer - Sync completed."); + Task.Run(async () => + { + await Task.Delay(3000); + await UpdateSTIconHint(_normalTrayIcon, "FreeTube Syncer - Watching files..."); + }); } Log.Information("Filesystem Sync Monitor shutdown."); diff --git a/FreeTubeSyncer/Assets/awaiting_sync.png b/FreeTubeSyncer/Assets/awaiting_sync.png index 32337e5..5fe4366 100644 Binary files a/FreeTubeSyncer/Assets/awaiting_sync.png and b/FreeTubeSyncer/Assets/awaiting_sync.png differ diff --git a/FreeTubeSyncer/Assets/freetubesyncer.64.png b/FreeTubeSyncer/Assets/freetubesyncer.64.png new file mode 100644 index 0000000..ea2865c Binary files /dev/null and b/FreeTubeSyncer/Assets/freetubesyncer.64.png differ diff --git a/FreeTubeSyncer/Assets/sync_complete.png b/FreeTubeSyncer/Assets/sync_complete.png index a071175..92288b8 100644 Binary files a/FreeTubeSyncer/Assets/sync_complete.png and b/FreeTubeSyncer/Assets/sync_complete.png differ diff --git a/FreeTubeSyncer/FreeTubeSyncer.csproj b/FreeTubeSyncer/FreeTubeSyncer.csproj index 44fce9e..e8c435a 100644 --- a/FreeTubeSyncer/FreeTubeSyncer.csproj +++ b/FreeTubeSyncer/FreeTubeSyncer.csproj @@ -34,7 +34,8 @@ - - + + + diff --git a/FreeTubeSyncer/Library/DBSyncWatcher.cs b/FreeTubeSyncer/Library/DBSyncWatcher.cs index f7a6bbf..f178a58 100644 --- a/FreeTubeSyncer/Library/DBSyncWatcher.cs +++ b/FreeTubeSyncer/Library/DBSyncWatcher.cs @@ -36,10 +36,7 @@ public class DBSyncWatcher { if (e.ChangeType != WatcherChangeTypes.Changed) return; - while (Locked) - { - Thread.Sleep(100); - } + if (Locked) return; var dbName = Path.GetFileName(e.FullPath); diff --git a/FreeTubeSyncer/MainWindow.axaml b/FreeTubeSyncer/MainWindow.axaml index 9377531..8ee3fa1 100644 --- a/FreeTubeSyncer/MainWindow.axaml +++ b/FreeTubeSyncer/MainWindow.axaml @@ -8,6 +8,7 @@ Width="400" Height="345" x:Class="FreeTubeSyncer.MainWindow" x:DataType="vm:AppSettings" + Icon="/Assets/freetubesyncer.64.png" BackgroundStyle="GradientDarker" CanResize="False" CanMaximize="False" diff --git a/FreeTubeSyncer/Models/AppViewModel.cs b/FreeTubeSyncer/Models/AppViewModel.cs new file mode 100644 index 0000000..bed3056 --- /dev/null +++ b/FreeTubeSyncer/Models/AppViewModel.cs @@ -0,0 +1,10 @@ +using Avalonia.Controls; +using CommunityToolkit.Mvvm.ComponentModel; + +namespace FreeTubeSyncer.Models; + +public partial class AppViewModel : ObservableObject +{ + [ObservableProperty] private WindowIcon? _appIcon; + [ObservableProperty] private string _hintTooltip = "FreeTube Syncer"; +} \ No newline at end of file diff --git a/FreeTubeSyncer/REST/Syncer.cs b/FreeTubeSyncer/REST/Syncer.cs index b92c4ed..0726331 100644 --- a/FreeTubeSyncer/REST/Syncer.cs +++ b/FreeTubeSyncer/REST/Syncer.cs @@ -218,8 +218,9 @@ public class Syncer : ISyncer where T : class, IDataModel, new() foreach (var line in json) fh.Write(Encoding.UTF8.GetBytes(line + "\n")); fh.Flush(); - fh.Close(); } + + Task.Delay(100).Wait(); _watcher.Locked = false; Log.Information("Updated {DbName}, completed in {TimeSpan}", _dbName, DateTime.Now - start); _isDirty = false;