From bc3a1266f4aae37ebf623bf996f041ce6d301ffa Mon Sep 17 00:00:00 2001 From: Harsh Shandilya Date: Wed, 16 Aug 2023 11:25:13 +0530 Subject: [PATCH] refactor(android): drop Accompanist SystemUI Controller dependency --- android/build.gradle.kts | 1 - .../msfjarvis/claw/android/MainActivity.kt | 24 +- .../msfjarvis/claw/android/ui/LobstersApp.kt | 360 +++++++++--------- .../ui/decorations/TransparentSystemBars.kt | 25 -- android/src/main/res/values-night/bools.xml | 9 - android/src/main/res/values/bools.xml | 9 - android/src/main/res/values/themes.xml | 4 +- gradle/libs.versions.toml | 4 +- 8 files changed, 192 insertions(+), 244 deletions(-) delete mode 100644 android/src/main/kotlin/dev/msfjarvis/claw/android/ui/decorations/TransparentSystemBars.kt delete mode 100644 android/src/main/res/values-night/bools.xml delete mode 100644 android/src/main/res/values/bools.xml diff --git a/android/build.gradle.kts b/android/build.gradle.kts index 2fc6a755..caae4f45 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -64,7 +64,6 @@ whetstone { dependencies { implementation(platform(libs.androidx.compose.bom)) implementation(platform(libs.okhttp.bom)) - implementation(libs.accompanist.sysuicontroller) implementation(libs.androidx.activity.compose) implementation(libs.androidx.compose.material) implementation(libs.androidx.compose.material.icons.extended) diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/MainActivity.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/MainActivity.kt index 8d555323..f2369f3c 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/MainActivity.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/MainActivity.kt @@ -11,14 +11,16 @@ import android.net.Uri import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass +import androidx.compose.ui.platform.LocalUriHandler import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen -import androidx.core.view.WindowCompat import com.deliveryhero.whetstone.Whetstone import com.deliveryhero.whetstone.activity.ContributesActivityInjector import dev.msfjarvis.claw.android.ui.LobstersApp import dev.msfjarvis.claw.common.comments.HTMLConverter +import dev.msfjarvis.claw.common.theme.LobstersTheme import dev.msfjarvis.claw.common.urllauncher.UrlLauncher import javax.inject.Inject @@ -34,16 +36,20 @@ class MainActivity : ComponentActivity() { super.onCreate(savedInstanceState) installSplashScreen() Whetstone.inject(this) - WindowCompat.setDecorFitsSystemWindows(window, false) + enableEdgeToEdge() setContent { val windowSizeClass = calculateWindowSizeClass(this) - - LobstersApp( - urlLauncher = urlLauncher, - htmlConverter = htmlConverter, - windowSizeClass = windowSizeClass, - setWebUri = { url -> webUri = url }, - ) + LobstersTheme( + dynamicColor = true, + providedValues = arrayOf(LocalUriHandler provides urlLauncher), + ) { + LobstersApp( + urlLauncher = urlLauncher, + htmlConverter = htmlConverter, + windowSizeClass = windowSizeClass, + setWebUri = { url -> webUri = url }, + ) + } } } diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt index b2a55b94..0f12963e 100644 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt +++ b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/LobstersApp.kt @@ -39,7 +39,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId @@ -58,7 +57,6 @@ import dev.msfjarvis.claw.android.ui.datatransfer.DataTransferScreen import dev.msfjarvis.claw.android.ui.decorations.ClawNavigationBar import dev.msfjarvis.claw.android.ui.decorations.ClawNavigationRail import dev.msfjarvis.claw.android.ui.decorations.NavigationItem -import dev.msfjarvis.claw.android.ui.decorations.TransparentSystemBars import dev.msfjarvis.claw.android.ui.lists.DatabasePosts import dev.msfjarvis.claw.android.ui.lists.NetworkPosts import dev.msfjarvis.claw.android.ui.lists.SearchList @@ -68,7 +66,6 @@ import dev.msfjarvis.claw.android.viewmodel.ClawViewModel import dev.msfjarvis.claw.api.LobstersApi import dev.msfjarvis.claw.common.comments.CommentsPage import dev.msfjarvis.claw.common.comments.HTMLConverter -import dev.msfjarvis.claw.common.theme.LobstersTheme import dev.msfjarvis.claw.common.ui.decorations.ClawAppBar import dev.msfjarvis.claw.common.urllauncher.UrlLauncher import dev.msfjarvis.claw.common.user.UserProfile @@ -104,193 +101,186 @@ fun LobstersApp( val navigationType = ClawNavigationType.fromSize(windowSizeClass.widthSizeClass) - LobstersTheme( - dynamicColor = true, - providedValues = arrayOf(LocalUriHandler provides urlLauncher), - ) { - val navItems = - persistentListOf( - NavigationItem( - label = "Hottest", - route = Destinations.Hottest.route, - icon = Icons.Outlined.Whatshot, - selectedIcon = Icons.Filled.Whatshot, - ) { - coroutineScope.launch { hottestListState.animateScrollToItem(index = 0) } - }, - NavigationItem( - label = "Newest", - route = Destinations.Newest.route, - icon = Icons.Outlined.NewReleases, - selectedIcon = Icons.Filled.NewReleases, - ) { - coroutineScope.launch { newestListState.animateScrollToItem(index = 0) } - }, - NavigationItem( - label = "Saved", - route = Destinations.Saved.route, - icon = Icons.Outlined.FavoriteBorder, - selectedIcon = Icons.Filled.Favorite, - ) { - coroutineScope.launch { savedListState.animateScrollToItem(index = 0) } - }, - NavigationItem( - label = "Search", - route = Destinations.Search.route, - icon = Icons.Outlined.Search, - selectedIcon = Icons.Filled.Search, - ) { - coroutineScope.launch { searchListState.animateScrollToItem(index = 0) } - }, - ) + val navItems = + persistentListOf( + NavigationItem( + label = "Hottest", + route = Destinations.Hottest.route, + icon = Icons.Outlined.Whatshot, + selectedIcon = Icons.Filled.Whatshot, + ) { + coroutineScope.launch { hottestListState.animateScrollToItem(index = 0) } + }, + NavigationItem( + label = "Newest", + route = Destinations.Newest.route, + icon = Icons.Outlined.NewReleases, + selectedIcon = Icons.Filled.NewReleases, + ) { + coroutineScope.launch { newestListState.animateScrollToItem(index = 0) } + }, + NavigationItem( + label = "Saved", + route = Destinations.Saved.route, + icon = Icons.Outlined.FavoriteBorder, + selectedIcon = Icons.Filled.Favorite, + ) { + coroutineScope.launch { savedListState.animateScrollToItem(index = 0) } + }, + NavigationItem( + label = "Search", + route = Destinations.Search.route, + icon = Icons.Outlined.Search, + selectedIcon = Icons.Filled.Search, + ) { + coroutineScope.launch { searchListState.animateScrollToItem(index = 0) } + }, + ) - TransparentSystemBars() - - Scaffold( - topBar = { - if (currentDestination != Destinations.Search.route) { - ClawAppBar( - navigationIcon = { - if ( - navController.previousBackStackEntry != null && - navItems.none { it.route == currentDestination } + Scaffold( + topBar = { + if (currentDestination != Destinations.Search.route) { + ClawAppBar( + navigationIcon = { + if ( + navController.previousBackStackEntry != null && + navItems.none { it.route == currentDestination } + ) { + IconButton( + onClick = { if (!navController.popBackStack()) context.getActivity()?.finish() }, ) { - IconButton( - onClick = { if (!navController.popBackStack()) context.getActivity()?.finish() }, - ) { - Icon( - imageVector = Icons.Filled.ArrowBack, - contentDescription = "Go back to previous screen", - ) - } + Icon( + imageVector = Icons.Filled.ArrowBack, + contentDescription = "Go back to previous screen", + ) } - }, - title = { - if (navItems.any { it.route == currentDestination }) { - Text(text = stringResource(R.string.app_name), fontWeight = FontWeight.Bold) + } + }, + title = { + if (navItems.any { it.route == currentDestination }) { + Text(text = stringResource(R.string.app_name), fontWeight = FontWeight.Bold) + } + }, + actions = { + if (navItems.any { it.route == currentDestination }) { + IconButton(onClick = { navController.navigate(Destinations.DataTransfer.route) }) { + Icon( + imageVector = Icons.Filled.ImportExport, + contentDescription = "Data transfer options", + ) } - }, - actions = { - if (navItems.any { it.route == currentDestination }) { - IconButton(onClick = { navController.navigate(Destinations.DataTransfer.route) }) { - Icon( - imageVector = Icons.Filled.ImportExport, - contentDescription = "Data transfer options", - ) - } - } - }, - ) - } - }, - bottomBar = { - AnimatedVisibility(visible = navigationType == ClawNavigationType.BOTTOM_NAVIGATION) { - ClawNavigationBar( - navController = navController, - items = navItems, - isVisible = navItems.any { it.route == currentDestination }, - ) - } - }, - snackbarHost = { SnackbarHost(snackbarHostState) }, - modifier = modifier.semantics { testTagsAsResourceId = true }, - ) { paddingValues -> - Row(modifier = Modifier.padding(paddingValues)) { - AnimatedVisibility(visible = navigationType == ClawNavigationType.NAVIGATION_RAIL) { - ClawNavigationRail( - navController = navController, - items = navItems, - isVisible = navItems.any { it.route == currentDestination }, - ) - } + } + }, + ) + } + }, + bottomBar = { + AnimatedVisibility(visible = navigationType == ClawNavigationType.BOTTOM_NAVIGATION) { + ClawNavigationBar( + navController = navController, + items = navItems, + isVisible = navItems.any { it.route == currentDestination }, + ) + } + }, + snackbarHost = { SnackbarHost(snackbarHostState) }, + modifier = modifier.semantics { testTagsAsResourceId = true }, + ) { paddingValues -> + Row(modifier = Modifier.padding(paddingValues)) { + AnimatedVisibility(visible = navigationType == ClawNavigationType.NAVIGATION_RAIL) { + ClawNavigationRail( + navController = navController, + items = navItems, + isVisible = navItems.any { it.route == currentDestination }, + ) + } - NavHost( - navController = navController, - startDestination = Destinations.startDestination.route, - // Make animations 2x faster than default specs - enterTransition = { fadeIn(animationSpec = tween(350)) }, - exitTransition = { fadeOut(animationSpec = tween(350)) }, - ) { - val uri = LobstersApi.BASE_URL - composable(route = Destinations.Hottest.route) { - setWebUri("https://lobste.rs/") - NetworkPosts( - lazyPagingItems = hottestPosts, - listState = hottestListState, - isPostSaved = viewModel::isPostSaved, - isPostRead = viewModel::isPostRead, - postActions = postActions, - ) - } - composable(route = Destinations.Newest.route) { - setWebUri("https://lobste.rs/") - NetworkPosts( - lazyPagingItems = newestPosts, - listState = newestListState, - isPostSaved = viewModel::isPostSaved, - isPostRead = viewModel::isPostRead, - postActions = postActions, - ) - } - composable(route = Destinations.Saved.route) { - setWebUri(null) - DatabasePosts( - items = savedPosts, - listState = savedListState, - postActions = postActions, - ) - } - composable(Destinations.Search.route) { - setWebUri("https://lobste.rs/search") - SearchList( - items = viewModel.searchResults, - listState = searchListState, - isPostSaved = viewModel::isPostSaved, - postActions = postActions, - searchQuery = viewModel.searchQuery, - setSearchQuery = { query -> viewModel.searchQuery = query }, - ) - } - composable( - route = Destinations.Comments.route, - arguments = listOf(navArgument("postId") { type = NavType.StringType }), - deepLinks = - listOf( - navDeepLink { uriPattern = "$uri/s/${Destinations.Comments.placeholder}/.*" }, - navDeepLink { uriPattern = "$uri/s/${Destinations.Comments.placeholder}" }, - ), - ) { backStackEntry -> - val postId = requireNotNull(backStackEntry.arguments?.getString("postId")) - setWebUri("https://lobste.rs/s/$postId") - CommentsPage( - postId = postId, - postActions = postActions, - htmlConverter = htmlConverter, - getSeenComments = viewModel::getSeenComments, - markSeenComments = viewModel::markSeenComments, - ) - } - composable( - route = Destinations.User.route, - arguments = listOf(navArgument("username") { type = NavType.StringType }), - deepLinks = - listOf(navDeepLink { uriPattern = "$uri/u/${Destinations.User.placeholder}" }), - ) { backStackEntry -> - val username = requireNotNull(backStackEntry.arguments?.getString("username")) - setWebUri("https://lobste.rs/u/$username") - UserProfile( - username = username, - getProfile = viewModel::getUserProfile, - ) - } - composable(route = Destinations.DataTransfer.route) { - DataTransferScreen( - context = context, - importPosts = viewModel::importPosts, - exportPosts = viewModel::exportPosts, - snackbarHostState = snackbarHostState, - ) - } + NavHost( + navController = navController, + startDestination = Destinations.startDestination.route, + // Make animations 2x faster than default specs + enterTransition = { fadeIn(animationSpec = tween(350)) }, + exitTransition = { fadeOut(animationSpec = tween(350)) }, + ) { + val uri = LobstersApi.BASE_URL + composable(route = Destinations.Hottest.route) { + setWebUri("https://lobste.rs/") + NetworkPosts( + lazyPagingItems = hottestPosts, + listState = hottestListState, + isPostSaved = viewModel::isPostSaved, + isPostRead = viewModel::isPostRead, + postActions = postActions, + ) + } + composable(route = Destinations.Newest.route) { + setWebUri("https://lobste.rs/") + NetworkPosts( + lazyPagingItems = newestPosts, + listState = newestListState, + isPostSaved = viewModel::isPostSaved, + isPostRead = viewModel::isPostRead, + postActions = postActions, + ) + } + composable(route = Destinations.Saved.route) { + setWebUri(null) + DatabasePosts( + items = savedPosts, + listState = savedListState, + postActions = postActions, + ) + } + composable(Destinations.Search.route) { + setWebUri("https://lobste.rs/search") + SearchList( + items = viewModel.searchResults, + listState = searchListState, + isPostSaved = viewModel::isPostSaved, + postActions = postActions, + searchQuery = viewModel.searchQuery, + setSearchQuery = { query -> viewModel.searchQuery = query }, + ) + } + composable( + route = Destinations.Comments.route, + arguments = listOf(navArgument("postId") { type = NavType.StringType }), + deepLinks = + listOf( + navDeepLink { uriPattern = "$uri/s/${Destinations.Comments.placeholder}/.*" }, + navDeepLink { uriPattern = "$uri/s/${Destinations.Comments.placeholder}" }, + ), + ) { backStackEntry -> + val postId = requireNotNull(backStackEntry.arguments?.getString("postId")) + setWebUri("https://lobste.rs/s/$postId") + CommentsPage( + postId = postId, + postActions = postActions, + htmlConverter = htmlConverter, + getSeenComments = viewModel::getSeenComments, + markSeenComments = viewModel::markSeenComments, + ) + } + composable( + route = Destinations.User.route, + arguments = listOf(navArgument("username") { type = NavType.StringType }), + deepLinks = + listOf(navDeepLink { uriPattern = "$uri/u/${Destinations.User.placeholder}" }), + ) { backStackEntry -> + val username = requireNotNull(backStackEntry.arguments?.getString("username")) + setWebUri("https://lobste.rs/u/$username") + UserProfile( + username = username, + getProfile = viewModel::getUserProfile, + ) + } + composable(route = Destinations.DataTransfer.route) { + DataTransferScreen( + context = context, + importPosts = viewModel::importPosts, + exportPosts = viewModel::exportPosts, + snackbarHostState = snackbarHostState, + ) } } } diff --git a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/decorations/TransparentSystemBars.kt b/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/decorations/TransparentSystemBars.kt deleted file mode 100644 index fa4d7123..00000000 --- a/android/src/main/kotlin/dev/msfjarvis/claw/android/ui/decorations/TransparentSystemBars.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright © 2023 Harsh Shandilya. - * Use of this source code is governed by an MIT-style - * license that can be found in the LICENSE file or at - * https://opensource.org/licenses/MIT. - */ -package dev.msfjarvis.claw.android.ui.decorations - -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.ui.graphics.Color -import com.google.accompanist.systemuicontroller.rememberSystemUiController - -@Composable -fun TransparentSystemBars() { - val systemUiController = rememberSystemUiController() - val useDarkIcons = !isSystemInDarkTheme() - - DisposableEffect(systemUiController, useDarkIcons) { - systemUiController.setSystemBarsColor(color = Color.Transparent, darkIcons = useDarkIcons) - - onDispose {} - } -} diff --git a/android/src/main/res/values-night/bools.xml b/android/src/main/res/values-night/bools.xml deleted file mode 100644 index 5aa45310..00000000 --- a/android/src/main/res/values-night/bools.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - false - diff --git a/android/src/main/res/values/bools.xml b/android/src/main/res/values/bools.xml deleted file mode 100644 index 13c4d573..00000000 --- a/android/src/main/res/values/bools.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - true - diff --git a/android/src/main/res/values/themes.xml b/android/src/main/res/values/themes.xml index 8b622cca..a5e498e2 100644 --- a/android/src/main/res/values/themes.xml +++ b/android/src/main/res/values/themes.xml @@ -19,7 +19,5 @@ true - +