diff --git a/clashN/clashN/App.xaml b/clashN/clashN/App.xaml index 126dfe4..0ac50ce 100644 --- a/clashN/clashN/App.xaml +++ b/clashN/clashN/App.xaml @@ -8,7 +8,7 @@ ShutdownMode="OnExplicitShutdown" StartupUri="Views/MainWindow.xaml"> - + + 11 + 12 + 13 + 14 + + + diff --git a/clashN/clashN/App.xaml.cs b/clashN/clashN/App.xaml.cs index 20b4d09..b3b8692 100644 --- a/clashN/clashN/App.xaml.cs +++ b/clashN/clashN/App.xaml.cs @@ -1,4 +1,6 @@ -using clashN.Tool; +using clashN.Handler; +using clashN.Mode; +using clashN.Tool; using System.Windows; using System.Windows.Threading; @@ -10,7 +12,7 @@ namespace clashN public partial class App : Application { public static EventWaitHandle ProgramStarted; - + private static Config _config; public App() { // Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetCallingAssembly()); @@ -46,12 +48,24 @@ namespace clashN Utils.SaveLog($"clashN start up | {Utils.GetVersion()} | {Utils.GetExePath()}"); Logging.ClearLogs(); + Init(); + string lang = Utils.RegReadValue(Global.MyRegPath, Global.MyRegKeyLanguage, Global.Languages[0]); Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(lang); base.OnStartup(e); } + private void Init() + { + if (ConfigHandler.LoadConfig(ref _config) != 0) + { + UI.ShowWarning($"Loading GUI configuration file is abnormal,please restart the application{Environment.NewLine}加载GUI配置文件异常,请重启应用"); + Application.Current.Shutdown(); + Environment.Exit(0); + return; + } + } private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { Utils.SaveLog("App_DispatcherUnhandledException", e.Exception); diff --git a/clashN/clashN/Converters/MaterialDesignFonts.cs b/clashN/clashN/Converters/MaterialDesignFonts.cs index 389b281..8befa15 100644 --- a/clashN/clashN/Converters/MaterialDesignFonts.cs +++ b/clashN/clashN/Converters/MaterialDesignFonts.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using clashN.Handler; using System.Windows.Media; namespace clashN.Converters @@ -10,8 +9,22 @@ namespace clashN.Converters static MaterialDesignFonts() { - var fontPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources\Fonts\"); - MyFont = new FontFamily(new Uri($"file:///{fontPath}"), "./#Source Han Sans CN"); + try + { + var fontFamily = LazyConfig.Instance.GetConfig().uiItem.currentFontFamily; + if (!string.IsNullOrEmpty(fontFamily)) + { + var fontPath = Utils.GetFontsPath(); + MyFont = new FontFamily(new Uri(@$"file:///{fontPath}\"), $"./#{fontFamily}"); + } + } + catch + { + } + if (MyFont is null) + { + MyFont = new FontFamily("Microsoft YaHei"); + } } } } \ No newline at end of file diff --git a/clashN/clashN/Global.cs b/clashN/clashN/Global.cs index d2008e3..5d3123c 100644 --- a/clashN/clashN/Global.cs +++ b/clashN/clashN/Global.cs @@ -87,6 +87,7 @@ /// Icon /// public const string CustomIconName = "clashN.ico"; + public const int MinFontSize = 10; public const string StatisticLogOverall = "StatisticLogOverall.json"; @@ -108,7 +109,7 @@ public static readonly List proxyVehicleType = new List { "file", "http" }; - public static readonly List Languages = new List { "zh-Hans", "en","fa-IR" }; + public static readonly List Languages = new List { "zh-Hans", "en", "fa-IR" }; public static readonly List LogLevel = new List { "debug", "info", "warning", "error", "silent" }; diff --git a/clashN/clashN/Mode/Config.cs b/clashN/clashN/Mode/Config.cs index 8202f08..192ead6 100644 --- a/clashN/clashN/Mode/Config.cs +++ b/clashN/clashN/Mode/Config.cs @@ -197,6 +197,14 @@ namespace clashN.Mode public bool colorModeDark { get; set; } public string? colorPrimaryName { get; set; } + public string currentFontFamily { get; set; } + public int currentFontSize { get; set; } + + public int proxiesSorting { get; set; } + public bool proxiesAutoRefresh { get; set; } + + public int connectionsSorting { get; set; } + public bool connectionsAutoRefresh { get; set; } } diff --git a/clashN/clashN/Resources/Fonts/SourceHanSansCN-Regular.ttf b/clashN/clashN/Resources/Fonts/SourceHanSansCN-Regular.ttf deleted file mode 100644 index 5c6a238..0000000 Binary files a/clashN/clashN/Resources/Fonts/SourceHanSansCN-Regular.ttf and /dev/null differ diff --git a/clashN/clashN/Resx/ResUI.Designer.cs b/clashN/clashN/Resx/ResUI.Designer.cs index 321ad80..30223b7 100644 --- a/clashN/clashN/Resx/ResUI.Designer.cs +++ b/clashN/clashN/Resx/ResUI.Designer.cs @@ -1384,6 +1384,33 @@ namespace clashN.Resx { } } + /// + /// 查找类似 FontFamily(Require restart) 的本地化字符串。 + /// + public static string TbSettingsFontFamily { + get { + return ResourceManager.GetString("TbSettingsFontFamily", resourceCulture); + } + } + + /// + /// 查找类似 Copy the font TTF file to the directory guiFonts, restart the settings 的本地化字符串。 + /// + public static string TbSettingsFontFamilyTip { + get { + return ResourceManager.GetString("TbSettingsFontFamilyTip", resourceCulture); + } + } + + /// + /// 查找类似 FontSize 的本地化字符串。 + /// + public static string TbSettingsFontSize { + get { + return ResourceManager.GetString("TbSettingsFontSize", resourceCulture); + } + } + /// /// 查找类似 Http Port 的本地化字符串。 /// diff --git a/clashN/clashN/Resx/ResUI.resx b/clashN/clashN/Resx/ResUI.resx index 825b4d1..7c0a5d2 100644 --- a/clashN/clashN/Resx/ResUI.resx +++ b/clashN/clashN/Resx/ResUI.resx @@ -664,4 +664,13 @@ Type + + FontFamily(Require restart) + + + Copy the font TTF file to the directory guiFonts, restart the settings + + + FontSize + \ No newline at end of file diff --git a/clashN/clashN/Resx/ResUI.zh-Hans.resx b/clashN/clashN/Resx/ResUI.zh-Hans.resx index d1784b2..82c708c 100644 --- a/clashN/clashN/Resx/ResUI.zh-Hans.resx +++ b/clashN/clashN/Resx/ResUI.zh-Hans.resx @@ -667,4 +667,13 @@ 类型 + + 当前字体(需重启) + + + 拷贝字体TTF文件到目录guiFonts,重启 + + + 字体大小 + \ No newline at end of file diff --git a/clashN/clashN/Tool/Utils.cs b/clashN/clashN/Tool/Utils.cs index 497c20f..9103d7f 100644 --- a/clashN/clashN/Tool/Utils.cs +++ b/clashN/clashN/Tool/Utils.cs @@ -1112,6 +1112,22 @@ namespace clashN } return Path.Combine(_tempPath, filename); } + public static string GetFontsPath(string filename = "") + { + string _tempPath = Path.Combine(StartupPath(), "guiFonts"); + if (!Directory.Exists(_tempPath)) + { + Directory.CreateDirectory(_tempPath); + } + if (string.IsNullOrEmpty(filename)) + { + return _tempPath; + } + else + { + return Path.Combine(_tempPath, filename); + } + } #endregion #region Log diff --git a/clashN/clashN/ViewModels/ConnectionsViewModel.cs b/clashN/clashN/ViewModels/ConnectionsViewModel.cs index 099ff3c..843a073 100644 --- a/clashN/clashN/ViewModels/ConnectionsViewModel.cs +++ b/clashN/clashN/ViewModels/ConnectionsViewModel.cs @@ -37,6 +37,10 @@ namespace clashN.ViewModels _noticeHandler = Locator.Current.GetService(); _config = LazyConfig.Instance.GetConfig(); + AutoRefreshInterval = 10; + SortingSelected = _config.uiItem.connectionsSorting; + AutoRefresh = _config.uiItem.connectionsAutoRefresh; + var canEditRemove = this.WhenAnyValue( x => x.SelectedSource, selectedSource => selectedSource != null && !selectedSource.id.IsNullOrEmpty()); @@ -46,6 +50,11 @@ namespace clashN.ViewModels y => y != null && y >= 0) .Subscribe(c => DoSortingSelected(c)); + this.WhenAnyValue( + x => x.AutoRefresh, + y => y == true) + .Subscribe(c => { _config.uiItem.connectionsAutoRefresh = AutoRefresh; }); + ConnectionCloseCmd = ReactiveCommand.Create(() => { ClashConnectionClose(false); @@ -56,10 +65,6 @@ namespace clashN.ViewModels ClashConnectionClose(true); }); - AutoRefreshInterval = 10; - SortingSelected = 4; - AutoRefresh = true; - Init(); } @@ -69,6 +74,10 @@ namespace clashN.ViewModels { return; } + if (SortingSelected != _config.uiItem.connectionsSorting) + { + _config.uiItem.connectionsSorting = SortingSelected; + } GetClashConnections(); } @@ -128,7 +137,7 @@ namespace clashN.ViewModels model.id = item.id; model.network = item.metadata.network; model.type = item.metadata.type; - model.host = $"{item.metadata.host}:{item.metadata.destinationPort}"; + model.host = $"{(item.metadata.host.IsNullOrEmpty() ? item.metadata.destinationIP : item.metadata.host)}:{item.metadata.destinationPort}"; var sp = (dtNow - item.start); model.time = sp.TotalSeconds < 0 ? 1 : sp.TotalSeconds; model.upload = item.upload; diff --git a/clashN/clashN/ViewModels/MainWindowViewModel.cs b/clashN/clashN/ViewModels/MainWindowViewModel.cs index a60d12f..85f5fcf 100644 --- a/clashN/clashN/ViewModels/MainWindowViewModel.cs +++ b/clashN/clashN/ViewModels/MainWindowViewModel.cs @@ -92,6 +92,8 @@ namespace clashN.ViewModels public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue) { + _config = LazyConfig.Instance.GetConfig(); + Locator.CurrentMutable.RegisterLazySingleton(() => new NoticeHandler(snackbarMessageQueue), typeof(NoticeHandler)); _noticeHandler = Locator.Current.GetService(); @@ -264,12 +266,8 @@ namespace clashN.ViewModels private void Init() { - if (ConfigHandler.LoadConfig(ref _config) != 0) - { - UI.ShowWarning($"Loading GUI configuration file is abnormal,please restart the application{Environment.NewLine}GUIļ쳣,Ӧ"); - Environment.Exit(0); - return; - } + + MainFormHandler.Instance.BackupGuiNConfig(_config, true); MainFormHandler.Instance.InitRegister(_config); @@ -293,7 +291,7 @@ namespace clashN.ViewModels { if (notify) { - _noticeHandler?.Enqueue(msg); + _noticeHandler?.Enqueue(msg); _noticeHandler?.SendMessage(msg); } else diff --git a/clashN/clashN/ViewModels/ProxiesViewModel.cs b/clashN/clashN/ViewModels/ProxiesViewModel.cs index 21ead05..254de75 100644 --- a/clashN/clashN/ViewModels/ProxiesViewModel.cs +++ b/clashN/clashN/ViewModels/ProxiesViewModel.cs @@ -49,7 +49,7 @@ namespace clashN.ViewModels public bool AutoRefresh { get; set; } [Reactive] public bool EnableTun { get; set; } - + public ProxiesViewModel() { @@ -58,14 +58,15 @@ namespace clashN.ViewModels SelectedGroup = new(); SelectedDetail = new(); - AutoRefresh = true; + AutoRefresh = _config.uiItem.proxiesAutoRefresh; EnableTun = _config.enableTun; + SortingSelected = _config.uiItem.proxiesSorting; //GetClashProxies(true); this.WhenAnyValue( - x => x.SelectedGroup, - y => y != null && !y.name.IsNullOrEmpty()) - .Subscribe(c => RefreshProxyDetails(c)); + x => x.SelectedGroup, + y => y != null && !y.name.IsNullOrEmpty()) + .Subscribe(c => RefreshProxyDetails(c)); this.WhenAnyValue( x => x.SystemProxySelected, @@ -87,6 +88,11 @@ namespace clashN.ViewModels y => y == true) .Subscribe(c => DoEnableTun(c)); + this.WhenAnyValue( + x => x.AutoRefresh, + y => y == true) + .Subscribe(c => { _config.uiItem.proxiesAutoRefresh = AutoRefresh; }); + ProxiesReloadCmd = ReactiveCommand.Create(() => { ProxiesReload(); @@ -142,6 +148,10 @@ namespace clashN.ViewModels { return; } + if (SortingSelected != _config.uiItem.proxiesSorting) + { + _config.uiItem.proxiesSorting = SortingSelected; + } RefreshProxyDetails(c); } @@ -187,9 +197,9 @@ namespace clashN.ViewModels { if (_config.enableTun != EnableTun) { - _config.enableTun = EnableTun; + _config.enableTun = EnableTun; TunModeSwitch(); - } + } } void TunModeSwitch() diff --git a/clashN/clashN/ViewModels/SettingsViewModel.cs b/clashN/clashN/ViewModels/SettingsViewModel.cs index cc0cc2d..a44515f 100644 --- a/clashN/clashN/ViewModels/SettingsViewModel.cs +++ b/clashN/clashN/ViewModels/SettingsViewModel.cs @@ -13,6 +13,7 @@ using ReactiveUI.Validation.Helpers; using Splat; using System.IO; using System.Reactive; +using System.Windows; namespace clashN.ViewModels { @@ -55,6 +56,8 @@ namespace clashN.ViewModels [Reactive] public string SubConvertUrl { get; set; } [Reactive] + public string currentFontFamily { get; set; } + [Reactive] public bool AutoHideStartup { get; set; } public ReactiveCommand SetLoopbackCmd { get; } public ReactiveCommand SetGlobalHotkeyCmd { get; } @@ -81,6 +84,8 @@ namespace clashN.ViewModels public bool ColorModeDark { get; set; } [Reactive] public string CurrentLanguage { get; set; } + [Reactive] + public int CurrentFontSize { get; set; } #endregion public ReactiveCommand SaveCommand { get; } @@ -111,6 +116,7 @@ namespace clashN.ViewModels autoUpdateSubInterval = _config.autoUpdateSubInterval; autoDelayTestInterval = _config.autoDelayTestInterval; SubConvertUrl = _config.constItem.subConvertUrl; + currentFontFamily = _config.uiItem.currentFontFamily; AutoHideStartup = _config.autoHideStartup; SetLoopbackCmd = ReactiveCommand.Create(() => @@ -135,6 +141,7 @@ namespace clashN.ViewModels SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.uiItem.colorPrimaryName); } CurrentLanguage = Utils.RegReadValue(Global.MyRegPath, Global.MyRegKeyLanguage, Global.Languages[0]); + CurrentFontSize = _config.uiItem.currentFontSize; this.WhenAnyValue( x => x.ColorModeDark, @@ -181,6 +188,37 @@ namespace clashN.ViewModels } }); + this.WhenAnyValue( + x => x.CurrentFontSize, + y => y > 0) + .Subscribe(c => + { + if (_config.uiItem.colorModeDark != ColorModeDark) + { + _config.uiItem.colorModeDark = ColorModeDark; + Locator.Current.GetService()?.ModifyTheme(ColorModeDark); + ConfigHandler.SaveConfig(ref _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["StdFontSize1"] = size; + Application.Current.Resources["StdFontSize2"] = size + 1; + Application.Current.Resources["StdFontSize3"] = size + 2; + Application.Current.Resources["StdFontSize4"] = size + 3; + + ConfigHandler.SaveConfig(ref _config); + } + }); + //CMD SaveCommand = ReactiveCommand.Create(() => { @@ -209,6 +247,7 @@ namespace clashN.ViewModels _config.autoUpdateSubInterval = autoUpdateSubInterval; _config.autoDelayTestInterval = autoDelayTestInterval; _config.constItem.subConvertUrl = SubConvertUrl; + _config.uiItem.currentFontFamily = currentFontFamily; _config.autoHideStartup = AutoHideStartup; //System proxy diff --git a/clashN/clashN/Views/ConnectionsView.xaml b/clashN/clashN/Views/ConnectionsView.xaml index 1958331..7f9bae7 100644 --- a/clashN/clashN/Views/ConnectionsView.xaml +++ b/clashN/clashN/Views/ConnectionsView.xaml @@ -75,7 +75,8 @@ EnableRowVirtualization="True" GridLinesVisibility="All" HeadersVisibility="Column" - IsReadOnly="True"> + IsReadOnly="True" + Style="{StaticResource DefDataGrid}"> diff --git a/clashN/clashN/Views/GlobalHotkeySettingWindow.xaml b/clashN/clashN/Views/GlobalHotkeySettingWindow.xaml index 7cf28ce..b94d0b3 100644 --- a/clashN/clashN/Views/GlobalHotkeySettingWindow.xaml +++ b/clashN/clashN/Views/GlobalHotkeySettingWindow.xaml @@ -3,6 +3,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Views="clr-namespace:clashN.Views" + xmlns:conv="clr-namespace:clashN.Converters" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" @@ -14,8 +15,10 @@ Height="500" x:TypeArguments="vms:ProfileEditViewModel" Background="{DynamicResource MaterialDesignPaper}" + FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}" KeyDown="GlobalHotkeySettingWindow_KeyDown" ResizeMode="NoResize" + TextElement.FontFamily="{x:Static conv:MaterialDesignFonts.MyFont}" TextElement.Foreground="{DynamicResource MaterialDesignBody}" TextOptions.TextFormattingMode="Display" TextOptions.TextRenderingMode="Auto" @@ -68,7 +71,7 @@ VerticalAlignment="Top" AcceptsReturn="True" IsReadOnly="True" - Style="{StaticResource MaterialDesignOutlinedTextBox}" /> + Style="{StaticResource MyOutlinedTextBox}" /> + Style="{StaticResource MyOutlinedTextBox}" /> + Style="{StaticResource MyOutlinedTextBox}" /> + Style="{StaticResource MyOutlinedTextBox}" /> + Style="{StaticResource MyOutlinedTextBox}" /> diff --git a/clashN/clashN/Views/PromotionView.xaml b/clashN/clashN/Views/PromotionView.xaml index 68cb47a..417c751 100644 --- a/clashN/clashN/Views/PromotionView.xaml +++ b/clashN/clashN/Views/PromotionView.xaml @@ -47,6 +47,7 @@ @@ -65,6 +66,7 @@ materialDesign:ButtonProgressAssist.Value="-1" Click="btnPromotion_Click" Content="{x:Static resx:ResUI.TbPromotion}" + FontSize="{DynamicResource StdFontSize2}" Style="{StaticResource MaterialDesignRaisedButton}" /> diff --git a/clashN/clashN/Views/SettingsView.xaml b/clashN/clashN/Views/SettingsView.xaml index 6a9e017..9a9668a 100644 --- a/clashN/clashN/Views/SettingsView.xaml +++ b/clashN/clashN/Views/SettingsView.xaml @@ -50,6 +50,17 @@ Margin="8" materialDesign:HintAssist.Hint="Language" Style="{StaticResource DefComboBox}" /> + + + + @@ -98,7 +109,8 @@ Grid.Row="1" Grid.Column="1" Width="200" - Margin="8" /> + Margin="8" + Style="{StaticResource DefTextBox}" /> + Margin="8" + Style="{StaticResource DefTextBox}" /> + Margin="8" + Style="{StaticResource DefTextBox}" /> + Margin="8" + Style="{StaticResource DefTextBox}" /> + materialDesign:HintAssist.Hint="Level" + Style="{StaticResource DefComboBox}" /> + + + Margin="8" + Style="{StaticResource DefTextBox}" /> + Margin="8" + Style="{StaticResource DefTextBox}" /> + IsEditable="True" + Style="{StaticResource DefComboBox}" /> + + + +