Skip to content

Commit 167f954

Browse files
Merge pull request #4 from paulcoding810/feat/use-app-viewmodel
Create AppViewModel to hold current site and page
2 parents 8f40331 + b6846c9 commit 167f954

File tree

5 files changed

+81
-73
lines changed

5 files changed

+81
-73
lines changed

app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt

Lines changed: 22 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -9,43 +9,43 @@ import androidx.compose.animation.fadeOut
99
import androidx.compose.runtime.Composable
1010
import androidx.compose.runtime.collectAsState
1111
import androidx.compose.runtime.getValue
12+
import androidx.lifecycle.viewmodel.compose.viewModel
1213
import androidx.navigation.NamedNavArgument
1314
import androidx.navigation.NavBackStackEntry
1415
import androidx.navigation.NavDeepLink
1516
import androidx.navigation.NavGraphBuilder
1617
import androidx.navigation.compose.NavHost
1718
import androidx.navigation.compose.composable
1819
import androidx.navigation.compose.rememberNavController
20+
import com.paulcoding.hviewer.model.PostItem
1921
import com.paulcoding.hviewer.model.SiteConfigs
2022
import com.paulcoding.hviewer.network.Github
2123
import com.paulcoding.hviewer.ui.page.post.PostPage
2224
import com.paulcoding.hviewer.ui.page.posts.PostsPage
2325
import com.paulcoding.hviewer.ui.page.search.SearchPage
2426
import com.paulcoding.hviewer.ui.page.settings.SettingsPage
2527
import com.paulcoding.hviewer.ui.page.sites.SitesPage
26-
import com.paulcoding.hviewer.ui.page.topics.TopicsPage
27-
import java.net.URLDecoder
28-
import java.net.URLEncoder
29-
import java.nio.charset.StandardCharsets
3028

