1+ // This file contains portions of code from the Files App project, licensed under the MIT License.
2+
3+ using System . Reflection ;
4+
5+ namespace Riverside . Extensions . WinUI ;
6+
7+ /// <summary>
8+ /// Represents a unified application class that can be used across all platforms.
9+ /// It provides a common set of properties and methods that can be used in any project.
10+ /// </summary>
11+ /// <seealso cref="Application"/>
12+ public abstract partial class UnifiedApp : Application
13+ {
14+ private static CommandBarFlyout ? _LastOpenedFlyout ;
15+
16+ #if ! Wpf && ! UWP
17+ /// <summary>
18+ /// Gets a dictionary of windows identified by a string key.
19+ /// </summary>
20+ public Dictionary < string , Window > Windows { get ; } = [ ] ;
21+ #endif
22+
23+ /// <summary>
24+ /// Gets the application version.
25+ /// </summary>
26+ public static readonly string AppVersion =
27+ #if Wpf
28+ $ "{ Assembly . GetEntryAssembly ( ) ? . GetName ( ) . Version ? . Major } ." +
29+ $ "{ Assembly . GetEntryAssembly ( ) ? . GetName ( ) . Version ? . Minor } ." +
30+ $ "{ Assembly . GetEntryAssembly ( ) ? . GetName ( ) . Version ? . Build } ." +
31+ $ "{ Assembly . GetEntryAssembly ( ) ? . GetName ( ) . Version ? . Revision } ";
32+ #else
33+ $ "{ Package . Current . Id . Version . Major } ." +
34+ $ "{ Package . Current . Id . Version . Minor } ." +
35+ $ "{ Package . Current . Id . Version . Build } ." +
36+ $ "{ Package . Current . Id . Version . Revision } ";
37+ #endif
38+
39+ /// <summary>
40+ /// Gets the current <see cref="UnifiedApp"/> instance in use.
41+ /// </summary>
42+ public new static UnifiedApp Current
43+ => ( UnifiedApp ) Application . Current ;
44+
45+ /// <summary>
46+ /// Gets or sets the <see cref="IServiceProvider"/> instance to resolve application services.
47+ /// </summary>
48+ public IServiceProvider Services { get ; set ; }
49+
50+ #if ! Wpf
51+ /// <summary>
52+ /// Gets the application data container for local settings.
53+ /// </summary>
54+ public ApplicationDataContainer Settings = ApplicationData . Current . LocalSettings ;
55+ #endif
56+
57+ #if ! Wpf && ! UWP
58+ /// <summary>
59+ /// Opens a new window with the specified key, page type, and optional parameter.
60+ /// </summary>
61+ /// <typeparam name="TPage">The type of the page to navigate to.</typeparam>
62+ /// <param name="windowKey">The key to identify the window.</param>
63+ /// <param name="parameter">The parameter to pass to the page.</param>
64+ public void OpenNewWindow < TPage > ( string windowKey , object parameter = null )
65+ {
66+ if ( Windows . TryGetValue ( windowKey , out Window value ) )
67+ {
68+ value . Activate ( ) ;
69+ return ;
70+ }
71+
72+ Window newWindow = new ( ) ;
73+ Frame frame = new ( ) ;
74+ _ = frame . Navigate ( typeof ( TPage ) , parameter ) ;
75+ newWindow . Content = frame ;
76+ newWindow . Activate ( ) ;
77+
78+ Windows [ windowKey ] = newWindow ;
79+ }
80+ #endif
81+
82+ /// <summary>
83+ /// Gets or sets the last opened <see cref="CommandBarFlyout"/>.
84+ /// </summary>
85+ public static CommandBarFlyout ? LastOpenedFlyout
86+ {
87+ set
88+ {
89+ _LastOpenedFlyout = value ;
90+
91+ if ( _LastOpenedFlyout is not null )
92+ _LastOpenedFlyout . Closed += LastOpenedFlyout_Closed ;
93+ }
94+ }
95+
96+ /// <summary>
97+ /// Invoked when Navigation to a certain page fails
98+ /// </summary>
99+ /// <param name="sender">The <see cref="Frame"/> which failed navigation</param>
100+ /// <param name="e">Details about the navigation failure</param>
101+ public virtual void OnNavigationFailed ( object sender , NavigationFailedEventArgs e )
102+ => throw new Exception ( "Failed to load Page "
103+ #if Wpf
104+ + e . Uri ) ;
105+ #else
106+ + e . SourcePageType . FullName ) ;
107+ #endif
108+
109+ #if ! Wpf
110+ /// <summary>
111+ /// Invoked when the application execution is being suspended.
112+ /// </summary>
113+ /// <remarks>
114+ /// This is the standard method to save application state before the application is suspended.
115+ /// You can override it to save additional state, but you should always call the base implementation.
116+ /// </remarks>
117+ /// <param name="sender">The source of the suspend request.</param>
118+ /// <param name="e">Details about the suspend request.</param>
119+ public virtual void OnSuspending ( object sender , SuspendingEventArgs e )
120+ {
121+ SuspendingDeferral deferral = e . SuspendingOperation . GetDeferral ( ) ;
122+ deferral . Complete ( ) ;
123+ }
124+ #endif
125+
126+ /// <summary>
127+ /// Invoked when an unobserved task exception occurs.
128+ /// </summary>
129+ /// <param name="sender">The source of the unobserved task exception.</param>
130+ /// <param name="e">Details about the unobserved task exception.</param>
131+ public virtual void OnUnobservedException ( object ? sender , UnobservedTaskExceptionEventArgs e )
132+ => e . SetObserved ( ) ;
133+
134+ /// <summary>
135+ /// Invoked when an unhandled exception occurs.
136+ /// </summary>
137+ /// <remarks>
138+ /// This is the standard method to handle unhandled exceptions.
139+ /// You can override it to provide custom exception handling, but you should always call the base implementation.
140+ ///
141+ /// This base version also raises a new <see cref="ContentDialog"/> to display the exception message.
142+ /// </remarks>
143+ /// <param name="sender">The source of the unhandled exception.</param>
144+ /// <param name="e">Details about the unhandled exception.</param>
145+ public async virtual void OnUnhandledException ( object ? sender ,
146+ #if UWP
147+ Windows . UI . Xaml . UnhandledExceptionEventArgs e )
148+ #elif WinUI
149+ Microsoft. UI . Xaml . UnhandledExceptionEventArgs e )
150+ #else
151+ UnhandledExceptionEventArgs e)
152+ #endif
153+ {
154+ try
155+ {
156+ await new ContentDialog
157+ {
158+ Title = "Unhandled exception" ,
159+ Content =
160+ #if UWP
161+ e . Message ,
162+ #else
163+ "An unhandled exception occured." ,
164+ #endif
165+ CloseButtonText = "Close"
166+ }
167+ . ShowAsync ( ) ;
168+ }
169+ catch { }
170+ }
171+
172+ /// <summary>
173+ /// Gets invoked when the last opened flyout is closed.
174+ /// </summary>
175+ private static void LastOpenedFlyout_Closed ( object ? sender , object e )
176+ {
177+ if ( sender is not CommandBarFlyout commandBarFlyout )
178+ return ;
179+
180+ commandBarFlyout . Closed -= LastOpenedFlyout_Closed ;
181+ if ( _LastOpenedFlyout == commandBarFlyout )
182+ _LastOpenedFlyout = null ;
183+ }
184+ }
0 commit comments