Revamp compose-routing

This commit is contained in:
vfsfitvnm 2022-07-24 23:04:33 +02:00
parent 795bf3d56f
commit fcd84cde43
23 changed files with 122 additions and 474 deletions

View file

@ -43,9 +43,9 @@ import it.vfsfitvnm.vimusic.transaction
import it.vfsfitvnm.vimusic.ui.components.ChunkyButton
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
import it.vfsfitvnm.vimusic.ui.components.Pager
import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute
import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute
import it.vfsfitvnm.vimusic.ui.screens.rememberCreatePlaylistRoute
import it.vfsfitvnm.vimusic.ui.screens.albumRoute
import it.vfsfitvnm.vimusic.ui.screens.artistRoute
import it.vfsfitvnm.vimusic.ui.screens.viewPlaylistsRoute
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.addNext
import it.vfsfitvnm.vimusic.utils.asMediaItem
@ -235,9 +235,6 @@ fun BaseMediaItemMenu(
) {
val context = LocalContext.current
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
MediaItemMenu(
mediaItem = mediaItem,
onDismiss = onDismiss,
@ -299,8 +296,6 @@ fun MediaItemMenu(
Database.playlistPreviews(PlaylistSortBy.DateAdded, SortOrder.Descending)
}.collectAsState(initial = emptyList(), context = Dispatchers.IO)
val viewPlaylistsRoute = rememberCreatePlaylistRoute()
Menu(modifier = modifier) {
RouteHandler(
transitionSpec = {

View file

@ -81,9 +81,7 @@ import kotlinx.coroutines.runBlocking
@ExperimentalAnimationApi
@Composable
fun AlbumScreen(
browseId: String
) {
fun AlbumScreen(browseId: String) {
val lazyListState = rememberLazyListState()
val albumResult by remember(browseId) {
@ -99,21 +97,8 @@ fun AlbumScreen(
Database.albumSongs(browseId)
}.collectAsState(initial = emptyList(), context = Dispatchers.IO)
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val context = LocalContext.current

View file

@ -63,26 +63,11 @@ import kotlinx.coroutines.runBlocking
@ExperimentalAnimationApi
@Composable
fun ArtistScreen(
browseId: String,
) {
fun ArtistScreen(browseId: String) {
val lazyListState = rememberLazyListState()
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val binder = LocalPlayerServiceBinder.current

View file

@ -54,26 +54,11 @@ import kotlinx.coroutines.flow.map
@ExperimentalAnimationApi
@Composable
fun BuiltInPlaylistScreen(
builtInPlaylist: BuiltInPlaylist,
) {
fun BuiltInPlaylistScreen(builtInPlaylist: BuiltInPlaylist) {
val lazyListState = rememberLazyListState()
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val menuState = LocalMenuState.current

View file

@ -108,15 +108,6 @@ fun HomeScreen() {
val lazyListState = rememberLazyListState()
val lazyHorizontalGridState = rememberLazyGridState()
val intentUriRoute = rememberIntentUriRoute()
val settingsRoute = rememberSettingsRoute()
val playlistRoute = rememberLocalPlaylistRoute()
val builtInPlaylistRoute = rememberBuiltInPlaylistRoute()
val searchRoute = rememberSearchRoute()
val searchResultRoute = rememberSearchResultRoute()
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
var playlistSortBy by rememberPreference(playlistSortByKey, PlaylistSortBy.DateAdded)
var playlistSortOrder by rememberPreference(playlistSortOrderKey, SortOrder.Descending)
var playlistGridExpanded by rememberPreference(playlistGridExpandedKey, false)
@ -137,7 +128,7 @@ fun HomeScreen() {
SettingsScreen()
}
playlistRoute { playlistId ->
localPlaylistRoute { playlistId ->
LocalPlaylistScreen(
playlistId = playlistId ?: error("playlistId cannot be null")
)
@ -520,7 +511,7 @@ fun HomeScreen() {
.clickable(
indication = rememberRipple(bounded = true),
interactionSource = remember { MutableInteractionSource() },
onClick = { playlistRoute(playlistPreview.playlist.id) }
onClick = { localPlaylistRoute(playlistPreview.playlist.id) }
)
)
}

View file

@ -54,8 +54,6 @@ import kotlinx.coroutines.withContext
@ExperimentalAnimationApi
@Composable
fun IntentUriScreen(uri: Uri) {
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
val lazyListState = rememberLazyListState()
@ -98,17 +96,7 @@ fun IntentUriScreen(uri: Uri) {
}
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val menuState = LocalMenuState.current

View file

@ -65,30 +65,15 @@ import kotlinx.coroutines.flow.map
@ExperimentalAnimationApi
@Composable
fun LocalPlaylistScreen(
playlistId: Long,
) {
fun LocalPlaylistScreen(playlistId: Long) {
val playlistWithSongs by remember(playlistId) {
Database.playlistWithSongs(playlistId).map { it ?: PlaylistWithSongs.NotFound }
}.collectAsState(initial = PlaylistWithSongs.Empty, context = Dispatchers.IO)
val lazyListState = rememberLazyListState()
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val hapticFeedback = LocalHapticFeedback.current

View file

@ -75,26 +75,11 @@ import kotlinx.coroutines.withContext
@ExperimentalAnimationApi
@Composable
fun PlaylistScreen(
browseId: String,
) {
fun PlaylistScreen(browseId: String) {
val lazyListState = rememberLazyListState()
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val context = LocalContext.current

View file

@ -1,104 +1,45 @@
package it.vfsfitvnm.vimusic.ui.screens
import android.annotation.SuppressLint
import android.net.Uri
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import it.vfsfitvnm.route.Route0
import it.vfsfitvnm.route.Route1
import it.vfsfitvnm.route.RouteHandlerScope
import it.vfsfitvnm.vimusic.enums.BuiltInPlaylist
@Composable
fun rememberIntentUriRoute(): Route1<Uri?> {
val uri = rememberSaveable {
mutableStateOf<Uri?>(null)
}
return remember {
Route1("IntentUriRoute", uri)
}
}
val aboutRoute = Route0("aboutRoute")
val albumRoute = Route1<String?>("albumRoute")
val appearanceSettingsRoute = Route0("appearanceSettingsRoute")
val artistRoute = Route1<String?>("artistRoute")
val backupAndRestoreRoute = Route0("backupAndRestoreRoute")
val builtInPlaylistRoute = Route1<BuiltInPlaylist>("builtInPlaylistRoute")
val cacheSettingsRoute = Route0("cacheSettingsRoute")
val intentUriRoute = Route1<Uri?>("intentUriRoute")
val localPlaylistRoute = Route1<Long?>("localPlaylistRoute")
val otherSettingsRoute = Route0("otherSettingsRoute")
val playerSettingsRoute = Route0("playerSettingsRoute")
val playlistRoute = Route1<String?>("playlistRoute")
val searchResultRoute = Route1<String>("searchResultRoute")
val searchRoute = Route1<String>("searchRoute")
val settingsRoute = Route0("settingsRoute")
val viewPlaylistsRoute = Route0("createPlaylistRoute")
@SuppressLint("ComposableNaming")
@Suppress("NOTHING_TO_INLINE")
@ExperimentalAnimationApi
@Composable
fun rememberPlaylistRoute(): Route1<String?> {
val browseId = rememberSaveable {
mutableStateOf<String?>(null)
inline fun RouteHandlerScope.globalRoutes() {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
return remember {
Route1("PlaylistRoute", browseId)
}
}
@Composable
fun rememberAlbumRoute(): Route1<String?> {
val browseId = rememberSaveable {
mutableStateOf<String?>(null)
}
return remember {
Route1("AlbumRoute", browseId)
}
}
@Composable
fun rememberArtistRoute(): Route1<String?> {
val browseId = rememberSaveable {
mutableStateOf<String?>(null)
}
return remember {
Route1("ArtistRoute", browseId)
}
}
@Composable
fun rememberLocalPlaylistRoute(): Route1<Long?> {
val playlistId = rememberSaveable {
mutableStateOf<Long?>(null)
}
return remember {
Route1("LocalPlaylistRoute", playlistId)
}
}
@Composable
fun rememberBuiltInPlaylistRoute(): Route1<BuiltInPlaylist> {
val playlistType = rememberSaveable {
mutableStateOf(BuiltInPlaylist.Favorites)
}
return remember {
Route1("BuiltInPlaylistRoute", playlistType)
}
}
@Composable
fun rememberSearchRoute(): Route1<String> {
val initialTextInput = remember {
mutableStateOf("")
}
return remember {
Route1("SearchRoute", initialTextInput)
}
}
@Composable
fun rememberCreatePlaylistRoute(): Route0 {
return remember {
Route0("CreatePlaylistRoute")
}
}
@Composable
fun rememberSearchResultRoute(): Route1<String> {
val searchQuery = rememberSaveable {
mutableStateOf("")
}
return remember {
Route1("SearchResultRoute", searchQuery)
}
}
@Composable
fun rememberSettingsRoute(): Route0 {
return remember {
Route0("SettingsRoute")
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
}

View file

@ -71,10 +71,7 @@ import kotlinx.coroutines.withContext
@ExperimentalAnimationApi
@Composable
fun SearchResultScreen(
query: String,
onSearchAgain: () -> Unit,
) {
fun SearchResultScreen(query: String, onSearchAgain: () -> Unit) {
val (colorPalette, typography) = LocalAppearance.current
val binder = LocalPlayerServiceBinder.current
@ -107,10 +104,6 @@ fun SearchResultScreen(
val thumbnailSizePx = Dimensions.thumbnails.song.px
val albumRoute = rememberAlbumRoute()
val playlistRoute = rememberPlaylistRoute()
val artistRoute = rememberArtistRoute()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
@ -118,14 +111,14 @@ fun SearchResultScreen(
)
}
playlistRoute { browseId ->
PlaylistScreen(
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: "browseId cannot be null"
)
}
artistRoute { browseId ->
ArtistScreen(
playlistRoute { browseId ->
PlaylistScreen(
browseId = browseId ?: "browseId cannot be null"
)
}

View file

@ -69,26 +69,9 @@ import kotlinx.coroutines.withContext
@ExperimentalAnimationApi
@Composable
fun SearchScreen(
initialTextInput: String,
onSearch: (String) -> Unit,
onUri: (Uri) -> Unit,
) {
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
fun SearchScreen(initialTextInput: String, onSearch: (String) -> Unit, onUri: (Uri) -> Unit) {
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val (colorPalette, typography) = LocalAppearance.current

View file

@ -29,15 +29,6 @@ import it.vfsfitvnm.vimusic.utils.*
@ExperimentalAnimationApi
@Composable
fun SettingsScreen() {
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
val appearanceSettingsRoute = rememberAppearanceSettingsRoute()
val playerSettingsRoute = rememberPlayerSettingsRoute()
val backupAndRestoreRoute = rememberBackupAndRestoreRoute()
val cacheSettingsRoute = rememberCacheSettingsRoute()
val otherSettingsRoute = rememberOtherSettingsRoute()
val aboutRoute = rememberAboutRoute()
val scrollState = rememberScrollState()
RouteHandler(
@ -53,17 +44,7 @@ fun SettingsScreen() {
}
}
) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
appearanceSettingsRoute {
AppearanceSettingsScreen()

View file

@ -27,10 +27,7 @@ import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.vimusic.BuildConfig
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen
import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen
import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute
import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute
import it.vfsfitvnm.vimusic.ui.screens.globalRoutes
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.bold
import it.vfsfitvnm.vimusic.utils.secondary
@ -39,23 +36,10 @@ import it.vfsfitvnm.vimusic.utils.semiBold
@ExperimentalAnimationApi
@Composable
fun AboutScreen() {
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
val scrollState = rememberScrollState()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val (colorPalette, typography) = LocalAppearance.current

View file

@ -25,12 +25,9 @@ import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.enums.ColorPaletteMode
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen
import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen
import it.vfsfitvnm.vimusic.ui.screens.EnumValueSelectorSettingsEntry
import it.vfsfitvnm.vimusic.ui.screens.SettingsEntryGroupText
import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute
import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute
import it.vfsfitvnm.vimusic.ui.screens.globalRoutes
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.colorPaletteModeKey
import it.vfsfitvnm.vimusic.utils.rememberPreference
@ -40,23 +37,11 @@ import it.vfsfitvnm.vimusic.utils.thumbnailRoundnessKey
@ExperimentalAnimationApi
@Composable
fun AppearanceSettingsScreen() {
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
val scrollState = rememberScrollState()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val (colorPalette, typography) = LocalAppearance.current

View file

@ -43,10 +43,7 @@ import it.vfsfitvnm.vimusic.service.PlayerService
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog
import it.vfsfitvnm.vimusic.ui.components.themed.TextCard
import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen
import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen
import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute
import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute
import it.vfsfitvnm.vimusic.ui.screens.globalRoutes
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.intent
import it.vfsfitvnm.vimusic.utils.semiBold
@ -59,23 +56,11 @@ import kotlin.system.exitProcess
@ExperimentalAnimationApi
@Composable
fun BackupAndRestoreScreen() {
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
val scrollState = rememberScrollState()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val (colorPalette, typography) = LocalAppearance.current

View file

@ -35,14 +35,11 @@ import it.vfsfitvnm.vimusic.enums.CoilDiskCacheMaxSize
import it.vfsfitvnm.vimusic.enums.ExoPlayerDiskCacheMaxSize
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.components.themed.TextCard
import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen
import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen
import it.vfsfitvnm.vimusic.ui.screens.DisabledSettingsEntry
import it.vfsfitvnm.vimusic.ui.screens.EnumValueSelectorSettingsEntry
import it.vfsfitvnm.vimusic.ui.screens.SettingsEntry
import it.vfsfitvnm.vimusic.ui.screens.SettingsEntryGroupText
import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute
import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute
import it.vfsfitvnm.vimusic.ui.screens.globalRoutes
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.coilDiskCacheMaxSizeKey
import it.vfsfitvnm.vimusic.utils.exoPlayerDiskCacheMaxSizeKey
@ -55,23 +52,11 @@ import kotlinx.coroutines.launch
@ExperimentalAnimationApi
@Composable
fun CacheSettingsScreen() {
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
val scrollState = rememberScrollState()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val context = LocalContext.current

View file

@ -35,13 +35,10 @@ import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.components.themed.TextCard
import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen
import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen
import it.vfsfitvnm.vimusic.ui.screens.SettingsEntry
import it.vfsfitvnm.vimusic.ui.screens.SettingsEntryGroupText
import it.vfsfitvnm.vimusic.ui.screens.SwitchSettingEntry
import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute
import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute
import it.vfsfitvnm.vimusic.ui.screens.globalRoutes
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.isIgnoringBatteryOptimizations
import it.vfsfitvnm.vimusic.utils.isInvincibilityEnabledKey
@ -51,23 +48,11 @@ import it.vfsfitvnm.vimusic.utils.semiBold
@ExperimentalAnimationApi
@Composable
fun OtherSettingsScreen() {
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
val scrollState = rememberScrollState()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val context = LocalContext.current

View file

@ -30,13 +30,10 @@ import it.vfsfitvnm.route.RouteHandler
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
import it.vfsfitvnm.vimusic.ui.screens.AlbumScreen
import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen
import it.vfsfitvnm.vimusic.ui.screens.SettingsEntry
import it.vfsfitvnm.vimusic.ui.screens.SettingsEntryGroupText
import it.vfsfitvnm.vimusic.ui.screens.SwitchSettingEntry
import it.vfsfitvnm.vimusic.ui.screens.rememberAlbumRoute
import it.vfsfitvnm.vimusic.ui.screens.rememberArtistRoute
import it.vfsfitvnm.vimusic.ui.screens.globalRoutes
import it.vfsfitvnm.vimusic.ui.styling.LocalAppearance
import it.vfsfitvnm.vimusic.utils.persistentQueueKey
import it.vfsfitvnm.vimusic.utils.rememberPreference
@ -47,23 +44,11 @@ import it.vfsfitvnm.vimusic.utils.volumeNormalizationKey
@ExperimentalAnimationApi
@Composable
fun PlayerSettingsScreen() {
val albumRoute = rememberAlbumRoute()
val artistRoute = rememberArtistRoute()
val scrollState = rememberScrollState()
RouteHandler(listenToGlobalEmitter = true) {
albumRoute { browseId ->
AlbumScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
artistRoute { browseId ->
ArtistScreen(
browseId = browseId ?: error("browseId cannot be null")
)
}
globalRoutes()
host {
val context = LocalContext.current

View file

@ -1,47 +0,0 @@
package it.vfsfitvnm.vimusic.ui.screens.settings
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import it.vfsfitvnm.route.Route0
@Composable
fun rememberAppearanceSettingsRoute(): Route0 {
return remember {
Route0("AppearanceSettingsRoute")
}
}
@Composable
fun rememberPlayerSettingsRoute(): Route0 {
return remember {
Route0("PlayerSettingsRoute")
}
}
@Composable
fun rememberBackupAndRestoreRoute(): Route0 {
return remember {
Route0("BackupAndRestoreRoute")
}
}
@Composable
fun rememberCacheSettingsRoute(): Route0 {
return remember {
Route0("CacheSettingsRoute")
}
}
@Composable
fun rememberOtherSettingsRoute(): Route0 {
return remember {
Route0("OtherSettingsRoute")
}
}
@Composable
fun rememberAboutRoute(): Route0 {
return remember {
Route0("AboutRoute")
}
}

View file

@ -1,10 +1,15 @@
@file:Suppress("UNCHECKED_CAST")
package it.vfsfitvnm.route
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.SaverScope
import androidx.compose.runtime.saveable.rememberSaveable
@Stable
@Immutable
open class Route internal constructor(val tag: String) {
override fun equals(other: Any?): Boolean {
return when {
@ -19,7 +24,7 @@ open class Route internal constructor(val tag: String) {
}
object GlobalEmitter {
var listener: ((Route) -> Unit)? = null
var listener: ((Route, Array<Any?>) -> Unit)? = null
}
object Saver : androidx.compose.runtime.saveable.Saver<Route?, String> {
@ -35,10 +40,8 @@ fun rememberRoute(route: Route? = null): MutableState<Route?> {
}
}
@Stable
class Route0(
tag: String
) : Route(tag) {
@Immutable
class Route0(tag: String) : Route(tag) {
context(RouteHandlerScope)
@Composable
operator fun invoke(content: @Composable () -> Unit) {
@ -48,64 +51,36 @@ class Route0(
}
fun global() {
GlobalEmitter.listener?.invoke(this)
GlobalEmitter.listener?.invoke(this, emptyArray())
}
}
@Stable
class Route1<P0>(
tag: String,
state0: MutableState<P0>
) : Route(tag) {
var p0 by state0
@Immutable
class Route1<P0>(tag: String) : Route(tag) {
context(RouteHandlerScope)
@Composable
operator fun invoke(content: @Composable (P0) -> Unit) {
if (this == route) {
if (route is Route1<*>) {
@Suppress("UNCHECKED_CAST")
(route as Route1<P0>).let { route ->
this.p0 = route.p0
}
}
content(this.p0)
content(parameters[0] as P0)
}
}
fun global(p0: P0 = this.p0) {
this.p0 = p0
GlobalEmitter.listener?.invoke(this)
fun global(p0: P0) {
GlobalEmitter.listener?.invoke(this, arrayOf(p0))
}
}
@Stable
class Route2<P0, P1>(
tag: String,
state0: MutableState<P0>,
state1: MutableState<P1>
) : Route(tag) {
var p0 by state0
var p1 by state1
@Immutable
class Route2<P0, P1>(tag: String) : Route(tag) {
context(RouteHandlerScope)
@Composable
operator fun invoke(content: @Composable (P0, P1) -> Unit) {
if (this == route) {
if (route is Route2<*, *>) {
@Suppress("UNCHECKED_CAST")
(route as Route2<P0, P1>).let { route ->
this.p0 = route.p0
this.p1 = route.p1
}
}
content(this.p0, this.p1)
content(parameters[0] as P0, parameters[1] as P1)
}
}
fun global(p0: P0 = this.p0, p1: P1 = this.p1) {
this.p0 = p0
this.p1 = p1
GlobalEmitter.listener?.invoke(this)
fun global(p0: P0, p1: P1) {
GlobalEmitter.listener?.invoke(this, arrayOf(p0, p1))
}
}

View file

@ -7,7 +7,12 @@ import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.updateTransition
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
@ExperimentalAnimationApi
@ -45,9 +50,14 @@ fun RouteHandler(
) {
val backDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher
val parameters = rememberSaveable {
arrayOfNulls<Any?>(2)
}
val scope = remember(route) {
RouteHandlerScope(
route = route,
parameters = parameters,
push = onRouteChanged,
pop = { if (handleBackPress) backDispatcher?.onBackPressed() else onRouteChanged(null) }
)
@ -55,7 +65,10 @@ fun RouteHandler(
if (listenToGlobalEmitter) {
LaunchedEffect(route) {
Route.GlobalEmitter.listener = if (route == null) onRouteChanged else null
Route.GlobalEmitter.listener = if (route == null) ({ newRoute, newParameters ->
newParameters.forEachIndexed(parameters::set)
onRouteChanged(newRoute)
}) else null
}
}
@ -65,7 +78,7 @@ fun RouteHandler(
updateTransition(targetState = scope, label = null).AnimatedContent(
transitionSpec = transitionSpec,
contentKey = { it.route?.tag },
contentKey = RouteHandlerScope::route,
modifier = modifier,
) {
it.content()

View file

@ -2,11 +2,12 @@ package it.vfsfitvnm.route
import android.annotation.SuppressLint
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
@Immutable
@Stable
class RouteHandlerScope(
val route: Route?,
val parameters: Array<Any?>,
private val push: (Route?) -> Unit,
val pop: () -> Unit,
) {
@ -18,23 +19,17 @@ class RouteHandlerScope(
}
}
operator fun Route0.invoke() {
operator fun Route.invoke() {
push(this)
}
operator fun <P0> Route1<P0>.invoke(
p0: P0 = this.p0
) {
this.p0 = p0
push(this)
operator fun <P0> Route.invoke(p0: P0) {
parameters[0] = p0
invoke()
}
operator fun <P0, P1> Route2<P0, P1>.invoke(
p0: P0 = this.p0,
p1: P1 = this.p1
) {
this.p0 = p0
this.p1 = p1
push(this)
operator fun <P0, P1> Route.invoke(p0: P0, p1: P1) {
parameters[1] = p1
invoke(p0)
}
}

View file

@ -1,8 +1,14 @@
package it.vfsfitvnm.route
import androidx.compose.animation.*
import androidx.compose.animation.AnimatedContentScope
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.with
@ExperimentalAnimationApi
val AnimatedContentScope<RouteHandlerScope>.leftSlide: ContentTransform