feat(widgets): open Alarms from the clock widgets, or a tab of your choice

Tapping the digital or analog clock widget now opens Alarms instead of
World clock, and both config screens gain an "On tap" setting (Alarms,
Timers, Stopwatch, World clock) stored per instance next to the style.
Instances placed before the setting existed open Alarms. The analog
config becomes a settings screen like the digital one, with the style
behind a row, to make room for it.

A widget tap sometimes showed whatever the app was last on instead of
its tab, for two reasons. The shell replayed a deep link as a tab tap
with restoreState, so it restored the tab's saved back stack, nested
screen and all (fixed by the pager shell, which pops to the tab). And
the widget intents carried only NEW_TASK, so with a picker or settings
page left on top of MainActivity the task was merely brought forward and
onNewIntent never ran. Every widget that opens the app now builds its
intent in one place with CLEAR_TOP and SINGLE_TOP as well.

Closes #8
This commit is contained in:
2026-10-05 19:42:14 +02:00
parent be526711d7
commit 462f9f8c9f
18 changed files with 324 additions and 47 deletions
+7 -1
View File
@@ -1334,7 +1334,13 @@ The policy the shell follows is a pure function, `ShellNavigation`:
one loses nothing;
- a tab an intent asks for (a notification, a widget, the exported door) is the
same pop and a jump — it always lands on the tab itself, never on whatever
nested screen was last open there;
nested screen was last open there. Widgets build that intent in one place,
`openAppIntent`, with `CLEAR_TOP` + `SINGLE_TOP` beside `NEW_TASK`, so an
activity left on top of `MainActivity` in its task (a picker the editor
opened) is finished and the intent reaches `onNewIntent` rather than the
task merely being brought forward. The two clock widgets open the tab picked
per instance in their config screen (`ClockWidgetTapTarget`, stored next to
the style; Alarms when unset — #8);
- back from any of the other three tabs returns to **Alarms**; back from Alarms
and from a null route leaves the app, and a nested screen's back belongs to
the `NavController`, not to us.