mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
0.5.5
现已支持更改关键设置时提醒重启功能
This commit is contained in:
@@ -96,15 +96,7 @@ public partial class App : Application
|
|||||||
|
|
||||||
private void OnTrayRestartClick(object? sender, EventArgs e)
|
private void OnTrayRestartClick(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
|
AppRestartService.TryRestartApplication();
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AppRestartService.TryRestartCurrentProcess())
|
|
||||||
{
|
|
||||||
desktop.Shutdown();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisableAvaloniaDataAnnotationValidation()
|
private void DisableAvaloniaDataAnnotationValidation()
|
||||||
|
|||||||
@@ -249,6 +249,13 @@
|
|||||||
"settings.about.render_mode.current_format": "Current backend: {0}",
|
"settings.about.render_mode.current_format": "Current backend: {0}",
|
||||||
"settings.about.render_mode.impl_format": "Runtime implementation: {0}",
|
"settings.about.render_mode.impl_format": "Runtime implementation: {0}",
|
||||||
"settings.about.render_mode.impl_unavailable": "Runtime implementation details are unavailable.",
|
"settings.about.render_mode.impl_unavailable": "Runtime implementation details are unavailable.",
|
||||||
|
"settings.restart_dialog.title": "Restart required",
|
||||||
|
"settings.restart_dialog.render_mode_message": "Restart the app to switch the rendering mode from \"{0}\" to \"{1}\". Restart now?",
|
||||||
|
"settings.restart_dialog.restart": "Restart now",
|
||||||
|
"settings.restart_dialog.cancel": "Cancel",
|
||||||
|
"settings.restart_dock.title": "Restart required",
|
||||||
|
"settings.restart_dock.description": "Some changes will take effect after restarting the app.",
|
||||||
|
"settings.restart_dock.button": "Restart app",
|
||||||
"settings.footer": "LanMountainDesktop Settings",
|
"settings.footer": "LanMountainDesktop Settings",
|
||||||
"filepicker.title": "Select wallpaper",
|
"filepicker.title": "Select wallpaper",
|
||||||
"filepicker.image_files": "Image files",
|
"filepicker.image_files": "Image files",
|
||||||
|
|||||||
@@ -249,6 +249,13 @@
|
|||||||
"settings.about.render_mode.current_format": "当前后端:{0}",
|
"settings.about.render_mode.current_format": "当前后端:{0}",
|
||||||
"settings.about.render_mode.impl_format": "运行时实现:{0}",
|
"settings.about.render_mode.impl_format": "运行时实现:{0}",
|
||||||
"settings.about.render_mode.impl_unavailable": "当前无法获取运行时实现信息。",
|
"settings.about.render_mode.impl_unavailable": "当前无法获取运行时实现信息。",
|
||||||
|
"settings.restart_dialog.title": "需要重启应用",
|
||||||
|
"settings.restart_dialog.render_mode_message": "需要重启应用,才能将渲染模式从“{0}”切换到“{1}”。是否现在重启?",
|
||||||
|
"settings.restart_dialog.restart": "立即重启",
|
||||||
|
"settings.restart_dialog.cancel": "取消",
|
||||||
|
"settings.restart_dock.title": "需要重启应用",
|
||||||
|
"settings.restart_dock.description": "部分更改需要在重启应用后才会生效。",
|
||||||
|
"settings.restart_dock.button": "重启应用",
|
||||||
"settings.footer": "LanMountainDesktop 设置",
|
"settings.footer": "LanMountainDesktop 设置",
|
||||||
"filepicker.title": "选择壁纸",
|
"filepicker.title": "选择壁纸",
|
||||||
"filepicker.image_files": "图片文件",
|
"filepicker.image_files": "图片文件",
|
||||||
|
|||||||
@@ -3,11 +3,28 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
|
|
||||||
namespace LanMountainDesktop.Services;
|
namespace LanMountainDesktop.Services;
|
||||||
|
|
||||||
public static class AppRestartService
|
public static class AppRestartService
|
||||||
{
|
{
|
||||||
|
public static bool TryRestartApplication()
|
||||||
|
{
|
||||||
|
if (!TryRestartCurrentProcess())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
|
{
|
||||||
|
desktop.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool TryRestartCurrentProcess()
|
public static bool TryRestartCurrentProcess()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
54
LanMountainDesktop/Services/PendingRestartStateService.cs
Normal file
54
LanMountainDesktop/Services/PendingRestartStateService.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace LanMountainDesktop.Services;
|
||||||
|
|
||||||
|
public static class PendingRestartStateService
|
||||||
|
{
|
||||||
|
public const string RenderModeReason = "RenderMode";
|
||||||
|
|
||||||
|
private static readonly object Gate = new();
|
||||||
|
private static readonly HashSet<string> PendingReasons = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
public static event Action? StateChanged;
|
||||||
|
|
||||||
|
public static bool HasPendingRestart
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (Gate)
|
||||||
|
{
|
||||||
|
return PendingReasons.Count > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasPendingReason(string reason)
|
||||||
|
{
|
||||||
|
lock (Gate)
|
||||||
|
{
|
||||||
|
return PendingReasons.Contains(reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetPending(string reason, bool pending)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(reason))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var changed = false;
|
||||||
|
lock (Gate)
|
||||||
|
{
|
||||||
|
changed = pending
|
||||||
|
? PendingReasons.Add(reason)
|
||||||
|
: PendingReasons.Remove(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
StateChanged?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -327,6 +327,7 @@ public partial class MainWindow
|
|||||||
SetAppRenderModeComboItemContent(AppRenderingModeHelper.Wgl, L("settings.about.render_mode.wgl", "WGL"));
|
SetAppRenderModeComboItemContent(AppRenderingModeHelper.Wgl, L("settings.about.render_mode.wgl", "WGL"));
|
||||||
SetAppRenderModeComboItemContent(AppRenderingModeHelper.Vulkan, L("settings.about.render_mode.vulkan", "Vulkan"));
|
SetAppRenderModeComboItemContent(AppRenderingModeHelper.Vulkan, L("settings.about.render_mode.vulkan", "Vulkan"));
|
||||||
UpdateCurrentRenderBackendStatus();
|
UpdateCurrentRenderBackendStatus();
|
||||||
|
UpdatePendingRestartDock();
|
||||||
|
|
||||||
if (WallpaperPlacementComboBox?.ItemCount >= 5)
|
if (WallpaperPlacementComboBox?.ItemCount >= 5)
|
||||||
{
|
{
|
||||||
|
|||||||
112
LanMountainDesktop/Views/MainWindow.RestartPrompt.cs
Normal file
112
LanMountainDesktop/Views/MainWindow.RestartPrompt.cs
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
using Avalonia.Threading;
|
||||||
|
using FluentAvalonia.UI.Controls;
|
||||||
|
using LanMountainDesktop.Services;
|
||||||
|
|
||||||
|
namespace LanMountainDesktop.Views;
|
||||||
|
|
||||||
|
public partial class MainWindow
|
||||||
|
{
|
||||||
|
private bool _isRestartPromptVisible;
|
||||||
|
|
||||||
|
private void OnPendingRestartStateChanged()
|
||||||
|
{
|
||||||
|
if (Dispatcher.UIThread.CheckAccess())
|
||||||
|
{
|
||||||
|
UpdatePendingRestartDock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dispatcher.UIThread.Post(UpdatePendingRestartDock);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePendingRestartDock()
|
||||||
|
{
|
||||||
|
PendingRestartDock.IsVisible = PendingRestartStateService.HasPendingRestart;
|
||||||
|
PendingRestartDockTitleTextBlock.Text = L("settings.restart_dock.title", "Restart required");
|
||||||
|
PendingRestartDockDescriptionTextBlock.Text = L(
|
||||||
|
"settings.restart_dock.description",
|
||||||
|
"Some changes will take effect after restarting the app.");
|
||||||
|
PendingRestartDockButtonTextBlock.Text = L("settings.restart_dock.button", "Restart app");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnPendingRestartDockButtonClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
await ShowGenericRestartPromptAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task ShowRenderModeRestartPromptAsync(string selectedMode)
|
||||||
|
{
|
||||||
|
var message = Lf(
|
||||||
|
"settings.restart_dialog.render_mode_message",
|
||||||
|
"Restart the app to switch the rendering mode from \"{0}\" to \"{1}\". Restart now?",
|
||||||
|
GetLocalizedAppRenderModeDisplayName(_runningAppRenderMode),
|
||||||
|
GetLocalizedAppRenderModeDisplayName(selectedMode));
|
||||||
|
|
||||||
|
return ShowRestartPromptCoreAsync(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task ShowGenericRestartPromptAsync()
|
||||||
|
{
|
||||||
|
return ShowRestartPromptCoreAsync(L(
|
||||||
|
"settings.restart_dock.description",
|
||||||
|
"Some changes will take effect after restarting the app."));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ShowRestartPromptCoreAsync(string message)
|
||||||
|
{
|
||||||
|
if (_isRestartPromptVisible)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isRestartPromptVisible = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var dialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = L("settings.restart_dialog.title", "Restart required"),
|
||||||
|
Content = message,
|
||||||
|
PrimaryButtonText = L("settings.restart_dialog.restart", "Restart now"),
|
||||||
|
CloseButtonText = L("settings.restart_dialog.cancel", "Cancel"),
|
||||||
|
DefaultButton = ContentDialogButton.Primary
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await dialog.ShowAsync(this);
|
||||||
|
if (result == ContentDialogResult.Primary)
|
||||||
|
{
|
||||||
|
if (!AppRestartService.TryRestartApplication())
|
||||||
|
{
|
||||||
|
UpdatePendingRestartDock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdatePendingRestartDock();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isRestartPromptVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetLocalizedAppRenderModeDisplayName(string renderMode)
|
||||||
|
{
|
||||||
|
if (renderMode == AppRenderBackendDiagnostics.Unknown)
|
||||||
|
{
|
||||||
|
return L("settings.about.render_mode.unknown", "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppRenderingModeHelper.Normalize(renderMode) switch
|
||||||
|
{
|
||||||
|
AppRenderingModeHelper.Software => L("settings.about.render_mode.software", "Software"),
|
||||||
|
AppRenderingModeHelper.AngleEgl => L("settings.about.render_mode.angle_egl", "angleEgl"),
|
||||||
|
AppRenderingModeHelper.Wgl => L("settings.about.render_mode.wgl", "WGL"),
|
||||||
|
AppRenderingModeHelper.Vulkan => L("settings.about.render_mode.vulkan", "Vulkan"),
|
||||||
|
_ => L("settings.about.render_mode.default", "Default")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1225,6 +1225,10 @@ public partial class MainWindow
|
|||||||
private void InitializeAppRenderModeSetting(AppSettingsSnapshot snapshot)
|
private void InitializeAppRenderModeSetting(AppSettingsSnapshot snapshot)
|
||||||
{
|
{
|
||||||
_selectedAppRenderMode = AppRenderingModeHelper.Normalize(snapshot.AppRenderMode);
|
_selectedAppRenderMode = AppRenderingModeHelper.Normalize(snapshot.AppRenderMode);
|
||||||
|
_runningAppRenderMode = ResolveActiveAppRenderModeForUi(_selectedAppRenderMode);
|
||||||
|
var renderModeForUi = PendingRestartStateService.HasPendingReason(PendingRestartStateService.RenderModeReason)
|
||||||
|
? _selectedAppRenderMode
|
||||||
|
: _runningAppRenderMode;
|
||||||
|
|
||||||
if (AppRenderModeComboBox is null)
|
if (AppRenderModeComboBox is null)
|
||||||
{
|
{
|
||||||
@@ -1235,7 +1239,7 @@ public partial class MainWindow
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
AppRenderModeComboBox.IsEnabled = OperatingSystem.IsWindows();
|
AppRenderModeComboBox.IsEnabled = OperatingSystem.IsWindows();
|
||||||
SelectAppRenderModeInUi(_selectedAppRenderMode);
|
SelectAppRenderModeInUi(renderModeForUi);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -1250,13 +1254,27 @@ public partial class MainWindow
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedItem = AppRenderModeComboBox.Items
|
AppRenderModeComboBox.SelectedIndex = GetAppRenderModeComboBoxIndex(renderMode);
|
||||||
.OfType<ComboBoxItem>()
|
}
|
||||||
.FirstOrDefault(item =>
|
|
||||||
string.Equals(item.Tag?.ToString(), renderMode, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
AppRenderModeComboBox.SelectedItem = selectedItem
|
private static int GetAppRenderModeComboBoxIndex(string renderMode)
|
||||||
?? AppRenderModeComboBox.Items.OfType<ComboBoxItem>().FirstOrDefault();
|
{
|
||||||
|
return AppRenderingModeHelper.Normalize(renderMode) switch
|
||||||
|
{
|
||||||
|
AppRenderingModeHelper.Software => 1,
|
||||||
|
AppRenderingModeHelper.AngleEgl => 2,
|
||||||
|
AppRenderingModeHelper.Wgl => 3,
|
||||||
|
AppRenderingModeHelper.Vulkan => 4,
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveActiveAppRenderModeForUi(string configuredRenderMode)
|
||||||
|
{
|
||||||
|
var detectedRenderMode = AppRenderBackendDiagnostics.Detect().ActualBackend;
|
||||||
|
return string.Equals(detectedRenderMode, AppRenderBackendDiagnostics.Unknown, StringComparison.Ordinal)
|
||||||
|
? configuredRenderMode
|
||||||
|
: AppRenderingModeHelper.Normalize(detectedRenderMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static WeatherLocationMode ParseWeatherLocationMode(string? value)
|
private static WeatherLocationMode ParseWeatherLocationMode(string? value)
|
||||||
@@ -1534,7 +1552,7 @@ public partial class MainWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
var selectedMode = AppRenderingModeHelper.Normalize(
|
var selectedMode = AppRenderingModeHelper.Normalize(
|
||||||
(AppRenderModeComboBox.SelectedItem as ComboBoxItem)?.Tag?.ToString());
|
TryGetSelectedComboBoxTag(AppRenderModeComboBox));
|
||||||
|
|
||||||
if (string.Equals(_selectedAppRenderMode, selectedMode, StringComparison.Ordinal))
|
if (string.Equals(_selectedAppRenderMode, selectedMode, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
@@ -1543,6 +1561,14 @@ public partial class MainWindow
|
|||||||
|
|
||||||
_selectedAppRenderMode = selectedMode;
|
_selectedAppRenderMode = selectedMode;
|
||||||
PersistSettings();
|
PersistSettings();
|
||||||
|
var requiresRestart = !string.Equals(_runningAppRenderMode, selectedMode, StringComparison.Ordinal);
|
||||||
|
PendingRestartStateService.SetPending(PendingRestartStateService.RenderModeReason, requiresRestart);
|
||||||
|
UpdatePendingRestartDock();
|
||||||
|
|
||||||
|
if (requiresRestart)
|
||||||
|
{
|
||||||
|
_ = ShowRenderModeRestartPromptAsync(selectedMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnSearchWeatherCityClick(object? sender, RoutedEventArgs e)
|
private async void OnSearchWeatherCityClick(object? sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -377,88 +377,138 @@
|
|||||||
<Border Classes="mica-strong"
|
<Border Classes="mica-strong"
|
||||||
CornerRadius="{DynamicResource DesignCornerRadiusXl}"
|
CornerRadius="{DynamicResource DesignCornerRadiusXl}"
|
||||||
Padding="18">
|
Padding="18">
|
||||||
<ui:NavigationView x:Name="SettingsNavView"
|
<Grid RowDefinitions="*,Auto"
|
||||||
PaneDisplayMode="Left"
|
RowSpacing="14">
|
||||||
IsSettingsVisible="False"
|
<ui:NavigationView x:Name="SettingsNavView"
|
||||||
OpenPaneLength="220"
|
Grid.Row="0"
|
||||||
SelectionChanged="OnSettingsNavSelectionChanged">
|
PaneDisplayMode="Left"
|
||||||
<ui:NavigationView.MenuItems>
|
IsSettingsVisible="False"
|
||||||
<ui:NavigationViewItem x:Name="SettingsNavWallpaperItem" Content="壁纸" Tag="Wallpaper" ToolTip.Tip="壁纸">
|
OpenPaneLength="220"
|
||||||
<ui:NavigationViewItem.IconSource>
|
SelectionChanged="OnSettingsNavSelectionChanged">
|
||||||
<ic:SymbolIconSource Symbol="Wallpaper" IconVariant="Regular" />
|
<ui:NavigationView.MenuItems>
|
||||||
</ui:NavigationViewItem.IconSource>
|
<ui:NavigationViewItem x:Name="SettingsNavWallpaperItem" Content="壁纸" Tag="Wallpaper" ToolTip.Tip="壁纸">
|
||||||
</ui:NavigationViewItem>
|
<ui:NavigationViewItem.IconSource>
|
||||||
<ui:NavigationViewItem x:Name="SettingsNavGridItem" Content="网格" Tag="Grid" ToolTip.Tip="网格">
|
<ic:SymbolIconSource Symbol="Wallpaper" IconVariant="Regular" />
|
||||||
<ui:NavigationViewItem.IconSource>
|
</ui:NavigationViewItem.IconSource>
|
||||||
<ic:SymbolIconSource Symbol="Grid" IconVariant="Regular" />
|
</ui:NavigationViewItem>
|
||||||
</ui:NavigationViewItem.IconSource>
|
<ui:NavigationViewItem x:Name="SettingsNavGridItem" Content="网格" Tag="Grid" ToolTip.Tip="网格">
|
||||||
</ui:NavigationViewItem>
|
<ui:NavigationViewItem.IconSource>
|
||||||
<ui:NavigationViewItem x:Name="SettingsNavColorItem" Content="颜色" Tag="Color" ToolTip.Tip="颜色">
|
<ic:SymbolIconSource Symbol="Grid" IconVariant="Regular" />
|
||||||
<ui:NavigationViewItem.IconSource>
|
</ui:NavigationViewItem.IconSource>
|
||||||
<ic:SymbolIconSource Symbol="Color" IconVariant="Regular" />
|
</ui:NavigationViewItem>
|
||||||
</ui:NavigationViewItem.IconSource>
|
<ui:NavigationViewItem x:Name="SettingsNavColorItem" Content="颜色" Tag="Color" ToolTip.Tip="颜色">
|
||||||
</ui:NavigationViewItem>
|
<ui:NavigationViewItem.IconSource>
|
||||||
<ui:NavigationViewItem x:Name="SettingsNavStatusBarItem" Content="状态栏" Tag="StatusBar" ToolTip.Tip="状态栏">
|
<ic:SymbolIconSource Symbol="Color" IconVariant="Regular" />
|
||||||
<ui:NavigationViewItem.IconSource>
|
</ui:NavigationViewItem.IconSource>
|
||||||
<ic:SymbolIconSource Symbol="Status" IconVariant="Regular" />
|
</ui:NavigationViewItem>
|
||||||
</ui:NavigationViewItem.IconSource>
|
<ui:NavigationViewItem x:Name="SettingsNavStatusBarItem" Content="状态栏" Tag="StatusBar" ToolTip.Tip="状态栏">
|
||||||
</ui:NavigationViewItem>
|
<ui:NavigationViewItem.IconSource>
|
||||||
<ui:NavigationViewItem x:Name="SettingsNavWeatherItem" Content="天气" Tag="Weather" ToolTip.Tip="天气">
|
<ic:SymbolIconSource Symbol="Status" IconVariant="Regular" />
|
||||||
<ui:NavigationViewItem.IconSource>
|
</ui:NavigationViewItem.IconSource>
|
||||||
<ic:SymbolIconSource Symbol="WeatherSunny" IconVariant="Regular" />
|
</ui:NavigationViewItem>
|
||||||
</ui:NavigationViewItem.IconSource>
|
<ui:NavigationViewItem x:Name="SettingsNavWeatherItem" Content="天气" Tag="Weather" ToolTip.Tip="天气">
|
||||||
</ui:NavigationViewItem>
|
<ui:NavigationViewItem.IconSource>
|
||||||
<ui:NavigationViewItem x:Name="SettingsNavRegionItem" Content="地区" Tag="Region" ToolTip.Tip="地区">
|
<ic:SymbolIconSource Symbol="WeatherSunny" IconVariant="Regular" />
|
||||||
<ui:NavigationViewItem.IconSource>
|
</ui:NavigationViewItem.IconSource>
|
||||||
<ic:SymbolIconSource Symbol="Globe" IconVariant="Regular" />
|
</ui:NavigationViewItem>
|
||||||
</ui:NavigationViewItem.IconSource>
|
<ui:NavigationViewItem x:Name="SettingsNavRegionItem" Content="地区" Tag="Region" ToolTip.Tip="地区">
|
||||||
</ui:NavigationViewItem>
|
<ui:NavigationViewItem.IconSource>
|
||||||
<ui:NavigationViewItem x:Name="SettingsNavUpdateItem" Content="更新" Tag="Update" ToolTip.Tip="更新">
|
<ic:SymbolIconSource Symbol="Globe" IconVariant="Regular" />
|
||||||
<ui:NavigationViewItem.IconSource>
|
</ui:NavigationViewItem.IconSource>
|
||||||
<ic:SymbolIconSource Symbol="ArrowSync" IconVariant="Regular" />
|
</ui:NavigationViewItem>
|
||||||
</ui:NavigationViewItem.IconSource>
|
<ui:NavigationViewItem x:Name="SettingsNavUpdateItem" Content="更新" Tag="Update" ToolTip.Tip="更新">
|
||||||
</ui:NavigationViewItem>
|
<ui:NavigationViewItem.IconSource>
|
||||||
<ui:NavigationViewItem x:Name="SettingsNavAboutItem" Content="关于" Tag="About" ToolTip.Tip="关于">
|
<ic:SymbolIconSource Symbol="ArrowSync" IconVariant="Regular" />
|
||||||
<ui:NavigationViewItem.IconSource>
|
</ui:NavigationViewItem.IconSource>
|
||||||
<ic:SymbolIconSource Symbol="Info" IconVariant="Regular" />
|
</ui:NavigationViewItem>
|
||||||
</ui:NavigationViewItem.IconSource>
|
<ui:NavigationViewItem x:Name="SettingsNavAboutItem" Content="关于" Tag="About" ToolTip.Tip="关于">
|
||||||
</ui:NavigationViewItem>
|
<ui:NavigationViewItem.IconSource>
|
||||||
<ui:NavigationViewItem x:Name="SettingsNavLauncherItem" Content="应用启动台" Tag="Launcher" ToolTip.Tip="应用启动台">
|
<ic:SymbolIconSource Symbol="Info" IconVariant="Regular" />
|
||||||
<ui:NavigationViewItem.IconSource>
|
</ui:NavigationViewItem.IconSource>
|
||||||
<ic:SymbolIconSource Symbol="Apps" IconVariant="Regular" />
|
</ui:NavigationViewItem>
|
||||||
</ui:NavigationViewItem.IconSource>
|
<ui:NavigationViewItem x:Name="SettingsNavLauncherItem" Content="应用启动台" Tag="Launcher" ToolTip.Tip="应用启动台">
|
||||||
</ui:NavigationViewItem>
|
<ui:NavigationViewItem.IconSource>
|
||||||
<ui:NavigationViewItem x:Name="SettingsNavPluginsItem" Content="插件" Tag="Plugins" ToolTip.Tip="插件">
|
<ic:SymbolIconSource Symbol="Apps" IconVariant="Regular" />
|
||||||
<ui:NavigationViewItem.IconSource>
|
</ui:NavigationViewItem.IconSource>
|
||||||
<ic:SymbolIconSource Symbol="PuzzlePiece" IconVariant="Regular" />
|
</ui:NavigationViewItem>
|
||||||
</ui:NavigationViewItem.IconSource>
|
<ui:NavigationViewItem x:Name="SettingsNavPluginsItem" Content="插件" Tag="Plugins" ToolTip.Tip="插件">
|
||||||
</ui:NavigationViewItem>
|
<ui:NavigationViewItem.IconSource>
|
||||||
</ui:NavigationView.MenuItems>
|
<ic:SymbolIconSource Symbol="PuzzlePiece" IconVariant="Regular" />
|
||||||
|
</ui:NavigationViewItem.IconSource>
|
||||||
|
</ui:NavigationViewItem>
|
||||||
|
</ui:NavigationView.MenuItems>
|
||||||
|
|
||||||
<ScrollViewer x:Name="SettingsContentScrollViewer"
|
<ScrollViewer x:Name="SettingsContentScrollViewer"
|
||||||
Padding="0,0,16,0"
|
Padding="0,0,16,0"
|
||||||
HorizontalScrollBarVisibility="Disabled"
|
HorizontalScrollBarVisibility="Disabled"
|
||||||
VerticalScrollBarVisibility="Auto">
|
VerticalScrollBarVisibility="Auto">
|
||||||
<Grid x:Name="SettingsContentPagesHost">
|
<Grid x:Name="SettingsContentPagesHost">
|
||||||
<pages:WallpaperSettingsPage x:Name="WallpaperSettingsPanel" IsVisible="True" />
|
<pages:WallpaperSettingsPage x:Name="WallpaperSettingsPanel" IsVisible="True" />
|
||||||
|
|
||||||
<pages:GridSettingsPage x:Name="GridSettingsPanel" IsVisible="False" />
|
<pages:GridSettingsPage x:Name="GridSettingsPanel" IsVisible="False" />
|
||||||
|
|
||||||
<pages:ColorSettingsPage x:Name="ColorSettingsPanel" IsVisible="False" />
|
<pages:ColorSettingsPage x:Name="ColorSettingsPanel" IsVisible="False" />
|
||||||
|
|
||||||
<pages:StatusBarSettingsPage x:Name="StatusBarSettingsPanel" IsVisible="False" />
|
<pages:StatusBarSettingsPage x:Name="StatusBarSettingsPanel" IsVisible="False" />
|
||||||
|
|
||||||
<pages:WeatherSettingsPage x:Name="WeatherSettingsPanel" IsVisible="False" />
|
<pages:WeatherSettingsPage x:Name="WeatherSettingsPanel" IsVisible="False" />
|
||||||
<pages:RegionSettingsPage x:Name="RegionSettingsPanel" IsVisible="False" />
|
<pages:RegionSettingsPage x:Name="RegionSettingsPanel" IsVisible="False" />
|
||||||
|
|
||||||
<pages:UpdateSettingsPage x:Name="UpdateSettingsPanel" IsVisible="False" />
|
<pages:UpdateSettingsPage x:Name="UpdateSettingsPanel" IsVisible="False" />
|
||||||
|
|
||||||
<pages:LauncherSettingsPage x:Name="LauncherSettingsPanel" IsVisible="False" />
|
<pages:LauncherSettingsPage x:Name="LauncherSettingsPanel" IsVisible="False" />
|
||||||
<pages:AboutSettingsPage x:Name="AboutSettingsPanel" IsVisible="False" />
|
<pages:AboutSettingsPage x:Name="AboutSettingsPanel" IsVisible="False" />
|
||||||
<pages:PluginSettingsPage x:Name="PluginSettingsPanel" IsVisible="False" />
|
<pages:PluginSettingsPage x:Name="PluginSettingsPanel" IsVisible="False" />
|
||||||
|
</Grid>
|
||||||
|
</ScrollViewer>
|
||||||
|
</ui:NavigationView>
|
||||||
|
|
||||||
|
<Border x:Name="PendingRestartDock"
|
||||||
|
Grid.Row="1"
|
||||||
|
IsVisible="False"
|
||||||
|
Classes="glass-panel"
|
||||||
|
CornerRadius="18"
|
||||||
|
Padding="14,12">
|
||||||
|
<Grid ColumnDefinitions="Auto,*,Auto"
|
||||||
|
ColumnSpacing="12">
|
||||||
|
<Border Width="34"
|
||||||
|
Height="34"
|
||||||
|
CornerRadius="17"
|
||||||
|
Background="{DynamicResource AdaptiveAccentBrush}">
|
||||||
|
<fi:FluentIcon Icon="ArrowSync"
|
||||||
|
IconVariant="Regular"
|
||||||
|
FontSize="16"
|
||||||
|
Foreground="White"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</Border>
|
||||||
|
<StackPanel Grid.Column="1"
|
||||||
|
Spacing="2"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<TextBlock x:Name="PendingRestartDockTitleTextBlock"
|
||||||
|
FontSize="13"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Text="Restart required" />
|
||||||
|
<TextBlock x:Name="PendingRestartDockDescriptionTextBlock"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||||
|
Text="Your changes will apply after restarting the app." />
|
||||||
|
</StackPanel>
|
||||||
|
<Button x:Name="PendingRestartDockButton"
|
||||||
|
Grid.Column="2"
|
||||||
|
Padding="14,8"
|
||||||
|
Click="OnPendingRestartDockButtonClick">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<fi:FluentIcon Icon="ArrowSync"
|
||||||
|
IconVariant="Regular" />
|
||||||
|
<TextBlock x:Name="PendingRestartDockButtonTextBlock"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="Restart app" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</Border>
|
||||||
</ui:NavigationView>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ public partial class MainWindow : Window
|
|||||||
private bool _suppressAutoStartToggleEvents;
|
private bool _suppressAutoStartToggleEvents;
|
||||||
private bool _suppressAppRenderModeSelectionEvents;
|
private bool _suppressAppRenderModeSelectionEvents;
|
||||||
private string _selectedAppRenderMode = AppRenderingModeHelper.Default;
|
private string _selectedAppRenderMode = AppRenderingModeHelper.Default;
|
||||||
|
private string _runningAppRenderMode = AppRenderingModeHelper.Default;
|
||||||
private string _weatherSearchKeyword = string.Empty;
|
private string _weatherSearchKeyword = string.Empty;
|
||||||
private bool _isWeatherSearchInProgress;
|
private bool _isWeatherSearchInProgress;
|
||||||
private bool _isWeatherPreviewInProgress;
|
private bool _isWeatherPreviewInProgress;
|
||||||
@@ -190,6 +191,7 @@ public partial class MainWindow : Window
|
|||||||
_fluentAvaloniaTheme = Application.Current?.Styles.OfType<FluentAvaloniaTheme>().FirstOrDefault();
|
_fluentAvaloniaTheme = Application.Current?.Styles.OfType<FluentAvaloniaTheme>().FirstOrDefault();
|
||||||
AppSettingsService.SettingsSaved += OnExternalAppSettingsSaved;
|
AppSettingsService.SettingsSaved += OnExternalAppSettingsSaved;
|
||||||
LauncherSettingsService.SettingsSaved += OnExternalLauncherSettingsSaved;
|
LauncherSettingsService.SettingsSaved += OnExternalLauncherSettingsSaved;
|
||||||
|
PendingRestartStateService.StateChanged += OnPendingRestartStateChanged;
|
||||||
PropertyChanged += OnWindowPropertyChanged;
|
PropertyChanged += OnWindowPropertyChanged;
|
||||||
InitializeDesktopSurfaceSwipeHandlers();
|
InitializeDesktopSurfaceSwipeHandlers();
|
||||||
InitializeDesktopComponentDragHandlers();
|
InitializeDesktopComponentDragHandlers();
|
||||||
@@ -314,6 +316,7 @@ public partial class MainWindow : Window
|
|||||||
InitializeWeatherSettings(snapshot);
|
InitializeWeatherSettings(snapshot);
|
||||||
_ = _componentSettingsService.Load();
|
_ = _componentSettingsService.Load();
|
||||||
InitializeAutoStartWithWindowsSetting(snapshot);
|
InitializeAutoStartWithWindowsSetting(snapshot);
|
||||||
|
InitializeAppRenderModeSetting(snapshot);
|
||||||
InitializeUpdateSettings(snapshot);
|
InitializeUpdateSettings(snapshot);
|
||||||
InitializeDesktopSurfaceState(desktopLayoutSnapshot);
|
InitializeDesktopSurfaceState(desktopLayoutSnapshot);
|
||||||
InitializeLauncherVisibilitySettings(launcherSnapshot);
|
InitializeLauncherVisibilitySettings(launcherSnapshot);
|
||||||
@@ -379,6 +382,7 @@ public partial class MainWindow : Window
|
|||||||
_wallpaperBitmap = null;
|
_wallpaperBitmap = null;
|
||||||
AppSettingsService.SettingsSaved -= OnExternalAppSettingsSaved;
|
AppSettingsService.SettingsSaved -= OnExternalAppSettingsSaved;
|
||||||
LauncherSettingsService.SettingsSaved -= OnExternalLauncherSettingsSaved;
|
LauncherSettingsService.SettingsSaved -= OnExternalLauncherSettingsSaved;
|
||||||
|
PendingRestartStateService.StateChanged -= OnPendingRestartStateChanged;
|
||||||
PropertyChanged -= OnWindowPropertyChanged;
|
PropertyChanged -= OnWindowPropertyChanged;
|
||||||
DesktopHost.SizeChanged -= OnDesktopHostSizeChanged;
|
DesktopHost.SizeChanged -= OnDesktopHostSizeChanged;
|
||||||
WallpaperPreviewHost.SizeChanged -= OnWallpaperPreviewHostSizeChanged;
|
WallpaperPreviewHost.SizeChanged -= OnWallpaperPreviewHostSizeChanged;
|
||||||
|
|||||||
@@ -64,6 +64,7 @@
|
|||||||
<ui:SettingsExpander.Footer>
|
<ui:SettingsExpander.Footer>
|
||||||
<ComboBox x:Name="AppRenderModeComboBox"
|
<ComboBox x:Name="AppRenderModeComboBox"
|
||||||
MinWidth="180"
|
MinWidth="180"
|
||||||
|
SelectedIndex="0"
|
||||||
HorizontalAlignment="Right">
|
HorizontalAlignment="Right">
|
||||||
<ComboBoxItem Content="Default" Tag="Default" />
|
<ComboBoxItem Content="Default" Tag="Default" />
|
||||||
<ComboBoxItem Content="Software" Tag="Software" />
|
<ComboBoxItem Content="Software" Tag="Software" />
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using FluentIcons.Avalonia.Fluent;
|
|||||||
using FluentIcons.Common;
|
using FluentIcons.Common;
|
||||||
using LanMountainDesktop.ComponentSystem;
|
using LanMountainDesktop.ComponentSystem;
|
||||||
using LanMountainDesktop.Models;
|
using LanMountainDesktop.Models;
|
||||||
|
using LanMountainDesktop.Services;
|
||||||
using LanMountainDesktop.Views.Components;
|
using LanMountainDesktop.Views.Components;
|
||||||
|
|
||||||
namespace LanMountainDesktop.Views;
|
namespace LanMountainDesktop.Views;
|
||||||
@@ -43,6 +44,7 @@ public partial class SettingsWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
_launcherIconCache.Clear();
|
_launcherIconCache.Clear();
|
||||||
|
PendingRestartStateService.StateChanged -= OnPendingRestartStateChanged;
|
||||||
base.OnClosed(e);
|
base.OnClosed(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ public partial class SettingsWindow
|
|||||||
SetAppRenderModeComboItemContent(AppRenderingModeHelper.Wgl, L("settings.about.render_mode.wgl", "WGL"));
|
SetAppRenderModeComboItemContent(AppRenderingModeHelper.Wgl, L("settings.about.render_mode.wgl", "WGL"));
|
||||||
SetAppRenderModeComboItemContent(AppRenderingModeHelper.Vulkan, L("settings.about.render_mode.vulkan", "Vulkan"));
|
SetAppRenderModeComboItemContent(AppRenderingModeHelper.Vulkan, L("settings.about.render_mode.vulkan", "Vulkan"));
|
||||||
UpdateCurrentRenderBackendStatus();
|
UpdateCurrentRenderBackendStatus();
|
||||||
|
UpdatePendingRestartDock();
|
||||||
|
|
||||||
var placementItems = WallpaperPlacementComboBox.Items.OfType<ComboBoxItem>().ToList();
|
var placementItems = WallpaperPlacementComboBox.Items.OfType<ComboBoxItem>().ToList();
|
||||||
if (placementItems.Count >= 5)
|
if (placementItems.Count >= 5)
|
||||||
|
|||||||
112
LanMountainDesktop/Views/SettingsWindow.RestartPrompt.cs
Normal file
112
LanMountainDesktop/Views/SettingsWindow.RestartPrompt.cs
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
using Avalonia.Threading;
|
||||||
|
using FluentAvalonia.UI.Controls;
|
||||||
|
using LanMountainDesktop.Services;
|
||||||
|
|
||||||
|
namespace LanMountainDesktop.Views;
|
||||||
|
|
||||||
|
public partial class SettingsWindow
|
||||||
|
{
|
||||||
|
private bool _isRestartPromptVisible;
|
||||||
|
|
||||||
|
private void OnPendingRestartStateChanged()
|
||||||
|
{
|
||||||
|
if (Dispatcher.UIThread.CheckAccess())
|
||||||
|
{
|
||||||
|
UpdatePendingRestartDock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dispatcher.UIThread.Post(UpdatePendingRestartDock);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePendingRestartDock()
|
||||||
|
{
|
||||||
|
PendingRestartDock.IsVisible = PendingRestartStateService.HasPendingRestart;
|
||||||
|
PendingRestartDockTitleTextBlock.Text = L("settings.restart_dock.title", "Restart required");
|
||||||
|
PendingRestartDockDescriptionTextBlock.Text = L(
|
||||||
|
"settings.restart_dock.description",
|
||||||
|
"Some changes will take effect after restarting the app.");
|
||||||
|
PendingRestartDockButtonTextBlock.Text = L("settings.restart_dock.button", "Restart app");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnPendingRestartDockButtonClick(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
await ShowGenericRestartPromptAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task ShowRenderModeRestartPromptAsync(string selectedMode)
|
||||||
|
{
|
||||||
|
var message = Lf(
|
||||||
|
"settings.restart_dialog.render_mode_message",
|
||||||
|
"Restart the app to switch the rendering mode from \"{0}\" to \"{1}\". Restart now?",
|
||||||
|
GetLocalizedAppRenderModeDisplayName(_runningAppRenderMode),
|
||||||
|
GetLocalizedAppRenderModeDisplayName(selectedMode));
|
||||||
|
|
||||||
|
return ShowRestartPromptCoreAsync(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task ShowGenericRestartPromptAsync()
|
||||||
|
{
|
||||||
|
return ShowRestartPromptCoreAsync(L(
|
||||||
|
"settings.restart_dock.description",
|
||||||
|
"Some changes will take effect after restarting the app."));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ShowRestartPromptCoreAsync(string message)
|
||||||
|
{
|
||||||
|
if (_isRestartPromptVisible)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_isRestartPromptVisible = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var dialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Title = L("settings.restart_dialog.title", "Restart required"),
|
||||||
|
Content = message,
|
||||||
|
PrimaryButtonText = L("settings.restart_dialog.restart", "Restart now"),
|
||||||
|
CloseButtonText = L("settings.restart_dialog.cancel", "Cancel"),
|
||||||
|
DefaultButton = ContentDialogButton.Primary
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await dialog.ShowAsync(this);
|
||||||
|
if (result == ContentDialogResult.Primary)
|
||||||
|
{
|
||||||
|
if (!AppRestartService.TryRestartApplication())
|
||||||
|
{
|
||||||
|
UpdatePendingRestartDock();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdatePendingRestartDock();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isRestartPromptVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetLocalizedAppRenderModeDisplayName(string renderMode)
|
||||||
|
{
|
||||||
|
if (renderMode == AppRenderBackendDiagnostics.Unknown)
|
||||||
|
{
|
||||||
|
return L("settings.about.render_mode.unknown", "Unknown");
|
||||||
|
}
|
||||||
|
|
||||||
|
return AppRenderingModeHelper.Normalize(renderMode) switch
|
||||||
|
{
|
||||||
|
AppRenderingModeHelper.Software => L("settings.about.render_mode.software", "Software"),
|
||||||
|
AppRenderingModeHelper.AngleEgl => L("settings.about.render_mode.angle_egl", "angleEgl"),
|
||||||
|
AppRenderingModeHelper.Wgl => L("settings.about.render_mode.wgl", "WGL"),
|
||||||
|
AppRenderingModeHelper.Vulkan => L("settings.about.render_mode.vulkan", "Vulkan"),
|
||||||
|
_ => L("settings.about.render_mode.default", "Default")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,12 +92,16 @@ public partial class SettingsWindow
|
|||||||
private void InitializeAppRenderModeSetting(AppSettingsSnapshot snapshot)
|
private void InitializeAppRenderModeSetting(AppSettingsSnapshot snapshot)
|
||||||
{
|
{
|
||||||
_selectedAppRenderMode = AppRenderingModeHelper.Normalize(snapshot.AppRenderMode);
|
_selectedAppRenderMode = AppRenderingModeHelper.Normalize(snapshot.AppRenderMode);
|
||||||
|
_runningAppRenderMode = ResolveActiveAppRenderModeForUi(_selectedAppRenderMode);
|
||||||
|
var renderModeForUi = PendingRestartStateService.HasPendingReason(PendingRestartStateService.RenderModeReason)
|
||||||
|
? _selectedAppRenderMode
|
||||||
|
: _runningAppRenderMode;
|
||||||
|
|
||||||
_suppressAppRenderModeSelectionEvents = true;
|
_suppressAppRenderModeSelectionEvents = true;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AppRenderModeComboBox.IsEnabled = OperatingSystem.IsWindows();
|
AppRenderModeComboBox.IsEnabled = OperatingSystem.IsWindows();
|
||||||
SelectAppRenderModeInUi(_selectedAppRenderMode);
|
SelectAppRenderModeInUi(renderModeForUi);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -107,13 +111,27 @@ public partial class SettingsWindow
|
|||||||
|
|
||||||
private void SelectAppRenderModeInUi(string renderMode)
|
private void SelectAppRenderModeInUi(string renderMode)
|
||||||
{
|
{
|
||||||
var selectedItem = AppRenderModeComboBox.Items
|
AppRenderModeComboBox.SelectedIndex = GetAppRenderModeComboBoxIndex(renderMode);
|
||||||
.OfType<ComboBoxItem>()
|
}
|
||||||
.FirstOrDefault(item =>
|
|
||||||
string.Equals(item.Tag?.ToString(), renderMode, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
AppRenderModeComboBox.SelectedItem = selectedItem
|
private static int GetAppRenderModeComboBoxIndex(string renderMode)
|
||||||
?? AppRenderModeComboBox.Items.OfType<ComboBoxItem>().FirstOrDefault();
|
{
|
||||||
|
return AppRenderingModeHelper.Normalize(renderMode) switch
|
||||||
|
{
|
||||||
|
AppRenderingModeHelper.Software => 1,
|
||||||
|
AppRenderingModeHelper.AngleEgl => 2,
|
||||||
|
AppRenderingModeHelper.Wgl => 3,
|
||||||
|
AppRenderingModeHelper.Vulkan => 4,
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveActiveAppRenderModeForUi(string configuredRenderMode)
|
||||||
|
{
|
||||||
|
var detectedRenderMode = AppRenderBackendDiagnostics.Detect().ActualBackend;
|
||||||
|
return string.Equals(detectedRenderMode, AppRenderBackendDiagnostics.Unknown, StringComparison.Ordinal)
|
||||||
|
? configuredRenderMode
|
||||||
|
: AppRenderingModeHelper.Normalize(detectedRenderMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static WeatherLocationMode ParseWeatherLocationMode(string? value)
|
private static WeatherLocationMode ParseWeatherLocationMode(string? value)
|
||||||
@@ -354,7 +372,7 @@ public partial class SettingsWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
var selectedMode = AppRenderingModeHelper.Normalize(
|
var selectedMode = AppRenderingModeHelper.Normalize(
|
||||||
(AppRenderModeComboBox.SelectedItem as ComboBoxItem)?.Tag?.ToString());
|
TryGetSelectedComboBoxTag(AppRenderModeComboBox));
|
||||||
|
|
||||||
if (string.Equals(_selectedAppRenderMode, selectedMode, StringComparison.Ordinal))
|
if (string.Equals(_selectedAppRenderMode, selectedMode, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
@@ -363,6 +381,14 @@ public partial class SettingsWindow
|
|||||||
|
|
||||||
_selectedAppRenderMode = selectedMode;
|
_selectedAppRenderMode = selectedMode;
|
||||||
PersistSettings();
|
PersistSettings();
|
||||||
|
var requiresRestart = !string.Equals(_runningAppRenderMode, selectedMode, StringComparison.Ordinal);
|
||||||
|
PendingRestartStateService.SetPending(PendingRestartStateService.RenderModeReason, requiresRestart);
|
||||||
|
UpdatePendingRestartDock();
|
||||||
|
|
||||||
|
if (requiresRestart)
|
||||||
|
{
|
||||||
|
_ = ShowRenderModeRestartPromptAsync(selectedMode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnSearchWeatherCityClick(object? sender, RoutedEventArgs e)
|
private async void OnSearchWeatherCityClick(object? sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -79,7 +79,10 @@
|
|||||||
Classes="mica-strong"
|
Classes="mica-strong"
|
||||||
CornerRadius="0,0,24,24"
|
CornerRadius="0,0,24,24"
|
||||||
Padding="18">
|
Padding="18">
|
||||||
|
<Grid RowDefinitions="*,Auto"
|
||||||
|
RowSpacing="14">
|
||||||
<ui:NavigationView x:Name="SettingsNavView"
|
<ui:NavigationView x:Name="SettingsNavView"
|
||||||
|
Grid.Row="0"
|
||||||
PaneDisplayMode="Left"
|
PaneDisplayMode="Left"
|
||||||
IsSettingsVisible="False"
|
IsSettingsVisible="False"
|
||||||
OpenPaneLength="240"
|
OpenPaneLength="240"
|
||||||
@@ -155,6 +158,53 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</ui:NavigationView>
|
</ui:NavigationView>
|
||||||
|
|
||||||
|
<Border x:Name="PendingRestartDock"
|
||||||
|
Grid.Row="1"
|
||||||
|
IsVisible="False"
|
||||||
|
Classes="glass-panel"
|
||||||
|
CornerRadius="18"
|
||||||
|
Padding="14,12">
|
||||||
|
<Grid ColumnDefinitions="Auto,*,Auto"
|
||||||
|
ColumnSpacing="12">
|
||||||
|
<Border Width="34"
|
||||||
|
Height="34"
|
||||||
|
CornerRadius="17"
|
||||||
|
Background="{DynamicResource AdaptiveAccentBrush}">
|
||||||
|
<fi:FluentIcon Icon="ArrowSync"
|
||||||
|
IconVariant="Regular"
|
||||||
|
FontSize="16"
|
||||||
|
Foreground="White"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</Border>
|
||||||
|
<StackPanel Grid.Column="1"
|
||||||
|
Spacing="2"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<TextBlock x:Name="PendingRestartDockTitleTextBlock"
|
||||||
|
FontSize="13"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Text="Restart required" />
|
||||||
|
<TextBlock x:Name="PendingRestartDockDescriptionTextBlock"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
Foreground="{DynamicResource AdaptiveTextSecondaryBrush}"
|
||||||
|
Text="Your changes will apply after restarting the app." />
|
||||||
|
</StackPanel>
|
||||||
|
<Button x:Name="PendingRestartDockButton"
|
||||||
|
Grid.Column="2"
|
||||||
|
Padding="14,8"
|
||||||
|
Click="OnPendingRestartDockButtonClick">
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||||
|
<fi:FluentIcon Icon="ArrowSync"
|
||||||
|
IconVariant="Regular" />
|
||||||
|
<TextBlock x:Name="PendingRestartDockButtonTextBlock"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="Restart app" />
|
||||||
|
</StackPanel>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ public partial class SettingsWindow : Window
|
|||||||
private int _statusBarCustomSpacingPercent = 12;
|
private int _statusBarCustomSpacingPercent = 12;
|
||||||
private int _desktopEdgeInsetPercent = DefaultEdgeInsetPercent;
|
private int _desktopEdgeInsetPercent = DefaultEdgeInsetPercent;
|
||||||
private string _selectedAppRenderMode = AppRenderingModeHelper.Default;
|
private string _selectedAppRenderMode = AppRenderingModeHelper.Default;
|
||||||
|
private string _runningAppRenderMode = AppRenderingModeHelper.Default;
|
||||||
private string _taskbarLayoutMode = TaskbarLayoutBottomFullRowMacStyle;
|
private string _taskbarLayoutMode = TaskbarLayoutBottomFullRowMacStyle;
|
||||||
private string _languageCode = "zh-CN";
|
private string _languageCode = "zh-CN";
|
||||||
private WeatherLocationMode _weatherLocationMode = WeatherLocationMode.CitySearch;
|
private WeatherLocationMode _weatherLocationMode = WeatherLocationMode.CitySearch;
|
||||||
@@ -165,6 +166,7 @@ public partial class SettingsWindow : Window
|
|||||||
InitializePluginSettingsNavigation();
|
InitializePluginSettingsNavigation();
|
||||||
_fluentAvaloniaTheme = Application.Current?.Styles.OfType<FluentAvaloniaTheme>().FirstOrDefault();
|
_fluentAvaloniaTheme = Application.Current?.Styles.OfType<FluentAvaloniaTheme>().FirstOrDefault();
|
||||||
RequestedThemeVariant = Application.Current?.RequestedThemeVariant ?? ThemeVariant.Default;
|
RequestedThemeVariant = Application.Current?.RequestedThemeVariant ?? ThemeVariant.Default;
|
||||||
|
PendingRestartStateService.StateChanged += OnPendingRestartStateChanged;
|
||||||
HookEvents();
|
HookEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user