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:
1 parent
be526711d7
commit
462f9f8c9f
18 files changed
+324
-47
No files matched your search
+25
@@ -0,0 +1,25 @@
|
||||
package de.jeanlucmakiola.clockula.domain.widget
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class ClockWidgetTapTargetTest {
|
||||
|
||||
@Test
|
||||
fun `null parses to Alarms, so clock widgets placed before the setting existed open Alarms`() {
|
||||
assertThat(parseClockWidgetTapTarget(null)).isEqualTo(ClockWidgetTapTarget.ALARMS)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `an unknown name parses to Alarms`() {
|
||||
assertThat(parseClockWidgetTapTarget("Nonexistent")).isEqualTo(ClockWidgetTapTarget.ALARMS)
|
||||
assertThat(parseClockWidgetTapTarget("")).isEqualTo(ClockWidgetTapTarget.ALARMS)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `each tap target's own name round-trips`() {
|
||||
ClockWidgetTapTarget.entries.forEach { target ->
|
||||
assertThat(parseClockWidgetTapTarget(target.name)).isEqualTo(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -238,4 +238,24 @@ class ShellNavigationTest {
|
||||
|
||||
assertThat(answers).containsExactly(ClockulaDestination.TIMERS, null, null).inOrder()
|
||||
}
|
||||
|
||||
// --- #8: a widget picks the tab it opens ---
|
||||
|
||||
@Test
|
||||
fun `every tab's show action asks for that tab`() {
|
||||
val resolved = ClockulaDestination.entries.map {
|
||||
ShellNavigation.tabForAction(ShellNavigation.showActionOf(it))
|
||||
}
|
||||
|
||||
assertThat(resolved).isEqualTo(ClockulaDestination.entries.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `every tab's show action opens it as a plain tab request`() {
|
||||
val requests = ClockulaDestination.entries.map {
|
||||
ShellNavigation.requestFor(ShellNavigation.showActionOf(it), null, emptyList())
|
||||
}
|
||||
|
||||
assertThat(requests).isEqualTo(ClockulaDestination.entries.map(ShellRequest::OpenTab))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package de.jeanlucmakiola.clockula.ui.widget
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import de.jeanlucmakiola.clockula.domain.widget.ClockWidgetTapTarget
|
||||
import de.jeanlucmakiola.clockula.domain.widget.parseClockWidgetTapTarget
|
||||
import de.jeanlucmakiola.clockula.ui.shell.ClockulaDestination
|
||||
import de.jeanlucmakiola.clockula.ui.shell.ShellNavigation
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
/**
|
||||
* A clock widget's tap (#8) reaches `MainActivity` as an action, and the shell
|
||||
* maps that action back to a tab: the round trip has to come out on the tab
|
||||
* the user picked, for every one of them.
|
||||
*/
|
||||
class ClockTapTargetTest {
|
||||
|
||||
@Test
|
||||
fun `every tap target is the tab of the same name, in the same order`() {
|
||||
val destinations = ClockWidgetTapTarget.entries.map { it.destination }
|
||||
|
||||
assertThat(destinations).isEqualTo(ClockulaDestination.entries.toList())
|
||||
ClockWidgetTapTarget.entries.forEach { assertThat(it.destination.name).isEqualTo(it.name) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `every tap target's action opens its own tab`() {
|
||||
ClockWidgetTapTarget.entries.forEach { target ->
|
||||
val action = ShellNavigation.showActionOf(target.destination)
|
||||
|
||||
assertThat(ShellNavigation.tabForAction(action)).isEqualTo(target.destination)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a widget with no stored tap target opens alarms`() {
|
||||
assertThat(parseClockWidgetTapTarget(null).destination).isEqualTo(ClockulaDestination.ALARMS)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user