From cf4ed75d4df51b377fc26961c8a4af380f2eba7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C9=91rry=20Shiv=C9=91m?= Date: Wed, 15 May 2024 19:15:07 +0530 Subject: [PATCH] feat: enable edge-to-edge and remove deprecated systemuicontroller (#173) * feat: enable edge-to-edge and remove deprecated systemuicontroller, while on that, also add logging interceptor in http client on debug mode * Make statusbar auto hide after some time if user swipes down in the reader --------- Signed-off-by: starry-shivam --- app/build.gradle | 3 +- .../main/java/com/starry/myne/MainActivity.kt | 17 ++++-- .../main/java/com/starry/myne/api/BookAPI.kt | 30 +++++++--- .../com/starry/myne/ui/common/TopAppBars.kt | 55 ++++++++++--------- .../detail/composables/BookDetailScreen.kt | 2 +- .../ui/screens/home/composables/HomeScreen.kt | 11 +++- .../library/composables/LibraryScreen.kt | 2 +- .../starry/myne/ui/screens/main/MainScreen.kt | 46 ++++------------ .../reader/activities/ReaderActivity.kt | 8 +-- .../reader/composables/ReaderScreen.kt | 19 ------- .../settings/composables/SettingsScreen.kt | 10 ++-- .../java/com/starry/myne/ui/theme/Theme.kt | 38 ++++++++++++- 12 files changed, 133 insertions(+), 108 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 103104f5..426d7e3b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -108,8 +108,6 @@ dependencies { implementation "androidx.compose.animation:animation" implementation "androidx.compose.runtime:runtime-livedata" implementation "androidx.compose.material3:material3" - // Accompanist compose. - implementation "com.google.accompanist:accompanist-systemuicontroller:0.28.0" // Material icons. implementation 'androidx.compose.material:material-icons-extended:1.6.7' // Material theme for main activity. @@ -120,6 +118,7 @@ dependencies { implementation 'com.google.code.gson:gson:2.10.1' // OkHttp library. implementation "com.squareup.okhttp3:okhttp:4.12.0" + implementation "com.squareup.okhttp3:logging-interceptor:4.12.0" // Coil Image loading library. implementation "io.coil-kt:coil-compose:2.4.0" // Room database components. diff --git a/app/src/main/java/com/starry/myne/MainActivity.kt b/app/src/main/java/com/starry/myne/MainActivity.kt index ee09a8be..d444ebc3 100644 --- a/app/src/main/java/com/starry/myne/MainActivity.kt +++ b/app/src/main/java/com/starry/myne/MainActivity.kt @@ -18,6 +18,7 @@ package com.starry.myne import android.os.Bundle import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme @@ -30,6 +31,7 @@ import androidx.lifecycle.ViewModelProvider import com.starry.myne.helpers.NetworkObserver import com.starry.myne.ui.screens.main.MainScreen import com.starry.myne.ui.screens.settings.viewmodels.SettingsViewModel +import com.starry.myne.ui.theme.AdjustEdgeToEdge import com.starry.myne.ui.theme.MyneTheme import dagger.hilt.android.AndroidEntryPoint @@ -53,10 +55,13 @@ class MainActivity : AppCompatActivity() { mainViewModel.isLoading.value } + enableEdgeToEdge() // enable edge to edge for the activity. + setContent { MyneTheme(settingsViewModel = settingsViewModel) { - val status by networkObserver.observe().collectAsState( - initial = NetworkObserver.Status.Unavailable + AdjustEdgeToEdge( + activity = this, + themeState = settingsViewModel.getCurrentTheme() ) Surface( @@ -64,11 +69,11 @@ class MainActivity : AppCompatActivity() { color = MaterialTheme.colorScheme.background ) { val startDestination by mainViewModel.startDestination - MainScreen( - startDestination = startDestination, - networkStatus = status, - settingsViewModel = settingsViewModel + val status by networkObserver.observe().collectAsState( + initial = NetworkObserver.Status.Unavailable ) + + MainScreen(startDestination = startDestination, networkStatus = status) } } } diff --git a/app/src/main/java/com/starry/myne/api/BookAPI.kt b/app/src/main/java/com/starry/myne/api/BookAPI.kt index 3a5b67b6..12708987 100644 --- a/app/src/main/java/com/starry/myne/api/BookAPI.kt +++ b/app/src/main/java/com/starry/myne/api/BookAPI.kt @@ -30,6 +30,7 @@ import okhttp3.Callback import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response +import okhttp3.logging.HttpLoggingInterceptor import org.json.JSONException import org.json.JSONObject import java.io.File @@ -37,7 +38,6 @@ import java.io.IOException import java.net.URLEncoder import java.util.concurrent.TimeUnit import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine @@ -54,13 +54,25 @@ class BookAPI(context: Context) { private val googleApiKey = BuildConfig.GOOGLE_API_KEY ?: "AIzaSyBCaXx-U0sbEpGVPWylSggC4RaR4gCGkVE" // Backup API key - private val okHttpClient = OkHttpClient.Builder() - .connectTimeout(60, TimeUnit.SECONDS) - .writeTimeout(60, TimeUnit.SECONDS) - .readTimeout(100, TimeUnit.SECONDS) - .cache(Cache(File(context.cacheDir, "http-cache"), CacheInterceptor.CACHE_SIZE)) - .addNetworkInterceptor(CacheInterceptor()) - .build() + private val okHttpClient by lazy { + // Create an OkHttpClient with a cache and a network interceptor. + val okHttpBuilder = OkHttpClient.Builder() + .connectTimeout(60, TimeUnit.SECONDS) + .writeTimeout(60, TimeUnit.SECONDS) + .readTimeout(100, TimeUnit.SECONDS) + .cache(Cache(File(context.cacheDir, "http-cache"), CacheInterceptor.CACHE_SIZE)) + .addNetworkInterceptor(CacheInterceptor()) + + // Add logging interceptor if in debug mode. + if (BuildConfig.DEBUG) { + val logging = HttpLoggingInterceptor().apply { + level = HttpLoggingInterceptor.Level.BODY + } + okHttpBuilder.addInterceptor(logging).build() + } + // Finally build the OkHttpClient. + okHttpBuilder.build() + } private val gsonClient = Gson() // Gson client for parsing JSON responses. @@ -154,7 +166,7 @@ class BookAPI(context: Context) { val request = Request.Builder().get().url(url).build() okHttpClient.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { - continuation.resumeWithException(e) + continuation.resume(null) e.printStackTrace() } diff --git a/app/src/main/java/com/starry/myne/ui/common/TopAppBars.kt b/app/src/main/java/com/starry/myne/ui/common/TopAppBars.kt index c3b8f123..f3fc16b4 100644 --- a/app/src/main/java/com/starry/myne/ui/common/TopAppBars.kt +++ b/app/src/main/java/com/starry/myne/ui/common/TopAppBars.kt @@ -23,10 +23,13 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.ArrowBack @@ -56,12 +59,11 @@ fun CustomTopAppBar(headerText: String, iconRes: Int) { Column( modifier = Modifier .fillMaxWidth() - .padding(start = 20.dp, end = 20.dp, top = 10.dp, bottom = 8.dp) + .padding(horizontal = 20.dp, vertical = 8.dp) + .windowInsetsPadding(WindowInsets.statusBars) ) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(top = 7.dp), + modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { @@ -90,14 +92,9 @@ fun CustomTopAppBar(headerText: String, onBackButtonClicked: () -> Unit) { modifier = Modifier .fillMaxWidth() .padding(start = 20.dp, end = 20.dp, top = 16.dp, bottom = 8.dp) + .windowInsetsPadding(WindowInsets.statusBars) ) { - Row( - modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically - ) { - TopBarActionItem( - icon = Icons.AutoMirrored.Outlined.ArrowBack, onclick = onBackButtonClicked - ) - Spacer(modifier = Modifier.weight(1f)) + Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { Text( text = headerText, modifier = Modifier.padding(bottom = 16.dp), @@ -106,7 +103,14 @@ fun CustomTopAppBar(headerText: String, onBackButtonClicked: () -> Unit) { fontFamily = pacificoFont, fontSize = 24.sp ) - Spacer(modifier = Modifier.weight(2.35f)) + Row( + modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically + ) { + TopBarActionItem( + icon = Icons.AutoMirrored.Outlined.ArrowBack, onclick = onBackButtonClicked + ) + Spacer(modifier = Modifier.weight(1f)) + } } HorizontalDivider( thickness = 2.dp, color = MaterialTheme.colorScheme.surfaceColorAtElevation(4.dp) @@ -121,19 +125,13 @@ fun CustomTopAppBar( onBackButtonClicked: () -> Unit, onActionClicked: () -> Unit ) { - Column( modifier = Modifier .fillMaxWidth() .padding(start = 20.dp, end = 20.dp, top = 16.dp, bottom = 8.dp) + .windowInsetsPadding(WindowInsets.statusBars) ) { - Row( - modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically - ) { - TopBarActionItem( - icon = Icons.AutoMirrored.Outlined.ArrowBack, onclick = onBackButtonClicked - ) - Spacer(modifier = Modifier.weight(1f)) + Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { Text( text = headerText, modifier = Modifier.padding(bottom = 16.dp), @@ -142,10 +140,17 @@ fun CustomTopAppBar( fontFamily = pacificoFont, fontSize = 24.sp ) - Spacer(modifier = Modifier.weight(1f)) - TopBarActionItem( - icon = actionIcon, onclick = onActionClicked - ) + Row( + modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically + ) { + TopBarActionItem( + icon = Icons.AutoMirrored.Outlined.ArrowBack, onclick = onBackButtonClicked + ) + Spacer(modifier = Modifier.weight(1f)) + TopBarActionItem( + icon = actionIcon, onclick = onActionClicked + ) + } } HorizontalDivider( thickness = 2.dp, color = MaterialTheme.colorScheme.surfaceColorAtElevation(4.dp) @@ -178,7 +183,7 @@ private fun TopBarActionItem(icon: ImageVector, onclick: () -> Unit) { @Preview(showBackground = true) @Composable -fun TopAppBarsPV() { +private fun TopAppBarsPV() { Column(Modifier.fillMaxSize()) { CustomTopAppBar(headerText = "Something", iconRes = R.drawable.ic_nav_categories) CustomTopAppBar(headerText = "Something", onBackButtonClicked = {}) diff --git a/app/src/main/java/com/starry/myne/ui/screens/detail/composables/BookDetailScreen.kt b/app/src/main/java/com/starry/myne/ui/screens/detail/composables/BookDetailScreen.kt index 58b8d47c..0a3f48d5 100644 --- a/app/src/main/java/com/starry/myne/ui/screens/detail/composables/BookDetailScreen.kt +++ b/app/src/main/java/com/starry/myne/ui/screens/detail/composables/BookDetailScreen.kt @@ -503,7 +503,7 @@ private fun BookDetailTopBar( Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { Box( modifier = Modifier - .padding(22.dp) + .padding(horizontal = 22.dp, vertical = 16.dp) .clip(CircleShape) .background(MaterialTheme.colorScheme.surfaceColorAtElevation(4.dp)) .clickable { diff --git a/app/src/main/java/com/starry/myne/ui/screens/home/composables/HomeScreen.kt b/app/src/main/java/com/starry/myne/ui/screens/home/composables/HomeScreen.kt index 546add61..9e3f0c4d 100644 --- a/app/src/main/java/com/starry/myne/ui/screens/home/composables/HomeScreen.kt +++ b/app/src/main/java/com/starry/myne/ui/screens/home/composables/HomeScreen.kt @@ -19,6 +19,7 @@ package com.starry.myne.ui.screens.home.composables import androidx.activity.compose.BackHandler import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.Crossfade +import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -29,11 +30,14 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.statusBars +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.shape.RoundedCornerShape @@ -178,6 +182,7 @@ private fun HomeScreenScaffold( .padding(start = 20.dp, end = 20.dp, top = 10.dp, bottom = 8.dp) ) { Crossfade( + modifier = Modifier.animateContentSize(), targetState = topBarState.isSearchBarVisible, animationSpec = tween(durationMillis = 200), label = "search cross fade" ) { @@ -400,7 +405,7 @@ private fun HomeTopAppBar( Row( modifier = Modifier .fillMaxWidth() - .padding(top = 7.dp), + .windowInsetsPadding(WindowInsets.statusBars), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { @@ -440,7 +445,9 @@ private fun SearchAppBar( onSearchClicked: () -> Unit ) { Column( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .windowInsetsPadding(WindowInsets.statusBars) ) { val focusRequester = remember { FocusRequester() } OutlinedTextField( diff --git a/app/src/main/java/com/starry/myne/ui/screens/library/composables/LibraryScreen.kt b/app/src/main/java/com/starry/myne/ui/screens/library/composables/LibraryScreen.kt index 3c0710fe..7f8fe1c2 100644 --- a/app/src/main/java/com/starry/myne/ui/screens/library/composables/LibraryScreen.kt +++ b/app/src/main/java/com/starry/myne/ui/screens/library/composables/LibraryScreen.kt @@ -166,7 +166,7 @@ fun LibraryScreen(navController: NavController) { val showTapTargets = remember { mutableStateOf(false) } LaunchedEffect(key1 = viewModel.showOnboardingTapTargets.value) { - delay(800) // Delay to prevent flickering + delay(500) // Delay to prevent flickering showTapTargets.value = viewModel.showOnboardingTapTargets.value } diff --git a/app/src/main/java/com/starry/myne/ui/screens/main/MainScreen.kt b/app/src/main/java/com/starry/myne/ui/screens/main/MainScreen.kt index 93357a09..4bfe4207 100644 --- a/app/src/main/java/com/starry/myne/ui/screens/main/MainScreen.kt +++ b/app/src/main/java/com/starry/myne/ui/screens/main/MainScreen.kt @@ -17,16 +17,23 @@ package com.starry.myne.ui.screens.main import android.annotation.SuppressLint +import androidx.activity.SystemBarStyle +import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -34,6 +41,7 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -48,12 +56,9 @@ import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController -import com.google.accompanist.systemuicontroller.SystemUiController -import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.starry.myne.helpers.NetworkObserver import com.starry.myne.ui.navigation.BottomBarScreen import com.starry.myne.ui.navigation.NavGraph -import com.starry.myne.ui.screens.settings.viewmodels.SettingsViewModel import com.starry.myne.ui.screens.settings.viewmodels.ThemeMode import com.starry.myne.ui.theme.figeronaFont @@ -67,23 +72,11 @@ val bottomNavPadding = 70.dp fun MainScreen( startDestination: String, networkStatus: NetworkObserver.Status, - settingsViewModel: SettingsViewModel, ) { val navController = rememberNavController() - val systemUiController = rememberSystemUiController() - - systemUiController.setStatusBarColor( - color = MaterialTheme.colorScheme.background, - darkIcons = settingsViewModel.getCurrentTheme() == ThemeMode.Light - ) - Scaffold( bottomBar = { - BottomBar( - navController = navController, - systemUiController = systemUiController, - settingsViewModel = settingsViewModel - ) + BottomBar(navController = navController) }, containerColor = MaterialTheme.colorScheme.background ) { NavGraph( @@ -95,11 +88,7 @@ fun MainScreen( } @Composable -private fun BottomBar( - navController: NavHostController, - systemUiController: SystemUiController, - settingsViewModel: SettingsViewModel -) { +private fun BottomBar(navController: NavHostController) { val screens = listOf( BottomBarScreen.Home, BottomBarScreen.Categories, @@ -111,18 +100,6 @@ private fun BottomBar( val currentDestination = navBackStackEntry?.destination val bottomBarDestination = screens.any { it.route == currentDestination?.route } - if (bottomBarDestination) { - systemUiController.setNavigationBarColor( - color = MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp), - darkIcons = settingsViewModel.getCurrentTheme() == ThemeMode.Light - ) - } else { - systemUiController.setNavigationBarColor( - color = MaterialTheme.colorScheme.background, - darkIcons = settingsViewModel.getCurrentTheme() == ThemeMode.Light - ) - } - AnimatedVisibility(visible = bottomBarDestination, modifier = Modifier.fillMaxWidth(), enter = slideInVertically(initialOffsetY = { it }), @@ -132,7 +109,8 @@ private fun BottomBar( modifier = Modifier .background(MaterialTheme.colorScheme.surfaceColorAtElevation(3.dp)) .padding(12.dp) - .fillMaxWidth(), + .fillMaxWidth() + .windowInsetsPadding(WindowInsets.navigationBars), horizontalArrangement = Arrangement.SpaceAround, verticalAlignment = Alignment.CenterVertically, ) { diff --git a/app/src/main/java/com/starry/myne/ui/screens/reader/activities/ReaderActivity.kt b/app/src/main/java/com/starry/myne/ui/screens/reader/activities/ReaderActivity.kt index 07ecea6a..c3e52e72 100644 --- a/app/src/main/java/com/starry/myne/ui/screens/reader/activities/ReaderActivity.kt +++ b/app/src/main/java/com/starry/myne/ui/screens/reader/activities/ReaderActivity.kt @@ -38,7 +38,6 @@ import com.starry.myne.helpers.Constants import com.starry.myne.helpers.toToast import com.starry.myne.ui.screens.reader.composables.ReaderContent import com.starry.myne.ui.screens.reader.composables.ReaderScreen -import com.starry.myne.ui.screens.reader.composables.TransparentSystemBars import com.starry.myne.ui.screens.reader.viewmodels.ReaderViewModel import com.starry.myne.ui.screens.settings.viewmodels.SettingsViewModel import com.starry.myne.ui.theme.MyneTheme @@ -76,8 +75,11 @@ class ReaderActivity : AppCompatActivity() { // Fullscreen mode that ignores any cutout, notch etc. WindowCompat.setDecorFitsSystemWindows(window, false) val controller = WindowInsetsControllerCompat(window, window.decorView) - controller.hide(WindowInsetsCompat.Type.displayCutout()) + controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE controller.hide(WindowInsetsCompat.Type.systemBars()) + controller.hide(WindowInsetsCompat.Type.displayCutout()) + + // Set layout in display cutout mode for Android P and above. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES @@ -107,8 +109,6 @@ class ReaderActivity : AppCompatActivity() { finish() }) - TransparentSystemBars(settingsViewModel = settingsViewModel) - ReaderScreen( viewModel = viewModel, lazyListState = lazyListState, diff --git a/app/src/main/java/com/starry/myne/ui/screens/reader/composables/ReaderScreen.kt b/app/src/main/java/com/starry/myne/ui/screens/reader/composables/ReaderScreen.kt index 14aba7fc..b9992ca8 100644 --- a/app/src/main/java/com/starry/myne/ui/screens/reader/composables/ReaderScreen.kt +++ b/app/src/main/java/com/starry/myne/ui/screens/reader/composables/ReaderScreen.kt @@ -75,7 +75,6 @@ import androidx.compose.material3.rememberDrawerState import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState -import androidx.compose.runtime.SideEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -92,12 +91,9 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.starry.myne.R import com.starry.myne.ui.screens.reader.others.ReaderFont import com.starry.myne.ui.screens.reader.viewmodels.ReaderViewModel -import com.starry.myne.ui.screens.settings.viewmodels.SettingsViewModel -import com.starry.myne.ui.screens.settings.viewmodels.ThemeMode import com.starry.myne.ui.theme.figeronaFont import kotlinx.coroutines.launch @@ -526,19 +522,4 @@ private fun ReaderTextScaleButton( modifier = Modifier.size(ButtonDefaults.IconSize) ) } -} - - -@Composable -fun TransparentSystemBars(alpha: Float = 0f, settingsViewModel: SettingsViewModel) { - val systemUiController = rememberSystemUiController() - val useDarkIcons = settingsViewModel.getCurrentTheme() == ThemeMode.Light - val baseColor = MaterialTheme.colorScheme.primary - val color = remember(alpha, baseColor) { baseColor.copy(alpha = alpha) } - SideEffect { - systemUiController.setSystemBarsColor( - color = color, - darkIcons = useDarkIcons - ) - } } \ No newline at end of file diff --git a/app/src/main/java/com/starry/myne/ui/screens/settings/composables/SettingsScreen.kt b/app/src/main/java/com/starry/myne/ui/screens/settings/composables/SettingsScreen.kt index 408949ca..601fae01 100644 --- a/app/src/main/java/com/starry/myne/ui/screens/settings/composables/SettingsScreen.kt +++ b/app/src/main/java/com/starry/myne/ui/screens/settings/composables/SettingsScreen.kt @@ -103,6 +103,12 @@ fun SettingsScreen(navController: NavController) { Scaffold( modifier = Modifier.padding(bottom = bottomNavPadding), snackbarHost = { SnackbarHost(snackBarHostState) }, + topBar = { + CustomTopAppBar( + headerText = stringResource(id = R.string.settings_header), + iconRes = R.drawable.ic_nav_settings + ) + } ) { paddingValues -> Column( modifier = Modifier @@ -110,10 +116,6 @@ fun SettingsScreen(navController: NavController) { .background(MaterialTheme.colorScheme.background) .padding(paddingValues) ) { - CustomTopAppBar( - headerText = stringResource(id = R.string.settings_header), - iconRes = R.drawable.ic_nav_settings - ) Column(modifier = Modifier.verticalScroll(rememberScrollState())) { SettingsCard() GeneralOptionsUI(viewModel = viewModel, snackBarHostState = snackBarHostState) diff --git a/app/src/main/java/com/starry/myne/ui/theme/Theme.kt b/app/src/main/java/com/starry/myne/ui/theme/Theme.kt index 97d08868..1259e267 100644 --- a/app/src/main/java/com/starry/myne/ui/theme/Theme.kt +++ b/app/src/main/java/com/starry/myne/ui/theme/Theme.kt @@ -18,6 +18,9 @@ package com.starry.myne.ui.theme import android.content.Context import android.os.Build +import androidx.activity.SystemBarStyle +import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.ColorScheme import androidx.compose.material3.MaterialTheme @@ -26,6 +29,7 @@ import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext @@ -108,7 +112,7 @@ private val darkColors = darkColorScheme( surfaceContainerHighest = surfaceContainerHighestDark, ) - +// Get the color scheme based on the theme settings. private fun getColorScheme( themeState: ThemeMode, materialYouState: Boolean, @@ -145,6 +149,38 @@ private fun getColorScheme( } } +/** + * Helper composable function to fix the status bar icons on dark theme + * when using edge-to-edge mode. + * @param activity: MainActivity to enable edge-to-edge status bar. + * @param themeState: ThemeMode to check the current theme. + */ +@Composable +fun AdjustEdgeToEdge(activity: AppCompatActivity, themeState: ThemeMode) { + LaunchedEffect(themeState) { + if (themeState == ThemeMode.Dark) { + activity.enableEdgeToEdge( + statusBarStyle = SystemBarStyle.dark(android.graphics.Color.TRANSPARENT), + navigationBarStyle = SystemBarStyle.dark(android.graphics.Color.TRANSPARENT) + ) + } else { + activity.enableEdgeToEdge( + navigationBarStyle = SystemBarStyle.light( + android.graphics.Color.TRANSPARENT, + android.graphics.Color.TRANSPARENT + ) + ) + } + } +} + + +/** + * MyneTheme composable function to apply the theme to the app. + * @param darkTheme: Boolean to check if the theme is dark. + * @param settingsViewModel: SettingsViewModel to observe the theme settings. + * @param content: @Composable function to apply the theme to the content. + */ @Composable fun MyneTheme( darkTheme: Boolean = isSystemInDarkTheme(),