Skip to content

Commit

Permalink
Create AppViewModel to hold current site and page
Browse files Browse the repository at this point in the history
  • Loading branch information
paulcoding810 committed Dec 2, 2024
1 parent 8f40331 commit b6846c9
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 73 deletions.
75 changes: 22 additions & 53 deletions app/src/main/java/com/paulcoding/hviewer/ui/page/AppEntry.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,43 +9,43 @@ import androidx.compose.animation.fadeOut
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NamedNavArgument
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavDeepLink
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.paulcoding.hviewer.model.PostItem
import com.paulcoding.hviewer.model.SiteConfigs
import com.paulcoding.hviewer.network.Github
import com.paulcoding.hviewer.ui.page.post.PostPage
import com.paulcoding.hviewer.ui.page.posts.PostsPage
import com.paulcoding.hviewer.ui.page.search.SearchPage
import com.paulcoding.hviewer.ui.page.settings.SettingsPage
import com.paulcoding.hviewer.ui.page.sites.SitesPage
import com.paulcoding.hviewer.ui.page.topics.TopicsPage
import java.net.URLDecoder
import java.net.URLEncoder
import java.nio.charset.StandardCharsets

@Composable
fun AppEntry() {
val navController = rememberNavController()

val githubState by Github.stateFlow.collectAsState()
val siteConfigs = githubState.siteConfigs ?: SiteConfigs()
val appViewModel: AppViewModel = viewModel()

fun navToImages(post: PostItem) {
appViewModel.setCurrentPost(post)
navController.navigate(Route.POST)
}

NavHost(navController, Route.SITES) {
animatedComposable(Route.SITES) {
SitesPage(siteConfigs = siteConfigs,
refresh = { Github.refreshLocalConfigs() },
navToTopics = { site ->
val firstTopic = siteConfigs.sites[site]?.tags?.keys?.first()
if (firstTopic != null) {
navController.navigate("${Route.POSTS}/$site/$firstTopic")
} else {
navController.navigate("${Route.TOPICS}/$site")
}
appViewModel.setSiteConfig(siteConfigs.sites[site]!!)
navController.navigate(Route.POSTS)
}, navToSettings = {
navController.navigate(Route.SETTINGS)
},
Expand All @@ -54,59 +54,28 @@ fun AppEntry() {
animatedComposable(Route.SETTINGS) {
SettingsPage(goBack = { navController.popBackStack() })
}
animatedComposable("${Route.TOPICS}/{site}") { backStackEntry ->
val site = backStackEntry.arguments?.getString("site") ?: ""
val siteConfig = siteConfigs.sites[site]

if (siteConfig != null)
TopicsPage(
siteConfig = siteConfig,
navToTopic = { topic ->
navController.navigate(
"${Route.POSTS}/${site}/$topic"
)
},
goBack = { navController.popBackStack() })
}
animatedComposable("${Route.POSTS}/{site}/{topic}") { backStackEntry ->
val topic = backStackEntry.arguments?.getString("topic") ?: ""
val site = backStackEntry.arguments?.getString("site") ?: ""
val siteConfig = siteConfigs.sites[site]!!

animatedComposable(Route.POSTS) {
PostsPage(
siteConfig = siteConfig,
navToImages = { postUrl: String ->
navController.navigate(
"${Route.POST}/${site}/${topic}/${
URLEncoder.encode(postUrl, StandardCharsets.UTF_8.toString())
}"
)
appViewModel,
navToImages = { post: PostItem ->
navToImages(post)
},
navToSearch = { navController.navigate("${Route.SEARCH}/$site") },
navToSearch = { navController.navigate(Route.SEARCH) },
goBack = { navController.popBackStack() },
)
}
animatedComposable("${Route.POST}/{site}/{topic}/{postUrl}") { backStackEntry ->
val postUrl = backStackEntry.arguments?.getString("postUrl") ?: ""
val site = backStackEntry.arguments?.getString("site") ?: ""
val decodedUrl = URLDecoder.decode(postUrl, StandardCharsets.UTF_8.toString())
animatedComposable(Route.POST) {
PostPage(
siteConfig = siteConfigs.sites[site]!!, postUrl = decodedUrl, goBack = {
appViewModel,
goBack = {
navController.popBackStack()
})
}
animatedComposable("${Route.SEARCH}/{site}") { backStackEntry ->
val site = backStackEntry.arguments?.getString("site") ?: ""
val siteConfig = siteConfigs.sites[site]!!

animatedComposable(Route.SEARCH) {
SearchPage(
siteConfig = siteConfig,
navToImages = { postUrl: String ->
navController.navigate(
"${Route.POST}/${site}/search/${
URLEncoder.encode(postUrl, StandardCharsets.UTF_8.toString())
}"
)
appViewModel = appViewModel,
navToImages = { post: PostItem ->
navToImages(post)
},
goBack = { navController.popBackStack() },
)
Expand Down
26 changes: 26 additions & 0 deletions app/src/main/java/com/paulcoding/hviewer/ui/page/AppViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.paulcoding.hviewer.ui.page

import androidx.lifecycle.ViewModel
import com.paulcoding.hviewer.model.PostItem
import com.paulcoding.hviewer.model.SiteConfig
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update

class AppViewModel : ViewModel() {
private var _stateFlow = MutableStateFlow(UiState())
val stateFlow = _stateFlow.asStateFlow()

fun setCurrentPost(post: PostItem) {
_stateFlow.update { it.copy(post = post) }
}

fun setSiteConfig(siteConfig: SiteConfig) {
_stateFlow.update { it.copy(siteConfig = siteConfig) }
}

data class UiState(
val post: PostItem = PostItem(),
val siteConfig: SiteConfig = SiteConfig(),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,21 @@ import com.paulcoding.hviewer.ui.component.HImage
import com.paulcoding.hviewer.ui.component.HLoading
import com.paulcoding.hviewer.ui.component.HPageProgress
import com.paulcoding.hviewer.ui.component.HideSystemBars
import com.paulcoding.hviewer.ui.page.AppViewModel
import me.saket.telephoto.zoomable.DoubleClickToZoomListener
import me.saket.telephoto.zoomable.ZoomSpec
import me.saket.telephoto.zoomable.rememberZoomableState
import me.saket.telephoto.zoomable.zoomable

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PostPage(siteConfig: SiteConfig, postUrl: String, goBack: () -> Unit) {
fun PostPage(appViewModel: AppViewModel, goBack: () -> Unit) {
val appState by appViewModel.stateFlow.collectAsState()
val post = appState.post
val siteConfig = appState.siteConfig

val viewModel: PostViewModel = viewModel(
factory = PostViewModelFactory(postUrl, siteConfig = siteConfig)
factory = PostViewModelFactory(post.url, siteConfig = siteConfig)
)

val uiState by viewModel.stateFlow.collectAsState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,21 @@ import com.paulcoding.hviewer.ui.component.HImage
import com.paulcoding.hviewer.ui.component.HLoading
import com.paulcoding.hviewer.ui.component.HPageProgress
import com.paulcoding.hviewer.ui.icon.Search
import com.paulcoding.hviewer.ui.page.AppViewModel
import kotlinx.coroutines.launch


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PostsPage(
navToImages: (postUrl: String) -> Unit,
appViewModel: AppViewModel,
navToImages: (PostItem) -> Unit,
navToSearch: () -> Unit,
siteConfig: SiteConfig,
goBack: () -> Unit
) {
val appState by appViewModel.stateFlow.collectAsState()
val siteConfig = appState.siteConfig

val listTopic = siteConfig.tags.keys.toList()
val pagerState = rememberPagerState { listTopic.size }
val selectedTabIndex = pagerState.currentPage
Expand Down Expand Up @@ -98,8 +102,8 @@ fun PostsPage(
page,
onPageChange = { currentPage, total ->
pageProgress = currentPage to total
}) { postUrl ->
navToImages(postUrl)
}) { post ->
navToImages(post)
}
}
}
Expand All @@ -111,7 +115,7 @@ fun PageContent(
siteConfig: SiteConfig,
topic: String,
onPageChange: (Int, Int) -> Unit,
onClick: (String) -> Unit
onClick: (PostItem) -> Unit
) {
val viewModel: PostsViewModel = viewModel(
factory = PostsViewModelFactory(siteConfig, topic),
Expand Down Expand Up @@ -144,8 +148,8 @@ fun PageContent(
state = listState
) {
items(uiState.postItems) { post ->
PostItemView(post) { postUrl ->
onClick(postUrl)
PostItemView(post) {
onClick(post)
}
}
if (uiState.isLoading)
Expand All @@ -165,11 +169,11 @@ fun PageContent(
}

@Composable
fun PostItemView(postItem: PostItem, viewPost: (postUrl: String) -> Unit) {
fun PostItemView(postItem: PostItem, viewPost: () -> Unit) {
return Column(modifier = Modifier
.padding(horizontal = 16.dp, vertical = 12.dp)
.clickable {
viewPost(postItem.url)
viewPost()
}) {
Text(postItem.name)
HImage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,26 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.paulcoding.hviewer.MainApp.Companion.appContext
import com.paulcoding.hviewer.extensions.isScrolledToEnd
import com.paulcoding.hviewer.model.SiteConfig
import com.paulcoding.hviewer.model.PostItem
import com.paulcoding.hviewer.ui.component.HBackIcon
import com.paulcoding.hviewer.ui.component.HEmpty
import com.paulcoding.hviewer.ui.component.HLoading
import com.paulcoding.hviewer.ui.component.HPageProgress
import com.paulcoding.hviewer.ui.icon.EditIcon
import com.paulcoding.hviewer.ui.page.AppViewModel
import com.paulcoding.hviewer.ui.page.posts.PostItemView


@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SearchPage(
navToImages: (postUrl: String) -> Unit,
siteConfig: SiteConfig,
goBack: () -> Unit
appViewModel: AppViewModel,
navToImages: (post: PostItem) -> Unit,
goBack: () -> Unit,
) {
val appState by appViewModel.stateFlow.collectAsState()
val siteConfig = appState.siteConfig

val viewModel: SearchViewModel = viewModel(
factory = SearchViewModelFactory(siteConfig),
)
Expand Down Expand Up @@ -100,8 +104,8 @@ fun SearchPage(
Icon(EditIcon, contentDescription = "Search")
}
}
PageContent(viewModel = viewModel) { postUrl ->
navToImages(postUrl)
PageContent(viewModel = viewModel) { post ->
navToImages(post)
}
}
}
Expand All @@ -111,7 +115,7 @@ fun SearchPage(
@Composable
fun PageContent(
viewModel: SearchViewModel,
onClick: (String) -> Unit
onClick: (PostItem) -> Unit
) {
val listState = rememberLazyListState()
val uiState by viewModel.stateFlow.collectAsState()
Expand All @@ -130,8 +134,8 @@ fun PageContent(
state = listState
) {
items(uiState.postItems) { post ->
PostItemView(post) { postUrl ->
onClick(postUrl)
PostItemView(post) {
onClick(post)
}
}
if (uiState.isLoading)
Expand Down

0 comments on commit b6846c9

Please sign in to comment.