Skip to content

Commit

Permalink
refactor: Moved to the new type-safe navigation system
Browse files Browse the repository at this point in the history
Signed-off-by: Gabriel Fontán <gabilessto@gmail.com>
  • Loading branch information
BobbyESP committed May 26, 2024
1 parent 1a51f1a commit 50e158e
Show file tree
Hide file tree
Showing 11 changed files with 179 additions and 163 deletions.
24 changes: 24 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 0 additions & 11 deletions .idea/other.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions app/src/main/java/com/bobbyesp/metadator/ext/Song.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.bobbyesp.metadator.ext

import com.bobbyesp.metadator.model.ParcelableSong
import com.bobbyesp.model.Song

fun Song.toParcelableSong(): ParcelableSong {
val artistsList = this.artist.toList()
val mainArtist = artistsList.first().toString()
return ParcelableSong(
name = this.title,
mainArtist = mainArtist,
localSongPath = this.path,
artworkPath = this.artworkPath,
fileName = this.fileName
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable

@Parcelize
@Serializable
@Immutable
@Serializable
data class ParcelableSong(
val name: String,
val mainArtist: String,
Expand Down
78 changes: 41 additions & 37 deletions app/src/main/java/com/bobbyesp/metadator/presentation/Navigation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,28 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.util.fastAny
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.navigation
import androidx.navigation.navArgument
import androidx.navigation.toRoute
import com.bobbyesp.metadator.App
import com.bobbyesp.metadator.R
import com.bobbyesp.metadator.model.ParcelableSong
import com.bobbyesp.metadator.presentation.common.Home
import com.bobbyesp.metadator.presentation.common.LocalDrawerState
import com.bobbyesp.metadator.presentation.common.LocalNavController
import com.bobbyesp.metadator.presentation.common.LocalPlayerAwareWindowInsets
import com.bobbyesp.metadator.presentation.common.LocalSnackbarHostState
import com.bobbyesp.metadator.presentation.common.NavArgs
import com.bobbyesp.metadator.presentation.common.Route
import com.bobbyesp.metadator.presentation.common.TagEditorParcelableSongParamType
import com.bobbyesp.metadator.presentation.common.Mediaplayer
import com.bobbyesp.metadator.presentation.common.MediaplayerNavigator
import com.bobbyesp.metadator.presentation.common.MetadatorNavigator
import com.bobbyesp.metadator.presentation.common.NavigationUtilities.IconsUtil.getDestinationIcon
import com.bobbyesp.metadator.presentation.common.NavigationUtilities.getDestinationTitle
import com.bobbyesp.metadator.presentation.common.TagEditor
import com.bobbyesp.metadator.presentation.common.UtilitiesNavigator
import com.bobbyesp.metadator.presentation.common.parcelableType
import com.bobbyesp.metadator.presentation.common.routesToNavigate
import com.bobbyesp.metadator.presentation.pages.MediaStorePageViewModel
import com.bobbyesp.metadator.presentation.pages.home.HomePage
Expand All @@ -78,10 +86,8 @@ import com.bobbyesp.metadator.presentation.pages.utilities.tageditor.ID3Metadata
import com.bobbyesp.metadator.presentation.pages.utilities.tageditor.ID3MetadataEditorPageViewModel
import com.bobbyesp.ui.components.bottomsheet.draggable.rememberDraggableBottomSheetState
import com.bobbyesp.ui.components.tags.RoundedTag
import com.bobbyesp.ui.motion.animatedComposable
import com.bobbyesp.ui.motion.slideInVerticallyComposable
import com.bobbyesp.utilities.navigation.getParcelable
import kotlinx.coroutines.launch
import kotlin.reflect.typeOf

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Composable
Expand All @@ -90,14 +96,15 @@ fun Navigator() {
val drawerState = LocalDrawerState.current

val navBackStackEntry by navController.currentBackStackEntryAsState()

val currentRootRoute = rememberSaveable(navBackStackEntry, key = "currentRootRoute") {
mutableStateOf(
navBackStackEntry?.destination?.parent?.route ?: Route.MetadatorNavigator.route
navBackStackEntry?.destination?.parent
)
}
val currentRoute = rememberSaveable(navBackStackEntry, key = "currentRoute") {
mutableStateOf(
navBackStackEntry?.destination?.route ?: Route.MetadatorNavigator.Home.route
navBackStackEntry?.destination
)
}

Expand All @@ -107,7 +114,7 @@ fun Navigator() {

//able to open drawer when the user is in one of the main routes (root routes)
val canOpenDrawer by remember(currentRoute) {
mutableStateOf(routesToNavigate.fastAny { it.route == currentRootRoute.value })
mutableStateOf(routesToNavigate.fastAny { it == currentRootRoute.value })
}

val mediaStoreViewModel = hiltViewModel<MediaStorePageViewModel>()
Expand Down Expand Up @@ -170,10 +177,12 @@ fun Navigator() {
fontFamily = FontFamily.Monospace
)
routesToNavigate.forEachIndexed { _, route ->
val isSelected = currentRootRoute.value == route.route
val isSelected = currentRootRoute.value == route
NavigationDrawerItem(
label = {
Text(text = route.title?.let { stringResource(id = it) } ?: "")
Text(
text = route.getDestinationTitle()
?.let { stringResource(id = it) } ?: "")
},
selected = isSelected,
onClick = {
Expand All @@ -183,8 +192,8 @@ fun Navigator() {
}
return@NavigationDrawerItem
} else {
navController.navigate(route.route) {
popUpTo(Route.MainHost.route) {
navController.navigate(route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
Expand All @@ -197,8 +206,10 @@ fun Navigator() {
},
icon = {
Icon(
imageVector = route.icon ?: Icons.Rounded.Square,
contentDescription = route.title?.let { stringResource(id = it) })
imageVector = route.getDestinationIcon()
?: Icons.Rounded.Square,
contentDescription = route.getDestinationTitle()
?.let { stringResource(id = it) })
},
badge = {

Expand Down Expand Up @@ -279,45 +290,38 @@ fun Navigator() {
.fillMaxWidth()
.align(Alignment.Center),
navController = navController,
startDestination = Route.MetadatorNavigator.route,
route = Route.MainHost.route,
startDestination = MetadatorNavigator,
) {
navigation(
startDestination = Route.MetadatorNavigator.Home.route,
route = Route.MetadatorNavigator.route
navigation<MetadatorNavigator>(
startDestination = Home,
) {
animatedComposable(Route.MetadatorNavigator.Home.route) {
composable<Home> {
HomePage(viewModel = mediaStoreViewModel)
}
}

navigation(
startDestination = Route.MediaplayerNavigator.Mediaplayer.route,
route = Route.MediaplayerNavigator.route
navigation<MediaplayerNavigator>(
startDestination = Mediaplayer,
) {
animatedComposable(Route.MediaplayerNavigator.Mediaplayer.route) {
composable<Mediaplayer> {
MediaplayerPage(mediaplayerViewModel, mediaPlayerSheetState)
}
}

navigation(
startDestination = Route.UtilitiesNavigator.TagEditor.route,
route = Route.UtilitiesNavigator.route
navigation<UtilitiesNavigator>(
startDestination = TagEditor::class,
) {
slideInVerticallyComposable(
route = Route.UtilitiesNavigator.TagEditor.route,
arguments = listOf(navArgument(NavArgs.TagEditorSelectedSong.key) {
type = TagEditorParcelableSongParamType
})
composable<TagEditor>(
typeMap = mapOf(typeOf<ParcelableSong>() to parcelableType<ParcelableSong>())
) {
val parcelableSongParcelable =
it.getParcelable<ParcelableSong>(NavArgs.TagEditorSelectedSong.key)
val song =
it.toRoute<TagEditor>()

val viewModel = hiltViewModel<ID3MetadataEditorPageViewModel>()

ID3MetadataEditorPage(
viewModel = viewModel,
parcelableSong = parcelableSongParcelable!!
parcelableSong = song.selectedSong
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,41 @@ package com.bobbyesp.metadator.presentation.common
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import androidx.navigation.NavType
import com.bobbyesp.metadator.model.ParcelableSong
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

@Suppress("DEPRECATION")
val ParcelableSongParamType = object : NavType<ParcelableSong>(isNullableAllowed = false) {
override fun get(bundle: Bundle, key: String): ParcelableSong? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
bundle.getParcelable(NavArgs.SelectedSong.key, ParcelableSong::class.java)
inline fun <reified T : Parcelable> parcelableType(
isNullableAllowed: Boolean = false,
json: Json = Json,
) = object : NavType<T>(isNullableAllowed = isNullableAllowed) {
override fun get(bundle: Bundle, key: String) =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
bundle.getParcelable(key, T::class.java)
} else {
bundle.getParcelable(NavArgs.SelectedSong.key)
@Suppress("DEPRECATION") bundle.getParcelable(key)
}
}

override fun put(bundle: Bundle, key: String, value: ParcelableSong) {
bundle.putParcelable(key, value)
}
override fun parseValue(value: String): T = json.decodeFromString(value)

override fun parseValue(value: String): ParcelableSong {
return Json.decodeFromString(Uri.decode(value))
}
override fun serializeAsValue(value: T): String = Uri.encode(json.encodeToString(value))

override fun put(bundle: Bundle, key: String, value: T) = bundle.putParcelable(key, value)
}

@Suppress("DEPRECATION")
val TagEditorParcelableSongParamType = object : NavType<ParcelableSong>(isNullableAllowed = false) {
override fun get(bundle: Bundle, key: String): ParcelableSong? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
bundle.getParcelable(NavArgs.TagEditorSelectedSong.key, ParcelableSong::class.java)
} else {
bundle.getParcelable(NavArgs.TagEditorSelectedSong.key)
}
}
inline fun <reified T : Any> serializableType(
isNullableAllowed: Boolean = false,
json: Json = Json,
) = object : NavType<T>(isNullableAllowed = isNullableAllowed) {
override fun get(bundle: Bundle, key: String) =
bundle.getString(key)?.let<String, T>(json::decodeFromString)

override fun put(bundle: Bundle, key: String, value: ParcelableSong) {
bundle.putParcelable(key, value)
}
override fun parseValue(value: String): T = json.decodeFromString(value)

override fun serializeAsValue(value: T): String = Uri.encode(json.encodeToString(value))

override fun parseValue(value: String): ParcelableSong {
return Json.decodeFromString(Uri.decode(value))
override fun put(bundle: Bundle, key: String, value: T) {
bundle.putString(key, json.encodeToString(value))
}
}
Loading

0 comments on commit 50e158e

Please sign in to comment.