mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 00:54:26 +08:00
fix.在线安装器,启动器
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
<SolidColorBrush x:Key="InstallerSurfaceAltBrush" Color="#F7F7F7" />
|
||||
<SolidColorBrush x:Key="InstallerSubtleFillBrush" Color="#F5F5F5" />
|
||||
<SolidColorBrush x:Key="InstallerSubtleFillHoverBrush" Color="#EFEFEF" />
|
||||
<SolidColorBrush x:Key="InstallerSubtleFillPressedBrush" Color="#E5E5E5" />
|
||||
<SolidColorBrush x:Key="InstallerBorderBrush" Color="#14000000" />
|
||||
<SolidColorBrush x:Key="InstallerStrongBorderBrush" Color="#29000000" />
|
||||
<SolidColorBrush x:Key="InstallerTextPrimaryBrush" Color="#1A1A1A" />
|
||||
@@ -47,6 +48,7 @@
|
||||
<SolidColorBrush x:Key="InstallerSurfaceAltBrush" Color="#252525" />
|
||||
<SolidColorBrush x:Key="InstallerSubtleFillBrush" Color="#333333" />
|
||||
<SolidColorBrush x:Key="InstallerSubtleFillHoverBrush" Color="#3A3A3A" />
|
||||
<SolidColorBrush x:Key="InstallerSubtleFillPressedBrush" Color="#444444" />
|
||||
<SolidColorBrush x:Key="InstallerBorderBrush" Color="#24FFFFFF" />
|
||||
<SolidColorBrush x:Key="InstallerStrongBorderBrush" Color="#3DFFFFFF" />
|
||||
<SolidColorBrush x:Key="InstallerTextPrimaryBrush" Color="#F3F3F3" />
|
||||
|
||||
@@ -2,6 +2,8 @@ namespace LanDesktopPLONDS.Installer.Services;
|
||||
|
||||
public static class InstallerPathGuard
|
||||
{
|
||||
public const string ApplicationDirectoryName = "LanMountainDesktop";
|
||||
|
||||
public static string GetDefaultInstallPath()
|
||||
{
|
||||
var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
|
||||
@@ -12,7 +14,29 @@ public static class InstallerPathGuard
|
||||
"Programs");
|
||||
}
|
||||
|
||||
return Path.Combine(programFiles, "LanMountainDesktop");
|
||||
return Path.Combine(programFiles, ApplicationDirectoryName);
|
||||
}
|
||||
|
||||
public static string GetInstallPathForSelectedFolder(string selectedFolder)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(selectedFolder))
|
||||
{
|
||||
throw new ArgumentException("Selected folder is required.", nameof(selectedFolder));
|
||||
}
|
||||
|
||||
var fullPath = Path.GetFullPath(selectedFolder.Trim());
|
||||
var root = Path.GetPathRoot(fullPath);
|
||||
var trimmedPath = fullPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
var trimmedRoot = root?.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
|
||||
var basePath = string.Equals(trimmedPath, trimmedRoot, StringComparison.OrdinalIgnoreCase)
|
||||
? fullPath
|
||||
: trimmedPath;
|
||||
var selectedName = Path.GetFileName(trimmedPath);
|
||||
var installPath = string.Equals(selectedName, ApplicationDirectoryName, StringComparison.OrdinalIgnoreCase)
|
||||
? trimmedPath
|
||||
: Path.Combine(basePath, ApplicationDirectoryName);
|
||||
|
||||
return NormalizeInstallPath(installPath);
|
||||
}
|
||||
|
||||
public static string NormalizeInstallPath(string path)
|
||||
|
||||
@@ -15,43 +15,9 @@ public sealed partial class InstallerStepViewModel(
|
||||
[ObservableProperty]
|
||||
private bool _isSelected;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isCompleted;
|
||||
|
||||
public InstallerStepId StepId { get; } = stepId;
|
||||
|
||||
public string Title { get; } = title;
|
||||
|
||||
public Icon Icon { get; } = icon;
|
||||
|
||||
public bool IsLocked => !IsUnlocked;
|
||||
|
||||
public Icon DisplayIcon => IsLocked
|
||||
? Icon.LockClosed
|
||||
: IsCompleted
|
||||
? Icon.CheckmarkCircle
|
||||
: Icon;
|
||||
|
||||
public bool IsAvailable => IsUnlocked && !IsSelected && !IsCompleted;
|
||||
|
||||
partial void OnIsUnlockedChanged(bool value)
|
||||
{
|
||||
_ = value;
|
||||
OnPropertyChanged(nameof(IsLocked));
|
||||
OnPropertyChanged(nameof(IsAvailable));
|
||||
OnPropertyChanged(nameof(DisplayIcon));
|
||||
}
|
||||
|
||||
partial void OnIsSelectedChanged(bool value)
|
||||
{
|
||||
_ = value;
|
||||
OnPropertyChanged(nameof(IsAvailable));
|
||||
}
|
||||
|
||||
partial void OnIsCompletedChanged(bool value)
|
||||
{
|
||||
_ = value;
|
||||
OnPropertyChanged(nameof(DisplayIcon));
|
||||
OnPropertyChanged(nameof(IsAvailable));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ public sealed partial class MainWindowViewModel : ObservableObject
|
||||
private readonly IPrivacyDeviceIdentityProvider _privacyIdentity;
|
||||
private readonly InstallerPrivacyConsentStore _privacyConsentStore;
|
||||
private CancellationTokenSource? _installCts;
|
||||
private bool _isNavigatingInternally;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyCanExecuteChangedFor(nameof(NextCommand))]
|
||||
@@ -72,9 +71,6 @@ public sealed partial class MainWindowViewModel : ObservableObject
|
||||
[ObservableProperty]
|
||||
private bool _createStartupShortcut;
|
||||
|
||||
[ObservableProperty]
|
||||
private InstallerStepViewModel? _selectedStep;
|
||||
|
||||
public MainWindowViewModel(
|
||||
IOnlineInstallService installService,
|
||||
IPrivacyDeviceIdentityProvider privacyIdentity,
|
||||
@@ -92,7 +88,6 @@ public sealed partial class MainWindowViewModel : ObservableObject
|
||||
new InstallerStepViewModel(InstallerStepId.Complete, "完成安装", Icon.Circle)
|
||||
];
|
||||
SyncSteps();
|
||||
SelectedStep = Steps[0];
|
||||
DeviceIdPreview = _privacyIdentity.GetOrCreateDeviceId();
|
||||
PrivacyConfirmed = _privacyConsentStore.HasConfirmed(DeviceIdPreview);
|
||||
}
|
||||
@@ -173,22 +168,6 @@ public sealed partial class MainWindowViewModel : ObservableObject
|
||||
OnPropertyChanged(nameof(CanStartInstall));
|
||||
}
|
||||
|
||||
partial void OnSelectedStepChanged(InstallerStepViewModel? value)
|
||||
{
|
||||
if (_isNavigatingInternally || value is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsInstalling && value.StepId <= MaxUnlockedStep)
|
||||
{
|
||||
CurrentStep = value.StepId;
|
||||
return;
|
||||
}
|
||||
|
||||
SyncSteps();
|
||||
}
|
||||
|
||||
[RelayCommand(CanExecute = nameof(CanGoNext))]
|
||||
private async Task NextAsync()
|
||||
{
|
||||
@@ -231,6 +210,17 @@ public sealed partial class MainWindowViewModel : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void SelectStep(InstallerStepViewModel? step)
|
||||
{
|
||||
if (step is null || IsInstalling || step.StepId > MaxUnlockedStep)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentStep = step.StepId;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task BrowseAsync()
|
||||
{
|
||||
@@ -245,7 +235,7 @@ public sealed partial class MainWindowViewModel : ObservableObject
|
||||
var selected = await BrowseRequested(InstallPath);
|
||||
if (!string.IsNullOrWhiteSpace(selected))
|
||||
{
|
||||
InstallPath = selected;
|
||||
InstallPath = InstallerPathGuard.GetInstallPathForSelectedFolder(selected);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -348,23 +338,10 @@ public sealed partial class MainWindowViewModel : ObservableObject
|
||||
|
||||
private void SyncSteps()
|
||||
{
|
||||
_isNavigatingInternally = true;
|
||||
try
|
||||
foreach (var step in Steps)
|
||||
{
|
||||
foreach (var step in Steps)
|
||||
{
|
||||
step.IsUnlocked = step.StepId <= MaxUnlockedStep;
|
||||
step.IsSelected = step.StepId == CurrentStep;
|
||||
step.IsCompleted = step.StepId < CurrentStep;
|
||||
if (step.StepId == CurrentStep && !ReferenceEquals(SelectedStep, step))
|
||||
{
|
||||
SelectedStep = step;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isNavigatingInternally = false;
|
||||
step.IsUnlocked = step.StepId <= MaxUnlockedStep;
|
||||
step.IsSelected = step.StepId == CurrentStep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
MinWidth="900"
|
||||
MinHeight="620"
|
||||
CanResize="True"
|
||||
x:Name="Root"
|
||||
Title="{Binding WindowTitle}"
|
||||
Background="{DynamicResource InstallerWindowBackgroundBrush}"
|
||||
Background="Transparent"
|
||||
TransparencyLevelHint="Mica, AcrylicBlur, None"
|
||||
ExtendClientAreaToDecorationsHint="True"
|
||||
ExtendClientAreaTitleBarHeightHint="48"
|
||||
WindowDecorations="None">
|
||||
@@ -23,40 +25,54 @@
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
<Setter Property="LineHeight" Value="20" />
|
||||
</Style>
|
||||
<Style Selector="ListBox.step-list">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
</Style>
|
||||
<Style Selector="ListBox.step-list ListBoxItem">
|
||||
<Style Selector="Button.step-nav-item">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<ContentPresenter Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DesignCornerRadiusMd}" />
|
||||
<Setter Property="Margin" Value="0,0,0,4" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="Margin" Value="0,0,0,3" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="MinHeight" Value="48" />
|
||||
<Setter Property="MinHeight" Value="40" />
|
||||
</Style>
|
||||
<Style Selector="ListBox.step-list ListBoxItem:pointerover">
|
||||
<Style Selector="Button.step-nav-item:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource InstallerSubtleFillHoverBrush}" />
|
||||
</Style>
|
||||
<Style Selector="ListBox.step-list ListBoxItem:selected">
|
||||
<Setter Property="Background" Value="{DynamicResource InstallerSubtleFillBrush}" />
|
||||
<Style Selector="Button.step-nav-item:pressed">
|
||||
<Setter Property="Background" Value="{DynamicResource InstallerSubtleFillPressedBrush}" />
|
||||
</Style>
|
||||
<Style Selector="ListBox.step-list ListBoxItem:disabled">
|
||||
<Style Selector="Button.step-nav-item:disabled">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Opacity" Value="1" />
|
||||
</Style>
|
||||
<Style Selector="Button.step-nav-item:disabled TextBlock.step-title">
|
||||
<Setter Property="Foreground" Value="{DynamicResource InstallerDisabledTextBrush}" />
|
||||
</Style>
|
||||
<Style Selector="Button.step-nav-item:disabled fi|FluentIcon">
|
||||
<Setter Property="Foreground" Value="{DynamicResource InstallerDisabledTextBrush}" />
|
||||
</Style>
|
||||
<Style Selector="Border.step-nav-selected-fill">
|
||||
<Setter Property="Background" Value="{DynamicResource InstallerSubtleFillBrush}" />
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DesignCornerRadiusMd}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.step-title">
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource InstallerTextPrimaryBrush}" />
|
||||
</Style>
|
||||
<Style Selector="Border.step-icon-host">
|
||||
<Setter Property="Width" Value="32" />
|
||||
<Setter Property="Height" Value="32" />
|
||||
<Setter Property="Background" Value="{DynamicResource InstallerSubtleFillBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource InstallerBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource DesignCornerRadiusSm}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource InstallerTextSecondaryBrush}" />
|
||||
</Style>
|
||||
<Style Selector="Border.info-panel">
|
||||
<Setter Property="Background" Value="{DynamicResource InstallerSurfaceAltBrush}" />
|
||||
@@ -95,13 +111,14 @@
|
||||
</Style>
|
||||
</Window.Styles>
|
||||
|
||||
<Grid x:Name="RootGrid"
|
||||
RowDefinitions="48,*"
|
||||
Background="{DynamicResource InstallerWindowBackgroundBrush}">
|
||||
<Border Background="{DynamicResource InstallerWindowBackgroundBrush}"
|
||||
CornerRadius="{DynamicResource DesignCornerRadiusXl}"
|
||||
ClipToBounds="True">
|
||||
<Grid x:Name="RootGrid"
|
||||
RowDefinitions="48,*"
|
||||
Background="Transparent">
|
||||
<Border Grid.Row="0"
|
||||
Background="{DynamicResource InstallerPaneBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource InstallerBorderBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Background="{DynamicResource InstallerWindowBackgroundBrush}"
|
||||
PointerPressed="OnTitleBarPointerPressed">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<StackPanel Orientation="Horizontal"
|
||||
@@ -147,12 +164,12 @@
|
||||
</Border>
|
||||
|
||||
<Grid Grid.Row="1"
|
||||
ColumnDefinitions="260,*">
|
||||
ColumnDefinitions="260,10,*"
|
||||
Margin="10,0,10,10">
|
||||
<Border Grid.Column="0"
|
||||
Background="{DynamicResource InstallerPaneBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource InstallerBorderBrush}"
|
||||
BorderThickness="0,0,1,0"
|
||||
Padding="24,28">
|
||||
CornerRadius="{DynamicResource DesignCornerRadiusLg}"
|
||||
Padding="22,24">
|
||||
<Grid RowDefinitions="Auto,*,Auto">
|
||||
<StackPanel Spacing="8">
|
||||
<TextBlock Text="阑山桌面"
|
||||
@@ -162,71 +179,50 @@
|
||||
Classes="caption-text" />
|
||||
</StackPanel>
|
||||
|
||||
<ListBox Grid.Row="1"
|
||||
Classes="step-list"
|
||||
Margin="0,28,0,0"
|
||||
ItemsSource="{Binding Steps}"
|
||||
SelectedItem="{Binding SelectedStep, Mode=TwoWay}">
|
||||
<ListBox.ItemTemplate>
|
||||
<ItemsControl Grid.Row="1"
|
||||
Margin="0,28,0,0"
|
||||
ItemsSource="{Binding Steps}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:InstallerStepViewModel">
|
||||
<Grid ColumnDefinitions="4,Auto,*"
|
||||
ColumnSpacing="12"
|
||||
IsEnabled="{Binding IsUnlocked}"
|
||||
Margin="8,6">
|
||||
<Border Background="{DynamicResource InstallerAccentBrush}"
|
||||
CornerRadius="{DynamicResource DesignCornerRadiusMicro}"
|
||||
IsVisible="{Binding IsSelected}" />
|
||||
<Border Grid.Column="1"
|
||||
Classes="step-icon-host">
|
||||
<Grid>
|
||||
<fi:FluentIcon Icon="{Binding DisplayIcon}"
|
||||
IconVariant="Regular"
|
||||
Foreground="{DynamicResource InstallerTextTertiaryBrush}"
|
||||
FontSize="16"
|
||||
IsVisible="{Binding IsLocked}" />
|
||||
<fi:FluentIcon Icon="{Binding DisplayIcon}"
|
||||
IconVariant="Regular"
|
||||
Foreground="{DynamicResource InstallerSuccessBrush}"
|
||||
FontSize="16"
|
||||
IsVisible="{Binding IsCompleted}" />
|
||||
<fi:FluentIcon Icon="{Binding DisplayIcon}"
|
||||
IconVariant="Regular"
|
||||
Foreground="{DynamicResource InstallerAccentBrush}"
|
||||
FontSize="16"
|
||||
IsVisible="{Binding IsSelected}" />
|
||||
<fi:FluentIcon Icon="{Binding DisplayIcon}"
|
||||
IconVariant="Regular"
|
||||
Foreground="{DynamicResource InstallerTextPrimaryBrush}"
|
||||
FontSize="16"
|
||||
IsVisible="{Binding IsAvailable}" />
|
||||
<Button Classes="step-nav-item"
|
||||
Command="{Binding #Root.DataContext.SelectStepCommand}"
|
||||
CommandParameter="{Binding}"
|
||||
IsEnabled="{Binding IsUnlocked}">
|
||||
<Grid MinHeight="40">
|
||||
<Border Classes="step-nav-selected-fill"
|
||||
IsVisible="{Binding IsSelected}" />
|
||||
<Grid ColumnDefinitions="Auto,*"
|
||||
ColumnSpacing="10"
|
||||
Margin="10,0">
|
||||
<Grid Width="18"
|
||||
VerticalAlignment="Center">
|
||||
<fi:FluentIcon Icon="{Binding Icon}"
|
||||
IconVariant="Regular"
|
||||
Foreground="{DynamicResource InstallerTextSecondaryBrush}"
|
||||
FontSize="17"
|
||||
IsVisible="{Binding !IsSelected}" />
|
||||
<fi:FluentIcon Icon="{Binding Icon}"
|
||||
IconVariant="Filled"
|
||||
Foreground="{DynamicResource InstallerTextPrimaryBrush}"
|
||||
FontSize="17"
|
||||
IsVisible="{Binding IsSelected}" />
|
||||
</Grid>
|
||||
<Grid Grid.Column="1"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Classes="step-title"
|
||||
Text="{Binding Title}"
|
||||
IsVisible="{Binding !IsSelected}" />
|
||||
<TextBlock Classes="step-title"
|
||||
Text="{Binding Title}"
|
||||
Foreground="{DynamicResource InstallerTextPrimaryBrush}"
|
||||
IsVisible="{Binding IsSelected}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
<Grid Grid.Column="2">
|
||||
<TextBlock Classes="step-title"
|
||||
Text="{Binding Title}"
|
||||
Foreground="{DynamicResource InstallerTextTertiaryBrush}"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsLocked}" />
|
||||
<TextBlock Classes="step-title"
|
||||
Text="{Binding Title}"
|
||||
Foreground="{DynamicResource InstallerSuccessBrush}"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsCompleted}" />
|
||||
<TextBlock Classes="step-title"
|
||||
Text="{Binding Title}"
|
||||
Foreground="{DynamicResource InstallerAccentBrush}"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsSelected}" />
|
||||
<TextBlock Classes="step-title"
|
||||
Text="{Binding Title}"
|
||||
Foreground="{DynamicResource InstallerTextPrimaryBrush}"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsAvailable}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<TextBlock Grid.Row="2"
|
||||
Classes="caption-text"
|
||||
@@ -234,9 +230,12 @@
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Grid Grid.Column="1"
|
||||
RowDefinitions="*,Auto"
|
||||
Background="{DynamicResource InstallerContentBackgroundBrush}">
|
||||
<Border Grid.Column="2"
|
||||
Background="{DynamicResource InstallerContentBackgroundBrush}"
|
||||
CornerRadius="{DynamicResource DesignCornerRadiusLg}"
|
||||
ClipToBounds="True">
|
||||
<Grid RowDefinitions="*,Auto"
|
||||
Background="Transparent">
|
||||
<ScrollViewer Grid.Row="0"
|
||||
Padding="36,34,42,24"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
@@ -488,9 +487,7 @@
|
||||
</ScrollViewer>
|
||||
|
||||
<Border Grid.Row="1"
|
||||
Background="{DynamicResource InstallerContentBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource InstallerBorderBrush}"
|
||||
BorderThickness="0,1,0,0"
|
||||
Background="Transparent"
|
||||
Padding="36,16,42,18">
|
||||
<Grid ColumnDefinitions="*,Auto,Auto"
|
||||
ColumnSpacing="8">
|
||||
@@ -531,7 +528,9 @@
|
||||
</Button>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
||||
|
||||
Reference in New Issue
Block a user