Skip to content

Commit 4333a58

Browse files
committed
Add minimize when expired option and a menu item.
1 parent a56b1d4 commit 4333a58

15 files changed

Lines changed: 308 additions & 59 deletions

File tree

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ jobs:
5858
run: dotnet test --configuration "${{env.CONFIG_PORTABLE}}" --no-build --verbosity normal
5959

6060
- name: Create ${{env.NAME}} ${{env.CONFIG_PORTABLE}} test report
61-
uses: dorny/test-reporter@v2.2.0
61+
uses: dorny/test-reporter@v2.3.0
6262
if: ${{success() || failure()}}
6363
with:
6464
name: tests
@@ -68,7 +68,7 @@ jobs:
6868
# Upload artifacts
6969

7070
- name: Publish ${{env.NAME}} ${{env.CONFIG}} Installer
71-
uses: actions/upload-artifact@v5.0.0
71+
uses: actions/upload-artifact@v6.0.0
7272
with:
7373
name: ${{env.NAME}}Installer
7474
path: |
@@ -77,7 +77,7 @@ jobs:
7777
retention-days: ${{env.RETENTION_DAYS}}
7878

7979
- name: Publish ${{env.NAME}} ${{env.CONFIG_PORTABLE}}
80-
uses: actions/upload-artifact@v5.0.0
80+
uses: actions/upload-artifact@v6.0.0
8181
with:
8282
name: ${{env.NAME}}Portable
8383
path: |
@@ -88,7 +88,7 @@ jobs:
8888
retention-days: ${{env.RETENTION_DAYS}}
8989

9090
- name: Publish ${{env.NAUDIO_ARTIFACT}}
91-
uses: actions/upload-artifact@v5.0.0
91+
uses: actions/upload-artifact@v6.0.0
9292
with:
9393
name: ${{env.NAUDIO_ARTIFACT}}
9494
path: |

