You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
5.4 KiB
179 lines
5.4 KiB
using System; |
|
using System.Diagnostics.CodeAnalysis; |
|
using System.IO; |
|
using AsyncAwaitBestPractices; |
|
using AsyncImageLoader; |
|
using Avalonia; |
|
using Avalonia.Controls; |
|
using Avalonia.Controls.Notifications; |
|
using Avalonia.Input; |
|
using Avalonia.Interactivity; |
|
using Avalonia.Media; |
|
using Avalonia.Media.Immutable; |
|
using Avalonia.Styling; |
|
using Avalonia.Threading; |
|
using FluentAvalonia.Styling; |
|
using FluentAvalonia.UI.Controls; |
|
using FluentAvalonia.UI.Media; |
|
using FluentAvalonia.UI.Windowing; |
|
using Microsoft.Extensions.DependencyInjection; |
|
using StabilityMatrix.Avalonia.Controls; |
|
using StabilityMatrix.Avalonia.Services; |
|
using StabilityMatrix.Avalonia.ViewModels; |
|
using StabilityMatrix.Core.Processes; |
|
|
|
namespace StabilityMatrix.Avalonia.Views; |
|
|
|
[SuppressMessage("ReSharper", "UnusedParameter.Local")] |
|
public partial class MainWindow : AppWindowBase |
|
{ |
|
public INotificationService? NotificationService { get; set; } |
|
|
|
public MainWindow() |
|
{ |
|
InitializeComponent(); |
|
|
|
#if DEBUG |
|
this.AttachDevTools(); |
|
#endif |
|
|
|
TitleBar.ExtendsContentIntoTitleBar = true; |
|
TitleBar.TitleBarHitTestType = TitleBarHitTestType.Complex; |
|
} |
|
|
|
protected override void OnOpened(EventArgs e) |
|
{ |
|
base.OnOpened(e); |
|
|
|
Application.Current!.ActualThemeVariantChanged += OnActualThemeVariantChanged; |
|
|
|
var theme = ActualThemeVariant; |
|
// Enable mica for Windows 11 |
|
if (IsWindows11 && theme != FluentAvaloniaTheme.HighContrastTheme) |
|
{ |
|
TryEnableMicaEffect(); |
|
} |
|
} |
|
|
|
protected override void OnClosing(WindowClosingEventArgs e) |
|
{ |
|
// Show confirmation if package running |
|
var launchPageViewModel = App.Services |
|
.GetRequiredService<LaunchPageViewModel>(); |
|
|
|
launchPageViewModel.OnMainWindowClosing(e); |
|
|
|
base.OnClosing(e); |
|
} |
|
|
|
protected override void OnLoaded(RoutedEventArgs e) |
|
{ |
|
base.OnLoaded(e); |
|
// Initialize notification service using this window as the visual root |
|
NotificationService?.Initialize(this); |
|
|
|
// Attach error notification handler for image loader |
|
if (ImageLoader.AsyncImageLoader is FallbackRamCachedWebImageLoader loader) |
|
{ |
|
loader.LoadFailed += OnImageLoadFailed; |
|
} |
|
} |
|
|
|
protected override void OnUnloaded(RoutedEventArgs e) |
|
{ |
|
base.OnUnloaded(e); |
|
|
|
// Detach error notification handler for image loader |
|
if (ImageLoader.AsyncImageLoader is FallbackRamCachedWebImageLoader loader) |
|
{ |
|
loader.LoadFailed -= OnImageLoadFailed; |
|
} |
|
} |
|
|
|
private void OnActualThemeVariantChanged(object? sender, EventArgs e) |
|
{ |
|
if (IsWindows11) |
|
{ |
|
if (ActualThemeVariant != FluentAvaloniaTheme.HighContrastTheme) |
|
{ |
|
TryEnableMicaEffect(); |
|
} |
|
else |
|
{ |
|
ClearValue(BackgroundProperty); |
|
ClearValue(TransparencyBackgroundFallbackProperty); |
|
} |
|
} |
|
} |
|
|
|
private void OnImageLoadFailed(object? sender, ImageLoadFailedEventArgs e) |
|
{ |
|
Dispatcher.UIThread.Post(() => |
|
{ |
|
var fileName = Path.GetFileName(e.Url); |
|
var displayName = string.IsNullOrEmpty(fileName) ? e.Url : fileName; |
|
NotificationService?.ShowPersistent( |
|
"Failed to load image", |
|
$"Could not load '{displayName}'\n({e.Exception.Message})", |
|
NotificationType.Warning); |
|
}); |
|
} |
|
|
|
private void TryEnableMicaEffect() |
|
{ |
|
TransparencyBackgroundFallback = Brushes.Transparent; |
|
TransparencyLevelHint = new[] |
|
{ |
|
WindowTransparencyLevel.Mica, |
|
WindowTransparencyLevel.AcrylicBlur, |
|
WindowTransparencyLevel.Blur |
|
}; |
|
|
|
if (ActualThemeVariant == ThemeVariant.Dark) |
|
{ |
|
var color = this.TryFindResource("SolidBackgroundFillColorBase", |
|
ThemeVariant.Dark, out var value) ? (Color2)(Color)value! : new Color2(32, 32, 32); |
|
|
|
color = color.LightenPercent(-0.8f); |
|
|
|
Background = new ImmutableSolidColorBrush(color, 0.8); |
|
} |
|
else if (ActualThemeVariant == ThemeVariant.Light) |
|
{ |
|
// Similar effect here |
|
var color = this.TryFindResource("SolidBackgroundFillColorBase", |
|
ThemeVariant.Light, out var value) ? (Color2)(Color)value! : new Color2(243, 243, 243); |
|
|
|
color = color.LightenPercent(0.5f); |
|
|
|
Background = new ImmutableSolidColorBrush(color, 0.9); |
|
} |
|
} |
|
|
|
private void FooterDownloadItem_OnTapped(object? sender, TappedEventArgs e) |
|
{ |
|
var item = sender as NavigationViewItem; |
|
var flyout = item!.ContextFlyout; |
|
flyout!.ShowAt(item); |
|
} |
|
|
|
private void FooterUpdateItem_OnTapped(object? sender, TappedEventArgs e) |
|
{ |
|
// show update window thing |
|
if (DataContext is not MainWindowViewModel vm) |
|
{ |
|
throw new NullReferenceException("DataContext is not MainWindowViewModel"); |
|
} |
|
Dispatcher.UIThread.InvokeAsync(vm.ShowUpdateDialog).SafeFireAndForget(); |
|
} |
|
|
|
private void FooterDiscordItem_OnTapped(object? sender, TappedEventArgs e) |
|
{ |
|
ProcessRunner.OpenUrl(Assets.DiscordServerUrl); |
|
} |
|
|
|
private void PatreonPatreonItem_OnTapped(object? sender, TappedEventArgs e) |
|
{ |
|
ProcessRunner.OpenUrl(Assets.PatreonUrl); |
|
} |
|
}
|
|
|