Multi-Platform Package Manager for Stable Diffusion
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

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);
}
}