feat.完善了时钟轻应用,为启动器提供了多语言支持

This commit is contained in:
lincube
2026-05-18 12:26:23 +08:00
parent 93758fc083
commit b6d820a320
63 changed files with 4581 additions and 342 deletions

View File

@@ -4,12 +4,14 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
xmlns:fi="using:FluentIcons.Avalonia"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d"
d:DesignWidth="520"
d:DesignHeight="480"
x:Class="LanMountainDesktop.Launcher.Views.DataLocationPromptWindow"
x:DataType="views:DataLocationPromptWindow"
Title="Choose Data Location"
x:CompileBindings="False"
Title="{x:Static res:Strings.DataLocation_Title}"
Width="520"
Height="480"
CanResize="False"
@@ -24,11 +26,11 @@
</Grid.RenderTransform>
<Grid Margin="36" RowDefinitions="Auto,*,Auto">
<StackPanel Grid.Row="0" Spacing="8" Margin="0,0,0,20">
<TextBlock Text="Choose Data Location"
<TextBlock Text="{x:Static res:Strings.DataLocation_ChooseLocation}"
FontSize="22"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="Choose where launcher and desktop data should be stored. You can change this later in settings."
<TextBlock Text="{x:Static res:Strings.DataLocation_ChooseLocationDesc}"
FontSize="13"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -45,7 +47,7 @@
<fi:SymbolIcon Symbol="Important"
FontSize="16"
Foreground="{DynamicResource SystemFillColorCriticalBrush}" />
<TextBlock Text="App folder is not writable"
<TextBlock Text="{x:Static res:Strings.DataLocation_NotWritable}"
FontWeight="SemiBold"
FontSize="13"
Foreground="{DynamicResource SystemFillColorCriticalBrush}" />
@@ -71,11 +73,11 @@
GroupName="DataLocation"
IsChecked="True" />
<StackPanel Grid.Column="1" Spacing="4">
<TextBlock Text="Store in the system user profile (Recommended)"
<TextBlock Text="{x:Static res:Strings.DataLocation_SystemProfile}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="Data stays tied to the current Windows user and remains intact across app reinstalls and updates."
<TextBlock Text="{x:Static res:Strings.DataLocation_SystemProfileDesc}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -102,11 +104,11 @@
GroupName="DataLocation"
IsEnabled="False" />
<StackPanel Grid.Column="1" Spacing="4">
<TextBlock Text="Store next to the app"
<TextBlock Text="{x:Static res:Strings.DataLocation_Portable}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="Useful for portable installs. The whole app folder can be moved to another machine together with its data."
<TextBlock Text="{x:Static res:Strings.DataLocation_PortableDesc}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -146,7 +148,7 @@
Theme="{DynamicResource ButtonTheme}"
IsVisible="False" />
<Button x:Name="ConfirmButton"
Content="Confirm"
Content="{x:Static res:Strings.DataLocation_ButtonConfirm}"
Theme="{DynamicResource AccentButtonTheme}" />
</StackPanel>
</Grid>

View File

@@ -7,6 +7,7 @@ using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Styling;
using LanMountainDesktop.Launcher.Models;
using LanMountainDesktop.Launcher.Resources;
using LanMountainDesktop.Launcher.Services;
namespace LanMountainDesktop.Launcher.Views;
@@ -106,7 +107,7 @@ internal partial class DataLocationPromptWindow : Window
if (migrationInfoText is not null && hasExistingData)
{
migrationInfoText.Text = "Existing system data was detected. Choosing portable mode will migrate the current data automatically.";
migrationInfoText.Text = Strings.DataLocation_MigrateWarning;
}
}

View File

@@ -3,10 +3,12 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:LanMountainDesktop.Launcher.ViewModels"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="600"
x:Class="LanMountainDesktop.Launcher.Views.DevDebugWindow"
x:DataType="vm:DevDebugWindowViewModel"
Title="开发调试窗口 - Launcher"
x:CompileBindings="False"
Title="{x:Static res:Strings.DevDebug_Title}"
Width="500"
Height="600"
WindowStartupLocation="CenterScreen"
@@ -43,7 +45,7 @@
Padding="15">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0">
<TextBlock Text="🚀 启动画面 (SplashWindow)"
<TextBlock Text="{x:Static res:Strings.DevDebug_Splash}"
FontWeight="SemiBold"
FontSize="14" />
<TextBlock Text="显示启动进度和状态"
@@ -52,11 +54,11 @@
Margin="0,3,0,0" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="8">
<ToggleSwitch Content="启用功能"
<ToggleSwitch Content="{x:Static res:Strings.DevDebug_EnableFeature}"
IsChecked="{Binding IsSplashEnabled}"
OnContent="功能"
OffContent="查看" />
<Button Content="打开"
<Button Content="{x:Static res:Strings.DevDebug_Open}"
Command="{Binding OpenSplashCommand}"
HorizontalAlignment="Right" />
</StackPanel>
@@ -69,7 +71,7 @@
Padding="15">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0">
<TextBlock Text="❌ 错误页面 (ErrorWindow)"
<TextBlock Text="{x:Static res:Strings.DevDebug_Error}"
FontWeight="SemiBold"
FontSize="14" />
<TextBlock Text="显示错误信息和重试选项"
@@ -78,11 +80,11 @@
Margin="0,3,0,0" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="8">
<ToggleSwitch Content="启用功能"
<ToggleSwitch Content="{x:Static res:Strings.DevDebug_EnableFeature}"
IsChecked="{Binding IsErrorEnabled}"
OnContent="功能"
OffContent="查看" />
<Button Content="打开"
<Button Content="{x:Static res:Strings.DevDebug_Open}"
Command="{Binding OpenErrorCommand}"
HorizontalAlignment="Right" />
</StackPanel>
@@ -95,7 +97,7 @@
Padding="15">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0">
<TextBlock Text="⬆️ 更新页面 (UpdateWindow)"
<TextBlock Text="{x:Static res:Strings.DevDebug_Update}"
FontWeight="SemiBold"
FontSize="14" />
<TextBlock Text="显示更新进度和状态"
@@ -104,11 +106,11 @@
Margin="0,3,0,0" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="8">
<ToggleSwitch Content="启用功能"
<ToggleSwitch Content="{x:Static res:Strings.DevDebug_EnableFeature}"
IsChecked="{Binding IsUpdateEnabled}"
OnContent="功能"
OffContent="查看" />
<Button Content="打开"
<Button Content="{x:Static res:Strings.DevDebug_Open}"
Command="{Binding OpenUpdateCommand}"
HorizontalAlignment="Right" />
</StackPanel>
@@ -121,7 +123,7 @@
Padding="15">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0">
<TextBlock Text="👋 OOBE页面 (OobeWindow)"
<TextBlock Text="{x:Static res:Strings.DevDebug_Oobe}"
FontWeight="SemiBold"
FontSize="14" />
<TextBlock Text="首次运行引导页面"
@@ -130,11 +132,11 @@
Margin="0,3,0,0" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="8">
<ToggleSwitch Content="启用功能"
<ToggleSwitch Content="{x:Static res:Strings.DevDebug_EnableFeature}"
IsChecked="{Binding IsOobeEnabled}"
OnContent="功能"
OffContent="查看" />
<Button Content="打开"
<Button Content="{x:Static res:Strings.DevDebug_Open}"
Command="{Binding OpenOobeCommand}"
HorizontalAlignment="Right" />
</StackPanel>
@@ -147,7 +149,7 @@
Padding="15">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0">
<TextBlock Text="📁 数据位置选择 (DataLocationPromptWindow)"
<TextBlock Text="{x:Static res:Strings.DevDebug_DataLocation}"
FontWeight="SemiBold"
FontSize="14" />
<TextBlock Text="选择数据保存位置"
@@ -156,11 +158,11 @@
Margin="0,3,0,0" />
</StackPanel>
<StackPanel Grid.Column="1" Spacing="8">
<ToggleSwitch Content="启用功能"
<ToggleSwitch Content="{x:Static res:Strings.DevDebug_EnableFeature}"
IsChecked="{Binding IsDataLocationEnabled}"
OnContent="功能"
OffContent="查看" />
<Button Content="打开"
<Button Content="{x:Static res:Strings.DevDebug_Open}"
Command="{Binding OpenDataLocationCommand}"
HorizontalAlignment="Right" />
</StackPanel>
@@ -176,10 +178,10 @@
HorizontalAlignment="Center"
Spacing="10"
Margin="0,15">
<Button Content="全部设为查看模式"
<Button Content="{x:Static res:Strings.DevDebug_SetAllViewMode}"
Command="{Binding SetAllViewOnlyCommand}"
Background="{DynamicResource SystemControlBackgroundAltMediumBrush}" />
<Button Content="全部设为功能模式"
<Button Content="{x:Static res:Strings.DevDebug_SetAllFunctionMode}"
Command="{Binding SetAllFunctionalCommand}"
Background="{DynamicResource SystemControlHighlightAccentBrush}"
Foreground="White" />
@@ -197,7 +199,7 @@
Opacity="0.8"
TextTrimming="CharacterEllipsis" />
<Button Grid.Column="1"
Content="关闭"
Content="{x:Static res:Strings.DevDebug_Close}"
Command="{Binding CloseCommand}"
Padding="15,5" />
</Grid>

