From 0ec0d32414eb48b3a517fb4e4845569f795da620 Mon Sep 17 00:00:00 2001 From: CosmicPredator Date: Wed, 20 Mar 2024 23:41:23 +0530 Subject: [PATCH] Added a new Splash Screen - The splash screen is highly WIP. - It has breaking changes. - The build will pass but the App can't run due to some win32 issue. --- src/AniMoe.App/AniMoe.App.csproj | 8 ++- src/AniMoe.App/AniMoe.App.csproj.user | 3 + src/AniMoe.App/App.xaml.cs | 7 +- .../Converters/StringToCategoryString.cs | 1 - .../Dialogs/ExploreViewFilterDialog.xaml.cs | 4 +- .../Dialogs/MediaListFliterView.xaml.cs | 4 +- src/AniMoe.App/Models/AnimeListModel.cs | 2 +- src/AniMoe.App/Models/MangaListModel.cs | 2 +- src/AniMoe.App/NativeMethods.json | 5 ++ src/AniMoe.App/NativeMethods.txt | 4 ++ .../ViewModels/AnimeListViewModel.cs | 6 +- .../ViewModels/MangaListViewModel.cs | 6 +- src/AniMoe.App/ViewModels/MasterViewModel.cs | 10 +-- src/AniMoe.App/ViewModels/SplashViewModel.cs | 68 +++++++++++++++++++ src/AniMoe.App/Views/MasterView.xaml | 26 ++++--- src/AniMoe.App/Views/MasterView.xaml.cs | 4 +- src/AniMoe.App/Views/RootWindow.xaml.cs | 26 +++---- src/AniMoe.App/Views/SplashView.xaml | 39 +++++++++++ src/AniMoe.App/Views/SplashView.xaml.cs | 57 ++++++++++++++++ 19 files changed, 229 insertions(+), 53 deletions(-) create mode 100644 src/AniMoe.App/NativeMethods.json create mode 100644 src/AniMoe.App/NativeMethods.txt create mode 100644 src/AniMoe.App/ViewModels/SplashViewModel.cs create mode 100644 src/AniMoe.App/Views/SplashView.xaml create mode 100644 src/AniMoe.App/Views/SplashView.xaml.cs diff --git a/src/AniMoe.App/AniMoe.App.csproj b/src/AniMoe.App/AniMoe.App.csproj index 6bbcaa6..e754c4a 100644 --- a/src/AniMoe.App/AniMoe.App.csproj +++ b/src/AniMoe.App/AniMoe.App.csproj @@ -72,6 +72,7 @@ + @@ -106,10 +107,12 @@ + + all + - @@ -205,6 +208,9 @@ Always + + MSBuild:Compile + MSBuild:Compile diff --git a/src/AniMoe.App/AniMoe.App.csproj.user b/src/AniMoe.App/AniMoe.App.csproj.user index 24f1473..e5f7240 100644 --- a/src/AniMoe.App/AniMoe.App.csproj.user +++ b/src/AniMoe.App/AniMoe.App.csproj.user @@ -23,6 +23,9 @@ Designer + + Designer + Designer diff --git a/src/AniMoe.App/App.xaml.cs b/src/AniMoe.App/App.xaml.cs index 83016b3..8601ba5 100644 --- a/src/AniMoe.App/App.xaml.cs +++ b/src/AniMoe.App/App.xaml.cs @@ -75,6 +75,7 @@ public static IServiceProvider ConfigureServices() .AddScoped() .AddScoped() .AddScoped() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton(DispatcherQueue.GetForCurrentThread()) @@ -82,6 +83,7 @@ public static IServiceProvider ConfigureServices() .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton(); services.AddHttpClient(); @@ -109,8 +111,9 @@ protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventA Process.GetProcessById((int)mainInstance.ProcessId).Kill(); Log.Information("Authorization handled successfully and accessToken was saved"); } - m_window = new RootWindow(); - m_window.ExtendsContentIntoTitleBar = true; + //m_window = new RootWindow(); + m_window = new SplashView(); + //m_window.ExtendsContentIntoTitleBar = true; m_window.Activate(); Log.Information("RootWindow initialized"); } diff --git a/src/AniMoe.App/Converters/StringToCategoryString.cs b/src/AniMoe.App/Converters/StringToCategoryString.cs index 67c536e..ef247b5 100644 --- a/src/AniMoe.App/Converters/StringToCategoryString.cs +++ b/src/AniMoe.App/Converters/StringToCategoryString.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -using static PInvoke.User32; namespace AniMoe.App.Converters { diff --git a/src/AniMoe.App/Dialogs/ExploreViewFilterDialog.xaml.cs b/src/AniMoe.App/Dialogs/ExploreViewFilterDialog.xaml.cs index 390b604..f8e4262 100644 --- a/src/AniMoe.App/Dialogs/ExploreViewFilterDialog.xaml.cs +++ b/src/AniMoe.App/Dialogs/ExploreViewFilterDialog.xaml.cs @@ -20,7 +20,7 @@ namespace AniMoe.App.Dialogs { public sealed partial class ExploreViewFilterDialog : ContentDialog { - public MasterViewModel masterViewModel; + public SplashViewModel masterViewModel; public List FilterList; public Dictionary Filters = new(); public List FormatList; @@ -28,7 +28,7 @@ public sealed partial class ExploreViewFilterDialog : ContentDialog public ExploreViewFilterDialog(string mediaType) { - masterViewModel = App.Current.Services.GetRequiredService(); + masterViewModel = App.Current.Services.GetRequiredService(); MediaType = mediaType; InitializeComponent(); LoadFilterList(); diff --git a/src/AniMoe.App/Dialogs/MediaListFliterView.xaml.cs b/src/AniMoe.App/Dialogs/MediaListFliterView.xaml.cs index ad58d76..7aebee2 100644 --- a/src/AniMoe.App/Dialogs/MediaListFliterView.xaml.cs +++ b/src/AniMoe.App/Dialogs/MediaListFliterView.xaml.cs @@ -15,8 +15,8 @@ public sealed partial class MediaListFliterView : ContentDialog public MediaListFilterModel Model; private List genreList; public List AnimeFormatList; - public MasterViewModel DataModal = App.Current.Services - .GetRequiredService(); + public SplashViewModel DataModal = App.Current.Services + .GetRequiredService(); public int Year = DateTime.Now.Year + 1; public MediaListFliterView() { diff --git a/src/AniMoe.App/Models/AnimeListModel.cs b/src/AniMoe.App/Models/AnimeListModel.cs index 803c14e..1877388 100644 --- a/src/AniMoe.App/Models/AnimeListModel.cs +++ b/src/AniMoe.App/Models/AnimeListModel.cs @@ -130,7 +130,7 @@ public static partial class Initialize public static async Task FetchData() { IRequestHandler Handler = App.Current.Services.GetService(); - MasterViewModel Vm = App.Current.Services.GetRequiredService(); + SplashViewModel Vm = App.Current.Services.GetRequiredService(); AnimeListModel Model = await Handler.RequestApi( Queries.Query.MediaListQuery, new diff --git a/src/AniMoe.App/Models/MangaListModel.cs b/src/AniMoe.App/Models/MangaListModel.cs index db6f029..189d11a 100644 --- a/src/AniMoe.App/Models/MangaListModel.cs +++ b/src/AniMoe.App/Models/MangaListModel.cs @@ -113,7 +113,7 @@ public static partial class Initialize public static async Task FetchData() { IRequestHandler Handler = App.Current.Services.GetService(); - MasterViewModel Vm = App.Current.Services.GetRequiredService(); + SplashViewModel Vm = App.Current.Services.GetRequiredService(); MangaListModel Model = await Handler.RequestApi( Queries.Query.MediaListQuery, new diff --git a/src/AniMoe.App/NativeMethods.json b/src/AniMoe.App/NativeMethods.json new file mode 100644 index 0000000..17f762f --- /dev/null +++ b/src/AniMoe.App/NativeMethods.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://aka.ms/CsWin32.schema.json", + "className": "AniMoeAppNative", + "public": true +} \ No newline at end of file diff --git a/src/AniMoe.App/NativeMethods.txt b/src/AniMoe.App/NativeMethods.txt new file mode 100644 index 0000000..87b16aa --- /dev/null +++ b/src/AniMoe.App/NativeMethods.txt @@ -0,0 +1,4 @@ +SetWindowPos +GetSystemMetrics +SetWindowLongPtr +WINDOW_STYLE \ No newline at end of file diff --git a/src/AniMoe.App/ViewModels/AnimeListViewModel.cs b/src/AniMoe.App/ViewModels/AnimeListViewModel.cs index a1b548a..0330dae 100644 --- a/src/AniMoe.App/ViewModels/AnimeListViewModel.cs +++ b/src/AniMoe.App/ViewModels/AnimeListViewModel.cs @@ -24,7 +24,7 @@ namespace AniMoe.App.ViewModels public partial class AnimeListViewModel : ObservableObject { private AnimeListModel model; - private MasterViewModel StatusModel; + private SplashViewModel StatusModel; private bool loaded = false; private bool isLoading = true; private bool isEmpty = false; @@ -135,9 +135,9 @@ public void SearchTextChanged(object sender, TextChangedEventArgs e) } } - public AnimeListViewModel(MasterViewModel masterViewModel) + public AnimeListViewModel(SplashViewModel splashViewModel) { - StatusModel = masterViewModel; + StatusModel = splashViewModel; LoadView = new AsyncRelayCommand(async() => { await InitView(); diff --git a/src/AniMoe.App/ViewModels/MangaListViewModel.cs b/src/AniMoe.App/ViewModels/MangaListViewModel.cs index 727cd7a..7358977 100644 --- a/src/AniMoe.App/ViewModels/MangaListViewModel.cs +++ b/src/AniMoe.App/ViewModels/MangaListViewModel.cs @@ -19,7 +19,7 @@ namespace AniMoe.App.ViewModels public partial class MangaListViewModel : ObservableObject { private MangaListModel model; - private MasterViewModel StatusModel; + private SplashViewModel StatusModel; private bool loaded = false; private bool isLoading = true; private bool isEmpty = false; @@ -123,9 +123,9 @@ public void SearchTextChanged(object sender, TextChangedEventArgs e) } } - public MangaListViewModel(MasterViewModel masterViewModel) + public MangaListViewModel(SplashViewModel splashViewModel) { - StatusModel = masterViewModel; + StatusModel = splashViewModel; LoadView = new AsyncRelayCommand(async () => { await InitView(); diff --git a/src/AniMoe.App/ViewModels/MasterViewModel.cs b/src/AniMoe.App/ViewModels/MasterViewModel.cs index b477874..790b9e4 100644 --- a/src/AniMoe.App/ViewModels/MasterViewModel.cs +++ b/src/AniMoe.App/ViewModels/MasterViewModel.cs @@ -42,16 +42,18 @@ public bool IsVisible public IAsyncRelayCommand LoadData { get; } - public MasterViewModel() + public MasterViewModel(MasterModel model, MediaListStatusModel _mediaListStatusModel) { + mediaListStatusModel = _mediaListStatusModel; + Model = model; LoadData = new AsyncRelayCommand(LoadModel); } public async Task LoadModel() { - IsVisible = false; - NavItemsEnable = true; - await LoadFromApi(); + //IsVisible = false; + //NavItemsEnable = true; + //await LoadFromApi(); NavItemsEnable = false; IsVisible = true; } diff --git a/src/AniMoe.App/ViewModels/SplashViewModel.cs b/src/AniMoe.App/ViewModels/SplashViewModel.cs new file mode 100644 index 0000000..2319da9 --- /dev/null +++ b/src/AniMoe.App/ViewModels/SplashViewModel.cs @@ -0,0 +1,68 @@ +using AniMoe.App.Models.MasterModel; +using AniMoe.App.Models.MediaListStatusModel; +using AniMoe.App.Services; +using AniMoe.App.Views; +using CommunityToolkit.Mvvm.ComponentModel; +using Microsoft.UI.Xaml; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace AniMoe.App.ViewModels +{ + public partial class SplashViewModel : ObservableObject + { + public MediaListStatusModel mediaListStatusModel; + private readonly ILocalSettings _localSettings; + private RootWindow rootWindow = null; + + [ObservableProperty] private MasterModel model; + + [ObservableProperty] string _statusText; + + public SplashViewModel(MasterModel model, ILocalSettings settings) + { + _localSettings = settings; + StatusText = "Registering Dependencies..."; + model = Model; + } + + public async void Window_Activated(object sender, WindowActivatedEventArgs args) + { + var ins = Application.Current as App; + var window = ins.m_window; + if (window is SplashView splashView) return; + if (window is RootWindow roowindow) return; + if (_localSettings.IsSettingExists("accessToken")) + await LoadFromApi(); + if (rootWindow == null) + { + var mwindow = new RootWindow(); + mwindow.ExtendsContentIntoTitleBar = true; + ((Window)sender).Close(); + mwindow.Activate(); + ins.m_window = mwindow; + } + } + + public async Task LoadFromApi() + { + StatusText = "Fetching user data..."; + Model = await Models.MasterModel.Initialize.FetchData(); + + StatusText = "Fetching Anime & Manga lists..."; + mediaListStatusModel + = await Models.MediaListStatusModel.Initialize.FetchData(Model.Data.User.Id); + EnumValue defaultValue = new EnumValue { Name = "Select One" }; + Model.Data.MediaSourceList.EnumValues.Insert(0, defaultValue); + Model.Data.MediaSeasonList.EnumValues.Insert(0, defaultValue); + Model.Data.MediaFormatList.EnumValues.Insert(0, defaultValue); + + StatusText = "Launching AniMoe..."; + } + } +} diff --git a/src/AniMoe.App/Views/MasterView.xaml b/src/AniMoe.App/Views/MasterView.xaml index 166e5a5..38e5554 100644 --- a/src/AniMoe.App/Views/MasterView.xaml +++ b/src/AniMoe.App/Views/MasterView.xaml @@ -11,15 +11,17 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:DefaultBindMode="OneWay" mc:Ignorable="d"> - + + + + - + - + - + - + - + @@ -96,8 +93,9 @@ x:Name="Spinner" HorizontalAlignment="Center" VerticalAlignment="Center" - x:Load="{x:Bind ViewModel.NavItemsEnable}" IsActive="True" + x:Load="False" IsIndeterminate="True" /> + diff --git a/src/AniMoe.App/Views/MasterView.xaml.cs b/src/AniMoe.App/Views/MasterView.xaml.cs index 3171938..e64689a 100644 --- a/src/AniMoe.App/Views/MasterView.xaml.cs +++ b/src/AniMoe.App/Views/MasterView.xaml.cs @@ -12,11 +12,11 @@ namespace AniMoe.App.Views { public sealed partial class MasterView : Page { - public MasterViewModel ViewModel; + public SplashViewModel ViewModel; DispatcherQueue dispatcherQueue = DispatcherQueue.GetForCurrentThread(); public MasterView() { - ViewModel = App.Current.Services.GetRequiredService(); + ViewModel = App.Current.Services.GetRequiredService(); this.InitializeComponent(); DataContext = ViewModel; } diff --git a/src/AniMoe.App/Views/RootWindow.xaml.cs b/src/AniMoe.App/Views/RootWindow.xaml.cs index 3b724f0..318a6f1 100644 --- a/src/AniMoe.App/Views/RootWindow.xaml.cs +++ b/src/AniMoe.App/Views/RootWindow.xaml.cs @@ -17,13 +17,14 @@ using Microsoft.UI.Xaml.Media.Animation; using Microsoft.UI.Xaml.Controls; using Windows.ApplicationModel.VoiceCommands; +using WinRT.Interop; namespace AniMoe.App.Views { public sealed partial class RootWindow : Window { #region Properties - private ILocalSettings _localSettings; + private readonly ILocalSettings _localSettings; public Thickness TitleBarThickness = new() { @@ -41,8 +42,8 @@ public RootWindow() this.SystemBackdrop = new MicaBackdrop { Kind = MicaKind.BaseAlt }; else this.SystemBackdrop = new DesktopAcrylicBackdrop(); - LoadIcon("Assets/Window-Icon.ico"); - _localSettings = App.Current.Services.GetService(); + SetAppWindowIcon(); + _localSettings = App.Current.Services.GetRequiredService(); AppTitleBar.Margin = TitleBarThickness; SetTitle(); SetView(); @@ -63,26 +64,17 @@ private void SetTitle() SetTitleBar( AppTitleBar ); } - private void LoadIcon(string iconName) + private void SetAppWindowIcon() { - var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); - IntPtr hIcon = PInvoke.User32.LoadImage(IntPtr.Zero, iconName, - PInvoke.User32.ImageType.IMAGE_ICON, 16, 16, PInvoke.User32.LoadImageFlags.LR_LOADFROMFILE); - - PInvoke.User32.SendMessage(hwnd, PInvoke.User32.WindowMessage.WM_SETICON, (IntPtr)0, hIcon); + IntPtr hWnd = WindowNative.GetWindowHandle(this); + WindowId id = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd); + var appWindow = AppWindow.GetFromWindowId(id); + appWindow.SetIcon("Assets/Window-Icon.ico"); } public void ChangeTitleBarThickness(Thickness thickness) { AppTitleBar.Margin = thickness; } - - [ComImport] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [Guid("AD056AB3-1FBB-4F8D-963D-7ED80A181C2D")] - internal interface IWindowNative - { - IntPtr WindowHandle { get; } - } } } diff --git a/src/AniMoe.App/Views/SplashView.xaml b/src/AniMoe.App/Views/SplashView.xaml new file mode 100644 index 0000000..bd1c602 --- /dev/null +++ b/src/AniMoe.App/Views/SplashView.xaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AniMoe.App/Views/SplashView.xaml.cs b/src/AniMoe.App/Views/SplashView.xaml.cs new file mode 100644 index 0000000..0284ac2 --- /dev/null +++ b/src/AniMoe.App/Views/SplashView.xaml.cs @@ -0,0 +1,57 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Navigation; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.Win32; +using WinRT.Interop; +using Windows.Win32.UI.WindowsAndMessaging; +using Windows.Win32.Foundation; +using AniMoe.App.ViewModels; +using Microsoft.Extensions.DependencyInjection; + +namespace AniMoe.App.Views +{ + public sealed partial class SplashView : Window + { + SplashViewModel ViewModel = App.Current.Services.GetRequiredService(); + + public SplashView() + { + this.InitializeComponent(); + convertToSplashWindow(); + } + + void convertToSplashWindow() + { + IntPtr hWnd = WindowNative.GetWindowHandle(this); + + var screenWidth = AniMoeAppNative.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CXSCREEN); + var screenHeight = AniMoeAppNative.GetSystemMetrics(SYSTEM_METRICS_INDEX.SM_CYSCREEN); + + var desiredWidth = 640; + var desiredHeight = 360; + + unchecked + { + AniMoeAppNative.SetWindowLongPtr((HWND)hWnd, WINDOW_LONG_PTR_INDEX.GWL_STYLE, (nint)WINDOW_STYLE.WS_POPUPWINDOW); + } + + AniMoeAppNative.SetWindowPos((HWND)hWnd, + (HWND)new IntPtr(0), + (screenWidth / 2) - (desiredWidth / 2), + (screenHeight / 2) - (desiredHeight / 2), + desiredWidth, desiredHeight, + SET_WINDOW_POS_FLAGS.SWP_NOZORDER); + } + } +}