Skip to content

Commit 4a135fa

Browse files
committed
android: move navigation button to activity level
1 parent 39a64ec commit 4a135fa

19 files changed

+213
-262
lines changed

android/app/src/main/java/me/kavishdevar/librepods/MainActivity.kt

Lines changed: 122 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,16 @@ import android.widget.Toast
3838
import androidx.activity.ComponentActivity
3939
import androidx.activity.compose.setContent
4040
import androidx.activity.enableEdgeToEdge
41+
import androidx.compose.animation.AnimatedVisibility
4142
import androidx.compose.animation.core.RepeatMode
4243
import androidx.compose.animation.core.animateFloat
4344
import androidx.compose.animation.core.infiniteRepeatable
4445
import androidx.compose.animation.core.rememberInfiniteTransition
4546
import androidx.compose.animation.core.tween
47+
import androidx.compose.animation.fadeIn
48+
import androidx.compose.animation.fadeOut
49+
import androidx.compose.animation.scaleIn
50+
import androidx.compose.animation.scaleOut
4651
import androidx.compose.animation.slideInHorizontally
4752
import androidx.compose.animation.slideOutHorizontally
4853
import androidx.compose.foundation.Canvas
@@ -69,9 +74,11 @@ import androidx.compose.material3.Card
6974
import androidx.compose.material3.CardDefaults
7075
import androidx.compose.material3.ExperimentalMaterial3Api
7176
import androidx.compose.material3.Icon
77+
import androidx.compose.material3.IconButton
7278
import androidx.compose.material3.MaterialTheme
7379
import androidx.compose.material3.Text
7480
import androidx.compose.runtime.Composable
81+
import androidx.compose.runtime.derivedStateOf
7582
import androidx.compose.runtime.LaunchedEffect
7683
import androidx.compose.runtime.getValue
7784
import androidx.compose.runtime.mutableStateOf
@@ -104,8 +111,11 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi
104111
import com.google.accompanist.permissions.MultiplePermissionsState
105112
import com.google.accompanist.permissions.isGranted
106113
import com.google.accompanist.permissions.rememberMultiplePermissionsState
114+
import com.kyant.backdrop.backdrops.rememberLayerBackdrop
115+
import com.kyant.backdrop.backdrops.layerBackdrop
107116
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
108117
import me.kavishdevar.librepods.constants.AirPodsNotifications
118+
import me.kavishdevar.librepods.composables.StyledIconButton
109119
import me.kavishdevar.librepods.screens.AccessibilitySettingsScreen
110120
import me.kavishdevar.librepods.screens.AdaptiveStrengthScreen
111121
import me.kavishdevar.librepods.screens.AirPodsSettingsScreen
@@ -300,108 +310,128 @@ fun Main() {
300310
val context = LocalContext.current
301311

302312
val navController = rememberNavController()
303-
304-
val sharedPreferences = context.getSharedPreferences("settings", MODE_PRIVATE)
305-
val isAvailableChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
306-
if (key == "CrossDeviceIsAvailable") {
307-
Log.d("MainActivity", "CrossDeviceIsAvailable changed")
308-
isRemotelyConnected.value = sharedPreferences.getBoolean("CrossDeviceIsAvailable", false)
309-
}
310-
}
311-
sharedPreferences.registerOnSharedPreferenceChangeListener(isAvailableChangeListener)
312-
Log.d("MainActivity", "CrossDeviceIsAvailable: ${sharedPreferences.getBoolean("CrossDeviceIsAvailable", false)} | isAvailable: ${CrossDevice.isAvailable}")
313-
isRemotelyConnected.value = sharedPreferences.getBoolean("CrossDeviceIsAvailable", false) || CrossDevice.isAvailable
314-
Log.d("MainActivity", "isRemotelyConnected: ${isRemotelyConnected.value}")
313+
315314
Box (
316315
modifier = Modifier
317-
.padding(0.dp)
318316
.fillMaxSize()
319-
.background(if (isSystemInDarkTheme()) Color.Black else Color(0xFFF2F2F7))
320-
) {
321-
NavHost(
322-
navController = navController,
323-
startDestination = if (hookAvailable) "settings" else "onboarding",
324-
enterTransition = {
325-
slideInHorizontally(
326-
initialOffsetX = { it },
327-
animationSpec = tween(durationMillis = 300)
328-
) // + fadeIn(animationSpec = tween(durationMillis = 300))
329-
},
330-
exitTransition = {
331-
slideOutHorizontally(
332-
targetOffsetX = { -it/4 },
333-
animationSpec = tween(durationMillis = 300)
334-
) // + fadeOut(animationSpec = tween(durationMillis = 150))
335-
},
336-
popEnterTransition = {
337-
slideInHorizontally(
338-
initialOffsetX = { -it/4 },
339-
animationSpec = tween(durationMillis = 300)
340-
) // + fadeIn(animationSpec = tween(durationMillis = 300))
341-
},
342-
popExitTransition = {
343-
slideOutHorizontally(
344-
targetOffsetX = { it },
345-
animationSpec = tween(durationMillis = 300)
346-
) // + fadeOut(animationSpec = tween(durationMillis = 150))
347-
}
317+
){
318+
val backButtonBackdrop = rememberLayerBackdrop()
319+
Box (
320+
modifier = Modifier
321+
.fillMaxSize()
322+
.background(if (isSystemInDarkTheme()) Color.Black else Color(0xFFF2F2F7))
323+
.layerBackdrop(backButtonBackdrop)
348324
) {
349-
composable("settings") {
350-
if (airPodsService.value != null) {
351-
AirPodsSettingsScreen(
352-
dev = airPodsService.value?.device,
353-
service = airPodsService.value!!,
325+
NavHost(
326+
navController = navController,
327+
startDestination = if (hookAvailable) "settings" else "onboarding",
328+
enterTransition = {
329+
slideInHorizontally(
330+
initialOffsetX = { it },
331+
animationSpec = tween(durationMillis = 300)
332+
) // + fadeIn(animationSpec = tween(durationMillis = 300))
333+
},
334+
exitTransition = {
335+
slideOutHorizontally(
336+
targetOffsetX = { -it/4 },
337+
animationSpec = tween(durationMillis = 300)
338+
) // + fadeOut(animationSpec = tween(durationMillis = 150))
339+
},
340+
popEnterTransition = {
341+
slideInHorizontally(
342+
initialOffsetX = { -it/4 },
343+
animationSpec = tween(durationMillis = 300)
344+
) // + fadeIn(animationSpec = tween(durationMillis = 300))
345+
},
346+
popExitTransition = {
347+
slideOutHorizontally(
348+
targetOffsetX = { it },
349+
animationSpec = tween(durationMillis = 300)
350+
) // + fadeOut(animationSpec = tween(durationMillis = 150))
351+
}
352+
) {
353+
composable("settings") {
354+
if (airPodsService.value != null) {
355+
AirPodsSettingsScreen(
356+
dev = airPodsService.value?.device,
357+
service = airPodsService.value!!,
358+
navController = navController,
359+
isConnected = isConnected.value,
360+
isRemotelyConnected = isRemotelyConnected.value
361+
)
362+
}
363+
}
364+
composable("debug") {
365+
DebugScreen(navController = navController)
366+
}
367+
composable("long_press/{bud}") { navBackStackEntry ->
368+
LongPress(
354369
navController = navController,
355-
isConnected = isConnected.value,
356-
isRemotelyConnected = isRemotelyConnected.value
370+
name = navBackStackEntry.arguments?.getString("bud")!!
357371
)
358372
}
373+
composable("rename") {
374+
RenameScreen(navController)
375+
}
376+
composable("app_settings") {
377+
AppSettingsScreen(navController)
378+
}
379+
composable("troubleshooting") {
380+
TroubleshootingScreen(navController)
381+
}
382+
composable("head_tracking") {
383+
HeadTrackingScreen(navController)
384+
}
385+
composable("onboarding") {
386+
Onboarding(navController, context)
387+
}
388+
composable("accessibility") {
389+
AccessibilitySettingsScreen(navController)
390+
}
391+
composable("transparency_customization") {
392+
TransparencySettingsScreen(navController)
393+
}
394+
composable("hearing_aid") {
395+
HearingAidScreen(navController)
396+
}
397+
composable("hearing_aid_adjustments") {
398+
HearingAidAdjustmentsScreen(navController)
399+
}
400+
composable("adaptive_strength") {
401+
AdaptiveStrengthScreen(navController)
402+
}
403+
composable("camera_control") {
404+
CameraControlScreen(navController)
405+
}
406+
composable("open_source_licenses") {
407+
OpenSourceLicensesScreen(navController)
408+
}
359409
}
360-
composable("debug") {
361-
DebugScreen(navController = navController)
410+
}
411+
412+
val showBackButton = remember{ mutableStateOf(false) }
413+
414+
LaunchedEffect(navController) {
415+
navController.addOnDestinationChangedListener { _, destination, _ ->
416+
showBackButton.value = destination.route != "settings" && destination.route != "onboarding"
417+
Log.d("MainActivity", "Navigated to ${destination.route}, showBackButton: ${showBackButton.value}")
362418
}
363-
composable("long_press/{bud}") { navBackStackEntry ->
364-
LongPress(
365-
navController = navController,
366-
name = navBackStackEntry.arguments?.getString("bud")!!
419+
}
420+
421+
AnimatedVisibility(
422+
visible = showBackButton.value,
423+
enter = fadeIn(animationSpec = tween()) + scaleIn(initialScale = 0f, animationSpec = tween()),
424+
exit = fadeOut(animationSpec = tween()) + scaleOut(targetScale = 0.5f, animationSpec = tween(100)),
425+
modifier = Modifier
426+
.align(Alignment.TopStart)
427+
.padding(start = 8.dp, top = (context.resources.configuration.screenHeightDp.dp * 0.05f).value.dp)
428+
) {
429+
StyledIconButton(
430+
onClick = { navController.popBackStack() },
431+
icon = "􀯶",
432+
darkMode = isSystemInDarkTheme(),
433+
backdrop = backButtonBackdrop
367434
)
368-
}
369-
composable("rename") {
370-
RenameScreen(navController)
371-
}
372-
composable("app_settings") {
373-
AppSettingsScreen(navController)
374-
}
375-
composable("troubleshooting") {
376-
TroubleshootingScreen(navController)
377-
}
378-
composable("head_tracking") {
379-
HeadTrackingScreen(navController)
380-
}
381-
composable("onboarding") {
382-
Onboarding(navController, context)
383-
}
384-
composable("accessibility") {
385-
AccessibilitySettingsScreen(navController)
386-
}
387-
composable("transparency_customization") {
388-
TransparencySettingsScreen(navController)
389-
}
390-
composable("hearing_aid") {
391-
HearingAidScreen(navController)
392-
}
393-
composable("hearing_aid_adjustments") {
394-
HearingAidAdjustmentsScreen(navController)
395-
}
396-
composable("adaptive_strength") {
397-
AdaptiveStrengthScreen(navController)
398-
}
399-
composable("camera_control") {
400-
CameraControlScreen(navController)
401-
}
402-
composable("open_source_licenses") {
403-
OpenSourceLicensesScreen(navController)
404-
}
405435
}
406436
}
407437

android/app/src/main/java/me/kavishdevar/librepods/composables/StyledIconButton.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,16 @@ half4 main(float2 coord) {
127127
highlight = { Highlight.Ambient.copy(alpha = if (isDarkTheme) 1f else 0f) },
128128
shadow = {
129129
Shadow(
130-
radius = 48f.dp,
131-
color = Color.Black.copy(if (isDarkTheme) 0.08f else 0.4f)
130+
radius = 12f.dp,
131+
color = Color.Black.copy(if (isDarkTheme) 0.08f else 0.2f)
132132
)
133133
},
134134
layerBlock = {
135135
val width = size.width
136136
val height = size.height
137137

138138
val progress = progressAnimation.value
139-
val maxScale = 0.1f
140-
val scale = lerp(1f, 1f + maxScale, progress)
139+
val scale = lerp(1f, 1.5f, progress)
141140

142141
val maxOffset = size.minDimension
143142
val initialDerivative = 0.05f
@@ -220,7 +219,7 @@ half4 main(float2 coord) {
220219
},
221220
effects = {
222221
refractionWithDispersion(6f.dp.toPx(), size.height / 2f)
223-
blur(24f, TileMode.Decal)
222+
// blur(24f, TileMode.Decal)
224223
},
225224
)
226225
.pointerInput(animationScope) {

0 commit comments

Comments
 (0)