feat(profile): add saved section

This commit is contained in:
Diego Beraldin 2023-08-01 22:08:59 +02:00
parent ec5786c458
commit 4e4262510d
8 changed files with 117 additions and 8 deletions

View File

@ -24,10 +24,13 @@ actual fun getProfileLoggedViewModel(): ProfileLoggedViewModel {
return res return res
} }
actual fun getProfilePostsViewModel(user: UserModel): ProfilePostsViewModel { actual fun getProfilePostsViewModel(
user: UserModel,
savedOnly: Boolean,
): ProfilePostsViewModel {
val res: ProfilePostsViewModel by inject( val res: ProfilePostsViewModel by inject(
clazz = ProfilePostsViewModel::class.java, clazz = ProfilePostsViewModel::class.java,
parameters = { parametersOf(user) }, parameters = { parametersOf(user, savedOnly) },
) )
return res return res
} }

View File

@ -17,6 +17,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core_architecture.bindToLifecycl
import com.github.diegoberaldin.raccoonforlemmy.domain_lemmy.data.UserModel import com.github.diegoberaldin.raccoonforlemmy.domain_lemmy.data.UserModel
import com.github.diegoberaldin.raccoonforlemmy.feature_profile.content.logged.comments.ProfileCommentsScreen import com.github.diegoberaldin.raccoonforlemmy.feature_profile.content.logged.comments.ProfileCommentsScreen
import com.github.diegoberaldin.raccoonforlemmy.feature_profile.content.logged.posts.ProfilePostsScreen import com.github.diegoberaldin.raccoonforlemmy.feature_profile.content.logged.posts.ProfilePostsScreen
import com.github.diegoberaldin.raccoonforlemmy.feature_profile.content.logged.saved.ProfileSavedScreen
import com.github.diegoberaldin.raccoonforlemmy.feature_profile.di.getProfileLoggedViewModel import com.github.diegoberaldin.raccoonforlemmy.feature_profile.di.getProfileLoggedViewModel
internal class ProfileLoggedScreen( internal class ProfileLoggedScreen(
@ -61,6 +62,10 @@ internal class ProfileLoggedScreen(
} }
ProfileLoggedSection.SAVED -> { ProfileLoggedSection.SAVED -> {
ProfileSavedScreen(
modifier = Modifier.weight(1f).fillMaxWidth(),
user = user,
).Content()
} }
} }
} }

View File

