diff --git a/Controls/Components/LocalQuoteComponent.axaml.cs b/Controls/Components/LocalQuoteComponent.axaml.cs index 0caf9bb..5efb792 100644 --- a/Controls/Components/LocalQuoteComponent.axaml.cs +++ b/Controls/Components/LocalQuoteComponent.axaml.cs @@ -35,6 +35,7 @@ public partial class LocalQuoteComponent : ComponentBase, IN private readonly List _quotes = []; private readonly Animation _swapOutAnimation; private readonly Animation _swapInAnimation; + private readonly Random _random = new(); private int _currentIndex = -1; private string _loadedPath = string.Empty; private bool _isAnimating; @@ -174,6 +175,12 @@ private void OnSettingsPropertyChanged(object? sender, PropertyChangedEventArgs LoadQuotesFromFile(Settings.QuotesFilePath, showFirstQuote: true); EnsureTimersForQuoteState(); } + + if (e.PropertyName == nameof(Settings.PlaybackOrder)) + { + ShowNextQuote(); + EnsureTimersForQuoteState(); + } } /// @@ -323,7 +330,9 @@ private async void ShowNextQuote() // 因此需要在当前轮换开始时立即重置,而不是等动画播放完成后再重置。 RestartProgressCycle(_carouselTimer.Interval.TotalSeconds); - _currentIndex = (_currentIndex + 1) % _quotes.Count; + _currentIndex = Settings.PlaybackOrder == LocalQuotePlaybackOrder.Random + ? _random.Next(_quotes.Count) + : (_currentIndex + 1) % _quotes.Count; var next = _quotes[_currentIndex]; // 更新持久化数据 diff --git a/Controls/Components/LocalQuoteSettingsControl.axaml b/Controls/Components/LocalQuoteSettingsControl.axaml index c9c2ba0..08c0aec 100644 --- a/Controls/Components/LocalQuoteSettingsControl.axaml +++ b/Controls/Components/LocalQuoteSettingsControl.axaml @@ -55,6 +55,22 @@ Value="{Binding Settings.CarouselIntervalSeconds, Mode=TwoWay}" /> + + + + + + + + + + + + { public Array ProgressBarPositions { get; } = Enum.GetValues(typeof(LocalQuoteProgressBarPosition)); + public Array PlaybackOrders { get; } = Enum.GetValues(typeof(LocalQuotePlaybackOrder)); public LocalQuoteSettingsControl() { diff --git a/Models/ComponentSettings/LocalQuoteSettings.cs b/Models/ComponentSettings/LocalQuoteSettings.cs index 0eeeb9b..b030976 100644 --- a/Models/ComponentSettings/LocalQuoteSettings.cs +++ b/Models/ComponentSettings/LocalQuoteSettings.cs @@ -12,6 +12,14 @@ public enum LocalQuoteProgressBarPosition Top = 1 } +public enum LocalQuotePlaybackOrder +{ + [Description("逐行播放")] + Sequential = 0, + [Description("随机播放")] + Random = 1 +} + public partial class LocalQuoteSettings : ObservableObject { [ObservableProperty] @@ -37,4 +45,7 @@ public partial class LocalQuoteSettings : ObservableObject [ObservableProperty] private LocalQuoteProgressBarPosition _progressBarPosition = LocalQuoteProgressBarPosition.Bottom; + + [ObservableProperty] + private LocalQuotePlaybackOrder _playbackOrder = LocalQuotePlaybackOrder.Sequential; } diff --git a/Plugin.cs b/Plugin.cs index c335468..58ac528 100644 --- a/Plugin.cs +++ b/Plugin.cs @@ -20,6 +20,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; +using System.ComponentModel; using SystemTools.Actions; using SystemTools.ConfigHandlers; using SystemTools.Controls; @@ -144,6 +145,7 @@ public override void Initialize(HostBuilderContext context, IServiceCollection s _logger?.LogWarning("[SystemTools]人脸识别功能已自动关闭:缺少 runtimes、Models 或 OpenCvSharp/Dlib 依赖,并已清理对应验证器配置。"); } _logger?.LogInformation("[SystemTools]SystemTools 启动完成"); + RegisterOrUpdateFloatingWindowTrayMenu(); }; // ========== 注册实验性功能 ========== @@ -900,6 +902,91 @@ private void OnAppStopping(object? sender, EventArgs e) IAppHost.GetService().Stop(); } _logger?.LogInformation("[SystemTools]关闭插件SystemTools,保存配置..."); + UnregisterFloatingWindowTrayMenu(); GlobalConstants.MainConfig?.Save(); } + + private void RegisterOrUpdateFloatingWindowTrayMenu() + { + var config = GlobalConstants.MainConfig?.Data; + if (config == null) + { + return; + } + + if (_toggleFloatingWindowMenuItem == null) + { + _toggleFloatingWindowMenuItem = new NativeMenuItem(); + _toggleFloatingWindowMenuItem.Click += (_, _) => + { + var data = GlobalConstants.MainConfig?.Data; + if (data == null || !data.EnableFloatingWindowFeature) + { + return; + } + + data.ShowFloatingWindow = !data.ShowFloatingWindow; + IAppHost.GetService().UpdateWindowState(); + UpdateFloatingWindowTrayMenuHeader(); + GlobalConstants.MainConfig?.Save(); + }; + + config.PropertyChanged += OnMainConfigDataPropertyChanged; + } + + if (!config.EnableFloatingWindowFeature) + { + UnregisterFloatingWindowTrayMenu(); + return; + } + + var trayService = IAppHost.TryGetService(); + if (trayService == null) + { + return; + } + + if (!trayService.MoreOptionsMenuItems.Contains(_toggleFloatingWindowMenuItem)) + { + trayService.MoreOptionsMenuItems.Add(_toggleFloatingWindowMenuItem); + } + + UpdateFloatingWindowTrayMenuHeader(); + } + + private void UnregisterFloatingWindowTrayMenu() + { + var trayService = IAppHost.TryGetService(); + if (trayService == null || _toggleFloatingWindowMenuItem == null) + { + return; + } + + if (trayService.MoreOptionsMenuItems.Contains(_toggleFloatingWindowMenuItem)) + { + trayService.MoreOptionsMenuItems.Remove(_toggleFloatingWindowMenuItem); + } + } + + private void OnMainConfigDataPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + if (e.PropertyName is not (nameof(MainConfigData.ShowFloatingWindow) or nameof(MainConfigData.EnableFloatingWindowFeature))) + { + return; + } + + Dispatcher.UIThread.Post(RegisterOrUpdateFloatingWindowTrayMenu); + } + + private void UpdateFloatingWindowTrayMenuHeader() + { + if (_toggleFloatingWindowMenuItem == null) + { + return; + } + + _toggleFloatingWindowMenuItem.Header = GlobalConstants.MainConfig?.Data.ShowFloatingWindow == true + ? "隐藏悬浮窗" + : "显示悬浮窗"; + } } diff --git a/manifest.yml b/manifest.yml index c8a20a4..7e001d8 100644 --- a/manifest.yml +++ b/manifest.yml @@ -8,7 +8,7 @@ name: SystemTools description: 提供多彩而丰富的更多 组件/行动/触发器/实用工具 entranceAssembly: "SystemTools.dll" url: https://github.com/Programmer-MrWang/SystemTools -version: 2.5.0.105 +version: 2.5.0.106 apiVersion: 2.0.0.0 author: Programmer-MrWang readme: README.md