diff --git a/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt b/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt index 60ed1ba8d..e3296098d 100644 --- a/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt +++ b/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt @@ -1,23 +1,23 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.di -import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreenViewModel -import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreenViewModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailViewModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailViewModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel import org.koin.core.parameter.parametersOf import org.koin.java.KoinJavaComponent.inject -actual fun getPostDetailScreenViewModel(post: PostModel): PostDetailScreenViewModel { - val res: PostDetailScreenViewModel by inject( - clazz = PostDetailScreenViewModel::class.java, +actual fun getPostDetailScreenViewModel(post: PostModel): PostDetailViewModel { + val res: PostDetailViewModel by inject( + clazz = PostDetailViewModel::class.java, parameters = { parametersOf(post) }, ) return res } -actual fun getCommunityDetailScreenViewModel(community: CommunityModel): CommunityDetailScreenViewModel { - val res: CommunityDetailScreenViewModel by inject( - clazz = CommunityDetailScreenViewModel::class.java, +actual fun getCommunityDetailScreenViewModel(community: CommunityModel): CommunityDetailViewModel { + val res: CommunityDetailViewModel by inject( + clazz = CommunityDetailViewModel::class.java, parameters = { parametersOf(community) }, ) return res diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreenMviModel.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailMviModel.kt similarity index 84% rename from core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreenMviModel.kt rename to core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailMviModel.kt index 535f5fbf2..5277ec9ef 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreenMviModel.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailMviModel.kt @@ -4,8 +4,8 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel -interface CommunityDetailScreenMviModel : - MviModel { +interface CommunityDetailMviModel : + MviModel { sealed interface Intent { object Refresh : Intent diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreen.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreen.kt index 5fc4a744d..dfb0a0304 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreen.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreen.kt @@ -93,7 +93,7 @@ class CommunityDetailScreen( ) { padding -> val community = uiState.community val pullRefreshState = rememberPullRefreshState(uiState.refreshing, { - model.reduce(CommunityDetailScreenMviModel.Intent.Refresh) + model.reduce(CommunityDetailMviModel.Intent.Refresh) }) Box( modifier = Modifier.pullRefresh(pullRefreshState), @@ -186,7 +186,7 @@ class CommunityDetailScreen( post = post, onUpVote = { model.reduce( - CommunityDetailScreenMviModel.Intent.UpVotePost( + CommunityDetailMviModel.Intent.UpVotePost( it, post, ), @@ -194,7 +194,7 @@ class CommunityDetailScreen( }, onDownVote = { model.reduce( - CommunityDetailScreenMviModel.Intent.DownVotePost( + CommunityDetailMviModel.Intent.DownVotePost( it, post, ), @@ -202,7 +202,7 @@ class CommunityDetailScreen( }, onSave = { model.reduce( - CommunityDetailScreenMviModel.Intent.SavePost( + CommunityDetailMviModel.Intent.SavePost( it, post, ), @@ -212,7 +212,7 @@ class CommunityDetailScreen( } item { if (!uiState.loading && !uiState.refreshing && uiState.canFetchMore) { - model.reduce(CommunityDetailScreenMviModel.Intent.LoadNextPage) + model.reduce(CommunityDetailMviModel.Intent.LoadNextPage) } if (uiState.loading && !uiState.refreshing) { Box( diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreenViewModel.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreenViewModel.kt deleted file mode 100644 index ce782451d..000000000 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreenViewModel.kt +++ /dev/null @@ -1,164 +0,0 @@ -package com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail - -import cafe.adriel.voyager.core.model.ScreenModel -import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel -import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel -import com.github.diegoberaldin.raccoonforlemmy.core.preferences.KeyStoreKeys -import com.github.diegoberaldin.raccoonforlemmy.core.preferences.TemporaryKeyStore -import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository -import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel -import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel -import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType -import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository -import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostsRepository -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.IO -import kotlinx.coroutines.launch - -class CommunityDetailScreenViewModel( - private val mvi: DefaultMviModel, - private val community: CommunityModel, - private val identityRepository: IdentityRepository, - private val postsRepository: PostsRepository, - private val keyStore: TemporaryKeyStore, -) : MviModel by mvi, - ScreenModel { - private var currentPage: Int = 1 - override fun onStarted() { - mvi.onStarted() - mvi.updateState { it.copy(community = community) } - - if (mvi.uiState.value.posts.isEmpty()) { - refresh() - } - } - - override fun reduce(intent: CommunityDetailScreenMviModel.Intent) { - when (intent) { - CommunityDetailScreenMviModel.Intent.LoadNextPage -> loadNextPage() - CommunityDetailScreenMviModel.Intent.Refresh -> refresh() - - is CommunityDetailScreenMviModel.Intent.DownVotePost -> downVotePost( - intent.post, - intent.value, - ) - - is CommunityDetailScreenMviModel.Intent.SavePost -> savePost( - intent.post, - intent.value, - ) - - is CommunityDetailScreenMviModel.Intent.UpVotePost -> upVotePost( - intent.post, - intent.value, - ) - } - } - - private fun refresh() { - currentPage = 1 - mvi.updateState { it.copy(canFetchMore = true, refreshing = true) } - loadNextPage() - } - - private fun loadNextPage() { - val currentState = mvi.uiState.value - if (!currentState.canFetchMore || currentState.loading) { - return - } - - mvi.scope.launch(Dispatchers.IO) { - mvi.updateState { it.copy(loading = true) } - val auth = identityRepository.authToken.value - val refreshing = currentState.refreshing - val sort = keyStore[KeyStoreKeys.DefaultCommentSortType, 3].toSortType() - val commentList = postsRepository.getAll( - auth = auth, - communityId = community.id, - page = currentPage, - sort = sort, - ) - currentPage++ - val canFetchMore = commentList.size >= CommentRepository.DEFAULT_PAGE_SIZE - mvi.updateState { - val newItems = if (refreshing) { - commentList - } else { - it.posts + commentList - } - it.copy( - posts = newItems, - loading = false, - canFetchMore = canFetchMore, - refreshing = false, - ) - } - } - } - - private fun upVotePost(post: PostModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newItem = postsRepository.upVote( - auth = auth, - post = post, - voted = value, - ) - mvi.updateState { - it.copy( - posts = it.posts.map { p -> - if (p.id == post.id) { - newItem - } else { - p - } - }, - ) - } - } - } - - private fun downVotePost(post: PostModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newItem = postsRepository.downVote( - auth = auth, - post = post, - downVoted = value, - ) - mvi.updateState { - it.copy( - posts = it.posts.map { p -> - if (p.id == post.id) { - newItem - } else { - p - } - }, - ) - } - } - } - - private fun savePost(post: PostModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newItem = postsRepository.save( - auth = auth, - post = post, - saved = value, - ) - mvi.updateState { - it.copy( - posts = it.posts.map { p -> - if (p.id == post.id) { - newItem - } else { - p - } - }, - ) - } - } - } -} diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailViewModel.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailViewModel.kt new file mode 100644 index 000000000..9aaefbcc9 --- /dev/null +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailViewModel.kt @@ -0,0 +1,212 @@ +package com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail + +import cafe.adriel.voyager.core.model.ScreenModel +import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel +import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel +import com.github.diegoberaldin.raccoonforlemmy.core.preferences.KeyStoreKeys +import com.github.diegoberaldin.raccoonforlemmy.core.preferences.TemporaryKeyStore +import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostsRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO +import kotlinx.coroutines.launch + +class CommunityDetailViewModel( + private val mvi: DefaultMviModel, + private val community: CommunityModel, + private val identityRepository: IdentityRepository, + private val postsRepository: PostsRepository, + private val keyStore: TemporaryKeyStore, +) : MviModel by mvi, + ScreenModel { + private var currentPage: Int = 1 + override fun onStarted() { + mvi.onStarted() + mvi.updateState { it.copy(community = community) } + + if (mvi.uiState.value.posts.isEmpty()) { + refresh() + } + } + + override fun reduce(intent: CommunityDetailMviModel.Intent) { + when (intent) { + CommunityDetailMviModel.Intent.LoadNextPage -> loadNextPage() + CommunityDetailMviModel.Intent.Refresh -> refresh() + + is CommunityDetailMviModel.Intent.DownVotePost -> downVotePost( + intent.post, + intent.value, + ) + + is CommunityDetailMviModel.Intent.SavePost -> savePost( + intent.post, + intent.value, + ) + + is CommunityDetailMviModel.Intent.UpVotePost -> upVotePost( + intent.post, + intent.value, + ) + } + } + + private fun refresh() { + currentPage = 1 + mvi.updateState { it.copy(canFetchMore = true, refreshing = true) } + loadNextPage() + } + + private fun loadNextPage() { + val currentState = mvi.uiState.value + if (!currentState.canFetchMore || currentState.loading) { + return + } + + mvi.scope.launch(Dispatchers.IO) { + mvi.updateState { it.copy(loading = true) } + val auth = identityRepository.authToken.value + val refreshing = currentState.refreshing + val sort = keyStore[KeyStoreKeys.DefaultCommentSortType, 3].toSortType() + val commentList = postsRepository.getAll( + auth = auth, + communityId = community.id, + page = currentPage, + sort = sort, + ) + currentPage++ + val canFetchMore = commentList.size >= CommentRepository.DEFAULT_PAGE_SIZE + mvi.updateState { + val newItems = if (refreshing) { + commentList + } else { + it.posts + commentList + } + it.copy( + posts = newItems, + loading = false, + canFetchMore = canFetchMore, + refreshing = false, + ) + } + } + } + + private fun upVotePost(post: PostModel, value: Boolean) { + val newPost = postsRepository.asUpVoted(post, value) + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + newPost + } else { + p + } + }, + ) + } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + postsRepository.upVote( + auth = auth, + post = post, + voted = value, + ) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + post + } else { + p + } + }, + ) + } + } + } + } + + private fun downVotePost(post: PostModel, value: Boolean) { + val newPost = postsRepository.asDownVoted(post, value) + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + newPost + } else { + p + } + }, + ) + } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + postsRepository.downVote( + auth = auth, + post = post, + downVoted = value, + ) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + post + } else { + p + } + }, + ) + } + } + } + } + + private fun savePost(post: PostModel, value: Boolean) { + val newPost = postsRepository.asSaved(post, value) + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + newPost + } else { + p + } + }, + ) + } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + postsRepository.save( + auth = auth, + post = post, + saved = value, + ) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + post + } else { + p + } + }, + ) + } + } + } + } +} diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/CommonUiModule.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/CommonUiModule.kt index a0fca1049..5b8f286f3 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/CommonUiModule.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/CommonUiModule.kt @@ -1,16 +1,16 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.di import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel -import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreenMviModel -import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreenViewModel -import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreenMviModel -import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreenViewModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailMviModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailViewModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailMviModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailViewModel import org.koin.dsl.module val commonUiModule = module { factory { params -> - PostDetailScreenViewModel( - mvi = DefaultMviModel(PostDetailScreenMviModel.UiState()), + PostDetailViewModel( + mvi = DefaultMviModel(PostDetailMviModel.UiState()), post = params[0], identityRepository = get(), postsRepository = get(), @@ -20,8 +20,8 @@ val commonUiModule = module { ) } factory { params -> - CommunityDetailScreenViewModel( - mvi = DefaultMviModel(CommunityDetailScreenMviModel.UiState()), + CommunityDetailViewModel( + mvi = DefaultMviModel(CommunityDetailMviModel.UiState()), community = params[0], identityRepository = get(), postsRepository = get(), diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt index a84ce3c9d..8e8f27cf3 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt @@ -1,10 +1,10 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.di -import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreenViewModel -import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreenViewModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailViewModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailViewModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel -expect fun getPostDetailScreenViewModel(post: PostModel): PostDetailScreenViewModel +expect fun getPostDetailScreenViewModel(post: PostModel): PostDetailViewModel -expect fun getCommunityDetailScreenViewModel(community: CommunityModel): CommunityDetailScreenViewModel +expect fun getCommunityDetailScreenViewModel(community: CommunityModel): CommunityDetailViewModel diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreenMviModel.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailMviModel.kt similarity index 88% rename from core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreenMviModel.kt rename to core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailMviModel.kt index c0adee94b..315022c00 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreenMviModel.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailMviModel.kt @@ -4,8 +4,8 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel -interface PostDetailScreenMviModel : - MviModel { +interface PostDetailMviModel : + MviModel { sealed interface Intent { object Refresh : Intent diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreen.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreen.kt index 3ff1f6ad5..718815930 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreen.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreen.kt @@ -75,7 +75,7 @@ class PostDetailScreen( ) { padding -> val post = uiState.post val pullRefreshState = rememberPullRefreshState(uiState.refreshing, { - model.reduce(PostDetailScreenMviModel.Intent.Refresh) + model.reduce(PostDetailMviModel.Intent.Refresh) }) Box( modifier = Modifier.pullRefresh(pullRefreshState), @@ -111,13 +111,13 @@ class PostDetailScreen( downVoted = post.myVote < 0, saved = post.saved, onUpVote = { - model.reduce(PostDetailScreenMviModel.Intent.UpVotePost(it, post)) + model.reduce(PostDetailMviModel.Intent.UpVotePost(it, post)) }, onDownVote = { - model.reduce(PostDetailScreenMviModel.Intent.DownVotePost(it, post)) + model.reduce(PostDetailMviModel.Intent.DownVotePost(it, post)) }, onSave = { - model.reduce(PostDetailScreenMviModel.Intent.SavePost(it, post)) + model.reduce(PostDetailMviModel.Intent.SavePost(it, post)) }, ) } @@ -126,7 +126,7 @@ class PostDetailScreen( comment = comment, onUpVote = { model.reduce( - PostDetailScreenMviModel.Intent.UpVoteComment( + PostDetailMviModel.Intent.UpVoteComment( it, comment, ), @@ -134,7 +134,7 @@ class PostDetailScreen( }, onDownVote = { model.reduce( - PostDetailScreenMviModel.Intent.DownVoteComment( + PostDetailMviModel.Intent.DownVoteComment( it, comment, ), @@ -142,7 +142,7 @@ class PostDetailScreen( }, onSave = { model.reduce( - PostDetailScreenMviModel.Intent.SaveComment( + PostDetailMviModel.Intent.SaveComment( it, comment, ), @@ -152,7 +152,7 @@ class PostDetailScreen( } item { if (!uiState.loading && !uiState.refreshing && uiState.canFetchMore) { - model.reduce(PostDetailScreenMviModel.Intent.LoadNextPage) + model.reduce(PostDetailMviModel.Intent.LoadNextPage) } if (uiState.loading && !uiState.refreshing) { Box( diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreenViewModel.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreenViewModel.kt deleted file mode 100644 index f8002d26f..000000000 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreenViewModel.kt +++ /dev/null @@ -1,223 +0,0 @@ -package com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail - -import cafe.adriel.voyager.core.model.ScreenModel -import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel -import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel -import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenter -import com.github.diegoberaldin.raccoonforlemmy.core.preferences.KeyStoreKeys -import com.github.diegoberaldin.raccoonforlemmy.core.preferences.TemporaryKeyStore -import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository -import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel -import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel -import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType -import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository -import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostsRepository -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.IO -import kotlinx.coroutines.launch - -class PostDetailScreenViewModel( - private val mvi: DefaultMviModel, - private val post: PostModel, - private val identityRepository: IdentityRepository, - private val postsRepository: PostsRepository, - private val commentRepository: CommentRepository, - private val keyStore: TemporaryKeyStore, - private val notificationCenter: NotificationCenter, -) : MviModel by mvi, - ScreenModel { - private var currentPage: Int = 1 - override fun onStarted() { - mvi.onStarted() - mvi.updateState { it.copy(post = post) } - - if (mvi.uiState.value.comments.isEmpty()) { - refresh() - } - } - - override fun reduce(intent: PostDetailScreenMviModel.Intent) { - when (intent) { - PostDetailScreenMviModel.Intent.LoadNextPage -> loadNextPage() - PostDetailScreenMviModel.Intent.Refresh -> refresh() - is PostDetailScreenMviModel.Intent.DownVoteComment -> downVoteComment( - intent.comment, - intent.value, - ) - - is PostDetailScreenMviModel.Intent.DownVotePost -> downVotePost( - intent.post, - intent.value, - ) - - is PostDetailScreenMviModel.Intent.SaveComment -> saveComment( - intent.comment, - intent.value, - ) - - is PostDetailScreenMviModel.Intent.SavePost -> savePost( - intent.post, - intent.value, - ) - - is PostDetailScreenMviModel.Intent.UpVoteComment -> upVoteComment( - intent.comment, - intent.value, - ) - - is PostDetailScreenMviModel.Intent.UpVotePost -> upVotePost( - intent.post, - intent.value, - ) - } - } - - private fun refresh() { - currentPage = 1 - mvi.updateState { it.copy(canFetchMore = true, refreshing = true) } - loadNextPage() - } - - private fun loadNextPage() { - val currentState = mvi.uiState.value - if (!currentState.canFetchMore || currentState.loading) { - return - } - - mvi.scope.launch(Dispatchers.IO) { - mvi.updateState { it.copy(loading = true) } - val auth = identityRepository.authToken.value - val refreshing = currentState.refreshing - val sort = keyStore[KeyStoreKeys.DefaultCommentSortType, 3].toSortType() - val commentList = commentRepository.getAll( - auth = auth, - postId = post.id, - page = currentPage, - sort = sort, - ) - currentPage++ - val canFetchMore = commentList.size >= CommentRepository.DEFAULT_PAGE_SIZE - mvi.updateState { - val newcomments = if (refreshing) { - commentList - } else { - it.comments + commentList - } - it.copy( - comments = newcomments, - loading = false, - canFetchMore = canFetchMore, - refreshing = false, - ) - } - } - } - - private fun upVotePost(post: PostModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newPost = postsRepository.upVote( - auth = auth, - post = post, - voted = value, - ) - mvi.updateState { it.copy(post = newPost) } - notificationCenter.send(NotificationCenter.Event.PostUpdate(newPost)) - } - } - - private fun downVotePost(post: PostModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newPost = postsRepository.downVote( - auth = auth, - post = post, - downVoted = value, - ) - mvi.updateState { it.copy(post = newPost) } - notificationCenter.send(NotificationCenter.Event.PostUpdate(newPost)) - } - } - - private fun savePost(post: PostModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newPost = postsRepository.save( - auth = auth, - post = post, - saved = value, - ) - mvi.updateState { it.copy(post = newPost) } - notificationCenter.send(NotificationCenter.Event.PostUpdate(newPost)) - } - } - - private fun upVoteComment(comment: CommentModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newComment = commentRepository.upVote( - auth = auth, - comment = comment, - voted = value, - ) - mvi.updateState { - it.copy( - comments = it.comments.map { c -> - if (c.id == comment.id) { - newComment - } else { - c - } - }, - ) - } - notificationCenter.send(NotificationCenter.Event.CommentUpdate(newComment)) - } - } - - private fun downVoteComment(comment: CommentModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newComment = commentRepository.downVote( - auth = auth, - comment = comment, - downVoted = value, - ) - mvi.updateState { - it.copy( - comments = it.comments.map { c -> - if (c.id == comment.id) { - newComment - } else { - c - } - }, - ) - } - notificationCenter.send(NotificationCenter.Event.CommentUpdate(newComment)) - } - } - - private fun saveComment(comment: CommentModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newComment = commentRepository.save( - auth = auth, - comment = comment, - saved = value, - ) - mvi.updateState { - it.copy( - comments = it.comments.map { c -> - if (c.id == comment.id) { - newComment - } else { - c - } - }, - ) - } - notificationCenter.send(NotificationCenter.Event.CommentUpdate(newComment)) - } - } -} diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailViewModel.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailViewModel.kt new file mode 100644 index 000000000..d390cd61e --- /dev/null +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailViewModel.kt @@ -0,0 +1,290 @@ +package com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail + +import cafe.adriel.voyager.core.model.ScreenModel +import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel +import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel +import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenter +import com.github.diegoberaldin.raccoonforlemmy.core.preferences.KeyStoreKeys +import com.github.diegoberaldin.raccoonforlemmy.core.preferences.TemporaryKeyStore +import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostsRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO +import kotlinx.coroutines.launch + +class PostDetailViewModel( + private val mvi: DefaultMviModel, + private val post: PostModel, + private val identityRepository: IdentityRepository, + private val postsRepository: PostsRepository, + private val commentRepository: CommentRepository, + private val keyStore: TemporaryKeyStore, + private val notificationCenter: NotificationCenter, +) : MviModel by mvi, + ScreenModel { + private var currentPage: Int = 1 + override fun onStarted() { + mvi.onStarted() + mvi.updateState { it.copy(post = post) } + + if (mvi.uiState.value.comments.isEmpty()) { + refresh() + } + } + + override fun reduce(intent: PostDetailMviModel.Intent) { + when (intent) { + PostDetailMviModel.Intent.LoadNextPage -> loadNextPage() + PostDetailMviModel.Intent.Refresh -> refresh() + is PostDetailMviModel.Intent.DownVoteComment -> downVoteComment( + intent.comment, + intent.value, + ) + + is PostDetailMviModel.Intent.DownVotePost -> downVotePost( + intent.post, + intent.value, + ) + + is PostDetailMviModel.Intent.SaveComment -> saveComment( + intent.comment, + intent.value, + ) + + is PostDetailMviModel.Intent.SavePost -> savePost( + intent.post, + intent.value, + ) + + is PostDetailMviModel.Intent.UpVoteComment -> upVoteComment( + intent.comment, + intent.value, + ) + + is PostDetailMviModel.Intent.UpVotePost -> upVotePost( + intent.post, + intent.value, + ) + } + } + + private fun refresh() { + currentPage = 1 + mvi.updateState { it.copy(canFetchMore = true, refreshing = true) } + loadNextPage() + } + + private fun loadNextPage() { + val currentState = mvi.uiState.value + if (!currentState.canFetchMore || currentState.loading) { + return + } + + mvi.scope.launch(Dispatchers.IO) { + mvi.updateState { it.copy(loading = true) } + val auth = identityRepository.authToken.value + val refreshing = currentState.refreshing + val sort = keyStore[KeyStoreKeys.DefaultCommentSortType, 3].toSortType() + val commentList = commentRepository.getAll( + auth = auth, + postId = post.id, + page = currentPage, + sort = sort, + ) + currentPage++ + val canFetchMore = commentList.size >= CommentRepository.DEFAULT_PAGE_SIZE + mvi.updateState { + val newcomments = if (refreshing) { + commentList + } else { + it.comments + commentList + } + it.copy( + comments = newcomments, + loading = false, + canFetchMore = canFetchMore, + refreshing = false, + ) + } + } + } + + private fun upVotePost(post: PostModel, value: Boolean) { + val newPost = postsRepository.asUpVoted(post, value) + mvi.updateState { it.copy(post = newPost) } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + postsRepository.upVote( + auth = auth, + post = post, + voted = value, + ) + notificationCenter.send(NotificationCenter.Event.PostUpdate(newPost)) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { it.copy(post = post) } + } + } + } + + private fun downVotePost(post: PostModel, value: Boolean) { + val newPost = postsRepository.asDownVoted(post, value) + mvi.updateState { it.copy(post = newPost) } + + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + postsRepository.downVote( + auth = auth, + post = post, + downVoted = value, + ) + notificationCenter.send(NotificationCenter.Event.PostUpdate(newPost)) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { it.copy(post = post) } + } + } + } + + private fun savePost(post: PostModel, value: Boolean) { + val newPost = postsRepository.asSaved(post, value) + mvi.updateState { it.copy(post = newPost) } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + postsRepository.save( + auth = auth, + post = post, + saved = value, + ) + notificationCenter.send(NotificationCenter.Event.PostUpdate(newPost)) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { it.copy(post = post) } + } + } + } + + private fun upVoteComment(comment: CommentModel, value: Boolean) { + val newComment = commentRepository.asUpVoted(comment, value) + mvi.updateState { + it.copy( + comments = it.comments.map { c -> + if (c.id == comment.id) { + newComment + } else { + c + } + }, + ) + } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + commentRepository.upVote( + auth = auth, + comment = comment, + voted = value, + ) + notificationCenter.send(NotificationCenter.Event.CommentUpdate(newComment)) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { + it.copy( + comments = it.comments.map { c -> + if (c.id == comment.id) { + comment + } else { + c + } + }, + ) + } + } + } + } + + private fun downVoteComment(comment: CommentModel, value: Boolean) { + val newComment = commentRepository.asDownVoted(comment, value) + mvi.updateState { + it.copy( + comments = it.comments.map { c -> + if (c.id == comment.id) { + newComment + } else { + c + } + }, + ) + } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + commentRepository.downVote( + auth = auth, + comment = comment, + downVoted = value, + ) + notificationCenter.send(NotificationCenter.Event.CommentUpdate(newComment)) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { + it.copy( + comments = it.comments.map { c -> + if (c.id == comment.id) { + comment + } else { + c + } + }, + ) + } + } + } + } + + private fun saveComment(comment: CommentModel, value: Boolean) { + val newComment = commentRepository.asSaved(comment, value) + mvi.updateState { + it.copy( + comments = it.comments.map { c -> + if (c.id == comment.id) { + newComment + } else { + c + } + }, + ) + } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + commentRepository.save( + auth = auth, + comment = comment, + saved = value, + ) + notificationCenter.send(NotificationCenter.Event.CommentUpdate(newComment)) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { + it.copy( + comments = it.comments.map { c -> + if (c.id == comment.id) { + comment + } else { + c + } + }, + ) + } + } + } + } +} diff --git a/core-commonui/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt b/core-commonui/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt index a04403896..44ce11898 100644 --- a/core-commonui/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt +++ b/core-commonui/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt @@ -1,30 +1,30 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.di -import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreenViewModel -import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreenViewModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailViewModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailViewModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel import org.koin.core.component.KoinComponent import org.koin.core.component.inject import org.koin.core.parameter.parametersOf -actual fun getPostDetailScreenViewModel(post: PostModel): PostDetailScreenViewModel = +actual fun getPostDetailScreenViewModel(post: PostModel): PostDetailViewModel = PostDetailScreenViewModelHelper.getPostDetailModel(post) -actual fun getCommunityDetailScreenViewModel(community: CommunityModel): CommunityDetailScreenViewModel = +actual fun getCommunityDetailScreenViewModel(community: CommunityModel): CommunityDetailViewModel = PostDetailScreenViewModelHelper.getCommunityDetailModel(community) object PostDetailScreenViewModelHelper : KoinComponent { - fun getPostDetailModel(post: PostModel): PostDetailScreenViewModel { - val model: PostDetailScreenViewModel by inject( + fun getPostDetailModel(post: PostModel): PostDetailViewModel { + val model: PostDetailViewModel by inject( parameters = { parametersOf(post) }, ) return model } - fun getCommunityDetailModel(community: CommunityModel): CommunityDetailScreenViewModel { - val model: CommunityDetailScreenViewModel by inject( + fun getCommunityDetailModel(community: CommunityModel): CommunityDetailViewModel { + val model: CommunityDetailViewModel by inject( parameters = { parametersOf(community) }, ) return model diff --git a/domain-lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/CommentRepository.kt b/domain-lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/CommentRepository.kt index 9db585441..d01f74dab 100644 --- a/domain-lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/CommentRepository.kt +++ b/domain-lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/CommentRepository.kt @@ -36,49 +36,52 @@ class CommentRepository( return dto.map { it.toModel() } } - suspend fun upVote(comment: CommentModel, auth: String, voted: Boolean): CommentModel { + fun asUpVoted(comment: CommentModel, voted: Boolean) = comment.copy( + myVote = if (voted) 1 else 0, + score = when { + voted && comment.myVote < 0 -> comment.score + 2 + voted -> comment.score + 1 + !voted -> comment.score - 1 + else -> comment.score + }, + ) + + suspend fun upVote(comment: CommentModel, auth: String, voted: Boolean) { val data = CreateCommentLikeForm( commentId = comment.id, score = if (voted) 1 else 0, auth = auth, ) services.comment.like(data) - return comment.copy( - myVote = if (voted) 1 else 0, - score = when { - voted && comment.myVote < 0 -> comment.score + 2 - voted -> comment.score + 1 - !voted -> comment.score - 1 - else -> comment.score - }, - ) } - suspend fun downVote(comment: CommentModel, auth: String, downVoted: Boolean): CommentModel { + fun asDownVoted(comment: CommentModel, downVoted: Boolean) = comment.copy( + myVote = if (downVoted) -1 else 0, + score = when { + downVoted && comment.myVote > 0 -> comment.score - 2 + downVoted -> comment.score - 1 + !downVoted -> comment.score + 1 + else -> comment.score + }, + ) + + suspend fun downVote(comment: CommentModel, auth: String, downVoted: Boolean) { val data = CreateCommentLikeForm( commentId = comment.id, score = if (downVoted) -1 else 0, auth = auth, ) services.comment.like(data) - return comment.copy( - myVote = if (downVoted) -1 else 0, - score = when { - downVoted && comment.myVote > 0 -> comment.score - 2 - downVoted -> comment.score - 1 - !downVoted -> comment.score + 1 - else -> comment.score - }, - ) } - suspend fun save(comment: CommentModel, auth: String, saved: Boolean): CommentModel { + fun asSaved(comment: CommentModel, saved: Boolean) = comment.copy(saved = saved) + + suspend fun save(comment: CommentModel, auth: String, saved: Boolean) { val data = SaveCommentForm( commentId = comment.id, save = saved, auth = auth, ) services.comment.save(data) - return comment.copy(saved = saved) } } diff --git a/domain-lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/PostsRepository.kt b/domain-lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/PostsRepository.kt index 64427254a..a3527b89b 100644 --- a/domain-lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/PostsRepository.kt +++ b/domain-lemmy/repository/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/domain/lemmy/repository/PostsRepository.kt @@ -37,49 +37,52 @@ class PostsRepository( return dto.map { it.toModel() } } - suspend fun upVote(post: PostModel, auth: String, voted: Boolean): PostModel { + fun asUpVoted(post: PostModel, voted: Boolean) = post.copy( + myVote = if (voted) 1 else 0, + score = when { + voted && post.myVote < 0 -> post.score + 2 + voted -> post.score + 1 + !voted -> post.score - 1 + else -> post.score + }, + ) + + suspend fun upVote(post: PostModel, auth: String, voted: Boolean) { val data = CreatePostLikeForm( postId = post.id, score = if (voted) 1 else 0, auth = auth, ) services.post.like(data) - return post.copy( - myVote = if (voted) 1 else 0, - score = when { - voted && post.myVote < 0 -> post.score + 2 - voted -> post.score + 1 - !voted -> post.score - 1 - else -> post.score - }, - ) } - suspend fun downVote(post: PostModel, auth: String, downVoted: Boolean): PostModel { + fun asDownVoted(post: PostModel, downVoted: Boolean) = post.copy( + myVote = if (downVoted) -1 else 0, + score = when { + downVoted && post.myVote > 0 -> post.score - 2 + downVoted -> post.score - 1 + !downVoted -> post.score + 1 + else -> post.score + }, + ) + + suspend fun downVote(post: PostModel, auth: String, downVoted: Boolean) { val data = CreatePostLikeForm( postId = post.id, score = if (downVoted) -1 else 0, auth = auth, ) services.post.like(data) - return post.copy( - myVote = if (downVoted) -1 else 0, - score = when { - downVoted && post.myVote > 0 -> post.score - 2 - downVoted -> post.score - 1 - !downVoted -> post.score + 1 - else -> post.score - }, - ) } - suspend fun save(post: PostModel, auth: String, saved: Boolean): PostModel { + fun asSaved(post: PostModel, saved: Boolean): PostModel = post.copy(saved = saved) + + suspend fun save(post: PostModel, auth: String, saved: Boolean) { val data = SavePostForm( postId = post.id, save = saved, auth = auth, ) services.post.save(data) - return post.copy(saved = saved) } } diff --git a/feature-home/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt b/feature-home/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt index 6ee60860b..43ccc3064 100644 --- a/feature-home/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt +++ b/feature-home/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt @@ -1,9 +1,9 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.home.di -import com.github.diegoberaldin.raccoonforlemmy.feature.home.viewmodel.HomeScreenModel +import com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist.PostListViewModel import org.koin.java.KoinJavaComponent.inject -actual fun getHomeScreenModel(): HomeScreenModel { - val res: HomeScreenModel by inject(HomeScreenModel::class.java) +actual fun getHomeScreenModel(): PostListViewModel { + val res: PostListViewModel by inject(PostListViewModel::class.java) return res } diff --git a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/HomeModule.kt b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/HomeModule.kt index 80fead343..e420276c3 100644 --- a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/HomeModule.kt +++ b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/HomeModule.kt @@ -3,8 +3,8 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.home.di import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.commonUiModule import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.di.postsRepositoryModule -import com.github.diegoberaldin.raccoonforlemmy.feature.home.viewmodel.HomeScreenModel -import com.github.diegoberaldin.raccoonforlemmy.feature.home.viewmodel.HomeScreenMviModel +import com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist.PostListViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist.PostListMviModel import org.koin.dsl.module val homeTabModule = module { @@ -13,8 +13,8 @@ val homeTabModule = module { commonUiModule, ) factory { - HomeScreenModel( - mvi = DefaultMviModel(HomeScreenMviModel.UiState()), + PostListViewModel( + mvi = DefaultMviModel(PostListMviModel.UiState()), postsRepository = get(), apiConfigRepository = get(), identityRepository = get(), diff --git a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt index 9531078e3..8f597225d 100644 --- a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt +++ b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt @@ -1,5 +1,5 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.home.di -import com.github.diegoberaldin.raccoonforlemmy.feature.home.viewmodel.HomeScreenModel +import com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist.PostListViewModel -expect fun getHomeScreenModel(): HomeScreenModel +expect fun getHomeScreenModel(): PostListViewModel diff --git a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/viewmodel/HomeScreenMviModel.kt b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostListMviModel.kt similarity index 85% rename from feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/viewmodel/HomeScreenMviModel.kt rename to feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostListMviModel.kt index ad48b445c..c52cb708c 100644 --- a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/viewmodel/HomeScreenMviModel.kt +++ b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostListMviModel.kt @@ -1,12 +1,12 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.home.viewmodel +package com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.ListingType import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SortType -interface HomeScreenMviModel : - MviModel { +interface PostListMviModel : + MviModel { sealed interface Intent { object Refresh : Intent diff --git a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/ui/PostListScreen.kt b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostListScreen.kt similarity index 89% rename from feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/ui/PostListScreen.kt rename to feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostListScreen.kt index 998622361..d60fd84b1 100644 --- a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/ui/PostListScreen.kt +++ b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostListScreen.kt @@ -1,4 +1,4 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.home.ui +package com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -36,7 +36,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.ListingType import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.SortBottomSheet import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreen import com.github.diegoberaldin.raccoonforlemmy.feature.home.di.getHomeScreenModel -import com.github.diegoberaldin.raccoonforlemmy.feature.home.viewmodel.HomeScreenMviModel class PostListScreen : Screen { @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class) @@ -60,7 +59,7 @@ class PostListScreen : Screen { ListingTypeBottomSheet( isLogged = uiState.isLogged, onSelected = { - model.reduce(HomeScreenMviModel.Intent.ChangeListing(it)) + model.reduce(PostListMviModel.Intent.ChangeListing(it)) }, onHide = { bottomSheetNavigator.hide() @@ -72,7 +71,7 @@ class PostListScreen : Screen { bottomSheetNavigator.show( SortBottomSheet( onSelected = { - model.reduce(HomeScreenMviModel.Intent.ChangeSort(it)) + model.reduce(PostListMviModel.Intent.ChangeSort(it)) }, onHide = { bottomSheetNavigator.hide() @@ -84,7 +83,7 @@ class PostListScreen : Screen { }, ) { padding -> val pullRefreshState = rememberPullRefreshState(uiState.refreshing, { - model.reduce(HomeScreenMviModel.Intent.Refresh) + model.reduce(PostListMviModel.Intent.Refresh) }) Box( modifier = Modifier.padding(padding).pullRefresh(pullRefreshState), @@ -117,19 +116,19 @@ class PostListScreen : Screen { ) }, onUpVote = { - model.reduce(HomeScreenMviModel.Intent.UpVotePost(it, post)) + model.reduce(PostListMviModel.Intent.UpVotePost(it, post)) }, onDownVote = { - model.reduce(HomeScreenMviModel.Intent.DownVotePost(it, post)) + model.reduce(PostListMviModel.Intent.DownVotePost(it, post)) }, onSave = { - model.reduce(HomeScreenMviModel.Intent.SavePost(it, post)) + model.reduce(PostListMviModel.Intent.SavePost(it, post)) }, ) } item { if (!uiState.loading && !uiState.refreshing && uiState.canFetchMore) { - model.reduce(HomeScreenMviModel.Intent.LoadNextPage) + model.reduce(PostListMviModel.Intent.LoadNextPage) } if (uiState.loading && !uiState.refreshing) { Box( diff --git a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/viewmodel/HomeScreenModel.kt b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostListViewModel.kt similarity index 57% rename from feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/viewmodel/HomeScreenModel.kt rename to feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostListViewModel.kt index df86b7f9c..b0ce846c4 100644 --- a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/viewmodel/HomeScreenModel.kt +++ b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostListViewModel.kt @@ -1,4 +1,4 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.home.viewmodel +package com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist import cafe.adriel.voyager.core.model.ScreenModel import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel @@ -22,27 +22,27 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -class HomeScreenModel( - private val mvi: DefaultMviModel, +class PostListViewModel( + private val mvi: DefaultMviModel, private val postsRepository: PostsRepository, private val apiConfigRepository: ApiConfigurationRepository, private val identityRepository: IdentityRepository, private val keyStore: TemporaryKeyStore, private val notificationCenter: NotificationCenter, ) : ScreenModel, - MviModel by mvi { + MviModel by mvi { private var currentPage: Int = 1 - override fun reduce(intent: HomeScreenMviModel.Intent) { + override fun reduce(intent: PostListMviModel.Intent) { when (intent) { - HomeScreenMviModel.Intent.LoadNextPage -> loadNextPage() - HomeScreenMviModel.Intent.Refresh -> refresh() - is HomeScreenMviModel.Intent.ChangeSort -> applySortType(intent.value) - is HomeScreenMviModel.Intent.ChangeListing -> applyListingType(intent.value) - is HomeScreenMviModel.Intent.DownVotePost -> downVote(intent.post, intent.value) - is HomeScreenMviModel.Intent.SavePost -> save(intent.post, intent.value) - is HomeScreenMviModel.Intent.UpVotePost -> upVote(intent.post, intent.value) + PostListMviModel.Intent.LoadNextPage -> loadNextPage() + PostListMviModel.Intent.Refresh -> refresh() + is PostListMviModel.Intent.ChangeSort -> applySortType(intent.value) + is PostListMviModel.Intent.ChangeListing -> applyListingType(intent.value) + is PostListMviModel.Intent.DownVotePost -> downVote(intent.post, intent.value) + is PostListMviModel.Intent.SavePost -> save(intent.post, intent.value) + is PostListMviModel.Intent.UpVotePost -> upVote(intent.post, intent.value) } } @@ -143,67 +143,115 @@ class HomeScreenModel( } private fun upVote(post: PostModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newPost = postsRepository.upVote( - post = post, - auth = auth, - voted = value, + val newPost = postsRepository.asUpVoted(post, value) + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + newPost + } else { + p + } + }, ) - mvi.updateState { - it.copy( - posts = it.posts.map { p -> - if (p.id == post.id) { - newPost - } else { - p - } - }, + } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + postsRepository.upVote( + post = post, + auth = auth, + voted = value, ) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + post + } else { + p + } + }, + ) + } } } } private fun downVote(post: PostModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newPost = postsRepository.downVote( - post = post, - auth = auth, - downVoted = value, + val newPost = postsRepository.asDownVoted(post, value) + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + newPost + } else { + p + } + }, ) - mvi.updateState { - it.copy( - posts = it.posts.map { p -> - if (p.id == post.id) { - newPost - } else { - p - } - }, + } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + postsRepository.downVote( + post = post, + auth = auth, + downVoted = value, ) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + post + } else { + p + } + }, + ) + } } } } private fun save(post: PostModel, value: Boolean) { - mvi.scope.launch(Dispatchers.IO) { - val auth = identityRepository.authToken.value.orEmpty() - val newPost = postsRepository.save( - post = post, - auth = auth, - saved = value, + val newPost = postsRepository.asSaved(post, value) + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + newPost + } else { + p + } + }, ) - mvi.updateState { - it.copy( - posts = it.posts.map { p -> - if (p.id == post.id) { - newPost - } else { - p - } - }, + } + mvi.scope.launch(Dispatchers.IO) { + try { + val auth = identityRepository.authToken.value.orEmpty() + postsRepository.save( + post = post, + auth = auth, + saved = value, ) + } catch (e: Throwable) { + e.printStackTrace() + mvi.updateState { + it.copy( + posts = it.posts.map { p -> + if (p.id == post.id) { + post + } else { + p + } + }, + ) + } } } } diff --git a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/ui/PostsTopBar.kt b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostsTopBar.kt similarity index 97% rename from feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/ui/PostsTopBar.kt rename to feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostsTopBar.kt index 03f8f28df..e3076e7b9 100644 --- a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/ui/PostsTopBar.kt +++ b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/postlist/PostsTopBar.kt @@ -1,4 +1,4 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.home.ui +package com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement diff --git a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/ui/HomeTab.kt b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/ui/HomeTab.kt index ebf3dd6a7..312684f83 100644 --- a/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/ui/HomeTab.kt +++ b/feature-home/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/ui/HomeTab.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.graphics.vector.rememberVectorPainter import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.TabOptions +import com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist.PostListScreen import com.github.diegoberaldin.raccoonforlemmy.resources.MR import com.github.diegoberaldin.raccoonforlemmy.resources.di.getLanguageRepository import com.github.diegoberaldin.raccoonforlemmy.resources.di.staticString diff --git a/feature-home/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt b/feature-home/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt index 222562a7e..d207c9090 100644 --- a/feature-home/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt +++ b/feature-home/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/home/di/Utils.kt @@ -1,11 +1,11 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.home.di -import com.github.diegoberaldin.raccoonforlemmy.feature.home.viewmodel.HomeScreenModel +import com.github.diegoberaldin.raccoonforlemmy.feature.home.postlist.PostListViewModel import org.koin.core.component.KoinComponent import org.koin.core.component.inject actual fun getHomeScreenModel() = HomeScreenModelHelper.model object HomeScreenModelHelper : KoinComponent { - val model: HomeScreenModel by inject() + val model: PostListViewModel by inject() } diff --git a/feature-profile/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt b/feature-profile/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt index 9b4764b4f..506ac6894 100644 --- a/feature-profile/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt +++ b/feature-profile/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt @@ -5,12 +5,12 @@ import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.P import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.comments.ProfileCommentsViewModel import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.posts.ProfilePostsViewModel import com.github.diegoberaldin.raccoonforlemmy.feature.profile.login.LoginBottomSheetViewModel -import com.github.diegoberaldin.raccoonforlemmy.feature.profile.viewmodel.ProfileScreenModel +import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.ProfileContentViewModel import org.koin.core.parameter.parametersOf import org.koin.java.KoinJavaComponent.inject -actual fun getProfileScreenModel(): ProfileScreenModel { - val res: ProfileScreenModel by inject(ProfileScreenModel::class.java) +actual fun getProfileScreenModel(): ProfileContentViewModel { + val res: ProfileContentViewModel by inject(ProfileContentViewModel::class.java) return res } diff --git a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/viewmodel/ProfileScreenMviModel.kt b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/content/ProfileContentMviModel.kt similarity index 73% rename from feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/viewmodel/ProfileScreenMviModel.kt rename to feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/content/ProfileContentMviModel.kt index 0e255c360..5c580f51f 100644 --- a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/viewmodel/ProfileScreenMviModel.kt +++ b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/content/ProfileContentMviModel.kt @@ -1,10 +1,10 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.profile.viewmodel +package com.github.diegoberaldin.raccoonforlemmy.feature.profile.content import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel -interface ProfileScreenMviModel : - MviModel { +interface ProfileContentMviModel : + MviModel { sealed interface Intent { object Logout : Intent diff --git a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/ui/ProfileContentScreen.kt b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/content/ProfileContentScreen.kt similarity index 96% rename from feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/ui/ProfileContentScreen.kt rename to feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/content/ProfileContentScreen.kt index 64852a78b..f6ea09c93 100644 --- a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/ui/ProfileContentScreen.kt +++ b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/content/ProfileContentScreen.kt @@ -1,4 +1,4 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.profile.ui +package com.github.diegoberaldin.raccoonforlemmy.feature.profile.content import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box @@ -28,7 +28,6 @@ import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.P import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.notlogged.ProfileNotLoggedContent import com.github.diegoberaldin.raccoonforlemmy.feature.profile.di.getProfileScreenModel import com.github.diegoberaldin.raccoonforlemmy.feature.profile.login.LoginBottomSheet -import com.github.diegoberaldin.raccoonforlemmy.feature.profile.viewmodel.ProfileScreenMviModel import com.github.diegoberaldin.raccoonforlemmy.resources.MR import com.github.diegoberaldin.raccoonforlemmy.resources.di.getLanguageRepository import com.github.diegoberaldin.raccoonforlemmy.resources.di.staticString @@ -61,7 +60,7 @@ internal class ProfileContentScreen : Screen { if (uiState.currentUser != null) { Image( modifier = Modifier.onClick { - model.reduce(ProfileScreenMviModel.Intent.Logout) + model.reduce(ProfileContentMviModel.Intent.Logout) }, imageVector = Icons.Default.Logout, contentDescription = null, diff --git a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/viewmodel/ProfileScreenModel.kt b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/content/ProfileContentViewModel.kt similarity index 78% rename from feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/viewmodel/ProfileScreenModel.kt rename to feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/content/ProfileContentViewModel.kt index 311b5c666..b1d127840 100644 --- a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/viewmodel/ProfileScreenModel.kt +++ b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/content/ProfileContentViewModel.kt @@ -1,4 +1,4 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.profile.viewmodel +package com.github.diegoberaldin.raccoonforlemmy.feature.profile.content import cafe.adriel.voyager.core.model.ScreenModel import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel @@ -11,12 +11,12 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -class ProfileScreenModel( - private val mvi: DefaultMviModel, +class ProfileContentViewModel( + private val mvi: DefaultMviModel, private val identityRepository: IdentityRepository, private val siteRepository: SiteRepository, ) : ScreenModel, - MviModel by mvi { + MviModel by mvi { override fun onStarted() { mvi.onStarted() @@ -35,9 +35,9 @@ class ProfileScreenModel( }.launchIn(mvi.scope) } - override fun reduce(intent: ProfileScreenMviModel.Intent) { + override fun reduce(intent: ProfileContentMviModel.Intent) { when (intent) { - ProfileScreenMviModel.Intent.Logout -> identityRepository.clearToken() + ProfileContentMviModel.Intent.Logout -> identityRepository.clearToken() } } diff --git a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/ProfileModule.kt b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/ProfileModule.kt index edb450118..09f25ad32 100644 --- a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/ProfileModule.kt +++ b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/ProfileModule.kt @@ -9,14 +9,14 @@ import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.p import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.posts.ProfilePostsViewModel import com.github.diegoberaldin.raccoonforlemmy.feature.profile.login.LoginBottomSheetMviModel import com.github.diegoberaldin.raccoonforlemmy.feature.profile.login.LoginBottomSheetViewModel -import com.github.diegoberaldin.raccoonforlemmy.feature.profile.viewmodel.ProfileScreenModel -import com.github.diegoberaldin.raccoonforlemmy.feature.profile.viewmodel.ProfileScreenMviModel +import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.ProfileContentViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.ProfileContentMviModel import org.koin.dsl.module val profileTabModule = module { factory { - ProfileScreenModel( - mvi = DefaultMviModel(ProfileScreenMviModel.UiState()), + ProfileContentViewModel( + mvi = DefaultMviModel(ProfileContentMviModel.UiState()), identityRepository = get(), siteRepository = get(), ) diff --git a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt index 07d62085c..bbc20912d 100644 --- a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt +++ b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt @@ -5,9 +5,9 @@ import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.P import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.comments.ProfileCommentsViewModel import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.posts.ProfilePostsViewModel import com.github.diegoberaldin.raccoonforlemmy.feature.profile.login.LoginBottomSheetViewModel -import com.github.diegoberaldin.raccoonforlemmy.feature.profile.viewmodel.ProfileScreenModel +import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.ProfileContentViewModel -expect fun getProfileScreenModel(): ProfileScreenModel +expect fun getProfileScreenModel(): ProfileContentViewModel expect fun getLoginBottomSheetViewModel(): LoginBottomSheetViewModel diff --git a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/ui/ProfileTab.kt b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/ui/ProfileTab.kt index f45337dc1..e9cfbd7c7 100644 --- a/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/ui/ProfileTab.kt +++ b/feature-profile/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/ui/ProfileTab.kt @@ -11,6 +11,7 @@ import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.TabOptions import com.github.diegoberaldin.raccoonforlemmy.domain.identity.di.getApiConfigurationRepository +import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.ProfileContentScreen object ProfileTab : Tab { diff --git a/feature-profile/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt b/feature-profile/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt index b7c6e3a46..0496e0615 100644 --- a/feature-profile/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt +++ b/feature-profile/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/profile/di/Utils.kt @@ -5,7 +5,7 @@ import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.P import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.comments.ProfileCommentsViewModel import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.logged.posts.ProfilePostsViewModel import com.github.diegoberaldin.raccoonforlemmy.feature.profile.login.LoginBottomSheetViewModel -import com.github.diegoberaldin.raccoonforlemmy.feature.profile.viewmodel.ProfileScreenModel +import com.github.diegoberaldin.raccoonforlemmy.feature.profile.content.ProfileContentViewModel import org.koin.core.component.KoinComponent import org.koin.core.component.inject import org.koin.core.parameter.parametersOf @@ -27,7 +27,7 @@ actual fun getProfileCommentsViewModel(user: UserModel): ProfileCommentsViewMode ProfileScreenModelHelper.getCommentsModel(user) object ProfileScreenModelHelper : KoinComponent { - val profileModel: ProfileScreenModel by inject() + val profileModel: ProfileContentViewModel by inject() val loginModel: LoginBottomSheetViewModel by inject() val loggedModel: ProfileLoggedViewModel by inject() diff --git a/feature-search/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt b/feature-search/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt index f8c675f4d..3a5adf02b 100644 --- a/feature-search/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt +++ b/feature-search/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt @@ -1,9 +1,9 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.search.di -import com.github.diegoberaldin.raccoonforlemmy.feature.search.viewmodel.SearchScreenModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.communitylist.CommunityListViewModel import org.koin.java.KoinJavaComponent.inject -actual fun getSearchScreenModel(): SearchScreenModel { - val res: SearchScreenModel by inject(SearchScreenModel::class.java) +actual fun getSearchScreenModel(): CommunityListViewModel { + val res: CommunityListViewModel by inject(CommunityListViewModel::class.java) return res } diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/viewmodel/SearchScreenMviModel.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/communitylist/CommunityListMviModel.kt similarity index 85% rename from feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/viewmodel/SearchScreenMviModel.kt rename to feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/communitylist/CommunityListMviModel.kt index 7742541cb..8d5862163 100644 --- a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/viewmodel/SearchScreenMviModel.kt +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/communitylist/CommunityListMviModel.kt @@ -1,10 +1,10 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.search.viewmodel +package com.github.diegoberaldin.raccoonforlemmy.feature.search.communitylist import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel -interface SearchScreenMviModel : - MviModel { +interface CommunityListMviModel : + MviModel { sealed interface Intent { object Refresh : Intent object LoadNextPage : Intent diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/ui/CommunityListScreen.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/communitylist/CommunityListScreen.kt similarity index 93% rename from feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/ui/CommunityListScreen.kt rename to feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/communitylist/CommunityListScreen.kt index 4d6cf7182..970edf5c8 100644 --- a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/ui/CommunityListScreen.kt +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/communitylist/CommunityListScreen.kt @@ -1,4 +1,4 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.search.ui +package com.github.diegoberaldin.raccoonforlemmy.feature.search.communitylist import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -40,7 +40,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen import com.github.diegoberaldin.raccoonforlemmy.feature.search.di.getSearchScreenModel -import com.github.diegoberaldin.raccoonforlemmy.feature.search.viewmodel.SearchScreenMviModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.ui.CommunityItem import com.github.diegoberaldin.raccoonforlemmy.resources.MR import dev.icerock.moko.resources.compose.stringResource @@ -71,7 +71,7 @@ class CommunityListScreen : Screen { keyboardType = KeyboardType.Text, ), onValueChange = { value -> - model.reduce(SearchScreenMviModel.Intent.SetSearch(value)) + model.reduce(CommunityListMviModel.Intent.SetSearch(value)) }, ) Row( @@ -82,7 +82,7 @@ class CommunityListScreen : Screen { Checkbox( checked = uiState.subscribedOnly, onCheckedChange = { - model.reduce(SearchScreenMviModel.Intent.SetSubscribedOnly(it)) + model.reduce(CommunityListMviModel.Intent.SetSubscribedOnly(it)) }, colors = CheckboxDefaults.colors(checkedColor = MaterialTheme.colorScheme.primary), ) @@ -93,7 +93,7 @@ class CommunityListScreen : Screen { } Spacer(modifier = Modifier.weight(1f)) Button(onClick = { - model.reduce(SearchScreenMviModel.Intent.SearchFired) + model.reduce(CommunityListMviModel.Intent.SearchFired) }) { Text( text = stringResource(MR.strings.button_search), @@ -103,7 +103,7 @@ class CommunityListScreen : Screen { } val pullRefreshState = rememberPullRefreshState(uiState.refreshing, { - model.reduce(SearchScreenMviModel.Intent.Refresh) + model.reduce(CommunityListMviModel.Intent.Refresh) }) Box( modifier = Modifier.padding(Spacing.xxs).pullRefresh(pullRefreshState), @@ -129,7 +129,7 @@ class CommunityListScreen : Screen { } item { if (!uiState.loading && !uiState.refreshing && uiState.canFetchMore) { - model.reduce(SearchScreenMviModel.Intent.LoadNextPage) + model.reduce(CommunityListMviModel.Intent.LoadNextPage) } if (uiState.loading && !uiState.refreshing) { Box( diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/viewmodel/SearchScreenModel.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/communitylist/CommunityListViewModel.kt similarity index 84% rename from feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/viewmodel/SearchScreenModel.kt rename to feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/communitylist/CommunityListViewModel.kt index 2b04604c6..fd9c26047 100644 --- a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/viewmodel/SearchScreenModel.kt +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/communitylist/CommunityListViewModel.kt @@ -1,4 +1,4 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.search.viewmodel +package com.github.diegoberaldin.raccoonforlemmy.feature.search.communitylist import cafe.adriel.voyager.core.model.ScreenModel import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel @@ -14,13 +14,13 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -class SearchScreenModel( - private val mvi: DefaultMviModel, +class CommunityListViewModel( + private val mvi: DefaultMviModel, private val apiConfigRepository: ApiConfigurationRepository, private val identityRepository: IdentityRepository, private val communityRepository: CommunityRepository, ) : ScreenModel, - MviModel by mvi { + MviModel by mvi { private var currentPage: Int = 1 @@ -44,13 +44,13 @@ class SearchScreenModel( } } - override fun reduce(intent: SearchScreenMviModel.Intent) { + override fun reduce(intent: CommunityListMviModel.Intent) { when (intent) { - SearchScreenMviModel.Intent.LoadNextPage -> loadNextPage() - SearchScreenMviModel.Intent.Refresh -> refresh() - SearchScreenMviModel.Intent.SearchFired -> refresh() - is SearchScreenMviModel.Intent.SetSearch -> setSearch(intent.value) - is SearchScreenMviModel.Intent.SetSubscribedOnly -> applySubscribedOnly(intent.value) + CommunityListMviModel.Intent.LoadNextPage -> loadNextPage() + CommunityListMviModel.Intent.Refresh -> refresh() + CommunityListMviModel.Intent.SearchFired -> refresh() + is CommunityListMviModel.Intent.SetSearch -> setSearch(intent.value) + is CommunityListMviModel.Intent.SetSubscribedOnly -> applySubscribedOnly(intent.value) } } diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/SearchModule.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/SearchModule.kt index 3f694f96e..6501553c0 100644 --- a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/SearchModule.kt +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/SearchModule.kt @@ -1,14 +1,14 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.search.di import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel -import com.github.diegoberaldin.raccoonforlemmy.feature.search.viewmodel.SearchScreenModel -import com.github.diegoberaldin.raccoonforlemmy.feature.search.viewmodel.SearchScreenMviModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.communitylist.CommunityListViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.communitylist.CommunityListMviModel import org.koin.dsl.module val searchTabModule = module { factory { - SearchScreenModel( - mvi = DefaultMviModel(SearchScreenMviModel.UiState()), + CommunityListViewModel( + mvi = DefaultMviModel(CommunityListMviModel.UiState()), apiConfigRepository = get(), identityRepository = get(), communityRepository = get(), diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt index 0b7c15d54..853d9320f 100644 --- a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt @@ -1,5 +1,5 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.search.di -import com.github.diegoberaldin.raccoonforlemmy.feature.search.viewmodel.SearchScreenModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.communitylist.CommunityListViewModel -expect fun getSearchScreenModel(): SearchScreenModel \ No newline at end of file +expect fun getSearchScreenModel(): CommunityListViewModel \ No newline at end of file diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/ui/SearchTab.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/ui/SearchTab.kt index 8486fb2be..a48a97fe5 100644 --- a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/ui/SearchTab.kt +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/ui/SearchTab.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.graphics.vector.rememberVectorPainter import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.TabOptions +import com.github.diegoberaldin.raccoonforlemmy.feature.search.communitylist.CommunityListScreen import com.github.diegoberaldin.raccoonforlemmy.resources.MR import com.github.diegoberaldin.raccoonforlemmy.resources.di.getLanguageRepository import com.github.diegoberaldin.raccoonforlemmy.resources.di.staticString diff --git a/feature-search/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt b/feature-search/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt index 271706fad..e2bcef841 100644 --- a/feature-search/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt +++ b/feature-search/src/iosMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/di/Utils.kt @@ -1,11 +1,11 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.search.di -import com.github.diegoberaldin.raccoonforlemmy.feature.search.viewmodel.SearchScreenModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.communitylist.CommunityListViewModel import org.koin.core.component.KoinComponent import org.koin.core.component.inject actual fun getSearchScreenModel() = SearchScreenModelHelper.model object SearchScreenModelHelper : KoinComponent { - val model: SearchScreenModel by inject() + val model: CommunityListViewModel by inject() }