3129
@Composable
3230
fun AppEntry() {
3331
val navController = rememberNavController()
3432

3533
val githubState by Github.stateFlow.collectAsState()
3634
val siteConfigs = githubState.siteConfigs ?: SiteConfigs()
35+
val appViewModel: AppViewModel = viewModel()
36+
37+
fun navToImages(post: PostItem) {
38+
appViewModel.setCurrentPost(post)
39+
navController.navigate(Route.POST)
40+
}
3741

3842
NavHost(navController, Route.SITES) {
3943
animatedComposable(Route.SITES) {
4044
SitesPage(siteConfigs = siteConfigs,
4145
refresh = { Github.refreshLocalConfigs() },
4246
navToTopics = { site ->
43-
val firstTopic = siteConfigs.sites[site]?.tags?.keys?.first()
44-
if (firstTopic != null) {
45-
navController.navigate("${Route.POSTS}/$site/$firstTopic")
46-
} else {
47-
navController.navigate("${Route.TOPICS}/$site")
48-
}
47+
appViewModel.setSiteConfig(siteConfigs.sites[site]!!)
48+
navController.navigate(Route.POSTS)
4949
}, navToSettings = {
5050
navController.navigate(Route.SETTINGS)
5151
},
@@ -54,59 +54,28 @@ fun AppEntry() {
5454
animatedComposable(Route.SETTINGS) {
5555
SettingsPage(goBack = { navController.popBackStack() })
5656
}
57-
animatedComposable("${Route.TOPICS}/{site}") { backStackEntry ->
58-
val site = backStackEntry.arguments?.getString("site") ?: ""
59-
val siteConfig = siteConfigs.sites[site]
60-
61-
if (siteConfig != null)
62-
TopicsPage(
63-
siteConfig = siteConfig,
64-
navToTopic = { topic ->
65-
navController.navigate(
66-
"${Route.POSTS}/${site}/$topic"
67-
)
68-
},
69-
goBack = { navController.popBackStack() })
70-
}
71-
animatedComposable("${Route.POSTS}/{site}/{topic}") { backStackEntry ->
72-
val topic = backStackEntry.arguments?.getString("topic") ?: ""
73-
val site = backStackEntry.arguments?.getString("site") ?: ""
74-
val siteConfig = siteConfigs.sites[site]!!
75-
57+
animatedComposable(Route.POSTS) {
7658
PostsPage(
77-
siteConfig = siteConfig,
78-
navToImages = { postUrl: String ->
79-
navController.navigate(
80-
"${Route.POST}/${site}/${topic}/${
81-
URLEncoder.encode(postUrl, StandardCharsets.UTF_8.toString())
82-
}"
83-
)
59+
appViewModel,
60+
navToImages = { post: PostItem ->
61+
navToImages(post)
8462
},
85-
navToSearch = { navController.navigate("${Route.SEARCH}/$site") },
63+
navToSearch = { navController.navigate(Route.SEARCH) },
8664
goBack = { navController.popBackStack() },
8765
)
8866
}
89-
animatedComposable("${Route.POST}/{site}/{topic}/{postUrl}") { backStackEntry ->
90-
val postUrl = backStackEntry.arguments?.getString("postUrl") ?: ""
91-
val site = backStackEntry.arguments?.getString("site") ?: ""
92-
val decodedUrl = URLDecoder.decode(postUrl, StandardCharsets.UTF_8.toString())
67+
animatedComposable(Route.POST) {
9368
PostPage(
94-
siteConfig = siteConfigs.sites[site]!!, postUrl = decodedUrl, goBack = {
69+
appViewModel,
70+
goBack = {
9571
navController.popBackStack()
9672
})
9773
}
98-
animatedComposable("${Route.SEARCH}/{site}") { backStackEntry ->
99-
val site = backStackEntry.arguments?.getString("site") ?: ""
100-
val siteConfig = siteConfigs.sites[site]!!
101-
74+
animatedComposable(Route.SEARCH) {
10275
SearchPage(
103-
siteConfig = siteConfig,
104-
navToImages = { postUrl: String ->
105-
navController.navigate(
106-
"${Route.POST}/${site}/search/${
107-
URLEncoder.encode(postUrl, StandardCharsets.UTF_8.toString())
108-
}"
109-
)
76+
appViewModel = appViewModel,
77+
navToImages = { post: PostItem ->
78+
navToImages(post)
11079
},
11180
goBack = { navController.popBackStack() },
11281
)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.paulcoding.hviewer.ui.page
2+
3+
import androidx.lifecycle.ViewModel
4+
import com.paulcoding.hviewer.model.PostItem
5+
import com.paulcoding.hviewer.model.SiteConfig
6+
import kotlinx.coroutines.flow.MutableStateFlow
7+
import kotlinx.coroutines.flow.asStateFlow
8+
import kotlinx.coroutines.flow.update
9+
10+
class AppViewModel : ViewModel() {
11+
private var _stateFlow = MutableStateFlow(UiState())
12+
val stateFlow = _stateFlow.asStateFlow()
13+
14+
fun setCurrentPost(post: PostItem) {
15+
_stateFlow.update { it.copy(post = post) }
16+
}
17+
18+
fun setSiteConfig(siteConfig: SiteConfig) {
19+
_stateFlow.update { it.copy(siteConfig = siteConfig) }
20+
}
21+
22+
data class UiState(
23+
val post: PostItem = PostItem(),
24+
val siteConfig: SiteConfig = SiteConfig(),
25+
)
26+
}

app/src/main/java/com/paulcoding/hviewer/ui/page/post/PostPage.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,21 @@ import com.paulcoding.hviewer.ui.component.HImage
4040
import com.paulcoding.hviewer.ui.component.HLoading
4141
import com.paulcoding.hviewer.ui.component.HPageProgress
4242
import com.paulcoding.hviewer.ui.component.HideSystemBars
43+
import com.paulcoding.hviewer.ui.page.AppViewModel
4344
import me.saket.telephoto.zoomable.DoubleClickToZoomListener
4445
import me.saket.telephoto.zoomable.ZoomSpec
4546
import me.saket.telephoto.zoomable.rememberZoomableState
4647
import me.saket.telephoto.zoomable.zoomable
4748

4849
@OptIn(ExperimentalMaterial3Api::class)
4950
@Composable
50-
fun PostPage(siteConfig: SiteConfig, postUrl: String, goBack: () -> Unit) {
51+
fun PostPage(appViewModel: AppViewModel, goBack: () -> Unit) {
52+
val appState by appViewModel.stateFlow.collectAsState()
53+
val post = appState.post
54+
val siteConfig = appState.siteConfig
55+
5156
val viewModel: PostViewModel = viewModel(
52-
factory = PostViewModelFactory(postUrl, siteConfig = siteConfig)
57+
factory = PostViewModelFactory(post.url, siteConfig = siteConfig)
5358
)
5459

5560
val uiState by viewModel.stateFlow.collectAsState()

app/src/main/java/com/paulcoding/hviewer/ui/page/posts/PostsPage.kt

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,21 @@ import com.paulcoding.hviewer.ui.component.HImage
4141
import com.paulcoding.hviewer.ui.component.HLoading
4242
import com.paulcoding.hviewer.ui.component.HPageProgress
4343
import com.paulcoding.hviewer.ui.icon.Search
44+
import com.paulcoding.hviewer.ui.page.AppViewModel
4445
import kotlinx.coroutines.launch
4546

4647

4748
@OptIn(ExperimentalMaterial3Api::class)
4849
@Composable
4950
fun PostsPage(
50-
navToImages: (postUrl: String) -> Unit,
51+
appViewModel: AppViewModel,
52+
navToImages: (PostItem) -> Unit,
5153
navToSearch: () -> Unit,
52-
siteConfig: SiteConfig,
5354
goBack: () -> Unit
5455
) {
56+
val appState by appViewModel.stateFlow.collectAsState()
57+
val siteConfig = appState.siteConfig
58+
5559
val listTopic = siteConfig.tags.keys.toList()
5660
val pagerState = rememberPagerState { listTopic.size }
5761
val selectedTabIndex = pagerState.currentPage
@@ -98,8 +102,8 @@ fun PostsPage(
98102
page,
99103
onPageChange = { currentPage, total ->
100104
pageProgress = currentPage to total
101-
}) { postUrl ->
102-
navToImages(postUrl)
105+
}) { post ->
106+
navToImages(post)
103107
}
104108
}
105109
}
@@ -111,7 +115,7 @@ fun PageContent(
111115
siteConfig: SiteConfig,
112116
topic: String,
113117
onPageChange: (Int, Int) -> Unit,
114-
onClick: (String) -> Unit
118+
onClick: (PostItem) -> Unit
115119
) {
116120
val viewModel: PostsViewModel = viewModel(
117121
factory = PostsViewModelFactory(siteConfig, topic),
@@ -144,8 +148,8 @@ fun PageContent(
144148
state = listState
145149
) {
146150
items(uiState.postItems) { post ->
147-
PostItemView(post) { postUrl ->
148-
onClick(postUrl)
151+
PostItemView(post) {
152+
onClick(post)
149153
}
150154
}
151155
if (uiState.isLoading)
@@ -165,11 +169,11 @@ fun PageContent(
165169
}
166170

167171
@Composable
168-
fun PostItemView(postItem: PostItem, viewPost: (postUrl: String) -> Unit) {
172+
fun PostItemView(postItem: PostItem, viewPost: () -> Unit) {
169173
return Column(modifier = Modifier
170174
.padding(horizontal = 16.dp, vertical = 12.dp)
171175
.clickable {
172-
viewPost(postItem.url)
176+
viewPost()
173177
}) {
174178
Text(postItem.name)
175179
HImage(

app/src/main/java/com/paulcoding/hviewer/ui/page/search/SearchPage.kt

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,26 @@ import androidx.compose.ui.unit.dp
3434
import androidx.lifecycle.viewmodel.compose.viewModel
3535
import com.paulcoding.hviewer.MainApp.Companion.appContext
3636
import com.paulcoding.hviewer.extensions.isScrolledToEnd
37-
import com.paulcoding.hviewer.model.SiteConfig
37+
import com.paulcoding.hviewer.model.PostItem
3838
import com.paulcoding.hviewer.ui.component.HBackIcon
3939
import com.paulcoding.hviewer.ui.component.HEmpty
4040
import com.paulcoding.hviewer.ui.component.HLoading
4141
import com.paulcoding.hviewer.ui.component.HPageProgress
4242
import com.paulcoding.hviewer.ui.icon.EditIcon
43+
import com.paulcoding.hviewer.ui.page.AppViewModel
4344
import com.paulcoding.hviewer.ui.page.posts.PostItemView
4445

4546

4647
@OptIn(ExperimentalMaterial3Api::class)
4748
@Composable
4849
fun SearchPage(
49-
navToImages: (postUrl: String) -> Unit,
50-
siteConfig: SiteConfig,
51-
goBack: () -> Unit
50+
appViewModel: AppViewModel,
51+
navToImages: (post: PostItem) -> Unit,
52+
goBack: () -> Unit,
5253
) {
54+
val appState by appViewModel.stateFlow.collectAsState()
55+
val siteConfig = appState.siteConfig
56+
5357
val viewModel: SearchViewModel = viewModel(
5458
factory = SearchViewModelFactory(siteConfig),
5559
)
@@ -100,8 +104,8 @@ fun SearchPage(
100104
Icon(EditIcon, contentDescription = "Search")
101105
}
102106
}
103-
PageContent(viewModel = viewModel) { postUrl ->
104-
navToImages(postUrl)
107+
PageContent(viewModel = viewModel) { post ->
108+
navToImages(post)
105109
}
106110
}
107111
}
@@ -111,7 +115,7 @@ fun SearchPage(
111115
@Composable
112116
fun PageContent(
113117
viewModel: SearchViewModel,
114-
onClick: (String) -> Unit
118+
onClick: (PostItem) -> Unit
115119
) {
116120
val listState = rememberLazyListState()
117121
val uiState by viewModel.stateFlow.collectAsState()
@@ -130,8 +134,8 @@ fun PageContent(
130134
state = listState
131135
) {
132136
items(uiState.postItems) { post ->
133-
PostItemView(post) { postUrl ->
134-
onClick(postUrl)
137+
PostItemView(post) {
138+
onClick(post)
135139
}
136140
}
137141
if (uiState.isLoading)

0 commit comments

Comments
 (0)