mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-11-06 18:54:49 +01:00
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
|
val current = serverRepository.current.value
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
Timber.i("Received valid intent, switching to AppContent")
|
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(
|
setupNavigationManager.navigateTo(
|
||||||
SetupDestination.AppContent(current),
|
SetupDestination.AppContent(current),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,11 @@ class IntentService
|
||||||
Timber.v("Parsing intent %s", intent)
|
Timber.v("Parsing intent %s", intent)
|
||||||
Timber.v("Intent extras: %s", intent.extras)
|
Timber.v("Intent extras: %s", intent.extras)
|
||||||
Timber.v("Intent data: %s", intent.data)
|
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
|
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
|
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") {
|
if (action == Intent.ACTION_SEARCH || action == "search") {
|
||||||
val query = intent.getStringParam(SearchManager.QUERY)
|
val query = intent.getStringParam(SearchManager.QUERY)
|
||||||
return IntentResult.Target(Destination.Search(query ?: ""))
|
return IntentResult.Target(listOf(Destination.Search(query ?: "")))
|
||||||
}
|
}
|
||||||
val itemId =
|
val itemId =
|
||||||
intent.getStringParam("itemId")?.toUUIDOrNull()
|
intent.getStringParam("itemId")?.toUUIDOrNull()
|
||||||
|
|
@ -84,25 +93,39 @@ class IntentService
|
||||||
return IntentResult.Error("Could not fetch item $itemId")
|
return IntentResult.Error("Could not fetch item $itemId")
|
||||||
}
|
}
|
||||||
|
|
||||||
val destination =
|
val itemDestination = item.destination()
|
||||||
|
|
||||||
|
val destinations =
|
||||||
when (action) {
|
when (action) {
|
||||||
Intent.ACTION_VIEW, "view" -> {
|
Intent.ACTION_VIEW, "view" -> {
|
||||||
item.destination()
|
listOf(itemDestination)
|
||||||
}
|
}
|
||||||
|
|
||||||
"com.github.damontecres.wholphin.PLAYBACK", "play" -> {
|
"com.github.damontecres.wholphin.PLAYBACK", "play" -> {
|
||||||
val position = intent.getLongParam("position")?.coerceAtLeast(0)
|
val position = intent.getLongParam("position")?.coerceAtLeast(0)
|
||||||
Destination.Playback(
|
|
||||||
itemId = itemId,
|
val playbackDestination =
|
||||||
positionMs = position ?: 0L,
|
Destination.Playback(
|
||||||
)
|
itemId = itemId,
|
||||||
|
positionMs = position ?: 0L,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (itemDestination is Destination.Playback) {
|
||||||
|
listOf(playbackDestination)
|
||||||
|
} else {
|
||||||
|
listOf(
|
||||||
|
itemDestination,
|
||||||
|
playbackDestination,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
return IntentResult.Error("Invalid action: ${intent.action}")
|
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)
|
private fun Intent.getStringParam(key: String) = getStringExtra(key) ?: data?.getQueryParameter(key)
|
||||||
|
|
@ -159,6 +182,7 @@ sealed interface IntentResult {
|
||||||
data object NoOp : IntentResult
|
data object NoOp : IntentResult
|
||||||
|
|
||||||
data class Target(
|
data class Target(
|
||||||
val destination: Destination,
|
val destinations: List<Destination>,
|
||||||
|
val addHomeToBackStack: Boolean = true,
|
||||||
) : IntentResult
|
) : IntentResult
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue