Add back stack for deep link navigation (#1756)
## Description When testing the new deep link feature from this PR [#1688](https://github.com/damontecres/Wholphin/pull/1688) I noticed that the back button would close the app. As in, all routes are cleared and only the playback is in the nav stack. I figured a more desirable behavior would be to create a nav stack, always starting with the home screen, then also inserting the media item's details page, if available. To achieve this, I made the return Target.destinations a list of destinations, and updated the other two uses in IntentService. Open to implementation tweaks, or scrap it if this isn't how it should work, haha. ### Testing Tested deep links, which produced the following nav stacks: - Movie view - Home → Movie details - Movie playback (with and without position) - Home → Movie details → Playback - Series view - Home → Series details - Season view - Home → Season details - Episode view - Home → Episode details - Episode playback (with and without position) - Home → Episode details → Playback - Trailer/extras playback (no details page available) - Home → Playback - TV channel view - Home → Playback - TV channel playback - Home → Playback ## AI or LLM usage AI was used to generate the initial code, debug and test, then manual refactoring and cleanup was done. --------- Co-authored-by: Damontecres <damontecres@gmail.com>
This commit is contained in:
parent
a0966dd05a
commit
c1abb57cd2
2 changed files with 46 additions and 15 deletions
|
|
@ -449,7 +449,14 @@ class MainActivityViewModel
|
|||
val current = serverRepository.current.value
|
||||
if (current != null) {
|
||||
Timber.i("Received valid intent, switching to AppContent")
|
||||
navigationManager.replace(result.destination)
|
||||
|
||||
if (result.addHomeToBackStack) {
|
||||
navigationManager.reloadHome()
|
||||
} else {
|
||||
navigationManager.backStack.clear()
|
||||
}
|
||||
navigationManager.backStack.addAll(result.destinations)
|
||||
|
||||
setupNavigationManager.navigateTo(
|
||||
SetupDestination.AppContent(current),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -27,12 +27,11 @@ class IntentService
|
|||
Timber.v("Parsing intent %s", intent)
|
||||
Timber.v("Intent extras: %s", intent.extras)
|
||||
Timber.v("Intent data: %s", intent.data)
|
||||
if (intent.getStringParam("type") != null) {
|
||||
return getDestinationFromChannel(intent)?.let { IntentResult.Target(it) }
|
||||
?: IntentResult.Error("Invalid parameters")
|
||||
}
|
||||
val action = intent.action ?: intent.data?.host
|
||||
if (action == Intent.ACTION_MAIN || action.isNullOrBlank()) {
|
||||
if (
|
||||
intent.getStringParam("type") == null &&
|
||||
(action == Intent.ACTION_MAIN || action.isNullOrBlank())
|
||||
) {
|
||||
return IntentResult.NoOp
|
||||
}
|
||||
|
||||
|
|
@ -65,9 +64,19 @@ class IntentService
|
|||
}
|
||||
}
|
||||
|
||||
if (intent.getStringParam("type") != null) {
|
||||
return getDestinationFromChannel(intent)?.let {
|
||||
IntentResult.Target(
|
||||
destinations = listOf(it),
|
||||
addHomeToBackStack = false,
|
||||
)
|
||||
}
|
||||
?: IntentResult.Error("Invalid parameters")
|
||||
}
|
||||
|
||||
if (action == Intent.ACTION_SEARCH || action == "search") {
|
||||
val query = intent.getStringParam(SearchManager.QUERY)
|
||||
return IntentResult.Target(Destination.Search(query ?: ""))
|
||||
return IntentResult.Target(listOf(Destination.Search(query ?: "")))
|
||||
}
|
||||
val itemId =
|
||||
intent.getStringParam("itemId")?.toUUIDOrNull()
|
||||
|
|
@ -84,25 +93,39 @@ class IntentService
|
|||
return IntentResult.Error("Could not fetch item $itemId")
|
||||
}
|
||||
|
||||
val destination =
|
||||
val itemDestination = item.destination()
|
||||
|
||||
val destinations =
|
||||
when (action) {
|
||||
Intent.ACTION_VIEW, "view" -> {
|
||||
item.destination()
|
||||
listOf(itemDestination)
|
||||
}
|
||||
|
||||
"com.github.damontecres.wholphin.PLAYBACK", "play" -> {
|
||||
val position = intent.getLongParam("position")?.coerceAtLeast(0)
|
||||
Destination.Playback(
|
||||
itemId = itemId,
|
||||
positionMs = position ?: 0L,
|
||||
)
|
||||
|
||||
val playbackDestination =
|
||||
Destination.Playback(
|
||||
itemId = itemId,
|
||||
positionMs = position ?: 0L,
|
||||
)
|
||||
|
||||
if (itemDestination is Destination.Playback) {
|
||||
listOf(playbackDestination)
|
||||
} else {
|
||||
listOf(
|
||||
itemDestination,
|
||||
playbackDestination,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
return IntentResult.Error("Invalid action: ${intent.action}")
|
||||
}
|
||||
}
|
||||
return IntentResult.Target(destination)
|
||||
|
||||
return IntentResult.Target(destinations)
|
||||
}
|
||||
|
||||
private fun Intent.getStringParam(key: String) = getStringExtra(key) ?: data?.getQueryParameter(key)
|
||||
|
|
@ -159,6 +182,7 @@ sealed interface IntentResult {
|
|||
data object NoOp : IntentResult
|
||||
|
||||
data class Target(
|
||||
val destination: Destination,
|
||||
val destinations: List<Destination>,
|
||||
val addHomeToBackStack: Boolean = true,
|
||||
) : IntentResult
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue