Skip to content

Commit 50b4054

Browse files
committed
feat(ui): large screen support
1 parent 713b47d commit 50b4054

9 files changed

Lines changed: 118 additions & 15 deletions

File tree

‎app/build.gradle‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ dependencies {
171171

172172
// https://developer.android.com/jetpack/androidx/releases/compose-material3
173173
implementation "androidx.compose.material3:material3:$material3"
174+
implementation "androidx.compose.material3:material3-window-size-class:$material3"
174175

175176
// https://github.com/google/accompanist/releases
176177
implementation "com.google.accompanist:accompanist-systemuicontroller:$accompanist"

‎app/src/main/java/me/ash/reader/infrastructure/android/MainActivity.kt‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
99
import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
1010
import androidx.activity.compose.setContent
1111
import androidx.appcompat.app.AppCompatActivity
12+
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
13+
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
1214
import androidx.compose.runtime.CompositionLocalProvider
1315
import androidx.compose.runtime.DisposableEffect
1416
import androidx.core.util.Consumer
@@ -40,6 +42,7 @@ class MainActivity : AppCompatActivity() {
4042
@Inject
4143
lateinit var accountDao: AccountDao
4244

45+
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
4346
override fun onCreate(savedInstanceState: Bundle?) {
4447
super.onCreate(savedInstanceState)
4548
WindowCompat.setDecorFitsSystemWindows(window, false)
@@ -65,6 +68,7 @@ class MainActivity : AppCompatActivity() {
6568
}
6669

6770
setContent {
71+
val widthSizeClass = calculateWindowSizeClass(this).widthSizeClass
6872
CompositionLocalProvider(
6973
LocalImageLoader provides imageLoader,
7074
) {
@@ -82,7 +86,7 @@ class MainActivity : AppCompatActivity() {
8286
removeOnNewIntentListener(listener)
8387
}
8488
}
85-
HomeEntry(subscribeViewModel = subscribeViewModel)
89+
HomeEntry(subscribeViewModel = subscribeViewModel, widthSizeClass = widthSizeClass)
8690
}
8791
}
8892
}

‎app/src/main/java/me/ash/reader/ui/component/base/RYScaffold.kt‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import me.ash.reader.ui.theme.palette.onDark
1717
@OptIn(ExperimentalMaterial3Api::class)
1818
@Composable
1919
fun RYScaffold(
20+
modifier: Modifier = Modifier,
2021
containerColor: Color = MaterialTheme.colorScheme.surface,
2122
topBarTonalElevation: Dp = 0.dp,
2223
containerTonalElevation: Dp = 0.dp,
@@ -27,7 +28,7 @@ fun RYScaffold(
2728
content: @Composable () -> Unit = {},
2829
) {
2930
Scaffold(
30-
modifier = Modifier
31+
modifier = modifier
3132
.background(
3233
MaterialTheme.colorScheme.surfaceColorAtElevation(
3334
topBarTonalElevation,

‎app/src/main/java/me/ash/reader/ui/page/common/HomeEntry.kt‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.util.Log
44
import androidx.compose.animation.ExperimentalAnimationApi
55
import androidx.compose.foundation.background
66
import androidx.compose.material3.MaterialTheme
7+
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
78
import androidx.compose.runtime.*
89
import androidx.compose.runtime.saveable.rememberSaveable
910
import androidx.compose.ui.Modifier
@@ -23,6 +24,7 @@ import me.ash.reader.ui.page.home.HomeViewModel
2324
import me.ash.reader.ui.page.home.feeds.FeedsPage
2425
import me.ash.reader.ui.page.home.feeds.subscribe.SubscribeViewModel
2526
import me.ash.reader.ui.page.home.flow.FlowPage
27+
import me.ash.reader.ui.page.home.flow.FlowRoute
2628
import me.ash.reader.ui.page.home.reading.ReadingPage
2729
import me.ash.reader.ui.page.settings.SettingsPage
2830
import me.ash.reader.ui.page.settings.accounts.AccountDetailsPage
@@ -44,6 +46,7 @@ import me.ash.reader.ui.theme.AppTheme
4446
fun HomeEntry(
4547
homeViewModel: HomeViewModel = hiltViewModel(),
4648
subscribeViewModel: SubscribeViewModel = hiltViewModel(),
49+
widthSizeClass: WindowWidthSizeClass,
4750
) {
4851
val context = LocalContext.current
4952
var isReadingPage by rememberSaveable { mutableStateOf(false) }
@@ -58,6 +61,8 @@ fun HomeEntry(
5861
intent?.replaceExtras(null)
5962
}
6063

64+
val isExpandedScreen = widthSizeClass == WindowWidthSizeClass.Expanded
65+
6166
LaunchedEffect(Unit) {
6267
when (context.initialPage) {
6368
1 -> {
@@ -152,13 +157,14 @@ fun HomeEntry(
152157
)
153158
}
154159
forwardAndBackwardComposable(route = RouteName.FLOW) {
155-
FlowPage(
160+
FlowRoute(
156161
navController = navController,
157-
homeViewModel = homeViewModel,
162+
isExpandedScreen = isExpandedScreen,
163+
homeViewModel = homeViewModel
158164
)
159165
}
160166
forwardAndBackwardComposable(route = "${RouteName.READING}/{articleId}") {
161-
ReadingPage(navController = navController, homeViewModel = homeViewModel)
167+
ReadingPage(navController = navController, homeViewModel = homeViewModel, isExpandedScreen = isExpandedScreen)
162168
}
163169

164170
// Settings

‎app/src/main/java/me/ash/reader/ui/page/home/flow/FlowPage.kt‎

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import me.ash.reader.ui.component.base.*
3232
import me.ash.reader.ui.ext.collectAsStateValue
3333
import me.ash.reader.ui.page.common.RouteName
3434
import me.ash.reader.ui.page.home.HomeViewModel
35+
import me.ash.reader.ui.page.home.reading.ReadingPage
3536

3637
@OptIn(
3738
com.google.accompanist.pager.ExperimentalPagerApi::class,
@@ -41,6 +42,8 @@ import me.ash.reader.ui.page.home.HomeViewModel
4142
fun FlowPage(
4243
navController: NavHostController,
4344
flowViewModel: FlowViewModel = hiltViewModel(),
45+
isExpandedScreen: Boolean,
46+
onArticleClick: ((ArticleWithFeed) -> Unit)? = null,
4447
homeViewModel: HomeViewModel,
4548
) {
4649
val keyboardController = LocalSoftwareKeyboardController.current
@@ -145,7 +148,9 @@ fun FlowPage(
145148
onSearch = false
146149
}
147150

151+
val width = if (isExpandedScreen) Modifier.width(334.dp) else Modifier
148152
RYScaffold(
153+
modifier = width,
149154
topBarTonalElevation = topBarTonalElevation.value.dp,
150155
containerTonalElevation = articleListTonalElevation.value.dp,
151156
navigationIcon = {
@@ -290,8 +295,12 @@ fun FlowPage(
290295
isScrollInProgress = { listState.isScrollInProgress },
291296
onClick = {
292297
onSearch = false
293-
navController.navigate("${RouteName.READING}/${it.article.id}") {
294-
launchSingleTop = true
298+
if (onArticleClick == null) {
299+
navController.navigate("${RouteName.READING}/${it.article.id}") {
300+
launchSingleTop = true
301+
}
302+
} else {
303+
onArticleClick(it)
295304
}
296305
},
297306
onSwipeStartToEnd = onSwipeStartToEnd,
@@ -327,3 +336,28 @@ fun FlowPage(
327336
}
328337
)
329338
}
339+
340+
@Composable
341+
fun FlowWithArticleDetailsScreen(
342+
navController: NavHostController,
343+
isExpandedScreen: Boolean,
344+
homeViewModel: HomeViewModel,
345+
flowViewModel: FlowViewModel,
346+
) {
347+
var articleId : String? by remember {
348+
mutableStateOf(null)
349+
}
350+
351+
Row {
352+
FlowPage(
353+
navController = navController,
354+
isExpandedScreen = isExpandedScreen,
355+
onArticleClick = {
356+
articleId = it.article.id
357+
},
358+
homeViewModel = homeViewModel,
359+
flowViewModel = flowViewModel,
360+
)
361+
ReadingPage(navController = navController, homeViewModel = homeViewModel, isExpandedScreen = isExpandedScreen, articleId = articleId)
362+
}
363+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package me.ash.reader.ui.page.home.flow
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.hilt.navigation.compose.hiltViewModel
5+
import androidx.navigation.NavHostController
6+
import me.ash.reader.ui.page.home.HomeViewModel
7+
8+
enum class FlowScreenType {
9+
FlowWithArticleDetails,
10+
Flow,
11+
}
12+
13+
fun getFlowScreenType(isExpanded: Boolean): FlowScreenType = when (isExpanded) {
14+
true -> {
15+
FlowScreenType.FlowWithArticleDetails
16+
}
17+
false -> {
18+
FlowScreenType.Flow
19+
}
20+
}
21+
22+
@Composable
23+
fun FlowRoute(
24+
navController: NavHostController,
25+
isExpandedScreen: Boolean,
26+
homeViewModel: HomeViewModel,
27+
flowViewModel: FlowViewModel = hiltViewModel(),
28+
) {
29+
val flowScreenType = getFlowScreenType(isExpandedScreen)
30+
31+
when (flowScreenType) {
32+
FlowScreenType.FlowWithArticleDetails -> {
33+
FlowWithArticleDetailsScreen(
34+
navController = navController,
35+
isExpandedScreen = isExpandedScreen,
36+
homeViewModel = homeViewModel,
37+
flowViewModel = flowViewModel,
38+
)
39+
}
40+
FlowScreenType.Flow -> {
41+
FlowPage(
42+
navController = navController,
43+
isExpandedScreen = isExpandedScreen,
44+
homeViewModel = homeViewModel,
45+
flowViewModel = flowViewModel,
46+
)
47+
}
48+
}
49+
}

‎app/src/main/java/me/ash/reader/ui/page/home/flow/FlowViewModel.kt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import kotlinx.coroutines.delay
99
import kotlinx.coroutines.flow.MutableStateFlow
1010
import kotlinx.coroutines.flow.StateFlow
1111
import kotlinx.coroutines.flow.asStateFlow
12+
import kotlinx.coroutines.flow.update
1213
import kotlinx.coroutines.launch
1314
import me.ash.reader.domain.model.general.MarkAsReadConditions
1415
import me.ash.reader.domain.service.RssService

‎app/src/main/java/me/ash/reader/ui/page/home/reading/ReadingPage.kt‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ private const val DOWNWARD = -1
4545
fun ReadingPage(
4646
navController: NavHostController,
4747
homeViewModel: HomeViewModel,
48+
isExpandedScreen: Boolean,
49+
articleId: String? = null,
4850
readingViewModel: ReadingViewModel = hiltViewModel(),
4951
) {
5052
val tonalElevation = LocalReadingPageTonalElevation.current
@@ -66,9 +68,10 @@ fun ReadingPage(
6668

6769
val pagingItems = homeUiState.pagingData.collectAsLazyPagingItems().itemSnapshotList
6870

69-
LaunchedEffect(Unit) {
71+
LaunchedEffect(articleId) {
7072
navController.currentBackStackEntryFlow.collect {
71-
it.arguments?.getString("articleId")?.let { articleId ->
73+
val getArticleId : String? = articleId ?: it.arguments?.getString("articleId")
74+
getArticleId?.let { articleId ->
7275
if (readerState.articleId != articleId) {
7376
readingViewModel.initData(articleId)
7477
}
@@ -101,6 +104,7 @@ fun ReadingPage(
101104
windowInsets = WindowInsets(top = paddings.calculateTopPadding()),
102105
title = readerState.title,
103106
link = readerState.link,
107+
isExpandedScreen = isExpandedScreen,
104108
onClose = {
105109
navController.popBackStack()
106110
},

‎app/src/main/java/me/ash/reader/ui/page/home/reading/TopBar.kt‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ fun TopBar(
3535
windowInsets: WindowInsets = WindowInsets(0.dp),
3636
title: String? = "",
3737
link: String? = "",
38+
isExpandedScreen: Boolean,
3839
onClose: () -> Unit = {},
3940
) {
4041
val context = LocalContext.current
@@ -52,12 +53,14 @@ fun TopBar(
5253
modifier = Modifier,
5354
windowInsets = windowInsets,
5455
navigationIcon = {
55-
FeedbackIconButton(
56-
imageVector = Icons.Rounded.Close,
57-
contentDescription = stringResource(R.string.close),
58-
tint = MaterialTheme.colorScheme.onSurface
59-
) {
60-
onClose()
56+
if (!isExpandedScreen) {
57+
FeedbackIconButton(
58+
imageVector = Icons.Rounded.Close,
59+
contentDescription = stringResource(R.string.close),
60+
tint = MaterialTheme.colorScheme.onSurface
61+
) {
62+
onClose()
63+
}
6164
}
6265
},
6366
actions = {

0 commit comments

Comments
 (0)