address review: keep notification taps working after recreation

This commit is contained in:
austinried
2026-10-04 00:30:07 +00:00
parent 46ab8f66c4
commit fd3b1ce298
4 changed files with 50 additions and 42 deletions
@@ -24,7 +24,9 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
requestNotificationPermission()
enableEdgeToEdge()
if (intent?.action == ACTION_OPEN_NOW_PLAYING) nowPlayingRequest.intValue++
if (shouldRecordNowPlayingLaunch(intent?.action, restoringState = savedInstanceState != null)) {
nowPlayingRequest.intValue++
}
setContent {
SubtracksTheme {
SubtracksRoot(nowPlayingRequest = nowPlayingRequest.intValue)
@@ -50,3 +52,8 @@ class MainActivity : ComponentActivity() {
const val ACTION_OPEN_NOW_PLAYING = "com.subtracks.action.OPEN_NOW_PLAYING"
}
}
internal fun shouldRecordNowPlayingLaunch(
action: String?,
restoringState: Boolean,
): Boolean = action == MainActivity.ACTION_OPEN_NOW_PLAYING && !restoringState
@@ -166,12 +166,6 @@ internal fun resetOnSourceSwitch(
if (route in DETAIL_ROUTES) popDetail()
}
internal fun shouldOpenNowPlaying(
request: Int,
handled: Int,
playerVisible: Boolean,
): Boolean = playerVisible && request > handled
internal data class BackStackKey(
val route: String?,
val argument: String?,
@@ -227,7 +221,7 @@ private fun MainNavigation(nowPlayingRequest: Int) {
val downloads by downloadRepository.states().collectAsStateWithLifecycle()
var showingQueue by rememberSaveable { mutableStateOf(false) }
var nowPlayingOpen by rememberSaveable { mutableStateOf(false) }
var handledNowPlayingRequest by rememberSaveable { mutableStateOf(0) }
var handledNowPlayingRequest by remember { mutableStateOf(0) }
var nowPlayingProgress by remember { mutableFloatStateOf(0f) }
var miniPlayerTopPx by remember { mutableFloatStateOf(0f) }
var nowPlayingFadeOut by remember { mutableStateOf(false) }
@@ -313,8 +307,11 @@ private fun MainNavigation(nowPlayingRequest: Int) {
}
}
LaunchedEffect(nowPlayingRequest, playerVisible) {
if (shouldOpenNowPlaying(nowPlayingRequest, handledNowPlayingRequest, playerVisible)) {
if (playerVisible && nowPlayingRequest > handledNowPlayingRequest) {
handledNowPlayingRequest = nowPlayingRequest
if (navController.currentDestination?.route in DETAIL_ROUTES) {
navController.popBackStack(Routes.LIBRARY, inclusive = false)
}
settleNowPlaying(true)
}
}
@@ -0,0 +1,37 @@
package com.subtracks
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
class NowPlayingLaunchTest {
@Test
fun aFreshLaunchFromTheNotificationIsRecorded() {
assertTrue(
shouldRecordNowPlayingLaunch(
action = MainActivity.ACTION_OPEN_NOW_PLAYING,
restoringState = false,
),
)
}
@Test
fun recreatingTheActivityDoesNotReRecordTheLaunch() {
assertFalse(
shouldRecordNowPlayingLaunch(
action = MainActivity.ACTION_OPEN_NOW_PLAYING,
restoringState = true,
),
)
}
@Test
fun aNormalLaunchIsNotRecorded() {
assertFalse(shouldRecordNowPlayingLaunch(action = "android.intent.action.MAIN", restoringState = false))
}
@Test
fun aLaunchWithoutAnActionIsNotRecorded() {
assertFalse(shouldRecordNowPlayingLaunch(action = null, restoringState = false))
}
}
@@ -1,33 +0,0 @@
package com.subtracks.ui
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
class NowPlayingRequestTest {
@Test
fun aNotificationWithNothingPlayingDoesNotOpen() {
assertFalse(shouldOpenNowPlaying(request = 1, handled = 0, playerVisible = false))
}
@Test
fun aNotificationWithSomethingPlayingOpens() {
assertTrue(shouldOpenNowPlaying(request = 1, handled = 0, playerVisible = true))
}
@Test
fun anAlreadyHandledRequestDoesNotReopen() {
assertFalse(shouldOpenNowPlaying(request = 1, handled = 1, playerVisible = true))
}
@Test
fun aNewerRequestOpensAgain() {
assertTrue(shouldOpenNowPlaying(request = 2, handled = 1, playerVisible = true))
}
@Test
fun anOldRequestWaitsUntilSomethingIsPlaying() {
assertFalse(shouldOpenNowPlaying(request = 1, handled = 0, playerVisible = false))
assertTrue(shouldOpenNowPlaying(request = 1, handled = 0, playerVisible = true))
}
}