enhancement: community in profile menu (#1086)

This commit is contained in:
Diego Beraldin 2024-07-06 17:09:20 +02:00 committed by GitHub
parent 7885f6e1ae
commit e0f6072313
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 99 additions and 63 deletions

View File

@ -229,6 +229,8 @@ sealed interface NotificationCenterEvent {
data object ModeratorZone : ProfileSideMenuAction
data object CreateCommunity : ProfileSideMenuAction
data object Logout : ProfileSideMenuAction
}

View File

@ -36,7 +36,7 @@
"url": "https://github.com/reusityback"
},
{
"title": "outer_air",
"title": "outerair",
"avatar": "https://hosted.weblate.org/avatar/128/outer_air.png",
"subtitle": "Brazilian Portuguese translation",
"url": "https://hosted.weblate.org/user/outer_air"
@ -48,7 +48,7 @@
"url": "https://github.com/Tmpod"
},
{
"title": "Cloudless",
"title": "Cloudless",
"avatar": "https://lemmy.cafe/pictrs/image/e2f1f086-fe5a-4823-8676-e270b5554992.webp?format=webp",
"subtitle": "Traditional Chinese (TW, HK) translation",
"url": "https://lemmy.cafe/u/cloudless"

View File

@ -139,10 +139,21 @@ A special thanks goes to all those who contributed so far (in nearly chronologic
- [u/heyazorin](https://lemmy.ml/u/heyazorin)
- [u/thegiddystitcher](https://lemm.ee/u/thegiddystitcher)
- [u/SgtAStrawberry](https://lemmy.world/u/SgtAStrawberry)
- [outerair](https://hosted.weblate.org/user/outer_air)
- [u/Wild_Mastic](https://lemmy.world/u/Wild_Mastic)
- [reusityback](https://github.com/reusityback)
- [u/fisco](https://lemmy.ml/u/fisco)
- [u/Suoko](https://feddit.it/u/Suoko)
- [u/Mannivu](https://feddit.it/u/Mannivu)
- [u/Kir](https://feddit.it/u/Kir)
- [u/NicKoehler](https://feddit.it/u/NicKoehler)
- [Tmpod](https://github.com/Tmpod)
- [u/cloudless](https://lemmy.cafe/u/cloudless)
- [u/squirrel](https://discuss.tchncs.de/u/squirrel)
- [gallegonovato](https://hosted.weblate.org/user/gallegonovato)
- [Edanas](https://hosted.weblate.org/user/Edanas)
- [u/sag](https://lemm.ee/u/sag)
- [u/am41](https://sh.itjust.works/u/am41)
- all those who reported feedback and ideas through the Lemmy community, GitHub issues, emails,
private messages, homing pigeons and every other imaginable media.

View File

@ -64,6 +64,7 @@ kotlin {
implementation(projects.unit.createcomment)
implementation(projects.unit.createpost)
implementation(projects.unit.drafts)
implementation(projects.unit.editcommunity)
implementation(projects.unit.filteredcontents)
implementation(projects.unit.login)
implementation(projects.unit.manageaccounts)
@ -90,8 +91,14 @@ kotlin {
android {
namespace = "com.github.diegoberaldin.raccoonforlemmy.feature.profile"
compileSdk = libs.versions.android.targetSdk.get().toInt()
compileSdk =
libs.versions.android.targetSdk
.get()
.toInt()
defaultConfig {
minSdk = libs.versions.android.minSdk.get().toInt()
minSdk =
libs.versions.android.minSdk
.get()
.toInt()
}
}

View File

@ -53,6 +53,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalPixel
import com.github.diegoberaldin.raccoonforlemmy.feature.profile.menu.ProfileSideMenuScreen
import com.github.diegoberaldin.raccoonforlemmy.feature.profile.notlogged.ProfileNotLoggedScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.drafts.DraftsScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.editcommunity.EditCommunityScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.filteredcontents.FilteredContentsScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.filteredcontents.FilteredContentsType
import com.github.diegoberaldin.raccoonforlemmy.unit.filteredcontents.toInt
@ -148,6 +149,12 @@ internal object ProfileMainScreen : Tab {
NotificationCenterEvent.ProfileSideMenuAction.Logout -> {
logoutConfirmDialogOpen = true
}
NotificationCenterEvent.ProfileSideMenuAction.CreateCommunity -> {
navigationCoordinator.pushScreen(
EditCommunityScreen(),
)
}
}
}.launchIn(this)
}

View File

@ -7,6 +7,7 @@ import androidx.compose.material.icons.automirrored.filled.Logout
import androidx.compose.material.icons.filled.Book
import androidx.compose.material.icons.filled.Bookmark
import androidx.compose.material.icons.filled.Drafts
import androidx.compose.material.icons.filled.GroupAdd
import androidx.compose.material.icons.filled.ManageAccounts
import androidx.compose.material.icons.filled.Shield
import androidx.compose.material.icons.filled.ThumbsUpDown
@ -25,6 +26,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
internal fun ProfileMenuContent(
modifier: Modifier = Modifier,
isModerator: Boolean = false,
canCreateCommunity: Boolean = false,
) {
val notificationCenter = remember { getNotificationCenter() }
@ -75,6 +77,16 @@ internal fun ProfileMenuContent(
},
)
}
if (canCreateCommunity) {
SettingsRow(
title = LocalStrings.current.actionCreateCommunity,
icon = Icons.Default.GroupAdd,
onTap =
rememberCallback {
notificationCenter.send(NotificationCenterEvent.ProfileSideMenuAction.CreateCommunity)
},
)
}
SettingsRow(
title = LocalStrings.current.manageAccountsTitle,

View File

@ -10,6 +10,7 @@ interface ProfileSideMenuMviModel :
data class State(
val isModerator: Boolean = false,
val canCreateCommunity: Boolean = false,
)
sealed interface Effect

View File

@ -69,6 +69,7 @@ class ProfileSideMenuScreen : Screen {
end = Spacing.m,
),
isModerator = uiState.isModerator,
canCreateCommunity = uiState.canCreateCommunity,
)
}
}

View File

@ -3,6 +3,7 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.profile.menu
import cafe.adriel.voyager.core.model.screenModelScope
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.LemmyValueCache
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -23,6 +24,21 @@ class ProfileSideMenuViewModel(
)
}
}.launchIn(this)
combine(
lemmyValueCache.isCurrentUserAdmin,
lemmyValueCache.isCommunityCreationAdminOnly,
) { isAdmin, isCommunityCreationAdminOnly ->
updateState {
it.copy(
canCreateCommunity =
if (isCommunityCreationAdminOnly) {
isAdmin
} else {
true
},
)
}
}.launchIn(this)
}
}
}

View File

@ -1,10 +1,14 @@
package com.github.diegoberaldin.raccoonforlemmy
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.DrawerDefaults
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Surface
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalDrawerSheet
@ -56,6 +60,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getDrawerCoor
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getAccountRepository
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsRepository
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLanguageDirection
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.di.getApiConfigurationRepository
@ -336,6 +341,26 @@ fun App(onLoadingFinished: () -> Unit = {}) {
}
}
// scrim for draggable side menu
AnimatedVisibility(
modifier = Modifier.fillMaxSize(),
visible = sideMenuOpened,
) {
Surface(
modifier =
Modifier
.onClick(
onClick = {
navigationCoordinator.closeSideMenu()
},
),
color = DrawerDefaults.scrimColor,
) {
Box(modifier = Modifier.fillMaxSize())
}
}
// draggable side menu
DraggableSideMenu(
availableWidth = screenWidth.toLocalDp(),
opened = sideMenuOpened,

View File

@ -22,7 +22,6 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.imageUrl
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.LemmyValueCache
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.launchIn
@ -38,7 +37,6 @@ class FilteredContentsViewModel(
private val identityRepository: IdentityRepository,
private val postRepository: PostRepository,
private val commentRepository: CommentRepository,
private val siteRepository: SiteRepository,
private val imagePreloadManager: ImagePreloadManager,
private val hapticFeedback: HapticFeedback,
private val notificationCenter: NotificationCenter,

View File

@ -20,7 +20,6 @@ val filteredContentsModule =
postPaginationManager = get(),
commentPaginationManager = get(),
postNavigationManager = get(),
siteRepository = get(),
lemmyValueCache = get(),
)
}

View File

@ -53,14 +53,12 @@ kotlin {
implementation(projects.core.persistence)
implementation(projects.core.utils)
implementation(projects.unit.multicommunity)
implementation(projects.domain.identity)
implementation(projects.domain.lemmy.data)
implementation(projects.domain.lemmy.pagination)
implementation(projects.domain.lemmy.repository)
implementation(projects.unit.editcommunity)
implementation(projects.unit.multicommunity)
}
}
val commonTest by getting {

View File

@ -15,13 +15,21 @@ interface ManageSubscriptionsMviModel :
data object HapticIndication : Intent
data class Unsubscribe(val id: Long) : Intent
data class Unsubscribe(
val id: Long,
) : Intent
data class DeleteMultiCommunity(val id: Long) : Intent
data class DeleteMultiCommunity(
val id: Long,
) : Intent
data class ToggleFavorite(val id: Long) : Intent
data class ToggleFavorite(
val id: Long,
) : Intent
data class SetSearch(val value: String) : Intent
data class SetSearch(
val value: String,
) : Intent
data object LoadNextPage : Intent
}
@ -36,7 +44,6 @@ interface ManageSubscriptionsMviModel :
val searchText: String = "",
val canFetchMore: Boolean = true,
val loading: Boolean = false,
val canCreateCommunity: Boolean = false,
)
sealed interface Effect {

View File

@ -75,7 +75,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigation
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
import com.github.diegoberaldin.raccoonforlemmy.unit.editcommunity.EditCommunityScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.multicommunity.detail.MultiCommunityScreen
import com.github.diegoberaldin.raccoonforlemmy.unit.multicommunity.editor.MultiCommunityEditorScreen
import kotlinx.coroutines.flow.launchIn
@ -247,39 +246,6 @@ class ManageSubscriptionsScreen : Screen {
state = lazyListState,
verticalArrangement = Arrangement.spacedBy(Spacing.xxs),
) {
if (uiState.canCreateCommunity) {
// create community header
item {
Row(
modifier =
Modifier.fillMaxWidth().padding(horizontal = Spacing.s),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
modifier = Modifier.padding(vertical = Spacing.xs),
text = LocalStrings.current.actionCreateCommunity,
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onBackground,
)
Spacer(modifier = Modifier.weight(1f))
Icon(
modifier =
Modifier
.padding(horizontal = Spacing.xs)
.onClick(
onClick = {
navigatorCoordinator.pushScreen(
EditCommunityScreen(),
)
},
),
imageVector = Icons.Default.AddCircle,
contentDescription = null,
tint = MaterialTheme.colorScheme.onBackground,
)
}
}
}
item {
Row(
modifier = Modifier.fillMaxWidth().padding(horizontal = Spacing.s),

View File

@ -16,9 +16,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.vibrate.HapticFeedbac
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 com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.LemmyValueCache
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
@ -37,7 +35,6 @@ class ManageSubscriptionsViewModel(
private val communityPaginationManager: CommunityPaginationManager,
private val hapticFeedback: HapticFeedback,
private val notificationCenter: NotificationCenter,
private val lemmyValueCache: LemmyValueCache,
) : DefaultMviModel<ManageSubscriptionsMviModel.Intent, ManageSubscriptionsMviModel.UiState, ManageSubscriptionsMviModel.Effect>(
initialState = ManageSubscriptionsMviModel.UiState(),
),
@ -64,16 +61,6 @@ class ManageSubscriptionsViewModel(
handleCommunityUpdate(evt.value)
}.launchIn(this)
// determine whether community creation is available
combine(
lemmyValueCache.isCurrentUserAdmin,
lemmyValueCache.isCommunityCreationAdminOnly,
) { isAdmin, isCommunityCreationAdminOnly ->
updateState {
it.copy(canCreateCommunity = isAdmin || !isCommunityCreationAdminOnly)
}
}.launchIn(this)
uiState
.map { it.searchText }
.distinctUntilChanged()

View File

@ -20,7 +20,6 @@ val manageSubscriptionsModule =
settingsRepository = get(),
favoriteCommunityRepository = get(),
communityPaginationManager = get(),
lemmyValueCache = get(),
)
}
}