diff --git a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs index c98f26cc..9a4b18e3 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 @@ namespace v2rayN.ViewModels 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 @@ namespace v2rayN.ViewModels [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 @@ namespace v2rayN.ViewModels } Init(); - BindingUI(); - RestoreUI(); #region WhenAnyValue && ReactiveCommand @@ -824,33 +800,6 @@ namespace v2rayN.ViewModels catch { } } - //private void ImportOldGuiConfig() - //{ - // if (UI.OpenFileDialog(out string fileName, - // "guiNConfig|*.json|All|*.*") != true) - // { - // return; - // } - // if (Utils.IsNullOrEmpty(fileName)) - // { - // return; - // } - - // var ret = ConfigHandler.ImportOldGuiConfig(_config, fileName); - // if (ret == 0) - // { - // RefreshRoutingsMenu(); - // InitSubscriptionView(); - // RefreshServers(); - // Reload(); - // _noticeHandler?.Enqueue(ResUI.OperationSuccess); - // } - // else - // { - // _noticeHandler?.Enqueue(ResUI.OperationFailed); - // } - //} - #endregion Setting #region CheckUpdate @@ -1078,7 +1027,6 @@ namespace v2rayN.ViewModels var bl = blShow ?? !_showInTaskbar; if (bl) { - //Application.Current.MainWindow.ShowInTaskbar = true; Application.Current.MainWindow.Show(); if (Application.Current.MainWindow.WindowState == WindowState.Minimized) { @@ -1090,135 +1038,11 @@ namespace v2rayN.ViewModels else { Application.Current.MainWindow.Hide(); - //Application.Current.MainWindow.ShowInTaskbar = false; - //IntPtr windowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle; - //Utile.RegWriteValue(Global.MyRegPath, Utile.WindowHwndKey, Convert.ToString((long)windowHandle)); } _showInTaskbar = bl; _config.uiItem.showInTaskbar = _showInTaskbar; } - 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 InboundDisplayStaus() { StringBuilder sb = new(); @@ -1255,27 +1079,6 @@ namespace v2rayN.ViewModels } } - 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 00000000..aa4fed23 --- /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 e405ed37..3aaf8686 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 3c3a0d8f..bacf2205 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 @@ namespace v2rayN.Views 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 @@ namespace v2rayN.Views 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 @@ namespace v2rayN.Views 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 @@ namespace v2rayN.Views 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 00000000..21d2ebf2 --- /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 00000000..e2c2636d --- /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); + }); + } + } +}