FAQ.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ The original **Hourglass** FAQ can be found [here](https://chris.dziemborowicz.c
4545
- [How to enable the Hourglass Jump List?](#how-to-enable-the-hourglass-jump-list)
4646
- [How to disable the Hourglass thumbnail toolbar?](#how-to-disable-the-hourglass-thumbnail-toolbar)
4747
- [How to always open the Hourglass timer windows centered?](#how-to-always-open-the-hourglass-timer-windows-centered)
48+
- [How to configure delay timeouts for automatic close, minimize or shut down when expired?](#how-to-configure-delay-timeouts-for-automatic-close-minimize-or-shut-down-when-expired)
4849
- [What should I do if the Hourglass does not start?](#what-should-i-do-if-the-hourglass-does-not-start)
4950
- [What should I do if there is no notification sound?](#what-should-i-do-if-there-is-no-notification-sound)
5051

@@ -484,6 +485,23 @@ The **Hourglass Portable** keeps settings next to the executable in the `Hourgla
484485
3. Set `AlwaysCenterWindow` to `True`.
485486
4. Launch the **Hourglass**.
486487

488+
## How to configure delay timeouts for automatic close, minimize or shut down when expired?
489+
490+
By default, when **Close when expired**, **Minimize when expired** or **Shut down when expired** options are enabled, the action is performed immediately after the timer expires. You can configure a delay timeout **in seconds** before the action is performed.
491+
492+
1. Exit the **Hourglass**.
493+
2. Open the `Hourglass.config` or `user.config` [settings](#how-to-find-the-hourglass-settings) file.
494+
3. Set one or more of the following values:
495+
- `CloseWhenExpiredSeconds` - delay in seconds before closing the timer window when **Close when expired** is enabled (default is `0`)
496+
- `MinimizeWhenExpiredSeconds` - delay in seconds before minimizing the timer window when **Minimize when expired** is enabled (default is `0`)
497+
- `ShutDownWhenExpiredSeconds` - delay in seconds before shutting down Windows when **Shut down when expired** is enabled (default is `0`)
498+
4. Launch the **Hourglass**.
499+
500+
> [!NOTE]
501+
> - Setting the value to `0` means the action will be performed immediately.
502+
> - The maximum allowed timeout value is `3600` seconds (`1 hour`).
503+
> - These settings only apply when the corresponding **Close when expired**, **Minimize when expired** or **Shut down when expired** options are enabled in the timer window context menu or via command-line.
504+
487505
## What should I do if the Hourglass does not start?
488506

489507
> [!IMPORTANT]

Hourglass/CommandLineArguments.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ public static string Usage
142142
/// </summary>
143143
public bool CloseWhenExpired { get; private set; }
144144

145+
/// <summary>
146+
/// Gets a value indicating whether the timer window should be minimized when the timer expires.
147+
/// </summary>
148+
public bool MinimizeWhenExpired { get; private set; }
149+
145150
/// <summary>
146151
/// Gets a value indicating whether Windows should be shut down when the timer expires.
147152
/// </summary>
@@ -329,6 +334,7 @@ public TimerOptions GetTimerOptions()
329334
PauseBeforeLoopTimer = PauseBeforeLoopTimer,
330335
PopUpWhenExpired = PopUpWhenExpired,
331336
CloseWhenExpired = CloseWhenExpired,
337+
MinimizeWhenExpired = MinimizeWhenExpired,
332338
ShutDownWhenExpired = ShutDownWhenExpired,
333339
Theme = Theme,
334340
Sound = Sound,
@@ -378,6 +384,7 @@ private static CommandLineArguments GetArgumentsFromMostRecentOptions()
378384
PauseBeforeLoopTimer = options.PauseBeforeLoopTimer,
379385
PopUpWhenExpired = options.PopUpWhenExpired,
380386
CloseWhenExpired = options.CloseWhenExpired,
387+
MinimizeWhenExpired = options.MinimizeWhenExpired,
381388
ShutDownWhenExpired = options.ShutDownWhenExpired,
382389
Theme = options.Theme,
383390
Sound = options.Sound,
@@ -424,6 +431,7 @@ private static CommandLineArguments GetArgumentsFromFactoryDefaults()
424431
PauseBeforeLoopTimer = defaultOptions.PauseBeforeLoopTimer,
425432
PopUpWhenExpired = defaultOptions.PopUpWhenExpired,
426433
CloseWhenExpired = defaultOptions.CloseWhenExpired,
434+
MinimizeWhenExpired = defaultOptions.MinimizeWhenExpired,
427435
ShutDownWhenExpired = defaultOptions.ShutDownWhenExpired,
428436
Theme = defaultOptions.Theme,
429437
Sound = defaultOptions.Sound,
@@ -701,6 +709,20 @@ private static CommandLineArguments GetCommandLineArguments(IEnumerable<string>
701709
argumentsBasedOnFactoryDefaults.CloseWhenExpired = closeWhenExpired;
702710
break;
703711

712+
case "--minimize-when-expired":
713+
case "-em":
714+
case "/em":
715+
ThrowIfDuplicateSwitch(specifiedSwitches, "--minimize-when-expired");
716+
717+
bool minimizeWhenExpired = GetBoolValue(
718+
arg,
719+
remainingArgs,
720+
argumentsBasedOnMostRecentOptions.MinimizeWhenExpired);
721+
722+
argumentsBasedOnMostRecentOptions.MinimizeWhenExpired = minimizeWhenExpired;
723+
argumentsBasedOnFactoryDefaults.MinimizeWhenExpired = minimizeWhenExpired;
724+
break;
725+
704726
case "--shut-down-when-expired":
705727
case "-x":
706728
case "/x":

Hourglass/Extensions/TimerWindowExtensions.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,41 +80,49 @@ bool NotThisWindow(TimerWindow thisWindow) =>
8080
}
8181
}
8282

83-
public void HideExpiredAfterDelay()
83+
public void ExecuteWhenExpiredAfterDelay(bool shouldExecute, TimeSpan? executeWhenExpiredTimeout, Action<TimerWindow?> action , bool executeWhenNoWindow = false)
8484
{
85-
if (window.Options.LockInterface)
85+
if (!shouldExecute)
8686
{
8787
return;
8888
}
8989

90-
var minimizeWhenExpired = Settings.Default.MinimizeWhenExpiredTimeout;
90+
window.UndoExecuteWhenExpired = false;
9191

92-
if (minimizeWhenExpired is null ||
93-
window.WindowState == WindowState.Minimized ||
94-
!window.IsVisible)
92+
if (executeWhenExpiredTimeout is null)
9593
{
94+
ExecuteWhenExpired(window);
9695
return;
9796
}
9897

99-
window.IsWindowStateChanged = false;
100-
10198
var windowWeakReference = new WeakReference<TimerWindow>(window);
10299

103100
var dispatcherTimer = new DispatcherTimer
104101
{
105-
Interval = minimizeWhenExpired.Value
102+
Interval = executeWhenExpiredTimeout.Value
106103
};
107104
dispatcherTimer.Tick += DispatcherTimerTick;
108105
dispatcherTimer.Start();
109106

110107

108+
void ExecuteWhenExpired(TimerWindow? targetWindow)
109+
{
110+
if (executeWhenNoWindow || targetWindow?.UndoExecuteWhenExpired == false)
111+
{
112+
action(targetWindow);
113+
targetWindow?.UndoExecuteWhenExpired = false;
114+
}
115+
}
116+
111117
void DispatcherTimerTick(object sender, EventArgs e)
112118
{
113119
((DispatcherTimer)sender).Stop();
114120

115-
if (windowWeakReference.TryGetTarget(out var targetWindow) && !targetWindow.IsWindowStateChanged)
121+
TimerWindow? targetWindow = null;
122+
123+
if (executeWhenNoWindow || windowWeakReference.TryGetTarget(out targetWindow))
116124
{
117-
targetWindow.WindowState = WindowState.Minimized;
125+
ExecuteWhenExpired(targetWindow);
118126
}
119127
}
120128
}

Hourglass/Properties/Resources.Designer.cs

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Hourglass/Properties/Resources.resx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -1368,6 +1368,14 @@ $</value>
13681368
<value>Prefer 24-_hour time when parsing</value>
13691369
<comment>The text for the prefer 24-hour time when parsing menu item, where the character following the optional underscore (_) is the access key</comment>
13701370
</data>
1371+
<data name="ContextMenuMinimizeWhenExpiredMenuItem" xml:space="preserve">
1372+
<value>Minimize when _expired</value>
1373+
<comment>The text for the minimize when expired menu item, where the character following the optional underscore (_) is the access key</comment>
1374+
</data>
1375+
<data name="ContextMenuTimeoutAfterPreposition" xml:space="preserve">
1376+
<value> after </value>
1377+
<comment>The preposition used to separate the menu item text from the timeout duration (e.g., "Close when expired after 5 seconds")</comment>
1378+
</data>
13711379
<data name="ContextMenuDigitalClockTimeMenuItem" xml:space="preserve">
13721380
<value>Display time in the digital _clock format</value>
13731381
<comment>The text for the display time in the digital clock format when displaying menu item, where the character following the optional underscore (_) is the access key</comment>

Hourglass/Properties/Settings.Designer.cs

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Hourglass/Properties/Settings.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,17 @@ public WindowSize? WindowSize
6969
set => WindowSizeInfo = WindowSizeInfo.FromWindowSize(value);
7070
}
7171

72-
public TimeSpan? MinimizeWhenExpiredTimeout
73-
{
74-
get
75-
{
76-
Default.Reload();
72+
public TimeSpan? MinimizeWhenExpiredTimeout =>
73+
GetWhenExpiredTimeout(MinimizeWhenExpiredSeconds);
7774

78-
return MinimizeWhenExpiredSeconds is > 0 and <= MaxTimeoutSeconds
79-
? TimeSpan.FromSeconds(MinimizeWhenExpiredSeconds)
80-
: null;
81-
}
82-
}
75+
public TimeSpan? CloseWhenExpiredTimeout =>
76+
GetWhenExpiredTimeout(CloseWhenExpiredSeconds);
77+
78+
public TimeSpan? ShutDownWhenExpiredTimeout =>
79+
GetWhenExpiredTimeout(ShutDownWhenExpiredSeconds);
80+
81+
private static TimeSpan? GetWhenExpiredTimeout(int timeout) =>
82+
timeout is > 0 and <= MaxTimeoutSeconds
83+
? TimeSpan.FromSeconds(timeout)
84+
: null;
8385
}

Hourglass/Properties/Settings.settings

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version='1.0' encoding='utf-8'?>
1+
<?xml version='1.0' encoding='utf-8'?>
22
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="Hourglass.Properties" GeneratedClassName="Settings">
33
<Profiles />
44
<Settings>
@@ -69,4 +69,7 @@
6969
<Value Profile="(Default)">0</Value>
7070
</Setting>
7171
</Settings>
72-
</SettingsFile>
72+
<Setting Name="ShutDownWhenExpiredSeconds" Type="System.Int32" Scope="User">
73+
<Value Profile="(Default)">0</Value>
74+
</Setting>
75+
</SettingsFile>

Hourglass/Resources/Usage.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,28 @@ Options:
167167
--close-when-expired on|off|last
168168
Closes the timer window when the timer expires.
169169

170+
CloseWhenExpiredSeconds configuration setting specifies close timeout.
171+
170172
Required no
171173
Default value last
172174
Alias -e, /e
173175

176+
--minimize-when-expired on|off|last
177+
Minimizes the timer window when the timer expires.
178+
179+
MinimizeWhenExpiredSeconds configuration setting specifies minimize
180+
timeout.
181+
182+
Required no
183+
Default value last
184+
Alias -em, /em
185+
174186
--shut-down-when-expired on|off
175187
Shuts down windows when the timer expires.
176188

189+
ShutDownWhenExpiredSeconds configuration setting specifies shut down
190+
timeout.
191+
177192
Required no
178193
Default value off
179194
Alias -x, /x
@@ -353,6 +368,7 @@ Options:
353368
--pause-after-loop-timer -pl off
354369
--pop-up-when-expired -p on
355370
--close-when-expired -e off
371+
--minimize-when-expired -em off
356372
--shut-down-when-expired -x off
357373
--theme -m accent
358374
--sound -s normal beep

0 commit comments

Comments
 (0)