mirror of https://github.com/2dust/v2rayN
commit
d9bf31d4f0
|
@ -20,6 +20,8 @@
|
||||||
<system:Double x:Key="StdFontSize1">13</system:Double>
|
<system:Double x:Key="StdFontSize1">13</system:Double>
|
||||||
<system:Double x:Key="StdFontSize2">14</system:Double>
|
<system:Double x:Key="StdFontSize2">14</system:Double>
|
||||||
<system:Double x:Key="StdFontSizeMsg">11</system:Double>
|
<system:Double x:Key="StdFontSizeMsg">11</system:Double>
|
||||||
|
|
||||||
|
<conv:InverseBooleanConverter x:Key="InverseBooleanConverter"/>
|
||||||
<Thickness
|
<Thickness
|
||||||
x:Key="ServerItemMargin"
|
x:Key="ServerItemMargin"
|
||||||
Bottom="4"
|
Bottom="4"
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace v2rayN.Converters
|
||||||
|
{
|
||||||
|
[ValueConversion(typeof(bool), typeof(bool))]
|
||||||
|
public class InverseBooleanConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if(targetType != typeof(bool))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("The target must be a boolean");
|
||||||
|
}
|
||||||
|
|
||||||
|
return !(bool)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -116,6 +116,7 @@ namespace v2rayN.Mode
|
||||||
public double mainGirdHeight1 { get; set; }
|
public double mainGirdHeight1 { get; set; }
|
||||||
public double mainGirdHeight2 { get; set; }
|
public double mainGirdHeight2 { get; set; }
|
||||||
public bool colorModeDark { get; set; }
|
public bool colorModeDark { get; set; }
|
||||||
|
public bool followSystemTheme { get; set; }
|
||||||
public string? colorPrimaryName { get; set; }
|
public string? colorPrimaryName { get; set; }
|
||||||
public string currentLanguage { get; set; }
|
public string currentLanguage { get; set; }
|
||||||
public string currentFontFamily { get; set; }
|
public string currentFontFamily { get; set; }
|
||||||
|
|
|
@ -2527,6 +2527,15 @@ namespace v2rayN.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Follow System Theme 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbSettingsFollowSystemTheme {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbSettingsFollowSystemTheme", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 FontSize 的本地化字符串。
|
/// 查找类似 FontSize 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -505,6 +505,9 @@
|
||||||
<data name="TbSettingsColorMode" xml:space="preserve">
|
<data name="TbSettingsColorMode" xml:space="preserve">
|
||||||
<value>Dark Mode</value>
|
<value>Dark Mode</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
||||||
|
<value>Follow System Theme</value>
|
||||||
|
</data>
|
||||||
<data name="TbSettingsLanguage" xml:space="preserve">
|
<data name="TbSettingsLanguage" xml:space="preserve">
|
||||||
<value>Language(Restart)</value>
|
<value>Language(Restart)</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
@ -505,6 +505,9 @@
|
||||||
<data name="TbSettingsColorMode" xml:space="preserve">
|
<data name="TbSettingsColorMode" xml:space="preserve">
|
||||||
<value>Тёмный режим</value>
|
<value>Тёмный режим</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
||||||
|
<value>следить за системной темой</value>
|
||||||
|
</data>
|
||||||
<data name="TbSettingsLanguage" xml:space="preserve">
|
<data name="TbSettingsLanguage" xml:space="preserve">
|
||||||
<value>Язык (требуется перезапуск)</value>
|
<value>Язык (требуется перезапуск)</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
@ -505,6 +505,9 @@
|
||||||
<data name="TbSettingsColorMode" xml:space="preserve">
|
<data name="TbSettingsColorMode" xml:space="preserve">
|
||||||
<value>暗黑模式</value>
|
<value>暗黑模式</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbSettingsFollowSystemTheme" xml:space="preserve">
|
||||||
|
<value>是否跟随系统主题</value>
|
||||||
|
</data>
|
||||||
<data name="TbSettingsLanguage" xml:space="preserve">
|
<data name="TbSettingsLanguage" xml:space="preserve">
|
||||||
<value>语言(重启)</value>
|
<value>语言(重启)</value>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
@ -1047,6 +1047,13 @@ namespace v2rayN
|
||||||
DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize);
|
DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool IsLightTheme()
|
||||||
|
{
|
||||||
|
using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize");
|
||||||
|
var value = key?.GetValue("AppsUseLightTheme");
|
||||||
|
return value is int i && i > 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion 杂项
|
#endregion 杂项
|
||||||
|
|
||||||
#region TempPath
|
#region TempPath
|
||||||
|
|
|
@ -12,8 +12,10 @@ using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Interop;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using v2rayN.Base;
|
using v2rayN.Base;
|
||||||
using v2rayN.Handler;
|
using v2rayN.Handler;
|
||||||
|
@ -237,6 +239,9 @@ namespace v2rayN.ViewModels
|
||||||
[Reactive]
|
[Reactive]
|
||||||
public int CurrentFontSize { get; set; }
|
public int CurrentFontSize { get; set; }
|
||||||
|
|
||||||
|
[Reactive]
|
||||||
|
public bool FollowSystemTheme { get; set; }
|
||||||
|
|
||||||
[Reactive]
|
[Reactive]
|
||||||
public string CurrentLanguage { get; set; }
|
public string CurrentLanguage { get; set; }
|
||||||
|
|
||||||
|
@ -244,7 +249,7 @@ namespace v2rayN.ViewModels
|
||||||
|
|
||||||
#region Init
|
#region Init
|
||||||
|
|
||||||
public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue, Action<EViewAction> updateView)
|
public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue, Action<EViewAction> updateView,HwndSource hwndSource)
|
||||||
{
|
{
|
||||||
_updateView = updateView;
|
_updateView = updateView;
|
||||||
ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
|
ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
|
||||||
|
@ -309,7 +314,7 @@ namespace v2rayN.ViewModels
|
||||||
y => y == true)
|
y => y == true)
|
||||||
.Subscribe(c => DoEnableTun(c));
|
.Subscribe(c => DoEnableTun(c));
|
||||||
|
|
||||||
BindingUI();
|
BindingUI(hwndSource);
|
||||||
RestoreUI();
|
RestoreUI();
|
||||||
AutoHideStartup();
|
AutoHideStartup();
|
||||||
|
|
||||||
|
@ -1665,9 +1670,10 @@ namespace v2rayN.ViewModels
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BindingUI()
|
private void BindingUI(HwndSource hwndSource)
|
||||||
{
|
{
|
||||||
ColorModeDark = _config.uiItem.colorModeDark;
|
ColorModeDark = _config.uiItem.colorModeDark;
|
||||||
|
FollowSystemTheme = _config.uiItem.followSystemTheme;
|
||||||
_swatches.AddRange(new SwatchesProvider().Swatches);
|
_swatches.AddRange(new SwatchesProvider().Swatches);
|
||||||
if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty())
|
if (!_config.uiItem.colorPrimaryName.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
|
@ -1690,6 +1696,57 @@ namespace v2rayN.ViewModels
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.WhenAnyValue(x => x.FollowSystemTheme,
|
||||||
|
y => y == true)
|
||||||
|
.Subscribe(c =>
|
||||||
|
{
|
||||||
|
if (_config.uiItem.followSystemTheme != FollowSystemTheme)
|
||||||
|
{
|
||||||
|
_config.uiItem.followSystemTheme = FollowSystemTheme;
|
||||||
|
if (FollowSystemTheme)
|
||||||
|
{
|
||||||
|
hwndSource.AddHook((IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) =>
|
||||||
|
{
|
||||||
|
const int WM_SETTINGCHANGE = 0x001A;
|
||||||
|
if (msg == WM_SETTINGCHANGE)
|
||||||
|
{
|
||||||
|
if (wParam == IntPtr.Zero && Marshal.PtrToStringUni(lParam) == "ImmersiveColorSet")
|
||||||
|
{
|
||||||
|
var isLightTheme = Utils.IsLightTheme();
|
||||||
|
ColorModeDark = !isLightTheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntPtr.Zero;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var isLightTheme = Utils.IsLightTheme();
|
||||||
|
ColorModeDark = !isLightTheme;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hwndSource.RemoveHook((IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) =>
|
||||||
|
{
|
||||||
|
const int WM_SETTINGCHANGE = 0x001A;
|
||||||
|
if (msg == WM_SETTINGCHANGE)
|
||||||
|
{
|
||||||
|
if (wParam == IntPtr.Zero && Marshal.PtrToStringUni(lParam) == "ImmersiveColorSet")
|
||||||
|
{
|
||||||
|
var isLightTheme = Utils.IsLightTheme();
|
||||||
|
ColorModeDark = !isLightTheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntPtr.Zero;
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigHandler.SaveConfig(ref _config);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.WhenAnyValue(
|
this.WhenAnyValue(
|
||||||
x => x.SelectedSwatch,
|
x => x.SelectedSwatch,
|
||||||
y => y != null && !y.Name.IsNullOrEmpty())
|
y => y != null && !y.Name.IsNullOrEmpty())
|
||||||
|
|
|
@ -301,6 +301,7 @@
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
|
@ -319,17 +320,30 @@
|
||||||
x:Name="togDarkMode"
|
x:Name="togDarkMode"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
|
Margin="8"
|
||||||
|
IsEnabled="{Binding ElementName=followSystemTheme, Path=IsChecked, Converter={StaticResource InverseBooleanConverter}}"/>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
|
Text="{x:Static resx:ResUI.TbSettingsFollowSystemTheme}" />
|
||||||
|
<ToggleButton
|
||||||
|
x:Name="followSystemTheme"
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="1"
|
||||||
Margin="8" />
|
Margin="8" />
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="1"
|
Grid.Row="2"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
Text="{x:Static resx:ResUI.TbSettingsColor}" />
|
Text="{x:Static resx:ResUI.TbSettingsColor}" />
|
||||||
<ComboBox
|
<ComboBox
|
||||||
x:Name="cmbSwatches"
|
x:Name="cmbSwatches"
|
||||||
Grid.Row="1"
|
Grid.Row="2"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Width="100"
|
Width="100"
|
||||||
Margin="8"
|
Margin="8"
|
||||||
|
@ -337,28 +351,28 @@
|
||||||
Style="{StaticResource DefComboBox}" />
|
Style="{StaticResource DefComboBox}" />
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="3"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
Text="{x:Static resx:ResUI.TbSettingsFontSize}" />
|
Text="{x:Static resx:ResUI.TbSettingsFontSize}" />
|
||||||
<ComboBox
|
<ComboBox
|
||||||
x:Name="cmbCurrentFontSize"
|
x:Name="cmbCurrentFontSize"
|
||||||
Grid.Row="2"
|
Grid.Row="3"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Width="100"
|
Width="100"
|
||||||
Margin="8"
|
Margin="8"
|
||||||
Style="{StaticResource DefComboBox}" />
|
Style="{StaticResource DefComboBox}" />
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="3"
|
Grid.Row="4"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
Text="{x:Static resx:ResUI.TbSettingsLanguage}" />
|
Text="{x:Static resx:ResUI.TbSettingsLanguage}" />
|
||||||
<ComboBox
|
<ComboBox
|
||||||
x:Name="cmbCurrentLanguage"
|
x:Name="cmbCurrentLanguage"
|
||||||
Grid.Row="3"
|
Grid.Row="4"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Width="100"
|
Width="100"
|
||||||
Margin="8"
|
Margin="8"
|
||||||
|
@ -560,7 +574,7 @@
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuSpeedServer"
|
x:Name="menuSpeedServer"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
Header="{x:Static resx:ResUI.menuSpeedServer}" />
|
Header="{x:Static resx:ResUI.menuSpeedServer}"/>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
x:Name="menuSortServerResult"
|
x:Name="menuSortServerResult"
|
||||||
Height="{StaticResource MenuItemHeight}"
|
Height="{StaticResource MenuItemHeight}"
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using Splat;
|
using Splat;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Controls.Primitives;
|
using System.Windows.Controls.Primitives;
|
||||||
|
@ -43,7 +44,10 @@ namespace v2rayN.Views
|
||||||
lstProfiles.Drop += LstProfiles_Drop;
|
lstProfiles.Drop += LstProfiles_Drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewModel = new MainWindowViewModel(MainSnackbar.MessageQueue!, UpdateViewHandler);
|
var helper = new WindowInteropHelper(this);
|
||||||
|
var hwndSource = HwndSource.FromHwnd(helper.EnsureHandle());
|
||||||
|
|
||||||
|
ViewModel = new MainWindowViewModel(MainSnackbar.MessageQueue!, UpdateViewHandler,hwndSource);
|
||||||
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
|
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
|
||||||
|
|
||||||
for (int i = Global.MinFontSize; i <= Global.MinFontSize + 8; i++)
|
for (int i = Global.MinFontSize; i <= Global.MinFontSize + 8; i++)
|
||||||
|
@ -183,6 +187,7 @@ namespace v2rayN.Views
|
||||||
|
|
||||||
//UI
|
//UI
|
||||||
this.Bind(ViewModel, vm => vm.ColorModeDark, v => v.togDarkMode.IsChecked).DisposeWith(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.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.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);
|
||||||
|
|
Loading…
Reference in New Issue