mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-22 00:54:26 +08:00
Simplify splash to fade; add themed about banners
Simplify splash startup visuals by removing the multi-mode/slide behavior and always using a fade animation. Update App to create SplashWindow without a StartupVisualMode parameter and remove related fields, layout configuration, slide animation, and easing helpers from SplashWindow. Clean up unused using. Replace the single about_banner asset with theme-aware variants (about_banner_dark.png and about_banner_light.png), delete the old about_banner.png, and update AboutSettingsPage to use a DynamicResource ImageBrush (AboutBannerBrush) that selects the appropriate banner per theme.
This commit is contained in:
@@ -143,8 +143,7 @@ public partial class App : Application
|
||||
|
||||
private static SplashWindow CreateSplashWindow()
|
||||
{
|
||||
var preferences = StartupVisualPreferencesResolver.Resolve();
|
||||
var window = new SplashWindow(preferences.Mode);
|
||||
var window = new SplashWindow();
|
||||
TrySetSplashVersionInfo(window, LauncherRuntimeContext.Current);
|
||||
return window;
|
||||
}
|
||||
|
||||
@@ -22,37 +22,15 @@
|
||||
|
||||
<Grid RowDefinitions="*,Auto"
|
||||
Background="#0B0B0B">
|
||||
<Grid Grid.Row="0">
|
||||
<Grid x:Name="CompactHero"
|
||||
Margin="24">
|
||||
<TextBlock x:Name="AppNameText"
|
||||
Text="LanMountain Desktop"
|
||||
FontSize="24"
|
||||
FontWeight="SemiBold"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Left"
|
||||
Foreground="#F6F7FB" />
|
||||
</Grid>
|
||||
|
||||
<Grid x:Name="FullscreenHero"
|
||||
IsVisible="False">
|
||||
<StackPanel HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="24">
|
||||
<Border Width="240"
|
||||
Height="240"
|
||||
Background="Transparent">
|
||||
<Image Source="/Assets/logo_nightly.png"
|
||||
Stretch="Uniform" />
|
||||
</Border>
|
||||
|
||||
<TextBlock Text="LanMountain Desktop"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="26"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#F6F7FB" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Grid.Row="0"
|
||||
Margin="24">
|
||||
<TextBlock x:Name="AppNameText"
|
||||
Text="LanMountain Desktop"
|
||||
FontSize="24"
|
||||
FontWeight="SemiBold"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalAlignment="Left"
|
||||
Foreground="#F6F7FB" />
|
||||
</Grid>
|
||||
|
||||
<Border Grid.Row="1"
|
||||
|
||||
@@ -7,7 +7,6 @@ using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
using LanMountainDesktop.Launcher.Services;
|
||||
using LanMountainDesktop.Shared.Contracts.Launcher;
|
||||
|
||||
namespace LanMountainDesktop.Launcher.Views;
|
||||
|
||||
@@ -15,25 +14,14 @@ public partial class SplashWindow : Window, ISplashStageReporter
|
||||
{
|
||||
private const int DebugModeClickThreshold = 5;
|
||||
private static readonly TimeSpan FadeAnimationDuration = TimeSpan.FromMilliseconds(160);
|
||||
private static readonly TimeSpan SlideAnimationDuration = TimeSpan.FromMilliseconds(260);
|
||||
|
||||
private readonly StartupVisualMode _mode;
|
||||
private int _versionTextClickCount;
|
||||
private bool _isDebugModeOpened;
|
||||
private bool _isOpened;
|
||||
private bool _layoutConfigured;
|
||||
private bool _dismissed;
|
||||
private PixelPoint _targetPosition;
|
||||
private PixelPoint _slideHiddenPosition;
|
||||
|
||||
public SplashWindow()
|
||||
: this(StartupVisualMode.Fade)
|
||||
{
|
||||
}
|
||||
|
||||
public SplashWindow(StartupVisualMode mode)
|
||||
{
|
||||
_mode = mode;
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
Loaded += OnWindowLoaded;
|
||||
Opened += OnWindowOpened;
|
||||
@@ -55,20 +43,9 @@ public partial class SplashWindow : Window, ISplashStageReporter
|
||||
}
|
||||
|
||||
_isOpened = true;
|
||||
ConfigureForVisualMode();
|
||||
|
||||
if (_mode == StartupVisualMode.Fade)
|
||||
{
|
||||
Opacity = 0d;
|
||||
await AnimateOpacityAsync(0d, 1d, FadeAnimationDuration).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Opacity = 1d;
|
||||
if (_mode == StartupVisualMode.SlideSplash)
|
||||
{
|
||||
await AnimateWindowPositionAsync(_slideHiddenPosition, _targetPosition, SlideAnimationDuration, EaseOutCubic).ConfigureAwait(false);
|
||||
}
|
||||
Opacity = 0d;
|
||||
await AnimateOpacityAsync(0d, 1d, FadeAnimationDuration).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task DismissAsync()
|
||||
@@ -80,25 +57,13 @@ public partial class SplashWindow : Window, ISplashStageReporter
|
||||
|
||||
_dismissed = true;
|
||||
|
||||
// 确保在UI线程上执行
|
||||
if (!Dispatcher.UIThread.CheckAccess())
|
||||
{
|
||||
await Dispatcher.UIThread.InvokeAsync(async () => await DismissAsync());
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigureForVisualMode();
|
||||
|
||||
if (_mode == StartupVisualMode.SlideSplash)
|
||||
{
|
||||
var from = Position;
|
||||
await AnimateWindowPositionAsync(from, _slideHiddenPosition, SlideAnimationDuration, EaseInCubic).ConfigureAwait(false);
|
||||
}
|
||||
else if (_mode == StartupVisualMode.Fade)
|
||||
{
|
||||
await AnimateOpacityAsync(Opacity, 0d, FadeAnimationDuration).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await AnimateOpacityAsync(Opacity, 0d, FadeAnimationDuration).ConfigureAwait(false);
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -194,46 +159,6 @@ public partial class SplashWindow : Window, ISplashStageReporter
|
||||
UpdateStatus("[Debug Mode] Splash Preview");
|
||||
}
|
||||
|
||||
private void ConfigureForVisualMode()
|
||||
{
|
||||
if (_layoutConfigured)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_layoutConfigured = true;
|
||||
var compactHero = this.FindControl<Grid>("CompactHero");
|
||||
var fullscreenHero = this.FindControl<Grid>("FullscreenHero");
|
||||
|
||||
if (_mode == StartupVisualMode.Fade)
|
||||
{
|
||||
compactHero?.SetCurrentValue(IsVisibleProperty, true);
|
||||
fullscreenHero?.SetCurrentValue(IsVisibleProperty, false);
|
||||
Background = new SolidColorBrush(Color.Parse("#0B0B0B"));
|
||||
Width = 480;
|
||||
Height = 320;
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||
return;
|
||||
}
|
||||
|
||||
compactHero?.SetCurrentValue(IsVisibleProperty, false);
|
||||
fullscreenHero?.SetCurrentValue(IsVisibleProperty, true);
|
||||
Background = Brushes.Black;
|
||||
WindowStartupLocation = WindowStartupLocation.Manual;
|
||||
|
||||
var screen = Screens?.Primary ?? Screens?.All.FirstOrDefault();
|
||||
var workingArea = screen?.WorkingArea ?? new PixelRect(0, 0, 1920, 1080);
|
||||
var scale = Math.Max(screen?.Scaling ?? 1d, 0.01d);
|
||||
|
||||
Width = workingArea.Width / scale;
|
||||
Height = workingArea.Height / scale;
|
||||
_targetPosition = new PixelPoint(workingArea.X, workingArea.Y);
|
||||
_slideHiddenPosition = new PixelPoint(workingArea.X + workingArea.Width, workingArea.Y);
|
||||
Position = _mode == StartupVisualMode.SlideSplash
|
||||
? _slideHiddenPosition
|
||||
: _targetPosition;
|
||||
}
|
||||
|
||||
private void OnVersionTextClick(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (_isDebugModeOpened)
|
||||
@@ -292,20 +217,6 @@ public partial class SplashWindow : Window, ISplashStageReporter
|
||||
}, duration, EaseOutCubic).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task AnimateWindowPositionAsync(
|
||||
PixelPoint from,
|
||||
PixelPoint to,
|
||||
TimeSpan duration,
|
||||
Func<double, double> easing)
|
||||
{
|
||||
await AnimateAsync(progress =>
|
||||
{
|
||||
var currentX = (int)Math.Round(from.X + ((to.X - from.X) * progress));
|
||||
var currentY = (int)Math.Round(from.Y + ((to.Y - from.Y) * progress));
|
||||
Position = new PixelPoint(currentX, currentY);
|
||||
}, duration, easing).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task AnimateAsync(Action<double> update, TimeSpan duration, Func<double, double> easing)
|
||||
{
|
||||
if (duration <= TimeSpan.Zero)
|
||||
@@ -347,6 +258,4 @@ public partial class SplashWindow : Window, ISplashStageReporter
|
||||
var inverse = 1d - value;
|
||||
return 1d - (inverse * inverse * inverse);
|
||||
}
|
||||
|
||||
private static double EaseInCubic(double value) => value * value * value;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 999 KiB |
BIN
LanMountainDesktop/Assets/about_banner_dark.png
Normal file
BIN
LanMountainDesktop/Assets/about_banner_dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 682 KiB |
BIN
LanMountainDesktop/Assets/about_banner_light.png
Normal file
BIN
LanMountainDesktop/Assets/about_banner_light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
@@ -6,6 +6,19 @@
|
||||
xmlns:fi="using:FluentIcons.Avalonia.Fluent"
|
||||
x:Class="LanMountainDesktop.Views.SettingsPages.AboutSettingsPage"
|
||||
x:DataType="vm:AboutSettingsPageViewModel">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<ImageBrush x:Key="AboutBannerBrush" Source="/Assets/about_banner_light.png" Stretch="Uniform" AlignmentX="Center" AlignmentY="Center" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<ImageBrush x:Key="AboutBannerBrush" Source="/Assets/about_banner_dark.png" Stretch="Uniform" AlignmentX="Center" AlignmentY="Center" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
|
||||
<UserControl.Styles>
|
||||
<Style Selector="StackPanel.about-page-container">
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
@@ -38,10 +51,7 @@
|
||||
Classes="about-hero-card"
|
||||
Height="240"
|
||||
PointerPressed="OnAboutHeroCardPointerPressed">
|
||||
<Image Source="/Assets/about_banner.png"
|
||||
Stretch="Uniform"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
<Panel Background="{DynamicResource AboutBannerBrush}" />
|
||||
</Border>
|
||||
|
||||
<TextBlock Classes="settings-subsection-title"
|
||||
|
||||
Reference in New Issue
Block a user