From 6297ef3b9780a926a5f647a64f4191f3dd5d8d60 Mon Sep 17 00:00:00 2001 From: Diego Beraldin Date: Wed, 27 Sep 2023 12:43:37 +0200 Subject: [PATCH] feat(explore): subscription management screen --- feature-search/build.gradle.kts | 1 + .../feature/search/di/Utils.kt | 9 +- .../feature/search/di/SearchModule.kt | 14 +- .../feature/search/di/Utils.kt | 7 +- .../{content => main}/ExploreMviModel.kt | 2 +- .../search/{content => main}/ExploreScreen.kt | 8 +- .../search/{content => main}/ExploreTopBar.kt | 29 +++- .../{content => main}/ExploreViewModel.kt | 4 +- .../ManageSubscriptionsMviModel.kt | 20 +++ .../ManageSubscriptionsScreen.kt | 136 ++++++++++++++++++ .../ManageSubscriptionsViewModel.kt | 63 ++++++++ .../feature/search/ui/SearchTab.kt | 2 +- .../feature/search/di/Utils.kt | 6 +- .../commonMain/resources/MR/base/strings.xml | 1 + .../commonMain/resources/MR/es/strings.xml | 1 + .../commonMain/resources/MR/it/strings.xml | 1 + 16 files changed, 287 insertions(+), 17 deletions(-) rename feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/{content => main}/ExploreMviModel.kt (99%) rename feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/{content => main}/ExploreScreen.kt (98%) rename feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/{content => main}/ExploreTopBar.kt (81%) rename feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/{content => main}/ExploreViewModel.kt (99%) create mode 100644 feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsMviModel.kt create mode 100644 feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsScreen.kt create mode 100644 feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsViewModel.kt diff --git a/feature-search/build.gradle.kts b/feature-search/build.gradle.kts index 4f3d77033..8cf997563 100644 --- a/feature-search/build.gradle.kts +++ b/feature-search/build.gradle.kts @@ -42,6 +42,7 @@ kotlin { implementation(projects.coreUtils) implementation(projects.corePreferences) implementation(projects.coreCommonui) + implementation(projects.coreCommonui.components) implementation(projects.coreNotifications) implementation(projects.domainIdentity) 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 1b3084a18..224c65c20 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,16 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.search.di -import com.github.diegoberaldin.raccoonforlemmy.feature.search.content.ExploreViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.main.ExploreViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions.ManageSubscriptionsViewModel import org.koin.java.KoinJavaComponent.inject actual fun getExploreViewModel(): ExploreViewModel { val res: ExploreViewModel by inject(ExploreViewModel::class.java) return res } + +actual fun getManageSubscriptionsViewModel(): ManageSubscriptionsViewModel { + val res: ManageSubscriptionsViewModel by inject(ManageSubscriptionsViewModel::class.java) + return res +} + 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 4ff221c9b..f36e8a555 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,8 +1,10 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.search.di import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel -import com.github.diegoberaldin.raccoonforlemmy.feature.search.content.ExploreMviModel -import com.github.diegoberaldin.raccoonforlemmy.feature.search.content.ExploreViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.main.ExploreMviModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.main.ExploreViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions.ManageSubscriptionsMviModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions.ManageSubscriptionsViewModel import org.koin.dsl.module val searchTabModule = module { @@ -20,4 +22,12 @@ val searchTabModule = module { hapticFeedback = get(), ) } + factory { + ManageSubscriptionsViewModel( + mvi = DefaultMviModel(ManageSubscriptionsMviModel.UiState()), + identityRepository = get(), + communityRepository = get(), + hapticFeedback = 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 d48d7f789..dacfdca5a 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,8 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.search.di -import com.github.diegoberaldin.raccoonforlemmy.feature.search.content.ExploreViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.main.ExploreViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions.ManageSubscriptionsViewModel -expect fun getExploreViewModel(): ExploreViewModel \ No newline at end of file +expect fun getExploreViewModel(): ExploreViewModel + +expect fun getManageSubscriptionsViewModel(): ManageSubscriptionsViewModel \ No newline at end of file diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreMviModel.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreMviModel.kt similarity index 99% rename from feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreMviModel.kt rename to feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreMviModel.kt index ba08761ff..b6a236873 100644 --- a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreMviModel.kt +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreMviModel.kt @@ -1,4 +1,4 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.search.content +package com.github.diegoberaldin.raccoonforlemmy.feature.search.main import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreScreen.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreScreen.kt similarity index 98% rename from feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreScreen.kt rename to feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreScreen.kt index 8d1973255..ecb649f42 100644 --- a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreScreen.kt +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreScreen.kt @@ -1,4 +1,4 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.search.content +package com.github.diegoberaldin.raccoonforlemmy.feature.search.main import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -73,6 +73,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SearchResultTy import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SortType import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel import com.github.diegoberaldin.raccoonforlemmy.feature.search.di.getExploreViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions.ManageSubscriptionsScreen import com.github.diegoberaldin.raccoonforlemmy.resources.MR import dev.icerock.moko.resources.compose.stringResource @@ -101,6 +102,7 @@ class ExploreScreen : Screen { scrollBehavior = scrollBehavior, listingType = uiState.listingType, sortType = uiState.sortType, + isLogged = uiState.isLogged, onSelectListingType = { val sheet = ListingTypeBottomSheet( isLogged = uiState.isLogged, @@ -125,6 +127,10 @@ class ExploreScreen : Screen { }, key, NotificationCenterContractKeys.ChangeSortType) bottomSheetNavigator.show(sheet) }, + onSettings = { + val sheet = ManageSubscriptionsScreen() + navigator?.push(sheet) + }, ) }, ) { padding -> diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreTopBar.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreTopBar.kt similarity index 81% rename from feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreTopBar.kt rename to feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreTopBar.kt index 0d7a422cd..589342815 100644 --- a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreTopBar.kt +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreTopBar.kt @@ -1,10 +1,12 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.search.content +package com.github.diegoberaldin.raccoonforlemmy.feature.search.main import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ManageAccounts import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -29,8 +31,10 @@ internal fun CommunityTopBar( scrollBehavior: TopAppBarScrollBehavior? = null, listingType: ListingType, sortType: SortType, - onSelectListingType: () -> Unit, - onSelectSortType: () -> Unit, + isLogged: Boolean = false, + onSelectListingType: (() -> Unit)? = null, + onSelectSortType: (() -> Unit)? = null, + onSettings: (() -> Unit)? = null, ) { TopAppBar( scrollBehavior = scrollBehavior, @@ -40,7 +44,7 @@ internal fun CommunityTopBar( navigationIcon = { Image( modifier = Modifier.onClick { - onSelectListingType() + onSelectListingType?.invoke() }, imageVector = listingType.toIcon(), contentDescription = null, @@ -63,7 +67,9 @@ internal fun CommunityTopBar( } }, actions = { - Row { + Row( + horizontalArrangement = Arrangement.spacedBy(Spacing.xs), + ) { val additionalLabel = when (sortType) { SortType.Top.Day -> stringResource(MR.strings.home_sort_type_top_day_short) SortType.Top.Month -> stringResource(MR.strings.home_sort_type_top_month_short) @@ -85,12 +91,23 @@ internal fun CommunityTopBar( } Image( modifier = Modifier.onClick { - onSelectSortType() + onSelectSortType?.invoke() }, imageVector = sortType.toIcon(), contentDescription = null, colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground), ) + + if (isLogged) { + Image( + modifier = Modifier.onClick { + onSettings?.invoke() + }, + imageVector = Icons.Default.ManageAccounts, + contentDescription = null, + colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground), + ) + } } }, ) diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreViewModel.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreViewModel.kt similarity index 99% rename from feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreViewModel.kt rename to feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreViewModel.kt index 59fd479be..d698b68c6 100644 --- a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/content/ExploreViewModel.kt +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/main/ExploreViewModel.kt @@ -1,7 +1,6 @@ -package com.github.diegoberaldin.raccoonforlemmy.feature.search.content +package com.github.diegoberaldin.raccoonforlemmy.feature.search.main import cafe.adriel.voyager.core.model.ScreenModel -import com.github.diegoberaldin.raccoonforlemmy.core.utils.HapticFeedback import com.github.diegoberaldin.raccoonforlemmy.core.appearance.repository.ThemeRepository import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel @@ -9,6 +8,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationC import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenterContractKeys import com.github.diegoberaldin.raccoonforlemmy.core.preferences.KeyStoreKeys import com.github.diegoberaldin.raccoonforlemmy.core.preferences.TemporaryKeyStore +import com.github.diegoberaldin.raccoonforlemmy.core.utils.HapticFeedback import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.ApiConfigurationRepository import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsMviModel.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsMviModel.kt new file mode 100644 index 000000000..f7699b7d9 --- /dev/null +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsMviModel.kt @@ -0,0 +1,20 @@ +package com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions + +import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel +import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel + +interface ManageSubscriptionsMviModel : + MviModel { + sealed interface Intent { + data object HapticIndication : Intent + + data class Unsubscribe(val index: Int) : Intent + } + + data class UiState( + val loading: Boolean = false, + val communities: List = emptyList(), + ) + + sealed interface Effect +} \ No newline at end of file diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsScreen.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsScreen.kt new file mode 100644 index 000000000..ac82c8e78 --- /dev/null +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsScreen.kt @@ -0,0 +1,136 @@ +package com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.DismissDirection +import androidx.compose.material.DismissValue +import androidx.compose.material.Icon +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.filled.Unsubscribe +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.input.nestedscroll.nestedScroll +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.core.commonui.communitydetail.CommunityDetailScreen +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommunityItem +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.ProgressHud +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator +import com.github.diegoberaldin.raccoonforlemmy.core.utils.onClick +import com.github.diegoberaldin.raccoonforlemmy.feature.search.di.getManageSubscriptionsViewModel +import com.github.diegoberaldin.raccoonforlemmy.resources.MR +import dev.icerock.moko.resources.compose.stringResource + +class ManageSubscriptionsScreen : Screen { + @OptIn(ExperimentalMaterial3Api::class) + @Composable + override fun Content() { + val model = rememberScreenModel { getManageSubscriptionsViewModel() } + model.bindToLifecycle(key) + val uiState by model.uiState.collectAsState() + val navigator = remember { getNavigationCoordinator().getRootNavigator() } + val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() + + Scaffold( + topBar = { + TopAppBar( + title = { + Text( + text = stringResource(MR.strings.explore_title_manage_subscriptions), + style = MaterialTheme.typography.titleLarge + ) + }, + scrollBehavior = scrollBehavior, + navigationIcon = { + Image( + modifier = Modifier.onClick { + navigator?.pop() + }, + imageVector = Icons.Default.ArrowBack, + contentDescription = null, + colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground), + ) + }, + ) + }, + ) { paddingValues -> + Box( + modifier = Modifier.padding(paddingValues), + ) { + LazyColumn( + modifier = Modifier + .nestedScroll(scrollBehavior.nestedScrollConnection) + ) { + itemsIndexed(uiState.communities) { idx, community -> + SwipeableCard( + modifier = Modifier.fillMaxWidth(), + directions = setOf(DismissDirection.EndToStart), + backgroundColor = { + when (it) { + DismissValue.DismissedToStart -> MaterialTheme.colorScheme.secondary + else -> Color.Transparent + } + }, + onGestureBegin = { + model.reduce(ManageSubscriptionsMviModel.Intent.HapticIndication) + }, + onDismissToStart = { + model.reduce( + ManageSubscriptionsMviModel.Intent.Unsubscribe(idx), + ) + }, + swipeContent = { _ -> + Icon( + modifier = Modifier.background( + color = MaterialTheme.colorScheme.onSecondary, + shape = CircleShape, + ).padding(Spacing.xs), + imageVector = Icons.Default.Unsubscribe, + contentDescription = null, + tint = MaterialTheme.colorScheme.secondary, + ) + }, + content = { + CommunityItem( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.background) + .onClick { + navigator?.push( + CommunityDetailScreen(community), + ) + }, + community = community, + ) + }, + ) + } + } + if (uiState.loading) { + ProgressHud() + } + } + } + } +} \ No newline at end of file diff --git a/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsViewModel.kt b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsViewModel.kt new file mode 100644 index 000000000..356ec67b6 --- /dev/null +++ b/feature-search/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/feature/search/managesubscriptions/ManageSubscriptionsViewModel.kt @@ -0,0 +1,63 @@ +package com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions + +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.utils.HapticFeedback +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.repository.CommunityRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO +import kotlinx.coroutines.launch + +class ManageSubscriptionsViewModel( + private val mvi: DefaultMviModel, + private val identityRepository: IdentityRepository, + private val communityRepository: CommunityRepository, + private val hapticFeedback: HapticFeedback, +) : ScreenModel, + MviModel by mvi { + + override fun onStarted() { + mvi.onStarted() + if (uiState.value.communities.isEmpty()) { + refresh() + } + } + + override fun reduce(intent: ManageSubscriptionsMviModel.Intent) { + when (intent) { + ManageSubscriptionsMviModel.Intent.HapticIndication -> hapticFeedback.vibrate() + is ManageSubscriptionsMviModel.Intent.Unsubscribe -> handleUnsubscription( + community = uiState.value.communities[intent.index] + ) + } + } + + private fun refresh() { + mvi.updateState { it.copy(loading = true) } + mvi.scope?.launch(Dispatchers.IO) { + val auth = identityRepository.authToken.value + val items = communityRepository.getSubscribed(auth).sortedBy { it.name } + mvi.updateState { + it.copy( + loading = false, + communities = items, + ) + } + } + } + + private fun handleUnsubscription(community: CommunityModel) { + mvi.scope?.launch { + val auth = identityRepository.authToken.value + communityRepository.unsubscribe( + auth = auth, id = community.id + ) + mvi.updateState { + it.copy(communities = it.communities.filter { c -> c.id != community.id }) + } + } + } +} \ 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 824826523..61e5d8ef7 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,7 +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.content.ExploreScreen +import com.github.diegoberaldin.raccoonforlemmy.feature.search.main.ExploreScreen 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 87b786ec8..0d7523211 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,15 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.search.di -import com.github.diegoberaldin.raccoonforlemmy.feature.search.content.ExploreViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.main.ExploreViewModel +import com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions.ManageSubscriptionsViewModel import org.koin.core.component.KoinComponent import org.koin.core.component.inject actual fun getExploreViewModel() = SearchScreenModelHelper.model +actual fun getManageSubscriptionsViewModel() = SearchScreenModelHelper.manageSuscriptionsViewModel + object SearchScreenModelHelper : KoinComponent { val model: ExploreViewModel by inject() + val manageSuscriptionsViewModel: ManageSubscriptionsViewModel by inject() } diff --git a/resources/src/commonMain/resources/MR/base/strings.xml b/resources/src/commonMain/resources/MR/base/strings.xml index 29f317555..1e6241c5c 100644 --- a/resources/src/commonMain/resources/MR/base/strings.xml +++ b/resources/src/commonMain/resources/MR/base/strings.xml @@ -63,6 +63,7 @@ Communities Users Search text + Manage subscriptions You are currently not logged in.\nPlease add an account to continue. diff --git a/resources/src/commonMain/resources/MR/es/strings.xml b/resources/src/commonMain/resources/MR/es/strings.xml index 175443668..c65248391 100644 --- a/resources/src/commonMain/resources/MR/es/strings.xml +++ b/resources/src/commonMain/resources/MR/es/strings.xml @@ -59,6 +59,7 @@ Comunidades Usuarios Texto de búsqueda + Gestionar subscripciones Acceso no efectuado.\nAñadir una cuenta para continuar. diff --git a/resources/src/commonMain/resources/MR/it/strings.xml b/resources/src/commonMain/resources/MR/it/strings.xml index e5da75903..ac4dcacbe 100644 --- a/resources/src/commonMain/resources/MR/it/strings.xml +++ b/resources/src/commonMain/resources/MR/it/strings.xml @@ -59,6 +59,7 @@ Comunità Utenti Testo di ricerca + Gestione iscruzione Login non effettuato.\nAggiungi un account per continuare.