mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 10:37:05 +05:30
android: refactor and extract things from LobstersApp
This commit is contained in:
parent
baa3830966
commit
ad5a01b8d0
4 changed files with 106 additions and 93 deletions
|
@ -1,29 +0,0 @@
|
|||
package dev.msfjarvis.claw.android.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import dev.msfjarvis.claw.common.theme.DarkThemeColors
|
||||
import dev.msfjarvis.claw.common.theme.LightThemeColors
|
||||
|
||||
@Composable
|
||||
fun decideColorScheme(context: Context): ColorScheme {
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
return if (Build.VERSION.SDK_INT >= 31) {
|
||||
if (isDarkTheme) {
|
||||
dynamicDarkColorScheme(context)
|
||||
} else {
|
||||
dynamicLightColorScheme(context)
|
||||
}
|
||||
} else {
|
||||
if (isDarkTheme) {
|
||||
DarkThemeColors
|
||||
} else {
|
||||
LightThemeColors
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,10 +12,7 @@ import androidx.compose.runtime.mutableStateOf
|
|||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
|
@ -35,8 +32,6 @@ import dev.msfjarvis.claw.common.comments.LocalHTMLConverter
|
|||
import dev.msfjarvis.claw.common.theme.LobstersTheme
|
||||
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
|
||||
|
||||
private const val ScrollDelta = 50
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LobstersApp(
|
||||
|
@ -45,34 +40,19 @@ fun LobstersApp(
|
|||
htmlConverter: HTMLConverter,
|
||||
setWebUri: (String) -> Unit,
|
||||
) {
|
||||
var isFabVisible by remember { mutableStateOf(false) }
|
||||
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val networkListState = rememberLazyListState()
|
||||
val savedListState = rememberLazyListState()
|
||||
val navController = rememberNavController()
|
||||
val postActions = rememberPostActions(urlLauncher, navController, viewModel)
|
||||
// The destination needs to be tracked here rather than used directly since
|
||||
// `NavController#currentDestination` is not a Composable state.
|
||||
var currentDestination by remember { mutableStateOf<String?>(null) }
|
||||
var isFabVisible by remember { mutableStateOf(false) }
|
||||
val nestedScrollConnection = remember {
|
||||
object : NestedScrollConnection {
|
||||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
||||
val delta = available.y
|
||||
val currentDestination by currentNavigationDestination(navController)
|
||||
val nestedScrollConnection = rememberNestedScrollConnection { isFabVisible = it }
|
||||
|
||||
if (delta > ScrollDelta) {
|
||||
isFabVisible = true
|
||||
} else if (delta < -ScrollDelta) {
|
||||
isFabVisible = false
|
||||
}
|
||||
val networkPosts = viewModel.pagerFlow.collectAsLazyPagingItems()
|
||||
val savedPosts by viewModel.savedPosts.collectAsState(emptyList())
|
||||
|
||||
// We didn't consume any offset here so return Offset.Zero
|
||||
return Offset.Zero
|
||||
}
|
||||
}
|
||||
}
|
||||
navController.addOnDestinationChangedListener { _, destination, _ ->
|
||||
currentDestination = destination.route ?: Destinations.Hottest.getRoute()
|
||||
}
|
||||
LobstersTheme(
|
||||
LocalUriHandler provides urlLauncher,
|
||||
LocalHTMLConverter provides htmlConverter,
|
||||
|
@ -85,8 +65,6 @@ fun LobstersApp(
|
|||
systemUiController.setStatusBarColor(color = statusBarColor)
|
||||
systemUiController.setNavigationBarColor(color = Color.Transparent)
|
||||
}
|
||||
val networkPosts = viewModel.pagerFlow.collectAsLazyPagingItems()
|
||||
val savedPosts by viewModel.savedPosts.collectAsState(emptyList())
|
||||
|
||||
Scaffold(
|
||||
topBar = { ClawAppBar(modifier = Modifier.statusBarsPadding()) },
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
package dev.msfjarvis.claw.android.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.navigation.NavController
|
||||
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
|
||||
import dev.msfjarvis.claw.common.posts.PostActions
|
||||
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
|
||||
import dev.msfjarvis.claw.database.local.SavedPost
|
||||
|
||||
@Composable
|
||||
fun rememberPostActions(
|
||||
urlLauncher: UrlLauncher,
|
||||
navController: NavController,
|
||||
viewModel: ClawViewModel,
|
||||
): PostActions {
|
||||
return remember {
|
||||
object : PostActions {
|
||||
override fun viewPost(postUrl: String, commentsUrl: String) {
|
||||
urlLauncher.openUri(postUrl.ifEmpty { commentsUrl })
|
||||
}
|
||||
|
||||
override fun viewComments(postId: String) {
|
||||
navController.navigate(Destinations.Comments.getRoute(postId))
|
||||
}
|
||||
|
||||
override fun viewCommentsPage(commentsUrl: String) {
|
||||
urlLauncher.openUri(commentsUrl)
|
||||
}
|
||||
|
||||
override fun toggleSave(post: SavedPost) {
|
||||
viewModel.toggleSave(post)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
100
android/src/main/kotlin/dev/msfjarvis/claw/android/ui/ext.kt
Normal file
100
android/src/main/kotlin/dev/msfjarvis/claw/android/ui/ext.kt
Normal file
|
@ -0,0 +1,100 @@
|
|||
package dev.msfjarvis.claw.android.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||
import androidx.navigation.NavController
|
||||
import dev.msfjarvis.claw.android.viewmodel.ClawViewModel
|
||||
import dev.msfjarvis.claw.common.posts.PostActions
|
||||
import dev.msfjarvis.claw.common.theme.DarkThemeColors
|
||||
import dev.msfjarvis.claw.common.theme.LightThemeColors
|
||||
import dev.msfjarvis.claw.common.urllauncher.UrlLauncher
|
||||
import dev.msfjarvis.claw.database.local.SavedPost
|
||||
|
||||
// The destination needs to be tracked like this rather than used directly since
|
||||
// `NavController#currentDestination` is not a Composable state.
|
||||
@Composable
|
||||
fun currentNavigationDestination(navController: NavController): State<String?> {
|
||||
val currentDestination = remember { mutableStateOf<String?>(null) }
|
||||
navController.addOnDestinationChangedListener { _, destination, _ ->
|
||||
currentDestination.value = destination.route
|
||||
}
|
||||
return currentDestination
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun decideColorScheme(context: Context): ColorScheme {
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
return if (Build.VERSION.SDK_INT >= 31) {
|
||||
if (isDarkTheme) {
|
||||
dynamicDarkColorScheme(context)
|
||||
} else {
|
||||
dynamicLightColorScheme(context)
|
||||
}
|
||||
} else {
|
||||
if (isDarkTheme) {
|
||||
DarkThemeColors
|
||||
} else {
|
||||
LightThemeColors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberPostActions(
|
||||
urlLauncher: UrlLauncher,
|
||||
navController: NavController,
|
||||
viewModel: ClawViewModel,
|
||||
): PostActions {
|
||||
return remember {
|
||||
object : PostActions {
|
||||
override fun viewPost(postUrl: String, commentsUrl: String) {
|
||||
urlLauncher.openUri(postUrl.ifEmpty { commentsUrl })
|
||||
}
|
||||
|
||||
override fun viewComments(postId: String) {
|
||||
navController.navigate(Destinations.Comments.getRoute(postId))
|
||||
}
|
||||
|
||||
override fun viewCommentsPage(commentsUrl: String) {
|
||||
urlLauncher.openUri(commentsUrl)
|
||||
}
|
||||
|
||||
override fun toggleSave(post: SavedPost) {
|
||||
viewModel.toggleSave(post)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val ScrollDelta = 50
|
||||
|
||||
@Composable
|
||||
fun rememberNestedScrollConnection(setVisibility: (Boolean) -> Unit): NestedScrollConnection {
|
||||
return remember {
|
||||
object : NestedScrollConnection {
|
||||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
||||
val delta = available.y
|
||||
|
||||
if (delta > ScrollDelta) {
|
||||
setVisibility(true)
|
||||
} else if (delta < -ScrollDelta) {
|
||||
setVisibility(false)
|
||||
}
|
||||
|
||||
// We didn't consume any offset here so return Offset.Zero
|
||||
return Offset.Zero
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue