From dfc5ec07052aa805012f71033f0c450427f7782b Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Mon, 5 Aug 2024 14:39:04 +0800 Subject: [PATCH] Improve UI --- .../v2rayN/ViewModels/MainWindowViewModel.cs | 197 ------------------ .../ViewModels/ThemeSettingViewModel.cs | 193 +++++++++++++++++ v2rayN/v2rayN/Views/MainWindow.xaml | 83 +------- v2rayN/v2rayN/Views/MainWindow.xaml.cs | 24 +-- v2rayN/v2rayN/Views/ThemeSettingView.xaml | 97 +++++++++ v2rayN/v2rayN/Views/ThemeSettingView.xaml.cs | 41 ++++ 6 files changed, 335 insertions(+), 300 deletions(-) create mode 100644 v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs create mode 100644 v2rayN/v2rayN/Views/ThemeSettingView.xaml create mode 100644 v2rayN/v2rayN/Views/ThemeSettingView.xaml.cs diff --git a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs index c98f26ccc0..9a4b18e3f2 100644 --- a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs +++ b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs @@ -1,7 +1,4 @@ -using DynamicData; using DynamicData.Binding; -using MaterialDesignColors; -using MaterialDesignColors.ColorManipulation; using MaterialDesignThemes.Wpf; using ReactiveUI; using ReactiveUI.Fody.Helpers; @@ -30,7 +27,6 @@ public class MainWindowViewModel : ReactiveObject private CoreHandler _coreHandler; private static Config _config; private NoticeHandler? _noticeHandler; - private readonly PaletteHelper _paletteHelper = new(); private Action _updateView; private bool _showInTaskbar; @@ -165,24 +161,6 @@ public class MainWindowViewModel : ReactiveObject [Reactive] public bool EnableTun { get; set; } - [Reactive] - public bool ColorModeDark { get; set; } - - private IObservableCollection _swatches = new ObservableCollectionExtended(); - public IObservableCollection Swatches => _swatches; - - [Reactive] - public Swatch SelectedSwatch { get; set; } - - [Reactive] - public int CurrentFontSize { get; set; } - - [Reactive] - public bool FollowSystemTheme { get; set; } - - [Reactive] - public string CurrentLanguage { get; set; } - [Reactive] public bool ShowClashUI { get; set; } @@ -219,8 +197,6 @@ public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue, Action t.Name == _config.uiItem.colorPrimaryName); - if (swatch != null - && swatch.ExemplarHue != null - && swatch.ExemplarHue?.Color != null) - { - ChangePrimaryColor(swatch.ExemplarHue.Color); - } - } - } - - private void BindingUI() - { - ColorModeDark = _config.uiItem.colorModeDark; - FollowSystemTheme = _config.uiItem.followSystemTheme; - _swatches.AddRange(new SwatchesProvider().Swatches); - if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty()) - { - SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.uiItem.colorPrimaryName); - } - CurrentFontSize = _config.uiItem.currentFontSize; - CurrentLanguage = _config.uiItem.currentLanguage; - - this.WhenAnyValue( - x => x.ColorModeDark, - y => y == true) - .Subscribe(c => - { - if (_config.uiItem.colorModeDark != ColorModeDark) - { - _config.uiItem.colorModeDark = ColorModeDark; - ModifyTheme(ColorModeDark); - ConfigHandler.SaveConfig(_config); - } - }); - - this.WhenAnyValue(x => x.FollowSystemTheme, - y => y == true) - .Subscribe(c => - { - if (_config.uiItem.followSystemTheme != FollowSystemTheme) - { - _config.uiItem.followSystemTheme = FollowSystemTheme; - ConfigHandler.SaveConfig(_config); - if (FollowSystemTheme) - { - ModifyTheme(!Utils.IsLightTheme()); - } - else - { - ModifyTheme(ColorModeDark); - } - } - }); - - this.WhenAnyValue( - x => x.SelectedSwatch, - y => y != null && !y.Name.IsNullOrEmpty()) - .Subscribe(c => - { - if (SelectedSwatch == null - || SelectedSwatch.Name.IsNullOrEmpty() - || SelectedSwatch.ExemplarHue == null - || SelectedSwatch.ExemplarHue?.Color == null) - { - return; - } - if (_config.uiItem.colorPrimaryName != SelectedSwatch?.Name) - { - _config.uiItem.colorPrimaryName = SelectedSwatch?.Name; - ChangePrimaryColor(SelectedSwatch.ExemplarHue.Color); - ConfigHandler.SaveConfig(_config); - } - }); - - this.WhenAnyValue( - x => x.CurrentFontSize, - y => y > 0) - .Subscribe(c => - { - if (CurrentFontSize >= Global.MinFontSize) - { - _config.uiItem.currentFontSize = CurrentFontSize; - double size = (long)CurrentFontSize; - Application.Current.Resources["StdFontSize"] = size; - Application.Current.Resources["StdFontSize1"] = size + 1; - Application.Current.Resources["StdFontSize2"] = size + 2; - Application.Current.Resources["StdFontSizeMsg"] = size - 1; - Application.Current.Resources["StdFontSize-1"] = size - 1; - - ConfigHandler.SaveConfig(_config); - } - }); - - this.WhenAnyValue( - x => x.CurrentLanguage, - y => y != null && !y.IsNullOrEmpty()) - .Subscribe(c => - { - if (!Utils.IsNullOrEmpty(CurrentLanguage) && _config.uiItem.currentLanguage != CurrentLanguage) - { - _config.uiItem.currentLanguage = CurrentLanguage; - Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage); - ConfigHandler.SaveConfig(_config); - _noticeHandler?.Enqueue(ResUI.NeedRebootTips); - } - }); - } - public void InboundDisplayStaus() { StringBuilder sb = new(); @@ -1255,27 +1079,6 @@ public void InboundDisplayStaus() } } - public void ModifyTheme(bool isDarkTheme) - { - var theme = _paletteHelper.GetTheme(); - - theme.SetBaseTheme(isDarkTheme ? BaseTheme.Dark : BaseTheme.Light); - _paletteHelper.SetTheme(theme); - - Utils.SetDarkBorder(Application.Current.MainWindow, isDarkTheme); - } - - public void ChangePrimaryColor(System.Windows.Media.Color color) - { - var theme = _paletteHelper.GetTheme(); - - theme.PrimaryLight = new ColorPair(color.Lighten()); - theme.PrimaryMid = new ColorPair(color); - theme.PrimaryDark = new ColorPair(color.Darken()); - - _paletteHelper.SetTheme(theme); - } - private void AutoHideStartup() { if (_config.uiItem.autoHideStartup) diff --git a/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs new file mode 100644 index 0000000000..aa4fed23c2 --- /dev/null +++ b/v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs @@ -0,0 +1,193 @@ +using DynamicData; +using DynamicData.Binding; +using MaterialDesignColors; +using MaterialDesignColors.ColorManipulation; +using MaterialDesignThemes.Wpf; +using ReactiveUI; +using ReactiveUI.Fody.Helpers; +using Splat; +using System.Reactive.Linq; +using System.Windows; +using v2rayN.Handler; +using v2rayN.Models; +using v2rayN.Resx; + +namespace v2rayN.ViewModels +{ + public class ThemeSettingViewModel : ReactiveObject + { + private static Config _config; + private NoticeHandler? _noticeHandler; + private readonly PaletteHelper _paletteHelper = new(); + + [Reactive] + public bool ColorModeDark { get; set; } + + private IObservableCollection _swatches = new ObservableCollectionExtended(); + public IObservableCollection Swatches => _swatches; + + [Reactive] + public Swatch SelectedSwatch { get; set; } + + [Reactive] + public int CurrentFontSize { get; set; } + + [Reactive] + public bool FollowSystemTheme { get; set; } + + [Reactive] + public string CurrentLanguage { get; set; } + + public ThemeSettingViewModel() + { + _config = LazyConfig.Instance.GetConfig(); + _noticeHandler = Locator.Current.GetService(); + MainFormHandler.Instance.RegisterSystemColorSet(_config, Application.Current.MainWindow, (bool bl) => { ModifyTheme(bl); }); + + BindingUI(); + RestoreUI(); + } + + private void RestoreUI() + { + if (FollowSystemTheme) + { + ModifyTheme(!Utils.IsLightTheme()); + } + else + { + ModifyTheme(_config.uiItem.colorModeDark); + } + + if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty()) + { + var swatch = new SwatchesProvider().Swatches.FirstOrDefault(t => t.Name == _config.uiItem.colorPrimaryName); + if (swatch != null + && swatch.ExemplarHue != null + && swatch.ExemplarHue?.Color != null) + { + ChangePrimaryColor(swatch.ExemplarHue.Color); + } + } + } + + private void BindingUI() + { + ColorModeDark = _config.uiItem.colorModeDark; + FollowSystemTheme = _config.uiItem.followSystemTheme; + _swatches.AddRange(new SwatchesProvider().Swatches); + if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty()) + { + SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.uiItem.colorPrimaryName); + } + CurrentFontSize = _config.uiItem.currentFontSize; + CurrentLanguage = _config.uiItem.currentLanguage; + + this.WhenAnyValue( + x => x.ColorModeDark, + y => y == true) + .Subscribe(c => + { + if (_config.uiItem.colorModeDark != ColorModeDark) + { + _config.uiItem.colorModeDark = ColorModeDark; + ModifyTheme(ColorModeDark); + ConfigHandler.SaveConfig(_config); + } + }); + + this.WhenAnyValue(x => x.FollowSystemTheme, + y => y == true) + .Subscribe(c => + { + if (_config.uiItem.followSystemTheme != FollowSystemTheme) + { + _config.uiItem.followSystemTheme = FollowSystemTheme; + ConfigHandler.SaveConfig(_config); + if (FollowSystemTheme) + { + ModifyTheme(!Utils.IsLightTheme()); + } + else + { + ModifyTheme(ColorModeDark); + } + } + }); + + this.WhenAnyValue( + x => x.SelectedSwatch, + y => y != null && !y.Name.IsNullOrEmpty()) + .Subscribe(c => + { + if (SelectedSwatch == null + || SelectedSwatch.Name.IsNullOrEmpty() + || SelectedSwatch.ExemplarHue == null + || SelectedSwatch.ExemplarHue?.Color == null) + { + return; + } + if (_config.uiItem.colorPrimaryName != SelectedSwatch?.Name) + { + _config.uiItem.colorPrimaryName = SelectedSwatch?.Name; + ChangePrimaryColor(SelectedSwatch.ExemplarHue.Color); + ConfigHandler.SaveConfig(_config); + } + }); + + this.WhenAnyValue( + x => x.CurrentFontSize, + y => y > 0) + .Subscribe(c => + { + if (CurrentFontSize >= Global.MinFontSize) + { + _config.uiItem.currentFontSize = CurrentFontSize; + double size = (long)CurrentFontSize; + Application.Current.Resources["StdFontSize"] = size; + Application.Current.Resources["StdFontSize1"] = size + 1; + Application.Current.Resources["StdFontSize2"] = size + 2; + Application.Current.Resources["StdFontSizeMsg"] = size - 1; + Application.Current.Resources["StdFontSize-1"] = size - 1; + + ConfigHandler.SaveConfig(_config); + } + }); + + this.WhenAnyValue( + x => x.CurrentLanguage, + y => y != null && !y.IsNullOrEmpty()) + .Subscribe(c => + { + if (!Utils.IsNullOrEmpty(CurrentLanguage) && _config.uiItem.currentLanguage != CurrentLanguage) + { + _config.uiItem.currentLanguage = CurrentLanguage; + Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage); + ConfigHandler.SaveConfig(_config); + _noticeHandler?.Enqueue(ResUI.NeedRebootTips); + } + }); + } + + public void ModifyTheme(bool isDarkTheme) + { + var theme = _paletteHelper.GetTheme(); + + theme.SetBaseTheme(isDarkTheme ? BaseTheme.Dark : BaseTheme.Light); + _paletteHelper.SetTheme(theme); + + Utils.SetDarkBorder(Application.Current.MainWindow, isDarkTheme); + } + + public void ChangePrimaryColor(System.Windows.Media.Color color) + { + var theme = _paletteHelper.GetTheme(); + + theme.PrimaryLight = new ColorPair(color.Lighten()); + theme.PrimaryMid = new ColorPair(color); + theme.PrimaryDark = new ColorPair(color.Darken()); + + _paletteHelper.SetTheme(theme); + } + } +} \ No newline at end of file diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml b/v2rayN/v2rayN/Views/MainWindow.xaml index e405ed374f..3aaf8686ed 100644 --- a/v2rayN/v2rayN/Views/MainWindow.xaml +++ b/v2rayN/v2rayN/Views/MainWindow.xaml @@ -301,88 +301,7 @@ HorizontalAlignment="Right" StaysOpen="True" Style="{StaticResource MaterialDesignToolForegroundPopupBox}"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml.cs b/v2rayN/v2rayN/Views/MainWindow.xaml.cs index 3c3a0d8f47..bacf22058f 100644 --- a/v2rayN/v2rayN/Views/MainWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/MainWindow.xaml.cs @@ -1,4 +1,5 @@ -using ReactiveUI; +using MaterialDesignThemes.Wpf; +using ReactiveUI; using Splat; using System.ComponentModel; using System.Reactive.Disposables; @@ -32,16 +33,6 @@ public MainWindow() ViewModel = new MainWindowViewModel(MainSnackbar.MessageQueue, null); Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel)); - for (int i = Global.MinFontSize; i <= Global.MinFontSize + 8; i++) - { - cmbCurrentFontSize.Items.Add(i.ToString()); - } - - Global.Languages.ForEach(it => - { - cmbCurrentLanguage.Items.Add(it); - }); - this.WhenActivated(disposables => { //servers @@ -130,14 +121,6 @@ public MainWindow() this.Bind(ViewModel, vm => vm.SelectedRouting, v => v.cmbRoutings2.SelectedItem).DisposeWith(disposables); this.OneWayBind(ViewModel, vm => vm.BlRouting, v => v.cmbRoutings2.Visibility).DisposeWith(disposables); - //UI - this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.followSystemTheme.IsChecked).DisposeWith(disposables); - this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables); - this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables); - if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal) { gridMain.Visibility = Visibility.Visible; @@ -169,8 +152,6 @@ public MainWindow() RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; } - MainFormHandler.Instance.RegisterSystemColorSet(_config, this, (bool bl) => { ViewModel?.ModifyTheme(bl); }); - if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal) { tabProfiles.Content ??= new ProfilesView(); @@ -192,6 +173,7 @@ public MainWindow() tabClashProxies2.Content ??= new ClashProxiesView(); tabClashConnections2.Content ??= new ClashConnectionsView(); } + pbTheme.Content ??= new ThemeSettingView(); RestoreUI(); AddHelpMenuItem(); diff --git a/v2rayN/v2rayN/Views/ThemeSettingView.xaml b/v2rayN/v2rayN/Views/ThemeSettingView.xaml new file mode 100644 index 0000000000..21d2ebf2ba --- /dev/null +++ b/v2rayN/v2rayN/Views/ThemeSettingView.xaml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/v2rayN/v2rayN/Views/ThemeSettingView.xaml.cs b/v2rayN/v2rayN/Views/ThemeSettingView.xaml.cs new file mode 100644 index 0000000000..e2c2636d4b --- /dev/null +++ b/v2rayN/v2rayN/Views/ThemeSettingView.xaml.cs @@ -0,0 +1,41 @@ +using ReactiveUI; +using Splat; +using System.Reactive.Disposables; +using System.Windows.Input; +using v2rayN.Handler; +using v2rayN.ViewModels; + +namespace v2rayN.Views +{ + /// + /// ThemeSettingView.xaml + /// + public partial class ThemeSettingView + { + public ThemeSettingView() + { + InitializeComponent(); + ViewModel = new ThemeSettingViewModel(); + + for (int i = Global.MinFontSize; i <= Global.MinFontSize + 8; i++) + { + cmbCurrentFontSize.Items.Add(i.ToString()); + } + + Global.Languages.ForEach(it => + { + cmbCurrentLanguage.Items.Add(it); + }); + + this.WhenActivated(disposables => + { + this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.FollowSystemTheme, v => v.followSystemTheme.IsChecked).DisposeWith(disposables); + this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables); + this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables); + }); + } + } +}