Skip to content

Commit

Permalink
fix: Improved list performance & added predictive back gesture
Browse files Browse the repository at this point in the history
This commit includes the following improvements:

- Enhanced list performance in the MediaStorePage by avoiding unnecessary recompositions when the list state changes.
- Added support for predictive back gestures to improve navigation flow and user experience.
- Updated Compose BOM to `compose-bom-alpha`.
  • Loading branch information
BobbyESP committed Nov 18, 2024
1 parent 3a6f313 commit 4b4b299
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,26 +42,27 @@ fun MediaStorePage(
onReloadMediaStore: () -> Unit,
onItemClicked: (Song) -> Unit
) {
val songsList = songs.value
Box(
modifier = modifier.fillMaxSize()
) {
Crossfade(
targetState = desiredLayout, label = "List item transition", animationSpec = tween(200)
) { type ->
when (songs.value) {
when (songsList) {
is ResourceState.Loading -> LoadingPage(text = stringResource(R.string.loading_mediastore))

is ResourceState.Error -> ErrorPage(
error = songs.value.message ?: "Unknown"
error = songsList.message ?: "Unknown"
) { onReloadMediaStore() }

is ResourceState.Success -> {
if (songs.value.data!!.isEmpty()) {
if (songsList.data!!.isEmpty()) {
EmptyMediaStore(
modifier = Modifier.fillMaxSize()
)
} else {
val songsList = songs.value.data!!
val dataSongsList = songsList.data!!
when (type) {
LayoutType.Grid -> {
LazyVerticalGridScrollbar(
Expand All @@ -82,10 +83,10 @@ fun MediaStorePage(
state = lazyGridState
) {
items(
count = songsList.size,
key = { index -> songsList[index].id },
contentType = { index -> songsList[index].id.toString() }) { index ->
val song = songsList[index]
count = dataSongsList.size,
key = { index -> dataSongsList[index].id },
contentType = { _ -> "songItem" }) { index ->
val song = dataSongsList[index]
VerticalSongCard(
song = song,
modifier = Modifier.animateItem(
Expand Down Expand Up @@ -114,10 +115,10 @@ fun MediaStorePage(
state = lazyListState,
) {
items(
count = songsList.size,
key = { index -> songsList[index].id },
contentType = { index -> songsList[index].id.toString() }) { index ->
val song = songsList[index]
count = dataSongsList.size,
key = { index -> dataSongsList[index].id },
contentType = { index -> dataSongsList[index].id.toString() }) { index ->
val song = dataSongsList[index]
HorizontalSongCard(
song = song,
modifier = Modifier.animateItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import com.bobbyesp.ui.motion.MotionConstants.DURATION_ENTER
import com.bobbyesp.ui.motion.MotionConstants.DURATION_EXIT
import com.bobbyesp.ui.motion.MotionConstants.InitialOffset
import kotlin.reflect.KType
import kotlin.text.toInt
import kotlin.times

fun <T> enterTween() = tween<T>(durationMillis = DURATION_ENTER, easing = EmphasizedEasing)

Expand All @@ -48,6 +50,19 @@ inline fun <reified T : Any> NavGraphBuilder.animatedComposable(
}
}

inline fun <reified T : Any> NavGraphBuilder.slideInVerticallyComposable(
deepLinks: List<NavDeepLink> = emptyList(),
typeMap: Map<KType, @JvmSuppressWildcards NavType<*>> = emptyMap(),
usePredictiveBack: Boolean = Build.VERSION.SDK_INT >= 34,
noinline content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit,
) {
if (usePredictiveBack) {
slideInVerticallyComposablePredictiveBack<T>(deepLinks, typeMap, content)
} else {
slideInVerticallyComposableLegacy<T>(deepLinks, typeMap ,content)
}
}

inline fun <reified T : Any> NavGraphBuilder.animatedComposablePredictiveBack(
deepLinks: List<NavDeepLink> = emptyList(),
noinline content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit,
Expand Down Expand Up @@ -117,7 +132,7 @@ inline fun <reified T : Any> NavGraphBuilder.animatedComposableVariant(
val springSpec =
spring(stiffness = Spring.StiffnessMedium, visibilityThreshold = IntOffset.VisibilityThreshold)

inline fun <reified T : Any> NavGraphBuilder.slideInVerticallyComposable(
inline fun <reified T : Any> NavGraphBuilder.slideInVerticallyComposableLegacy(
deepLinks: List<NavDeepLink> = emptyList(),
typeMap: Map<KType, @JvmSuppressWildcards NavType<*>> = emptyMap(),
noinline content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit,
Expand All @@ -134,4 +149,32 @@ inline fun <reified T : Any> NavGraphBuilder.slideInVerticallyComposable(
slideOutVertically(targetOffsetY = { it }, animationSpec = enterTween()) + fadeOut()
},
content = content,
)

inline fun <reified T : Any> NavGraphBuilder.slideInVerticallyComposablePredictiveBack(
deepLinks: List<NavDeepLink> = emptyList(),
typeMap: Map<KType, @JvmSuppressWildcards NavType<*>> = emptyMap(),
noinline content: @Composable AnimatedVisibilityScope.(NavBackStackEntry) -> Unit,
) =
composable<T>(
deepLinks = deepLinks,
typeMap = typeMap,
enterTransition = { materialSharedAxisYIn(initialOffsetY = { (it * 0.25f).toInt() }) },
exitTransition = {
materialSharedAxisYOut(targetOffsetY = { -(it * InitialOffset * 1.5f).toInt() })
},
popEnterTransition = {
scaleIn(
animationSpec = tween(durationMillis = 400, easing = EmphasizedDecelerate),
initialScale = 0.85f,
) + materialSharedAxisYIn(initialOffsetY = { -(it * InitialOffset * 1.5f).toInt() })
},
popExitTransition = {
materialSharedAxisYOut(targetOffsetY = { (it * InitialOffset * 1.5f).toInt() }) +
scaleOut(
targetScale = 0.85f,
animationSpec = tween(durationMillis = 400, easing = EmphasizedAccelerate),
)
},
content = content,
)
10 changes: 1 addition & 9 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ core-splashscreen = { group = "androidx.core", name = "core-splashscreen", versi
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity-compose" }
androidx-legacy-support-v4 = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacySupportV4" }
compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
compose-bom = { group = "androidx.compose", name = "compose-bom-alpha", version.ref = "compose-bom" }
firebase-crashlytics-gradle = { group = "com.google.firebase", name = "firebase-crashlytics-gradle", version.ref = "firebaseCrashlyticsGradle" }
lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-ktx" }
lifecycle-compose-runtime = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle-runtime-ktx" }
Expand Down Expand Up @@ -132,7 +132,6 @@ accompanist-flowlayout = { group = "com.google.accompanist", name = "accompanist
accompanist-material = { group = "com.google.accompanist", name = "accompanist-navigation-material", version.ref = "accompanist" }

#Image loading
compose-coil = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" }
landscapist-coil = { group = "com.github.skydoves", name = "landscapist-coil", version.ref = "landscapistCoil" }
coil = { group = "io.coil-kt", name = "coil", version.ref = "coil" }

Expand All @@ -146,11 +145,6 @@ ktor-okhttp = { group = "io.ktor", name = "ktor-client-okhttp", version.ref = "k
ktor-encoding = { group = "io.ktor", name = "ktor-client-encoding", version.ref = "ktor" }

#Dependency injection
compose-hilt-navigation = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hilt-ext" }
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
hilt-ext-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hilt-ext" }

koin-android = { group = "io.insert-koin", name = "koin-android", version.ref = "koin" }
koin-compose = { group = "io.insert-koin", name = "koin-androidx-compose", version.ref = "koin" }
koin-ksp-compiler = { group = "io.insert-koin", name = "koin-ksp-compiler", version.ref = "koin" }
Expand Down Expand Up @@ -213,7 +207,6 @@ android-kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
kotlin-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
androidTest = { id = "com.android.test", version.ref = "agp" }
firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlyticsGradle" }
Expand All @@ -225,7 +218,6 @@ core = ["core-ktx", "lifecycle-runtime-ktx", "lifecycle-compose-runtime", "lifec
ktor = ["ktor-android", "ktor-okhttp" ,"ktor-core", "ktor-serialization", "ktor-logging", "ktor-contentnegotiation", "ktor-encoding"]
accompanist = ["accompanist-navigation-animation", "accompanist-permissions", "accompanist-webview", "accompanist-pager-layouts", "accompanist-pager-indicators", "accompanist-flowlayout", "accompanist-material"]
compose = ["compose-ui-util", "compose-graphics", "compose-runtime", "compose-foundation", "compose-material-iconsExtended", "compose-animation", "compose-ui", "compose-material3", "compose-navigation", "compose-material3-windowSizeClass", "compose-constraintLayout"]
hilt = ["compose-hilt-navigation", "hilt-android"]
koin = ["koin-android", "koin-compose"]
pagination = ["paging-compose", "paging-runtime"]
googleServices = ["firebase-auth", "gms-playservices-auth", "google-services"]
Expand Down

0 comments on commit 4b4b299

Please sign in to comment.