@@ -39,6 +39,12 @@ public class Manager
3939
4040 private static readonly BlockingCollection < ExecutionState > _stateQueue ;
4141
42+ // Core icons used for the tray
43+ private static readonly Icon _timedIcon = new ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "Assets/Awake/timed.ico" ) ) ;
44+ private static readonly Icon _expirableIcon = new ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "Assets/Awake/expirable.ico" ) ) ;
45+ private static readonly Icon _indefiniteIcon = new ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "Assets/Awake/indefinite.ico" ) ) ;
46+ private static readonly Icon _disabledIcon = new ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "Assets/Awake/disabled.ico" ) ) ;
47+
4248 private static CancellationTokenSource _tokenSource ;
4349
4450 private static SettingsUtils ? _moduleSettings ;
@@ -135,7 +141,7 @@ internal static void SetIndefiniteKeepAwake(bool keepDisplayOn = false)
135141
136142 _stateQueue . Add ( ComputeAwakeState ( keepDisplayOn ) ) ;
137143
138- TrayHelper . SetShellIcon ( TrayHelper . HiddenWindowHandle , $ "{ Constants . FullAppName } [{ Resources . AWAKE_TRAY_TEXT_INDEFINITE } ]", new Icon ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "Assets/Awake/indefinite.ico" ) ) , TrayIconAction . Update ) ;
144+ TrayHelper . SetShellIcon ( TrayHelper . HiddenWindowHandle , $ "{ Constants . FullAppName } [{ Resources . AWAKE_TRAY_TEXT_INDEFINITE } ]", _indefiniteIcon , TrayIconAction . Update ) ;
139145
140146 if ( IsUsingPowerToysConfig )
141147 {
@@ -172,14 +178,23 @@ internal static void SetExpirableKeepAwake(DateTimeOffset expireAt, bool keepDis
172178 Logger . LogInfo ( $ "Starting expirable log for { expireAt } ") ;
173179 _stateQueue . Add ( ComputeAwakeState ( keepDisplayOn ) ) ;
174180
175- TrayHelper . SetShellIcon ( TrayHelper . HiddenWindowHandle , $ "{ Constants . FullAppName } [{ Resources . AWAKE_TRAY_TEXT_EXPIRATION } ]", new Icon ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "Assets/Awake/expirable.ico" ) ) , TrayIconAction . Update ) ;
181+ TrayHelper . SetShellIcon ( TrayHelper . HiddenWindowHandle , $ "{ Constants . FullAppName } [{ Resources . AWAKE_TRAY_TEXT_EXPIRATION } - { expireAt } ]", _expirableIcon , TrayIconAction . Update ) ;
176182
177183 Observable . Timer ( expireAt - DateTimeOffset . Now ) . Subscribe (
178184 _ =>
179185 {
180186 Logger . LogInfo ( $ "Completed expirable keep-awake.") ;
181187 CancelExistingThread ( ) ;
182- SetPassiveKeepAwake ( ) ;
188+
189+ if ( IsUsingPowerToysConfig )
190+ {
191+ SetPassiveKeepAwake ( ) ;
192+ }
193+ else
194+ {
195+ Logger . LogInfo ( "Exiting after expirable keep awake." ) ;
196+ CompleteExit ( Environment . ExitCode ) ;
197+ }
183198 } ,
184199 _tokenSource . Token ) ;
185200 }
@@ -224,16 +239,40 @@ internal static void SetTimedKeepAwake(uint seconds, bool keepDisplayOn = true)
224239 Logger . LogInfo ( $ "Timed keep awake started for { seconds } seconds.") ;
225240 _stateQueue . Add ( ComputeAwakeState ( keepDisplayOn ) ) ;
226241
227- TrayHelper . SetShellIcon ( TrayHelper . HiddenWindowHandle , $ "{ Constants . FullAppName } [{ Resources . AWAKE_TRAY_TEXT_TIMED } ]", new Icon ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "Assets/Awake/timed.ico" ) ) , TrayIconAction . Update ) ;
242+ TrayHelper . SetShellIcon ( TrayHelper . HiddenWindowHandle , $ "{ Constants . FullAppName } [{ Resources . AWAKE_TRAY_TEXT_TIMED } ]", _timedIcon , TrayIconAction . Update ) ;
228243
229- Observable . Timer ( TimeSpan . FromSeconds ( seconds ) ) . Subscribe (
230- _ =>
231- {
232- Logger . LogInfo ( $ "Completed timed thread.") ;
233- CancelExistingThread ( ) ;
234- SetPassiveKeepAwake ( ) ;
235- } ,
236- _tokenSource . Token ) ;
244+ var timerObservable = Observable . Timer ( TimeSpan . FromSeconds ( seconds ) ) ;
245+ var intervalObservable = Observable . Interval ( TimeSpan . FromSeconds ( 1 ) ) . TakeUntil ( timerObservable ) ;
246+
247+ var combinedObservable = Observable . CombineLatest ( intervalObservable , timerObservable . StartWith ( 0 ) , ( elapsedSeconds , _ ) => elapsedSeconds + 1 ) ;
248+
249+ combinedObservable . Subscribe (
250+ elapsedSeconds =>
251+ {
252+ var timeRemaining = seconds - ( uint ) elapsedSeconds ;
253+ if ( timeRemaining >= 0 )
254+ {
255+ TrayHelper . SetShellIcon ( TrayHelper . HiddenWindowHandle , $ "{ Constants . FullAppName } [{ Resources . AWAKE_TRAY_TEXT_TIMED } ]\n { TimeSpan . FromSeconds ( timeRemaining ) . ToHumanReadableString ( ) } ", _timedIcon , TrayIconAction . Update ) ;
256+ }
257+ } ,
258+ ( ) =>
259+ {
260+ Console . WriteLine ( "Completed timed thread." ) ;
261+ CancelExistingThread ( ) ;
262+
263+ if ( IsUsingPowerToysConfig )
264+ {
265+ // If we're using PowerToys settings, we need to make sure that
266+ // we just switch over the Passive Keep-Awake.
267+ SetPassiveKeepAwake ( ) ;
268+ }
269+ else
270+ {
271+ Logger . LogInfo ( "Exiting after timed keep-awake." ) ;
272+ CompleteExit ( Environment . ExitCode ) ;
273+ }
274+ } ,
275+ _tokenSource . Token ) ;
237276
238277 if ( IsUsingPowerToysConfig )
239278 {
@@ -264,9 +303,7 @@ internal static void SetTimedKeepAwake(uint seconds, bool keepDisplayOn = true)
264303 /// Performs a clean exit from Awake.
265304 /// </summary>
266305 /// <param name="exitCode">Exit code to exit with.</param>
267- /// <param name="exitSignal">Exit signal tracking the state.</param>
268- /// <param name="force">Determines whether to force exit and post a quitting message.</param>
269- internal static void CompleteExit ( int exitCode , ManualResetEvent ? exitSignal , bool force = false )
306+ internal static void CompleteExit ( int exitCode )
270307 {
271308 SetPassiveKeepAwake ( updateSettings : false ) ;
272309
@@ -277,22 +314,12 @@ internal static void CompleteExit(int exitCode, ManualResetEvent? exitSignal, bo
277314
278315 // Close the message window that we used for the tray.
279316 Bridge . SendMessage ( TrayHelper . HiddenWindowHandle , Native . Constants . WM_CLOSE , 0 , 0 ) ;
280- }
281-
282- if ( force )
283- {
284- Bridge . PostQuitMessage ( exitCode ) ;
285- }
286317
287- try
288- {
289- exitSignal ? . Set ( ) ;
290318 Bridge . DestroyWindow ( TrayHelper . HiddenWindowHandle ) ;
291319 }
292- catch ( Exception ex )
293- {
294- Logger . LogError ( $ "Exit signal error ${ ex } ") ;
295- }
320+
321+ Bridge . PostQuitMessage ( exitCode ) ;
322+ Environment . Exit ( exitCode ) ;
296323 }
297324
298325 /// <summary>
@@ -350,7 +377,7 @@ internal static void SetPassiveKeepAwake(bool updateSettings = true)
350377
351378 CancelExistingThread ( ) ;
352379
353- TrayHelper . SetShellIcon ( TrayHelper . HiddenWindowHandle , $ "{ Constants . FullAppName } [{ Resources . AWAKE_TRAY_TEXT_OFF } ]", new Icon ( Path . Combine ( AppDomain . CurrentDomain . BaseDirectory , "Assets/Awake/disabled.ico" ) ) , TrayIconAction . Update ) ;
380+ TrayHelper . SetShellIcon ( TrayHelper . HiddenWindowHandle , $ "{ Constants . FullAppName } [{ Resources . AWAKE_TRAY_TEXT_OFF } ]", _disabledIcon , TrayIconAction . Update ) ;
354381
355382 if ( IsUsingPowerToysConfig && updateSettings )
356383 {
0 commit comments