@ -34,7 +34,11 @@ internal class ProfilePostsScreen(
@OptIn(ExperimentalMaterialApi::class) @OptIn(ExperimentalMaterialApi::class)
@Composable @Composable
override fun Content() { override fun Content() {
val model = rememberScreenModel { getProfilePostsViewModel(user) } val model = rememberScreenModel {
getProfilePostsViewModel(
user = user,
)
}
model.bindToLifecycle(key) model.bindToLifecycle(key)
val uiState by model.uiState.collectAsState() val uiState by model.uiState.collectAsState()

View File

@ -14,6 +14,7 @@ import kotlinx.coroutines.launch
class ProfilePostsViewModel( class ProfilePostsViewModel(
private val mvi: DefaultMviModel<ProfilePostsMviModel.Intent, ProfilePostsMviModel.UiState, ProfilePostsMviModel.Effect>, private val mvi: DefaultMviModel<ProfilePostsMviModel.Intent, ProfilePostsMviModel.UiState, ProfilePostsMviModel.Effect>,
private val user: UserModel, private val user: UserModel,
private val savedOnly: Boolean = false,
private val identityRepository: IdentityRepository, private val identityRepository: IdentityRepository,
private val userRepository: UserRepository, private val userRepository: UserRepository,
) : ScreenModel, ) : ScreenModel,
@ -51,6 +52,7 @@ class ProfilePostsViewModel(
val postList = userRepository.getUserPosts( val postList = userRepository.getUserPosts(
auth = auth, auth = auth,
id = user.id, id = user.id,
savedOnly = savedOnly,
page = currentPage, page = currentPage,
) )
currentPage++ currentPage++

View File

@ -0,0 +1,88 @@
package com.github.diegoberaldin.raccoonforlemmy.feature_profile.content.logged.saved
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.screen.Screen
import com.github.diegoberaldin.raccoonforlemmy.core_appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core_architecture.bindToLifecycle
import com.github.diegoberaldin.raccoonforlemmy.domain_lemmy.data.UserModel
import com.github.diegoberaldin.raccoonforlemmy.feature_profile.content.logged.posts.ProfilePostCard
import com.github.diegoberaldin.raccoonforlemmy.feature_profile.content.logged.posts.ProfilePostsMviModel
import com.github.diegoberaldin.raccoonforlemmy.feature_profile.di.getProfilePostsViewModel
internal class ProfileSavedScreen(
private val modifier: Modifier = Modifier,
private val user: UserModel,
) : Screen {
@OptIn(ExperimentalMaterialApi::class)
@Composable
override fun Content() {
val model = rememberScreenModel {
getProfilePostsViewModel(
user = user,
savedOnly = true,
)
}
model.bindToLifecycle(key)
val uiState by model.uiState.collectAsState()
val pullRefreshState = rememberPullRefreshState(uiState.refreshing, {
model.reduce(ProfilePostsMviModel.Intent.Refresh)
})
Box(
modifier = modifier.pullRefresh(pullRefreshState),
) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
) {
items(uiState.posts) { post ->
ProfilePostCard(post)
}
item {
if (!uiState.loading && !uiState.refreshing && uiState.canFetchMore) {
model.reduce(ProfilePostsMviModel.Intent.LoadNextPage)
}
if (uiState.loading && !uiState.refreshing) {
Box(
modifier = Modifier.fillMaxWidth().padding(Spacing.xs),
contentAlignment = Alignment.Center,
) {
CircularProgressIndicator(
modifier = Modifier.size(25.dp),
color = MaterialTheme.colorScheme.primary,
)
}
}
}
}
PullRefreshIndicator(
refreshing = uiState.refreshing,
state = pullRefreshState,
modifier = Modifier.align(Alignment.TopCenter),
backgroundColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface,
)
}
}
}

View File

@ -36,6 +36,7 @@ val profileTabModule = module {
ProfilePostsViewModel( ProfilePostsViewModel(
mvi = DefaultMviModel(ProfilePostsMviModel.UiState()), mvi = DefaultMviModel(ProfilePostsMviModel.UiState()),
user = params[0], user = params[0],
savedOnly = params[1],
identityRepository = get(), identityRepository = get(),
userRepository = get(), userRepository = get(),
) )

View File

@ -13,6 +13,9 @@ expect fun getLoginBottomSheetViewModel(): LoginBottomSheetViewModel
expect fun getProfileLoggedViewModel(): ProfileLoggedViewModel expect fun getProfileLoggedViewModel(): ProfileLoggedViewModel
expect fun getProfilePostsViewModel(user: UserModel): ProfilePostsViewModel expect fun getProfilePostsViewModel(
user: UserModel,
savedOnly: Boolean = false,
): ProfilePostsViewModel
expect fun getProfileCommentsViewModel(user: UserModel): ProfileCommentsViewModel expect fun getProfileCommentsViewModel(user: UserModel): ProfileCommentsViewModel

View File

@ -17,8 +17,11 @@ actual fun getLoginBottomSheetViewModel() = ProfileScreenModelHelper.loginModel
actual fun getProfileLoggedViewModel(): ProfileLoggedViewModel = actual fun getProfileLoggedViewModel(): ProfileLoggedViewModel =
ProfileScreenModelHelper.loggedModel ProfileScreenModelHelper.loggedModel
actual fun getProfilePostsViewModel(user: UserModel): ProfilePostsViewModel = actual fun getProfilePostsViewModel(
ProfileScreenModelHelper.getPostsModel(user) user: UserModel,
savedOnly: Boolean,
): ProfilePostsViewModel =
ProfileScreenModelHelper.getPostsModel(user = user, savedOnly = savedOnly)
actual fun getProfileCommentsViewModel(user: UserModel): ProfileCommentsViewModel = actual fun getProfileCommentsViewModel(user: UserModel): ProfileCommentsViewModel =
ProfileScreenModelHelper.getCommentsModel(user) ProfileScreenModelHelper.getCommentsModel(user)
@ -28,9 +31,9 @@ object ProfileScreenModelHelper : KoinComponent {
val loginModel: LoginBottomSheetViewModel by inject() val loginModel: LoginBottomSheetViewModel by inject()
val loggedModel: ProfileLoggedViewModel by inject() val loggedModel: ProfileLoggedViewModel by inject()
fun getPostsModel(user: UserModel): ProfilePostsViewModel { fun getPostsModel(user: UserModel, savedOnly: Boolean): ProfilePostsViewModel {
val res: ProfilePostsViewModel by inject( val res: ProfilePostsViewModel by inject(
parameters = { parametersOf(user) }, parameters = { parametersOf(user, savedOnly) },
) )
return res return res
} }