View File

@@ -1,5 +1,6 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using LanMountainDesktop.Launcher.Resources;
using LanMountainDesktop.Launcher.Services;
using LanMountainDesktop.Launcher.ViewModels;
using LanMountainDesktop.Launcher.Views;
@@ -62,12 +63,12 @@ public partial class DevDebugWindow : Window
{
// 查看模式:显示模拟错误
errorWindow.SetDebugMode(true);
errorWindow.SetErrorMessage("[调试模式] 这是一个模拟的错误消息,用于查看错误页面的样式和布局。");
errorWindow.SetErrorMessage(Strings.Preview_ErrorMessage);
}
else
{
// 功能模式:显示真实错误
errorWindow.SetErrorMessage("找不到阑山桌面应用程序。\n\n请检查应用安装是否完整。");
errorWindow.SetErrorMessage(Strings.Error_HostNotFoundMessage);
}
errorWindow.Show();
@@ -160,7 +161,7 @@ public partial class DevDebugWindow : Window
/// </summary>
private async Task SimulateSplashProgress(SplashWindow splashWindow)
{
var stages = new[] { "初始化", "检查更新", "加载组件", "启动应用" };
var stages = new[] { Strings.Preview_SplashInitializing, Strings.Preview_SplashCheckingUpdates, Strings.Preview_SplashCheckingPlugins, Strings.Preview_SplashLaunchingHost };
var reporter = (ISplashStageReporter)splashWindow;
for (int i = 0; i < stages.Length; i++)

View File

@@ -3,12 +3,14 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d"
d:DesignWidth="420"
d:DesignHeight="320"
x:Class="LanMountainDesktop.Launcher.Views.ErrorDebugWindow"
x:DataType="views:ErrorDebugWindow"
Title="调试模式"
x:CompileBindings="False"
Title="{x:Static res:Strings.DebugDebug_Title}"
Width="420"
Height="320"
CanResize="False"
@@ -23,7 +25,7 @@
<Grid Margin="24" RowDefinitions="Auto,*,Auto">
<!-- 标题 -->
<TextBlock Grid.Row="0"
Text="调试设置"
Text="{x:Static res:Strings.DebugDebug_SettingsTitle}"
FontSize="20"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
@@ -37,18 +39,18 @@
Padding="16,12">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" VerticalAlignment="Center">
<TextBlock Text="开发模式"
<TextBlock Text="{x:Static res:Strings.DebugDebug_DevMode}"
FontSize="14"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="启用后自动扫描开发目录"
<TextBlock Text="{x:Static res:Strings.DebugDebug_DevModeDesc}"
FontSize="12"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Margin="0,2,0,0" />
</StackPanel>
<ToggleSwitch x:Name="DevModeToggle"
Grid.Column="1"
OnContent=""
OffContent="" />
OnContent="{x:Static res:Strings.DebugDebug_On}"
OffContent="{x:Static res:Strings.DebugDebug_Off}" />
</Grid>
</Border>
@@ -58,19 +60,19 @@
Padding="16,12">
<Grid RowDefinitions="Auto,Auto" ColumnDefinitions="*,Auto">
<TextBlock Grid.Row="0" Grid.Column="0"
Text="应用路径"
Text="{x:Static res:Strings.DebugDebug_AppPath}"
FontSize="14"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock x:Name="PathTextBlock"
Grid.Row="1" Grid.Column="0"
Text="未选择"
Text="{x:Static res:Strings.DebugDebug_NotSelected}"
FontSize="12"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
TextTrimming="CharacterEllipsis"
Margin="0,4,12,0" />
<Button x:Name="BrowseButton"
Grid.Row="0" Grid.RowSpan="2" Grid.Column="1"
Content="浏览..."
Content="{x:Static res:Strings.DebugDebug_Browse}"
VerticalAlignment="Center" />
</Grid>
</Border>
@@ -80,7 +82,7 @@
CornerRadius="{DynamicResource ControlCornerRadius}"
Padding="12,10"
IsVisible="True">
<TextBlock Text="此功能仅供开发人员使用"
<TextBlock Text="{x:Static res:Strings.DebugDebug_Warning}"
FontSize="12"
Foreground="{DynamicResource SystemFillColorCautionBrush}"
TextWrapping="Wrap" />
@@ -94,11 +96,11 @@
Spacing="12"
Margin="0,16,0,0">
<Button x:Name="CancelButton"
Content="取消"
Content="{x:Static res:Strings.DebugDebug_ButtonCancel}"
Width="80"
Height="32" />
<Button x:Name="OkButton"
Content="确定"
Content="{x:Static res:Strings.DebugDebug_ButtonOk}"
Width="80"
Height="32"
Theme="{DynamicResource AccentButtonTheme}" />

View File

@@ -2,6 +2,7 @@ using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage;
using LanMountainDesktop.Launcher.Resources;
namespace LanMountainDesktop.Launcher.Views;
@@ -87,7 +88,7 @@ public partial class ErrorDebugWindow : Window
var options = new FilePickerOpenOptions
{
Title = "Select LanMountainDesktop host executable",
Title = Strings.DebugDebug_SelectExeDialog,
AllowMultiple = false,
FileTypeFilter =
[
@@ -114,7 +115,7 @@ public partial class ErrorDebugWindow : Window
{
if (this.FindControl<TextBlock>("PathTextBlock") is { } pathTextBlock)
{
pathTextBlock.Text = string.IsNullOrEmpty(path) ? "Not selected" : path;
pathTextBlock.Text = string.IsNullOrEmpty(path) ? Strings.DebugDebug_NotSelected : path;
}
}
}

View File

@@ -5,10 +5,12 @@
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:fi="using:FluentIcons.Avalonia"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d"
x:Class="LanMountainDesktop.Launcher.Views.ErrorWindow"
x:DataType="views:ErrorWindow"
Title="LanMountain Desktop"
x:CompileBindings="False"
Title="{x:Static res:Strings.Error_Title}"
Width="760"
Height="460"
MinWidth="640"
@@ -46,14 +48,14 @@
<StackPanel Grid.Column="1"
Spacing="8">
<TextBlock x:Name="TitleText"
Text="Launcher could not confirm startup"
Text="{x:Static res:Strings.Error_TitleCannotConfirm}"
FontSize="22"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
TextWrapping="Wrap" />
<TextBlock x:Name="ErrorMessageText"
Text="LanMountain Desktop did not reach the expected startup state."
Text="{x:Static res:Strings.Error_MessageNotReached}"
FontSize="14"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap"
@@ -68,8 +70,8 @@
IsOpen="True"
IsClosable="False"
Severity="Warning"
Title="Startup recovery"
Message="You can inspect logs, wait for the current process, or activate the running desktop instance.">
Title="{x:Static res:Strings.Error_SuggestionTitle}"
Message="{x:Static res:Strings.Error_SuggestionMessage}">
<ui:FAInfoBar.IconSource>
<ui:FAFontIconSource Glyph="&#xF0288;"
FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
@@ -79,7 +81,7 @@
<Expander Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
Header="Diagnostic details"
Header="{x:Static res:Strings.Error_DiagnosticHeader}"
IsExpanded="True">
<TextBox x:Name="ErrorDetailsTextBox"
Margin="0,10,0,0"
@@ -108,7 +110,7 @@
Height="34">
<StackPanel Orientation="Horizontal" Spacing="6">
<fi:SymbolIcon Symbol="FolderOpen" IconVariant="Regular" FontSize="16"/>
<TextBlock Text="Open Logs"/>
<TextBlock Text="{x:Static res:Strings.Error_ButtonOpenLogs}"/>
</StackPanel>
</Button>
@@ -117,7 +119,7 @@
Height="34">
<StackPanel Orientation="Horizontal" Spacing="6">
<fi:SymbolIcon Symbol="Copy" IconVariant="Regular" FontSize="16"/>
<TextBlock Text="Copy"/>
<TextBlock Text="{x:Static res:Strings.Error_ButtonCopy}"/>
</StackPanel>
</Button>
</StackPanel>
@@ -126,7 +128,7 @@
Orientation="Horizontal"
Spacing="8">
<Button x:Name="SecondaryActionButton"
Content="Wait"
Content="{x:Static res:Strings.Error_ButtonWait}"
MinWidth="96"
Height="34"
IsVisible="False" />
@@ -136,13 +138,13 @@
Height="34">
<StackPanel Orientation="Horizontal" Spacing="6">
<fi:SymbolIcon Symbol="Dismiss" IconVariant="Regular" FontSize="16"/>
<TextBlock Text="Exit"/>
<TextBlock Text="{x:Static res:Strings.Error_ButtonExit}"/>
</StackPanel>
</Button>
<Button x:Name="PrimaryActionButton"
Classes="accent"
Content="Retry"
Content="{x:Static res:Strings.Error_ButtonRetry}"
MinWidth="112"
Height="34" />
</StackPanel>

View File

@@ -5,6 +5,7 @@ using Avalonia.Input.Platform;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using FluentAvalonia.UI.Controls;
using LanMountainDesktop.Launcher.Resources;
using LanMountainDesktop.Launcher.Services;
namespace LanMountainDesktop.Launcher.Views;
@@ -36,7 +37,7 @@ public partial class ErrorWindow : Window
public void SetErrorMessage(string message)
{
var normalizedMessage = string.IsNullOrWhiteSpace(message)
? "LanMountain Desktop did not reach the expected startup state."
? Strings.Error_MessageNotReached
: message.Trim();
var firstLine = normalizedMessage
.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries)
@@ -58,16 +59,16 @@ public partial class ErrorWindow : Window
_isDebugMode = isDebugMode;
if (isDebugMode && this.FindControl<TextBlock>("TitleText") is { } titleText)
{
titleText.Text = "[Debug] Launcher error";
titleText.Text = Strings.Error_DebugTitle;
}
}
public void ConfigureForHostNotFound()
{
ApplyActionLayout(
title: "Launcher could not find the desktop executable",
suggestion: "Pick another executable in debug mode, inspect logs, or retry after fixing the deployment path.",
primaryLabel: "Retry",
title: Strings.Error_HostNotFoundTitle,
suggestion: Strings.Error_HostNotFoundMessage,
primaryLabel: Strings.Error_ButtonRetry,
primaryAction: ErrorWindowResult.Retry,
secondaryLabel: null,
secondaryAction: null);
@@ -76,25 +77,27 @@ public partial class ErrorWindow : Window
public void ConfigureForGenericFailure(bool allowRetry)
{
ApplyActionLayout(
title: "Launcher could not confirm startup",
title: Strings.Error_TitleCannotConfirm,
suggestion: allowRetry
? "Inspect logs, then retry once the previous startup attempt has fully finished."
: "Inspect logs or exit. Launcher will avoid creating another desktop process while the old one is still running.",
primaryLabel: allowRetry ? "Retry" : "Activate",
? Strings.Error_GenericRetryMessage
: Strings.Error_GenericNoRetryMessage,
primaryLabel: allowRetry ? Strings.Error_ButtonRetry : Strings.Error_ButtonActivate,
primaryAction: allowRetry ? ErrorWindowResult.Retry : ErrorWindowResult.ActivateExisting,
secondaryLabel: allowRetry ? null : "Wait",
secondaryLabel: allowRetry ? null : Strings.Error_ButtonWait,
secondaryAction: allowRetry ? null : ErrorWindowResult.ContinueWaiting);
}
public void ConfigureForRunningHostFailure(int? hostPid)
{
var pidHint = hostPid is > 0 ? $" Current host PID: {hostPid}." : string.Empty;
var suggestion = hostPid is > 0
? string.Format(Strings.Error_PendingMessageWithPid, hostPid)
: Strings.Error_PendingMessage;
ApplyActionLayout(
title: "Startup is still pending",
suggestion: $"The desktop process is still running, so Launcher will not start a second instance.{pidHint}",
primaryLabel: "Activate",
title: Strings.Error_PendingTitle,
suggestion: suggestion,
primaryLabel: Strings.Error_ButtonActivate,
primaryAction: ErrorWindowResult.ActivateExisting,
secondaryLabel: "Wait",
secondaryLabel: Strings.Error_ButtonWait,
secondaryAction: ErrorWindowResult.ContinueWaiting);
}

View File

@@ -1,13 +1,15 @@
<Window xmlns="https://github.com/avaloniaui"
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d"
d:DesignWidth="600"
d:DesignHeight="500"
x:Class="LanMountainDesktop.Launcher.Views.LoadingDetailsWindow"
Title="LanMountain Desktop - Loading Details"
x:CompileBindings="False"
Title="{x:Static res:Strings.Loading_Title}"
Width="600"
Height="500"
WindowStartupLocation="CenterScreen"
@@ -23,12 +25,12 @@
Padding="20,16">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Starting LanMountain Desktop"
<TextBlock Text="{x:Static res:Strings.Loading_StartingDesktop}"
FontSize="18"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"/>
<TextBlock x:Name="SubtitleText"
Text="Initializing..."
Text="{x:Static res:Strings.Loading_StatusInitializing}"
FontSize="13"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"/>
</StackPanel>
@@ -86,14 +88,14 @@
<TextBlock x:Name="CurrentItemName"
Grid.Row="0" Grid.Column="1"
Text="Initializing..."
Text="{x:Static res:Strings.Loading_StatusInitializing}"
FontSize="15"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"/>
<TextBlock x:Name="CurrentItemDescription"
Grid.Row="1" Grid.Column="1"
Text="Preparing components"
Text="{x:Static res:Strings.Loading_StatusPreparing}"
FontSize="13"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Margin="0,4,0,0"/>
@@ -115,7 +117,7 @@
<Grid RowDefinitions="Auto,*">
<Grid Grid.Row="0" Margin="12,8" ColumnDefinitions="*,Auto,Auto">
<TextBlock Grid.Column="0"
Text="Loading Items"
Text="{x:Static res:Strings.Loading_LoadingItems}"
FontSize="12"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"/>
@@ -126,7 +128,7 @@
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Margin="0,0,4,0"/>
<TextBlock Grid.Column="2"
Text="Done"
Text="{x:Static res:Strings.Loading_Done}"
FontSize="12"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"/>
</Grid>
@@ -199,7 +201,7 @@
VerticalAlignment="Center"/>
<TextBlock x:Name="ErrorText"
Grid.Column="1"
Text="An error occurred while loading."
Text="{x:Static res:Strings.Loading_ErrorOccurred}"
FontSize="13"
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
TextWrapping="Wrap"/>
@@ -218,12 +220,12 @@
VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="8">
<Button x:Name="DetailsButton"
Content="Details"
Content="{x:Static res:Strings.Loading_ButtonDetails}"
Width="90"
Height="32"
FontSize="13"/>
<Button x:Name="CancelButton"
Content="Cancel"
Content="{x:Static res:Strings.Loading_ButtonCancel}"
Width="90"
Height="32"
FontSize="13"/>

View File

@@ -3,6 +3,7 @@ using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Threading;
using LanMountainDesktop.Launcher.Resources;
using LanMountainDesktop.Launcher.Services;
using LanMountainDesktop.Shared.Contracts.Launcher;
using System.Collections.ObjectModel;
@@ -57,7 +58,7 @@ public partial class LoadingDetailsWindow : Window
}
/// <summary>
/// 鏇存柊鍔犺浇鐘舵€? /// </summary>
/// 更新加载状<EFBFBD>? /// </summary>
public void UpdateLoadingState(LoadingStateMessage state)
{
Dispatcher.UIThread.Post(() =>
@@ -120,7 +121,7 @@ public partial class LoadingDetailsWindow : Window
}
/// <summary>
/// 鏇存柊褰撳墠娲诲姩椤? /// </summary>
/// 更新当前活动<EFBFBD>? /// </summary>
private void UpdateCurrentItem(LoadingStateMessage state)
{
var currentItem = state.ActiveItems.FirstOrDefault();
@@ -181,7 +182,7 @@ public partial class LoadingDetailsWindow : Window
}
}
// 鎸夌姸鎬佹帓搴忥細杩涜<EFBFBD>涓?-> 绛夊緟涓?-> 宸插畬鎴?-> 澶辫触
// 按状态排序进行<EFBFBD>?-> 等待<E7AD89>?-> 已完<E5B7B2>?-> 失败
var sortedItems = _items.OrderBy(i => GetStatePriority(i.State)).ToList();
_items.Clear();
foreach (var item in sortedItems)
@@ -234,20 +235,20 @@ public partial class LoadingDetailsWindow : Window
/// </summary>
private static string GetStageDescription(StartupStage stage) => stage switch
{
StartupStage.Initializing => "正在初始化系统...",
StartupStage.LoadingSettings => "正在加载设置...",
StartupStage.LoadingPlugins => "正在加载插件...",
StartupStage.InitializingUI => "正在初始化界面...",
StartupStage.ShellInitialized => "桌面外壳已初始化",
StartupStage.DesktopVisible => "桌面已经可见",
StartupStage.ActivationRedirected => "已激活现有实例",
StartupStage.ActivationFailed => "现有实例激活失败",
StartupStage.Ready => "加载完成",
_ => "正在加载..."
StartupStage.Initializing => "正在初始化系统...",
StartupStage.LoadingSettings => "正在加载设置...",
StartupStage.LoadingPlugins => "正在加载插件...",
StartupStage.InitializingUI => "正在初始化界面...",
StartupStage.ShellInitialized => "桌面程序已初始化",
StartupStage.DesktopVisible => "桌面已经可见",
StartupStage.ActivationRedirected => "已激活现有实例",
StartupStage.ActivationFailed => "激活现有实例失败",
StartupStage.Ready => Strings.Loading_StageReady,
_ => "正在加载..."
};
/// <summary>
/// 鑾峰彇椤规弿杩? /// </summary>
/// 获取项描<EFBFBD>? /// </summary>
private static string GetItemDescription(LoadingItem item)
{
if (!string.IsNullOrEmpty(item.Description))
@@ -255,17 +256,17 @@ public partial class LoadingDetailsWindow : Window
return item.Type switch
{
LoadingItemType.Plugin => "姝e湪鍔犺浇鎻掍欢...",
LoadingItemType.Component => "姝e湪鍔犺浇缁勪欢...",
LoadingItemType.Resource => "姝e湪鍔犺浇璧勬簮...",
LoadingItemType.Data => "姝e湪鍔犺浇鏁版嵁...",
LoadingItemType.Network => "姝e湪涓嬭浇...",
_ => "姝e湪澶勭悊..."
LoadingItemType.Plugin => Strings.Loading_ItemPlugin,
LoadingItemType.Component => Strings.Loading_ItemComponent,
LoadingItemType.Resource => Strings.Loading_ItemResource,
LoadingItemType.Data => Strings.Loading_ItemData,
LoadingItemType.Network => Strings.Loading_ItemDownload,
_ => Strings.Loading_ItemProcess
};
}
/// <summary>
/// 鑾峰彇椤瑰浘鏍? /// </summary>
/// 获取项图<EFBFBD>? /// </summary>
private static string GetItemIcon(LoadingItemType type) => type switch
{
LoadingItemType.Plugin => "\uE768",
@@ -294,7 +295,7 @@ public partial class LoadingDetailsWindow : Window
}
/// <summary>
/// 鍔犺浇椤硅<EFBFBD>鍥炬ā鍨?/// </summary>
/// 加载项视图模<EFBFBD>?/// </summary>
public class LoadingItemViewModel : INotifyPropertyChanged
{
public string Id { get; }
@@ -306,7 +307,7 @@ public class LoadingItemViewModel : INotifyPropertyChanged
public string StatusIcon => GetStatusIcon(State);
public IBrush StatusColor => GetStatusColor(State);
public string ProgressText => State == LoadingState.Completed ? "瀹屾垚" : $"{ProgressPercent}%";
public string ProgressText => State == LoadingState.Completed ? Strings.Loading_ItemComplete : $"{ProgressPercent}%";
public string TypeLabel => GetTypeLabel(Type);
public IBrush TypeBackground => GetTypeBackground(Type);
public IBrush TypeForeground => GetTypeForeground(Type);
@@ -359,14 +360,14 @@ public class LoadingItemViewModel : INotifyPropertyChanged
private static string GetTypeLabel(LoadingItemType type) => type switch
{
LoadingItemType.Plugin => "鎻掍欢",
LoadingItemType.Component => "缁勪欢",
LoadingItemType.Resource => "璧勬簮",
LoadingItemType.Data => "鏁版嵁",
LoadingItemType.Network => "缃戠粶",
LoadingItemType.Settings => "璁剧疆",
LoadingItemType.System => "绯荤粺",
_ => "鍏朵粬"
LoadingItemType.Plugin => Strings.Loading_TypePlugin,
LoadingItemType.Component => Strings.Loading_TypeComponent,
LoadingItemType.Resource => Strings.Loading_TypeResource,
LoadingItemType.Data => Strings.Loading_TypeData,
LoadingItemType.Network => Strings.Loading_TypeNetwork,
LoadingItemType.Settings => Strings.Loading_TypeSettings,
LoadingItemType.System => Strings.Loading_TypeSystem,
_ => Strings.Loading_TypeOther
};
private static IBrush GetTypeBackground(LoadingItemType type) => type switch

View File

@@ -3,12 +3,14 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d"
d:DesignWidth="520"
d:DesignHeight="360"
x:Class="LanMountainDesktop.Launcher.Views.MigrationPromptWindow"
x:DataType="views:MigrationPromptWindow"
Title="阑山桌面 - 版本迁移"
x:CompileBindings="False"
Title="{x:Static res:Strings.Migration_Title}"
Width="520"
Height="360"
CanResize="False"
@@ -51,7 +53,7 @@
<!-- 说明文字 -->
<TextBlock x:Name="DescriptionText"
Text="检测到您的系统中安装了旧版本的阑山桌面0.8.4)。新版本采用了全新的架构,建议卸载旧版本以获得更好的体验。"
Text="{x:Static res:Strings.Migration_DetectedDesc}"
FontSize="14"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap"
@@ -65,7 +67,7 @@
<Grid RowDefinitions="Auto,Auto,Auto" ColumnDefinitions="Auto,*">
<!-- 版本号 -->
<TextBlock Grid.Row="0" Grid.Column="0"
Text="版本:"
Text="{x:Static res:Strings.Migration_Version}"
FontSize="12"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"/>
<TextBlock x:Name="VersionText"
@@ -77,7 +79,7 @@
<!-- 安装路径 -->
<TextBlock Grid.Row="1" Grid.Column="0"
Text="位置:"
Text="{x:Static res:Strings.Migration_Location}"
FontSize="12"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
Margin="0,4,0,0"/>
@@ -91,13 +93,13 @@
<!-- 安装类型 -->
<TextBlock Grid.Row="2" Grid.Column="0"
Text="类型:"
Text="{x:Static res:Strings.Migration_Type}"
FontSize="12"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
Margin="0,4,0,0"/>
<TextBlock x:Name="TypeText"
Grid.Row="2" Grid.Column="1"
Text="安装版"
Text="{x:Static res:Strings.Migration_Installed}"
FontSize="12"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
Margin="8,4,0,0"/>
@@ -105,7 +107,7 @@
</Border>
<!-- 提示信息 -->
<TextBlock Text="卸载旧版本不会影响新版本的使用,您的个人数据将保留。"
<TextBlock Text="{x:Static res:Strings.Migration_UninstallNote}"
FontSize="12"
Foreground="{DynamicResource TextFillColorTertiaryBrush}"
TextWrapping="Wrap"
@@ -121,7 +123,7 @@
<!-- 左侧:查看位置按钮 -->
<Button x:Name="ShowLocationButton"
Grid.Column="0"
Content="查看位置"
Content="{x:Static res:Strings.Migration_ButtonViewLocation}"
Width="100"
Height="32"
FontSize="13"
@@ -137,7 +139,7 @@
Height="32"
FontSize="13"/>
<Button x:Name="UninstallButton"
Content="卸载旧版本"
Content="{x:Static res:Strings.Migration_ButtonUninstall}"
Width="100"
Height="32"
FontSize="13"

View File

@@ -1,6 +1,7 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using LanMountainDesktop.Launcher.Resources;
using LanMountainDesktop.Launcher.Services;
namespace LanMountainDesktop.Launcher.Views;
@@ -46,15 +47,15 @@ public partial class MigrationPromptWindow : Window
{
typeText.Text = info.InstallType switch
{
LegacyInstallType.Registry => "安装版",
LegacyInstallType.Portable => "便携版",
_ => "未知"
LegacyInstallType.Registry => Strings.Migration_Installed,
LegacyInstallType.Portable => Strings.Migration_Portable,
_ => Strings.Migration_Unknown
};
}
if (descriptionText != null)
{
descriptionText.Text = $"检测到您的系统中安装了旧版本的阑山桌面({info.Version})。新版本采用了全新的架构,建议卸载旧版本以获得更好的体验。";
descriptionText.Text = string.Format(Strings.Migration_DetectedDescFormat, info.Version);
}
}

View File

@@ -5,10 +5,12 @@
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:fi="using:FluentIcons.Avalonia"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d"
x:Class="LanMountainDesktop.Launcher.Views.MultiInstancePromptWindow"
x:DataType="views:MultiInstancePromptWindow"
Title="LanMountain Desktop"
x:CompileBindings="False"
Title="{x:Static res:Strings.MultiInstance_Title}"
Width="620"
Height="360"
MinWidth="560"
@@ -44,13 +46,13 @@
<StackPanel Grid.Column="1"
Spacing="8">
<TextBlock Text="LanMountain Desktop is already running"
<TextBlock Text="{x:Static res:Strings.MultiInstance_AlreadyRunning}"
FontSize="22"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
TextWrapping="Wrap" />
<TextBlock x:Name="MessageText"
Text="Launcher found an existing desktop instance and did not start another process."
Text="{x:Static res:Strings.MultiInstance_AlreadyRunningMessage}"
FontSize="14"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap"
@@ -64,8 +66,8 @@
IsOpen="True"
IsClosable="False"
Severity="Informational"
Title="Repeated launch"
Message="Your current setting is to show this prompt without opening the desktop automatically.">
Title="{x:Static res:Strings.MultiInstance_RepeatedLaunchTitle}"
Message="{x:Static res:Strings.MultiInstance_RepeatedLaunchMessage}">
<ui:FAInfoBar.IconSource>
<ui:FAFontIconSource Glyph="&#xF0288;"
FontFamily="avares://fluenticons.resources.avalonia/Assets#Seagull Fluent Icons" />
@@ -79,7 +81,7 @@
FontSize="12"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap"
Text="No second Host process was created." />
Text="{x:Static res:Strings.MultiInstance_NoSecondProcess}" />
</Grid>
<Border Grid.Row="1"
@@ -93,7 +95,7 @@
HorizontalAlignment="Left">
<StackPanel Orientation="Horizontal" Spacing="6">
<fi:SymbolIcon Symbol="Copy" IconVariant="Regular" FontSize="16"/>
<TextBlock Text="Copy"/>
<TextBlock Text="{x:Static res:Strings.MultiInstance_ButtonCopy}"/>
</StackPanel>
</Button>
@@ -105,7 +107,7 @@
Height="34">
<StackPanel Orientation="Horizontal" Spacing="6">
<fi:SymbolIcon Symbol="Dismiss" IconVariant="Regular" FontSize="16"/>
<TextBlock Text="Close"/>
<TextBlock Text="{x:Static res:Strings.MultiInstance_ButtonClose}"/>
</StackPanel>
</Button>
<Button x:Name="OpenDesktopButton"
@@ -114,7 +116,7 @@
Height="34">
<StackPanel Orientation="Horizontal" Spacing="6">
<fi:SymbolIcon Symbol="ArrowRight" IconVariant="Regular" FontSize="16"/>
<TextBlock Text="Open desktop"/>
<TextBlock Text="{x:Static res:Strings.MultiInstance_ButtonOpenDesktop}"/>
</StackPanel>
</Button>
</StackPanel>

View File

@@ -2,6 +2,7 @@ using Avalonia.Controls;
using Avalonia.Input.Platform;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using LanMountainDesktop.Launcher.Resources;
namespace LanMountainDesktop.Launcher.Views;
@@ -9,7 +10,7 @@ public partial class MultiInstancePromptWindow : Window
{
private readonly TaskCompletionSource<MultiInstancePromptResult> _completionSource =
new(TaskCreationOptions.RunContinuationsAsynchronously);
private string _details = "LanMountain Desktop is already running.";
private string _details = Strings.MultiInstance_AlreadyRunning;
public MultiInstancePromptWindow()
{
@@ -22,7 +23,7 @@ public partial class MultiInstancePromptWindow : Window
public void SetDetails(int processId, string shellState)
{
_details = $"Existing host PID: {processId}\nShell state: {shellState}\nNo second Host process was created.";
_details = string.Format(Strings.MultiInstance_DetailsFormat, processId, shellState);
if (this.FindControl<TextBlock>("DetailsText") is { } detailsText)
{

View File

@@ -5,12 +5,14 @@
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:fi="using:FluentIcons.Avalonia"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d"
d:DesignWidth="850"
d:DesignHeight="650"
x:Class="LanMountainDesktop.Launcher.Views.OobeWindow"
x:DataType="views:OobeWindow"
Title="欢迎使用阑山桌面"
x:CompileBindings="False"
Title="{x:Static res:Strings.Oobe_Title}"
Width="850"
Height="650"
CanResize="False"
@@ -149,7 +151,7 @@
<Button.RenderTransform>
<ScaleTransform ScaleX="0.1" ScaleY="0.1" />
</Button.RenderTransform>
<TextBlock Text="开始使用"
<TextBlock Text="{x:Static res:Strings.Oobe_ButtonGetStarted}"
FontSize="16"
FontWeight="SemiBold" />
</Button>
@@ -173,11 +175,11 @@
<!-- 步骤 2: 主题选择页面 -->
<Grid x:Name="ThemeStep" Margin="48" RowDefinitions="Auto,*,Auto" IsVisible="False">
<StackPanel Grid.Row="0" Spacing="8" Margin="0,0,0,24">
<TextBlock Text="个性化你的桌面"
<TextBlock Text="{x:Static res:Strings.Oobe_AppearanceTitle}"
FontSize="24"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="选择你喜欢的主题样式,可随时在设置中更改"
<TextBlock Text="{x:Static res:Strings.Oobe_AppearanceDesc}"
FontSize="13"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
</StackPanel>
@@ -189,7 +191,7 @@
CornerRadius="{DynamicResource DesignCornerRadiusMd}"
Padding="16">
<StackPanel Spacing="12">
<TextBlock Text="外观模式"
<TextBlock Text="{x:Static res:Strings.Oobe_AppearanceMode}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
@@ -215,7 +217,7 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<TextBlock Text="浅色模式"
<TextBlock Text="{x:Static res:Strings.Oobe_LightMode}"
FontSize="13"
HorizontalAlignment="Center"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
@@ -247,7 +249,7 @@
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<TextBlock Text="深色模式"
<TextBlock Text="{x:Static res:Strings.Oobe_DarkMode}"
FontSize="13"
HorizontalAlignment="Center"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
@@ -265,7 +267,7 @@
CornerRadius="{DynamicResource DesignCornerRadiusMd}"
Padding="16">
<StackPanel Spacing="12">
<TextBlock Text="主题色"
<TextBlock Text="{x:Static res:Strings.Oobe_ThemeColor}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
@@ -335,11 +337,11 @@
CornerRadius="{DynamicResource DesignCornerRadiusMd}"
Padding="16">
<StackPanel Spacing="12">
<TextBlock Text="莫奈取色来源"
<TextBlock Text="{x:Static res:Strings.Oobe_MonetSource}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="从壁纸自动提取主题色,让界面与桌面完美融合"
<TextBlock Text="{x:Static res:Strings.Oobe_MonetDesc}"
FontSize="12"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -359,11 +361,11 @@
VerticalAlignment="Center"
Margin="0,0,12,0" />
<StackPanel Grid.Column="1" Spacing="4">
<TextBlock Text="从桌面壁纸取色"
<TextBlock Text="{x:Static res:Strings.Oobe_MonetFromWallpaper}"
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="自动分析当前壁纸颜色生成主题"
<TextBlock Text="{x:Static res:Strings.Oobe_MonetFromWallpaperDesc}"
FontSize="11"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
</StackPanel>
@@ -384,11 +386,11 @@
VerticalAlignment="Center"
Margin="0,0,12,0" />
<StackPanel Grid.Column="1" Spacing="4">
<TextBlock Text="自定义图片取色"
<TextBlock Text="{x:Static res:Strings.Oobe_MonetFromCustomImage}"
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="选择一张图片作为取色来源"
<TextBlock Text="{x:Static res:Strings.Oobe_MonetFromCustomImageDesc}"
FontSize="11"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
</StackPanel>
@@ -409,11 +411,11 @@
VerticalAlignment="Center"
Margin="0,0,12,0" />
<StackPanel Grid.Column="1" Spacing="4">
<TextBlock Text="不使用莫奈取色"
<TextBlock Text="{x:Static res:Strings.Oobe_MonetDisabled}"
FontSize="13"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="使用固定的预设主题色"
<TextBlock Text="{x:Static res:Strings.Oobe_MonetDisabledDesc}"
FontSize="11"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
</StackPanel>
@@ -431,10 +433,10 @@
Spacing="12"
Margin="0,24,0,0">
<Button x:Name="ThemeBackButton"
Content="返回"
Content="{x:Static res:Strings.Oobe_ButtonBack}"
Theme="{DynamicResource ButtonTheme}" />
<Button x:Name="ThemeNextButton"
Content="下一步"
Content="{x:Static res:Strings.Oobe_ButtonNext}"
Theme="{DynamicResource AccentButtonTheme}" />
</StackPanel>
</Grid>
@@ -442,11 +444,11 @@
<!-- 步骤 3: 数据位置选择页面 -->
<Grid x:Name="DataLocationStep" Margin="48" RowDefinitions="Auto,*,Auto" IsVisible="False">
<StackPanel Grid.Row="0" Spacing="8" Margin="0,0,0,32">
<TextBlock Text="选择数据保存位置"
<TextBlock Text="{x:Static res:Strings.Oobe_DataLocationTitle}"
FontSize="28"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="决定将应用数据保存在哪里,可随时在设置中更改"
<TextBlock Text="{x:Static res:Strings.Oobe_DataLocationDesc}"
FontSize="14"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
</StackPanel>
@@ -462,12 +464,12 @@
<fi:SymbolIcon Symbol="ShieldError"
FontSize="20"
Foreground="{DynamicResource SystemFillColorCriticalBrush}" />
<TextBlock Text="无法保存到应用目录"
<TextBlock Text="{x:Static res:Strings.Oobe_NotWritable}"
FontWeight="SemiBold"
FontSize="14"
Foreground="{DynamicResource SystemFillColorCriticalBrush}" />
</StackPanel>
<TextBlock Text="当前安装目录需要管理员权限才能写入,数据将自动保存到系统用户目录。"
<TextBlock Text="{x:Static res:Strings.Oobe_NotWritableDesc}"
FontSize="13"
TextWrapping="Wrap"
Foreground="{DynamicResource SystemFillColorCriticalBrush}" />
@@ -494,12 +496,12 @@
<fi:SymbolIcon Symbol="Folder"
FontSize="24"
Foreground="{DynamicResource AccentFillColorDefaultBrush}" />
<TextBlock Text="保存在系统用户目录(推荐)"
<TextBlock Text="{x:Static res:Strings.Oobe_SystemProfile}"
FontSize="16"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
</StackPanel>
<TextBlock Text="数据与当前 Windows 用户绑定,重装应用或更新后数据不会丢失。适合大多数用户。"
<TextBlock Text="{x:Static res:Strings.Oobe_SystemProfileDesc}"
FontSize="13"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -537,12 +539,12 @@
<fi:SymbolIcon Symbol="Save"
FontSize="24"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
<TextBlock Text="保存在应用安装目录(便携模式)"
<TextBlock Text="{x:Static res:Strings.Oobe_Portable}"
FontSize="16"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
</StackPanel>
<TextBlock Text="便于携带,可随应用文件夹整体移动到其他电脑。适合在多台电脑间使用或需要便携运行的场景。"
<TextBlock Text="{x:Static res:Strings.Oobe_PortableDesc}"
FontSize="13"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -584,12 +586,12 @@
Spacing="12"
Margin="0,32,0,0">
<Button x:Name="DataLocationBackButton"
Content="返回"
Content="{x:Static res:Strings.Oobe_ButtonBack}"
Theme="{DynamicResource ButtonTheme}"
Width="100"
Height="36" />
<Button x:Name="DataLocationNextButton"
Content="下一步"
Content="{x:Static res:Strings.Oobe_ButtonNext}"
Theme="{DynamicResource AccentButtonTheme}"
Width="100"
Height="36" />
@@ -599,11 +601,11 @@
<!-- 步骤 4: 启动与展示(紧接数据保存位置) -->
<Grid x:Name="StartupPresentationStep" Margin="48" RowDefinitions="Auto,*,Auto" IsVisible="False">
<StackPanel Grid.Row="0" Spacing="8" Margin="0,0,0,16">
<TextBlock Text="启动与展示"
<TextBlock Text="{x:Static res:Strings.Oobe_StartupTitle}"
FontSize="24"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="这些选项可随时在桌面应用的「设置」中更改。主窗口滑动入场仅在 Windows 上可用。"
<TextBlock Text="{x:Static res:Strings.Oobe_StartupDesc}"
FontSize="13"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -616,11 +618,11 @@
Padding="16">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="在任务栏显示主桌面窗口"
<TextBlock Text="{x:Static res:Strings.Oobe_ShowInTaskbar}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="开启后最小化时可在任务栏保留条目;关闭则更多依赖托盘图标。"
<TextBlock Text="{x:Static res:Strings.Oobe_ShowInTaskbarDesc}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -638,11 +640,11 @@
<StackPanel Spacing="12">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="以滑动方式显示主窗口"
<TextBlock Text="{x:Static res:Strings.Oobe_SlideTransition}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="自屏幕边缘滑入;与「淡入」二选一。"
<TextBlock Text="{x:Static res:Strings.Oobe_SlideTransitionDesc}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -653,11 +655,11 @@
</Grid>
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="启动时使用淡入过渡"
<TextBlock Text="{x:Static res:Strings.Oobe_FadeTransition}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="在未启用滑动入场时建议使用。"
<TextBlock Text="{x:Static res:Strings.Oobe_FadeTransitionDesc}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -678,12 +680,12 @@
<fi:SymbolIcon Symbol="SlideLayout"
FontSize="20"
Foreground="{DynamicResource AccentFillColorDefaultBrush}" />
<TextBlock Text="融合桌面与弹入手势"
<TextBlock Text="{x:Static res:Strings.Oobe_FusedDesktop}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
</StackPanel>
<TextBlock Text="同时启用融合桌面与三指滑动手势,以便使用边缘弹入与相关实验特性(与设置中开发者选项一致)。"
<TextBlock Text="{x:Static res:Strings.Oobe_FusedDesktopDesc}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -699,12 +701,12 @@
Padding="16">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="登录 Windows 时自动启动阑山桌面"
<TextBlock Text="{x:Static res:Strings.Oobe_AutoStart}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock x:Name="OobeAutoStartDescriptionText"
Text="通过当前用户的启动项注册本启动器(与安装程序可选任务使用同一注册表项)。"
Text="{x:Static res:Strings.Oobe_AutoStartDesc}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -723,10 +725,10 @@
Spacing="12"
Margin="0,24,0,0">
<Button x:Name="StartupPresentationBackButton"
Content="返回"
Content="{x:Static res:Strings.Oobe_ButtonBack}"
Theme="{DynamicResource ButtonTheme}" />
<Button x:Name="StartupPresentationNextButton"
Content="下一步"
Content="{x:Static res:Strings.Oobe_ButtonNext}"
Theme="{DynamicResource AccentButtonTheme}" />
</StackPanel>
</Grid>
@@ -734,11 +736,11 @@
<!-- 步骤 5: 信息与隐私页面 -->
<Grid x:Name="PrivacyStep" Margin="48" RowDefinitions="Auto,*,Auto" IsVisible="False">
<StackPanel Grid.Row="0" Spacing="8" Margin="0,0,0,24">
<TextBlock Text="信息与隐私"
<TextBlock Text="{x:Static res:Strings.Oobe_PrivacyTitle}"
FontSize="24"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="选择是否参与遥测计划,查看隐私政策"
<TextBlock Text="{x:Static res:Strings.Oobe_PrivacyDesc}"
FontSize="13"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
</StackPanel>
@@ -750,11 +752,11 @@
Padding="16">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="发送匿名崩溃报告"
<TextBlock Text="{x:Static res:Strings.Oobe_CrashReports}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="帮助改进应用稳定性,不包含个人身份信息"
<TextBlock Text="{x:Static res:Strings.Oobe_CrashReportsDesc}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -773,11 +775,11 @@
Padding="16">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="发送匿名使用统计"
<TextBlock Text="{x:Static res:Strings.Oobe_UsageStats}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="帮助了解功能使用情况,优化产品体验"
<TextBlock Text="{x:Static res:Strings.Oobe_UsageStatsDesc}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -795,11 +797,11 @@
CornerRadius="{DynamicResource DesignCornerRadiusMd}"
Padding="16">
<StackPanel Spacing="8">
<TextBlock Text="隐私追踪 ID"
<TextBlock Text="{x:Static res:Strings.Oobe_PrivacyTrackingId}"
FontSize="14"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="此 ID 用于匿名标识您的设备,不包含任何个人信息"
<TextBlock Text="{x:Static res:Strings.Oobe_PrivacyTrackingIdDesc}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -823,12 +825,12 @@
<CheckBox x:Name="PrivacyAgreementCheckBox"
VerticalAlignment="Center" />
<StackPanel Orientation="Horizontal" Spacing="4" VerticalAlignment="Center">
<TextBlock Text="同意"
<TextBlock Text="{x:Static res:Strings.Oobe_Agree}"
FontSize="13"
VerticalAlignment="Center"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<Button x:Name="ViewPrivacyPolicyButton"
Content="《阑山桌面遥测隐私数据收集协议》"
Content="{x:Static res:Strings.Oobe_PrivacyPolicyLink}"
Background="Transparent"
BorderThickness="0"
Padding="0"
@@ -844,7 +846,7 @@
</StackPanel>
<!-- 提示文本 -->
<TextBlock Text="您必须阅读并同意隐私协议后,才能开启遥测功能。遥测数据仅用于改进应用稳定性和优化产品体验,不包含任何个人身份信息。"
<TextBlock Text="{x:Static res:Strings.Oobe_PrivacyAgreementNote}"
FontSize="12"
TextWrapping="Wrap"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
@@ -858,10 +860,10 @@
Spacing="12"
Margin="0,24,0,0">
<Button x:Name="PrivacyBackButton"
Content="返回"
Content="{x:Static res:Strings.Oobe_ButtonBack}"
Theme="{DynamicResource ButtonTheme}" />
<Button x:Name="PrivacyNextButton"
Content="下一步"
Content="{x:Static res:Strings.Oobe_ButtonNext}"
Theme="{DynamicResource AccentButtonTheme}" />
</StackPanel>
</Grid>
@@ -887,12 +889,12 @@
</Border>
<StackPanel Spacing="12" HorizontalAlignment="Center">
<TextBlock Text="欢迎使用阑山桌面"
<TextBlock Text="{x:Static res:Strings.Oobe_CompleteTitle}"
FontSize="32"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
HorizontalAlignment="Center" />
<TextBlock Text="你的桌面,不止一面"
<TextBlock Text="{x:Static res:Strings.Oobe_CompleteSubtitle}"
FontSize="16"
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
HorizontalAlignment="Center" />

View File

@@ -7,6 +7,7 @@ using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Threading;
using LanMountainDesktop.Launcher.Models;
using LanMountainDesktop.Launcher.Resources;
using LanMountainDesktop.Launcher.Services;
namespace LanMountainDesktop.Launcher.Views;
@@ -272,7 +273,7 @@ public partial class OobeWindow : Window
if (typingTextBlock == null || cursorBorder == null) return;
// 打字机效果:阑山桌面 LanMountain Desktop在同一行
var fullText = "阑山桌面 LanMountain Desktop";
var fullText = Strings.Oobe_TypingAppName;
for (int i = 0; i <= fullText.Length; i++)
{
typingTextBlock.Text = fullText.Substring(0, i);
@@ -375,7 +376,7 @@ public partial class OobeWindow : Window
}
// 打字机效果:下一代
var nextGenText = "下一代";
var nextGenText = Strings.Oobe_TypingNextGen;
for (int i = 0; i <= nextGenText.Length; i++)
{
nextGenTextBlock.Text = nextGenText.Substring(0, i);
@@ -392,7 +393,7 @@ public partial class OobeWindow : Window
}
// 打字机效果:互动信息看板
var dashboardText = "互动信息看板";
var dashboardText = Strings.Oobe_TypingDashboard;
for (int i = 0; i <= dashboardText.Length; i++)
{
dashboardTextBlock.Text = dashboardText.Substring(0, i);
@@ -531,8 +532,8 @@ public partial class OobeWindow : Window
if (this.FindControl<TextBlock>("OobeAutoStartDescriptionText") is { } autoStartDesc)
{
autoStartDesc.Text = OperatingSystem.IsWindows()
? "通过当前用户的启动项注册本启动器(与安装程序可选任务使用同一注册表项)。"
: "当前平台仅保存偏好;是否随系统自启动请使用系统提供的应用自启动设置。";
? Strings.Oobe_AutoStartDesc
: Strings.Oobe_AutoStartDescNonWindows;
}
_suppressOobeStartupTransitionHandlers = true;
@@ -770,7 +771,7 @@ public partial class OobeWindow : Window
}
if (this.FindControl<TextBlock>("MigrationInfoText") is { } migrationText)
{
migrationText.Text = "检测到现有数据,选择便携模式时将自动迁移。";
migrationText.Text = Strings.Oobe_MigrationDetected;
}
}
}

View File

@@ -4,10 +4,12 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:md="clr-namespace:Markdown.Avalonia;assembly=Markdown.Avalonia"
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d"
x:Class="LanMountainDesktop.Launcher.Views.PrivacyPolicyWindow"
x:DataType="views:PrivacyPolicyViewModel"
Title="阑山桌面遥测隐私数据收集协议"
x:CompileBindings="False"
Title="{x:Static res:Strings.Privacy_Title}"
Width="800"
Height="600"
MinWidth="600"
@@ -25,11 +27,11 @@
BorderThickness="0,0,0,1"
Padding="24,16">
<StackPanel Spacing="4">
<TextBlock Text="阑山桌面遥测隐私数据收集协议"
<TextBlock Text="{x:Static res:Strings.Privacy_Header}"
FontSize="20"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
<TextBlock Text="请仔细阅读以下协议内容,了解我们如何收集、使用和保护您的数据"
<TextBlock Text="{x:Static res:Strings.Privacy_Description}"
FontSize="13"
Foreground="{DynamicResource TextFillColorSecondaryBrush}" />
</StackPanel>
@@ -54,7 +56,7 @@
HorizontalAlignment="Right"
Spacing="12">
<Button x:Name="CloseButton"
Content="关闭"
Content="{x:Static res:Strings.Privacy_ButtonClose}"
Theme="{DynamicResource AccentButtonTheme}"
Width="100" />
</StackPanel>

View File

@@ -3,10 +3,12 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d"
x:Class="LanMountainDesktop.Launcher.Views.SplashWindow"
x:DataType="views:SplashWindow"
Title="LanMountain Desktop"
x:CompileBindings="False"
Title="{x:Static res:Strings.Splash_Title}"
Width="480"
Height="320"
CanResize="False"
@@ -66,7 +68,7 @@
FontSize="11"
Foreground="#B9C0CC"
HorizontalAlignment="Right"
Text="Initializing..." />
Text="{x:Static res:Strings.Splash_StatusInitializing}" />
</Grid>
<ProgressBar x:Name="ProgressIndicator"

View File

@@ -6,6 +6,7 @@ using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Threading;
using LanMountainDesktop.Launcher.Resources;
using LanMountainDesktop.Launcher.Services;
namespace LanMountainDesktop.Launcher.Views;
@@ -184,7 +185,7 @@ public partial class SplashWindow : Window, ISplashStageReporter
return;
}
UpdateStatus("[Debug Mode] Splash Preview");
UpdateStatus(Strings.Splash_DebugPreview);
}
private void OnVersionTextClick(object? sender, PointerPressedEventArgs e)

View File

@@ -3,12 +3,14 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:LanMountainDesktop.Launcher.Views"
xmlns:res="clr-namespace:LanMountainDesktop.Launcher.Resources"
mc:Ignorable="d"
d:DesignWidth="480"
d:DesignHeight="320"
x:Class="LanMountainDesktop.Launcher.Views.UpdateWindow"
x:DataType="views:UpdateWindow"
Title="阑山桌面 - 更新"
x:CompileBindings="False"
Title="{x:Static res:Strings.Update_Title}"
Width="480"
Height="320"
CanResize="False"
@@ -26,7 +28,7 @@
<Grid VerticalAlignment="Top" Margin="24,24,24,0">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center" Spacing="8">
<TextBlock x:Name="TitleText"
Text="阑山桌面"
Text="{x:Static res:Strings.Update_AppName}"
FontSize="24"
FontWeight="SemiBold"
Foreground="{DynamicResource TextFillColorPrimaryBrush}" />
@@ -34,7 +36,7 @@
CornerRadius="4"
Padding="6,2"
VerticalAlignment="Center">
<TextBlock Text="Update"
<TextBlock Text="{x:Static res:Strings.Update_StatusUpdate}"
FontSize="11"
FontWeight="SemiBold"
Foreground="{DynamicResource TextOnAccentFillColorPrimaryBrush}" />
@@ -80,7 +82,7 @@
Opacity="0.8"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Text="正在更新,请稍候..." />
Text="{x:Static res:Strings.Update_StatusUpdating}" />
<!-- 右下角:百分比 -->
<TextBlock x:Name="PercentText"

View File

@@ -1,6 +1,7 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using LanMountainDesktop.Launcher.Resources;
namespace LanMountainDesktop.Launcher.Views;
@@ -87,12 +88,12 @@ public partial class UpdateWindow : Window
if (success)
{
statusText.Text = "更新完成";
statusText.Text = Strings.Update_Complete;
}
else
{
titleText.Text = "更新失败";
statusText.Text = errorMessage ?? "更新过程中发生错误";
titleText.Text = Strings.Update_Failed;
statusText.Text = errorMessage ?? Strings.Update_FailedMessage;
}
});
}
@@ -115,8 +116,8 @@ public partial class UpdateWindow : Window
if (isDebugMode)
{
titleText.Text = "[调试模式] 更新页面";
statusText.Text = "预览更新进度界面";
titleText.Text = Strings.Update_DebugTitle;
statusText.Text = Strings.Update_DebugMessage;
}
});
}