feat: show moderators in community info; closes #314 (#317)

This commit is contained in:
Diego Beraldin 2023-12-17 11:49:08 +01:00 committed by GitHub
parent 9c5e09c74a
commit b126e2202a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 194 additions and 5 deletions

View File

@ -4,6 +4,7 @@ import androidx.compose.runtime.Stable
import cafe.adriel.voyager.core.model.ScreenModel
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.UserModel
@Stable
interface CommunityInfoMviModel :
@ -14,6 +15,8 @@ interface CommunityInfoMviModel :
data class UiState(
val community: CommunityModel = CommunityModel(),
val autoLoadImages: Boolean = true,
val moderators: List<UserModel> = emptyList(),
)
sealed interface Effect

View File

@ -9,7 +9,11 @@ import androidx.compose.foundation.layout.fillMaxHeight
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.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Cake
import androidx.compose.material.icons.filled.CalendarViewDay
@ -18,7 +22,6 @@ import androidx.compose.material.icons.filled.CalendarViewWeek
import androidx.compose.material.icons.filled.Group
import androidx.compose.material.icons.filled.Padding
import androidx.compose.material.icons.filled.Reply
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
@ -28,26 +31,44 @@ import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle
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.IconSize
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.BottomSheetHandle
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CustomImage
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CustomizedContent
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PlaceholderImage
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCardBody
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getCommunityInfoViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.userdetail.UserDetailScreen
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
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.core.utils.datetime.prettifyDate
import com.github.diegoberaldin.raccoonforlemmy.core.utils.getPrettyNumber
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class CommunityInfoScreen(
private val community: CommunityModel,
@ -58,6 +79,8 @@ class CommunityInfoScreen(
val model = rememberScreenModel { getCommunityInfoViewModel(community) }
model.bindToLifecycle(key)
val uiState by model.uiState.collectAsState()
val navigationCoordinator = remember { getNavigationCoordinator() }
val scope = rememberCoroutineScope()
Column(
modifier = Modifier
@ -166,14 +189,47 @@ class CommunityInfoScreen(
millionLabel = stringResource(MR.strings.profile_million_short),
),
)
Divider()
}
}
if (uiState.moderators.isNotEmpty()) {
item {
Text(
modifier = Modifier
.fillMaxWidth()
.padding(
top = Spacing.s,
bottom = Spacing.xs,
),
text = stringResource(MR.strings.community_info_moderators),
)
LazyRow(
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
) {
items(
count = uiState.moderators.size
) { idx ->
val user = uiState.moderators[idx]
ModeratorCell(
autoLoadImages = uiState.autoLoadImages,
user = user,
onOpenUser = rememberCallbackArgs {
navigationCoordinator.hideBottomSheet()
scope.launch {
delay(100)
navigationCoordinator.pushScreen(
UserDetailScreen(user),
)
}
}
)
}
}
}
}
item {
CustomizedContent {
PostCardBody(
modifier = Modifier.fillMaxWidth(),
modifier = Modifier.fillMaxWidth().padding(top = Spacing.m),
text = uiState.community.description,
)
}
@ -214,3 +270,78 @@ private fun CommunityInfoItem(
)
}
}
@Composable
private fun ModeratorCell(
user: UserModel,
autoLoadImages: Boolean = true,
onOpenUser: ((UserModel) -> Unit)? = null,
) {
val creatorName = user?.name.orEmpty()
val creatorHost = user?.host.orEmpty()
val creatorAvatar = user?.avatar.orEmpty()
val iconSize = IconSize.xl
val fullTextColor = MaterialTheme.colorScheme.onBackground
val ancillaryColor = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.75f)
Column(
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
horizontalAlignment = Alignment.CenterHorizontally,
) {
if (creatorAvatar.isNotEmpty()) {
CustomImage(
modifier = Modifier
.padding(Spacing.xxxs)
.size(iconSize)
.clip(RoundedCornerShape(iconSize / 2))
.onClick(
onClick = rememberCallback {
if (user != null) {
onOpenUser?.invoke(user)
}
},
),
quality = FilterQuality.Low,
url = creatorAvatar,
autoload = autoLoadImages,
contentDescription = null,
contentScale = ContentScale.FillBounds,
)
} else {
PlaceholderImage(
modifier = Modifier.onClick(
onClick = rememberCallback {
if (user != null) {
onOpenUser?.invoke(user)
}
},
),
size = iconSize,
title = creatorName,
)
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
modifier = Modifier.widthIn(max = 100.dp),
text = creatorName,
style = MaterialTheme.typography.labelMedium,
color = fullTextColor,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
if (creatorHost.isNotEmpty()) {
Text(
modifier = Modifier.widthIn(max = 100.dp),
text = creatorHost,
style = MaterialTheme.typography.labelSmall,
color = ancillaryColor,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
}
}

View File

@ -2,16 +2,38 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.communityInfo
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
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.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
class CommunityInfoViewModel(
private val mvi: DefaultMviModel<CommunityInfoMviModel.Intent, CommunityInfoMviModel.UiState, CommunityInfoMviModel.Effect>,
private val community: CommunityModel,
private val communityRepository: CommunityRepository,
private val settingsRepository: SettingsRepository,
) : CommunityInfoMviModel,
MviModel<CommunityInfoMviModel.Intent, CommunityInfoMviModel.UiState, CommunityInfoMviModel.Effect> by mvi {
override fun onStarted() {
mvi.onStarted()
mvi.updateState { it.copy(community = community) }
mvi.scope?.launch(Dispatchers.IO) {
settingsRepository.currentSettings.onEach {
mvi.updateState { it.copy(autoLoadImages = it.autoLoadImages) }
}.launchIn(this)
if (uiState.value.moderators.isEmpty()) {
val moderators = communityRepository.getModerators(
id = community.id
)
mvi.updateState { it.copy(moderators = moderators) }
}
}
}
}

View File

@ -94,6 +94,8 @@ val commonUiModule = module {
CommunityInfoViewModel(
mvi = DefaultMviModel(CommunityInfoMviModel.UiState()),
community = params[0],
communityRepository = get(),
settingsRepository = get(),
)
}
factory<UserDetailMviModel> { params ->

View File

@ -78,7 +78,7 @@ actual fun CustomMarkdown(
modifier = modifier
) {
val style = LocalMarkdownTypography.current.text
val fontScale = LocalDensity.current.fontScale * 1.25f
val fontScale = LocalDensity.current.fontScale * 1.3f
val canvasWidthMaybe = with(LocalDensity.current) { maxWidth.toPx() }.toInt()
val textSizeMaybe = with(LocalDensity.current) { (style.fontSize * fontScale).toPx() }
val defaultColor = LocalMarkdownColors.current.text

View File

@ -260,4 +260,5 @@
<string name="community_action_unsubscribe">إلغاء الاشتراك</string>
<string name="settings_search_posts_title_only">البحث عن المشاركات فقط في العنوان</string>
<string name="settings_content_font_family">عائلة خطوط المحتوى</string>
<string name="community_info_moderators">المشرفون</string>
</resources>

View File

@ -291,4 +291,5 @@
<string name="community_action_unsubscribe">Unsubscribe</string>
<string name="settings_search_posts_title_only">Search posts only in title</string>
<string name="settings_content_font_family">Content font family</string>
<string name="community_info_moderators">Moderators</string>
</resources>

View File

@ -271,4 +271,5 @@
<string name="community_action_unsubscribe">Отписване</string>
<string name="settings_search_posts_title_only">Търсете публикации само в заглавието</string>
<string name="settings_content_font_family">Семейство шрифтове за съдържание</string>
<string name="community_info_moderators">Модератори</string>
</resources>

View File

@ -262,4 +262,5 @@
<string name="community_action_unsubscribe">Odhlásit odběr</string>
<string name="settings_search_posts_title_only">Hledejte příspěvky pouze v názvu</string>
<string name="settings_content_font_family">Rodina písem obsahu</string>
<string name="community_info_moderators">Moderátoři</string>
</resources>

View File

@ -262,4 +262,5 @@
<string name="community_action_unsubscribe">Opsige abonnement</string>
<string name="settings_search_posts_title_only">Søg kun efter indlæg i titlen</string>
<string name="settings_content_font_family">Indhold skrifttypefamilie</string>
<string name="community_info_moderators">Moderatorer</string>
</resources>

View File

@ -268,4 +268,5 @@
<string name="community_action_unsubscribe">Abbestellen</string>
<string name="settings_search_posts_title_only">Durchsuchen Sie Beiträge nur nach Titel</string>
<string name="settings_content_font_family">Content-Schriftfamilie</string>
<string name="community_info_moderators">Moderatoren</string>
</resources>

View File

@ -272,4 +272,5 @@
<string name="community_action_unsubscribe">Απεγγραφή</string>
<string name="settings_search_posts_title_only">Αναζήτηση αναρτήσεων μόνο στον τίτλο</string>
<string name="settings_content_font_family">Γραμματοσειρά περιεχομένων</string>
<string name="community_info_moderators">Συντονιστές</string>
</resources>

View File

@ -261,4 +261,5 @@
<string name="community_action_unsubscribe">Malaboni</string>
<string name="settings_search_posts_title_only">Serĉi afiŝojn nur en titolo</string>
<string name="settings_content_font_family">Enhavo tiparo</string>
<string name="community_info_moderators">Moderigantoj</string>
</resources>

View File

@ -268,4 +268,5 @@
<string name="community_action_unsubscribe">Cancelar suscripción</string>
<string name="settings_search_posts_title_only">Buscar publicaciones sólo en el título</string>
<string name="settings_content_font_family">Fuente del contenido</string>
<string name="community_info_moderators">Moderadores</string>
</resources>

View File

@ -262,4 +262,5 @@
<string name="community_action_unsubscribe">Loobu tellimusest</string>
<string name="settings_search_posts_title_only">Otsi postitusi ainult pealkirjast</string>
<string name="settings_content_font_family">Sisu fondiperekond</string>
<string name="community_info_moderators">Moderaatorid</string>
</resources>

View File

@ -262,4 +262,5 @@
<string name="community_action_unsubscribe">Lopeta tilaus</string>
<string name="settings_search_posts_title_only">Hae viestejä vain otsikosta</string>
<string name="settings_content_font_family">Sisällön kirjasinperhe</string>
<string name="community_info_moderators">Moderaattorit</string>
</resources>

View File

@ -268,4 +268,5 @@
titre
</string>
<string name="settings_content_font_family">Police des contenus</string>
<string name="community_info_moderators">Modérateurs</string>
</resources>

View File

@ -271,4 +271,5 @@
<string name="community_action_unsubscribe">Díliostáil</string>
<string name="settings_search_posts_title_only">Cuardaigh postálacha i dteideal amháin</string>
<string name="settings_content_font_family">Teaghlach cló ábhar</string>
<string name="community_info_moderators">Modhnóirí</string>
</resources>

View File

@ -267,4 +267,5 @@
<string name="community_action_unsubscribe">Odjavi pretplatu</string>
<string name="settings_search_posts_title_only">Pretraži postove samo u naslovu</string>
<string name="settings_content_font_family">Obitelj fontova sadržaja</string>
<string name="community_info_moderators">Moderatori</string>
</resources>

View File

@ -266,4 +266,5 @@
<string name="community_action_unsubscribe">Leiratkozás</string>
<string name="settings_search_posts_title_only">Keresés a bejegyzésekben csak a címben</string>
<string name="settings_content_font_family">Tartalmi betűtípuscsalád</string>
<string name="community_info_moderators">Moderátorok</string>
</resources>

View File

@ -266,4 +266,5 @@
<string name="community_action_unsubscribe">Disiscriviti</string>
<string name="settings_search_posts_title_only">Cerca solo nel titolo dei post</string>
<string name="settings_content_font_family">Font contenuti</string>
<string name="community_info_moderators">Moderatori</string>
</resources>

View File

@ -265,4 +265,5 @@
<string name="community_action_unsubscribe">Atsisakyti prenumeratos</string>
<string name="settings_search_posts_title_only">Ieškoti įrašų tik pavadinime</string>
<string name="settings_content_font_family">Turinio šriftų šeima</string>
<string name="community_info_moderators">Moderatoriai</string>
</resources>

View File

@ -266,4 +266,5 @@
<string name="community_action_unsubscribe">Anulēt abonementu</string>
<string name="settings_search_posts_title_only">Meklēt ziņas tikai virsrakstā</string>
<string name="settings_content_font_family">Satura fontu saime</string>
<string name="community_info_moderators">Moderatori</string>
</resources>

View File

@ -267,4 +267,5 @@
<string name="community_action_unsubscribe">Annulla l-abbonament</string>
<string name="settings_search_posts_title_only">Fittex postijiet biss fit-titlu</string>
<string name="settings_content_font_family">Familja tat-tipa tal-kontenut</string>
<string name="community_info_moderators">Moderaturi</string>
</resources>

View File

@ -266,4 +266,5 @@
<string name="community_action_unsubscribe">Uitschrijven</string>
<string name="settings_search_posts_title_only">Zoek berichten alleen op titel</string>
<string name="settings_content_font_family">Inhoud lettertypefamilie</string>
<string name="community_info_moderators">Moderators</string>
</resources>

View File

@ -265,4 +265,5 @@
<string name="community_action_unsubscribe">Avslutte abonnementet</string>
<string name="settings_search_posts_title_only">Søk kun innlegg i tittel</string>
<string name="settings_content_font_family">Innhold fontfamilie</string>
<string name="community_info_moderators">Moderatorer</string>
</resources>

View File

@ -265,4 +265,5 @@
<string name="community_action_unsubscribe">Zrezygnuj z subskrypcji</string>
<string name="settings_search_posts_title_only">Szukaj postów tylko po tytule</string>
<string name="settings_content_font_family">Rodzina czcionek treści</string>
<string name="community_info_moderators">Moderatorzy</string>
</resources>

View File

@ -265,4 +265,5 @@
<string name="community_action_unsubscribe">Cancelar subscrição</string>
<string name="settings_search_posts_title_only">Pesquise postagens apenas no título</string>
<string name="settings_content_font_family">Fonte dos conteúdos</string>
<string name="community_info_moderators">Moderadores</string>
</resources>

View File

@ -263,4 +263,5 @@
<string name="community_action_unsubscribe">Dezabonează-te</string>
<string name="settings_search_posts_title_only">Căută postări numai în titlu</string>
<string name="settings_content_font_family">Font conținuturilor</string>
<string name="community_info_moderators">Moderatori</string>
</resources>

View File

@ -266,4 +266,5 @@
<string name="community_action_unsubscribe">Отписаться</string>
<string name="settings_search_posts_title_only">Искать сообщения только по заголовку</string>
<string name="settings_content_font_family">Размер шрифта контента</string>
<string name="community_info_moderators">Модераторы</string>
</resources>

View File

@ -263,4 +263,5 @@
<string name="community_action_unsubscribe">Säga upp</string>
<string name="settings_search_posts_title_only">Sök endast inlägg i rubriken</string>
<string name="settings_content_font_family">Teckenstorlek för innehåll</string>
<string name="community_info_moderators">Moderatorer</string>
</resources>

View File

@ -264,4 +264,5 @@
<string name="community_action_unsubscribe">Zrušte odber</string>
<string name="settings_search_posts_title_only">Hľadajte príspevky iba v názve</string>
<string name="settings_content_font_family">Veľkosť písma obsahu</string>
<string name="community_info_moderators">Moderátori</string>
</resources>

View File

@ -262,4 +262,5 @@
<string name="community_action_unsubscribe">Odjavi se</string>
<string name="settings_search_posts_title_only">Išči objave samo v naslovu</string>
<string name="settings_content_font_family">Velikost pisave vsebine</string>
<string name="community_info_moderators">Moderatorji</string>
</resources>

View File

@ -268,4 +268,5 @@
<string name="community_action_unsubscribe">Çregjistrohu</string>
<string name="settings_search_posts_title_only">Kërkoni postimet vetëm në titull</string>
<string name="settings_content_font_family">Madhësia e shkronjave të përmbajtjes</string>
<string name="community_info_moderators">Moderatorët</string>
</resources>

View File

@ -265,4 +265,5 @@
<string name="community_action_unsubscribe">Abonelikten çık</string>
<string name="settings_search_posts_title_only">Gönderileri yalnızca başlıkta ara</string>
<string name="settings_content_font_family">İçerik yazı tipi boyutu</string>
<string name="community_info_moderators">Moderatörler</string>
</resources>

View File

@ -265,4 +265,5 @@
<string name="community_action_unsubscribe">Відписатися</string>
<string name="settings_search_posts_title_only">Шукати публікації лише за назвою</string>
<string name="settings_content_font_family">Розмір шрифту вмісту</string>
<string name="community_info_moderators">Модератори</string>
</resources>