From c41bc4c66e27beebdf000d110359bd9c9db21cfb Mon Sep 17 00:00:00 2001 From: MAdMiZ Date: Tue, 6 Oct 2026 03:06:39 +0530 Subject: [PATCH 1/6] Add FAB micro animation --- .../ui/component/HomeFloatingActions.kt | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/darkxvenom/airbeats/ui/component/HomeFloatingActions.kt b/app/src/main/java/com/darkxvenom/airbeats/ui/component/HomeFloatingActions.kt index 57d4bcb0..d84aea3d 100644 --- a/app/src/main/java/com/darkxvenom/airbeats/ui/component/HomeFloatingActions.kt +++ b/app/src/main/java/com/darkxvenom/airbeats/ui/component/HomeFloatingActions.kt @@ -1,5 +1,8 @@ package com.darkxvenom.airbeats.ui.component +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.spring import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope @@ -26,6 +29,8 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.draw.scale import androidx.compose.ui.Modifier import androidx.compose.ui.hapticfeedback.HapticFeedbackType import androidx.compose.ui.platform.LocalHapticFeedback @@ -70,8 +75,27 @@ fun BoxScope.HomeFloatingActions( ) .then(modifier) ) { + val fabRotation by animateFloatAsState( + targetValue = if (expanded) 90f else 0f, + animationSpec = spring( + dampingRatio = Spring.DampingRatioNoBouncy, + stiffness = 500f, + ), + label = "homeFabRotation", + ) + val fabScale by animateFloatAsState( + targetValue = if (expanded) 0.94f else 1f, + animationSpec = spring( + dampingRatio = Spring.DampingRatioNoBouncy, + stiffness = 500f, + ), + label = "homeFabScale", + ) + FloatingActionButton( - modifier = Modifier.padding(16.dp), + modifier = Modifier + .padding(16.dp) + .scale(fabScale), onClick = { haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove) expanded = true @@ -81,7 +105,8 @@ fun BoxScope.HomeFloatingActions( ) { Icon( painter = painterResource(R.drawable.more_vert), - contentDescription = "Options" + contentDescription = "Options", + modifier = Modifier.rotate(fabRotation), ) } From b0d0e0b4c37609d53c40cac1a05c528ac680db56 Mon Sep 17 00:00:00 2001 From: MAdMiZ Date: Tue, 6 Oct 2026 03:07:15 +0530 Subject: [PATCH 2/6] Animate bottom navigation icons --- .../ui/component/MaterialBottomNavigationBar.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/darkxvenom/airbeats/ui/component/MaterialBottomNavigationBar.kt b/app/src/main/java/com/darkxvenom/airbeats/ui/component/MaterialBottomNavigationBar.kt index 2bb90b62..69d46a86 100644 --- a/app/src/main/java/com/darkxvenom/airbeats/ui/component/MaterialBottomNavigationBar.kt +++ b/app/src/main/java/com/darkxvenom/airbeats/ui/component/MaterialBottomNavigationBar.kt @@ -1,6 +1,7 @@ package com.darkxvenom.airbeats.ui.component import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.Spring @@ -34,6 +35,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.hapticfeedback.HapticFeedbackType @@ -126,6 +128,11 @@ private fun MaterialNavItem( animationSpec = materialNavSpring(), label = "navItemContent", ) + val iconScale by animateFloatAsState( + targetValue = if (selected) 1.06f else 1f, + animationSpec = materialNavSpring(), + label = "navItemIconScale", + ) Surface( onClick = onClick, @@ -146,7 +153,9 @@ private fun MaterialNavItem( painter = painterResource(id = iconRes), contentDescription = label, tint = contentColor, - modifier = Modifier.size(26.dp), + modifier = Modifier + .size(26.dp) + .scale(iconScale), ) AnimatedVisibility( visible = selected && label.isNotEmpty(), From fc54e26369b4a8f0e5bc5b085465630ca8d0b578 Mon Sep 17 00:00:00 2001 From: MAdMiZ Date: Tue, 6 Oct 2026 03:07:46 +0530 Subject: [PATCH 3/6] Optimize mini player thumbnail requests --- .../airbeats/ui/player/MiniPlayer.kt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/darkxvenom/airbeats/ui/player/MiniPlayer.kt b/app/src/main/java/com/darkxvenom/airbeats/ui/player/MiniPlayer.kt index 8b5f8763..378650fe 100644 --- a/app/src/main/java/com/darkxvenom/airbeats/ui/player/MiniPlayer.kt +++ b/app/src/main/java/com/darkxvenom/airbeats/ui/player/MiniPlayer.kt @@ -75,8 +75,8 @@ import androidx.compose.ui.graphics.rememberGraphicsLayer import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow @@ -187,7 +187,15 @@ fun MiniPlayer( else -> MaterialTheme.colorScheme.surfaceContainer.copy(alpha = 0.95f) } - val currentView = LocalView.current + val context = LocalContext.current + val thumbnailRequest = remember(mediaMetadata?.thumbnailUrl) { + mediaMetadata?.thumbnailUrl?.highQualityThumbnail()?.let { thumbnailUrl -> + ImageRequest.Builder(context) + .data(thumbnailUrl) + .crossfade(true) + .build() + } + } val layoutDirection = LocalLayoutDirection.current val coroutineScope = rememberCoroutineScope() @@ -382,12 +390,9 @@ fun MiniPlayer( } } ) { - mediaMetadata?.let { metadata -> + thumbnailRequest?.let { request -> AsyncImage( - model = ImageRequest.Builder(LocalView.current.context) - .data(metadata.thumbnailUrl?.highQualityThumbnail()) - .crossfade(true) - .build(), + model = request, contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier From 2e5de6ea9eadbe104776e57d68d5cb00a978349f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9D=90=92=F0=9D=90=AE=F0=9D=90=A7=F0=9D=90=9D?= =?UTF-8?q?=F0=9D=90=AB=F0=9D=90=9A=F0=9D=90=A6=20=F0=9D=90=98=F0=9D=90=9A?= =?UTF-8?q?=F0=9D=90=9D=F0=9D=90=9A=F0=9D=90=AF?= <159863013+SirYadav1@users.noreply.github.com> Date: Mon, 5 Oct 2026 19:28:41 +0530 Subject: [PATCH 4/6] Update libs.versions.toml --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 76671534..45d5b7ed 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ kotlin = "2.3.10" compose = "1.9.4" lifecycle = "2.9.4" material3 = "1.5.0-alpha18" -media3 = "1.8.0" +media3 = "1.11.1" room = "2.7.2" hilt = "2.58" ktor = "3.0.3" From 97aa7f4aa08d9e15ad8e8bdf611ec31e8436e40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9D=90=92=F0=9D=90=AE=F0=9D=90=A7=F0=9D=90=9D?= =?UTF-8?q?=F0=9D=90=AB=F0=9D=90=9A=F0=9D=90=A6=20=F0=9D=90=98=F0=9D=90=9A?= =?UTF-8?q?=F0=9D=90=9D=F0=9D=90=9A=F0=9D=90=AF?= <159863013+SirYadav1@users.noreply.github.com> Date: Mon, 5 Oct 2026 19:30:26 +0530 Subject: [PATCH 5/6] Update libs.versions.toml --- gradle/libs.versions.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 45d5b7ed..7d14df64 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -76,6 +76,7 @@ palette = { group = "androidx.palette", name = "palette", version = "1.0.0" } media3 = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "media3" } media3-okhttp = { group = "androidx.media3", name = "media3-datasource-okhttp", version.ref = "media3" } media3-session = { group = "androidx.media3", name = "media3-session", version.ref = "media3" } +media3-ui = { group = "androidx.media3", name = "media3-ui", version.ref = "media3" } room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" } room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" } From 99201e38ce293d4ef519836fb19cb853173bcc4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9D=90=92=F0=9D=90=AE=F0=9D=90=A7=F0=9D=90=9D?= =?UTF-8?q?=F0=9D=90=AB=F0=9D=90=9A=F0=9D=90=A6=20=F0=9D=90=98=F0=9D=90=9A?= =?UTF-8?q?=F0=9D=90=9D=F0=9D=90=9A=F0=9D=90=AF?= <159863013+SirYadav1@users.noreply.github.com> Date: Mon, 5 Oct 2026 19:31:40 +0530 Subject: [PATCH 6/6] Replace media3-ui dependency with libs.media3.ui --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 94988246..6e32c8f9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -214,7 +214,7 @@ dependencies { implementation(libs.media3) implementation(libs.media3.session) implementation(libs.media3.okhttp) - implementation("androidx.media3:media3-ui:1.8.0") + implementation(libs.media3.ui) implementation(libs.squigglyslider) // Google Cast & local streaming proxy