fix: prevent inbox and profile unlogged contents from being visible if logged

This commit is contained in:
Diego Beraldin 2023-09-21 13:49:46 +02:00
parent 1eff763bbf
commit 31d784d645
6 changed files with 86 additions and 79 deletions

View File

@ -7,8 +7,6 @@ import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.main.InboxMviModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.main.InboxViewModel import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.main.InboxViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.mentions.InboxMentionsMviModel import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.mentions.InboxMentionsMviModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.mentions.InboxMentionsViewModel import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.mentions.InboxMentionsViewModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.chat.InboxChatMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.chat.InboxChatViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list.InboxMessagesMviModel import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list.InboxMessagesMviModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list.InboxMessagesViewModel import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages.list.InboxMessagesViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.replies.InboxRepliesMviModel import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.replies.InboxRepliesMviModel
@ -24,7 +22,6 @@ val inboxTabModule = module {
mvi = DefaultMviModel(InboxMviModel.UiState()), mvi = DefaultMviModel(InboxMviModel.UiState()),
identityRepository = get(), identityRepository = get(),
userRepository = get(), userRepository = get(),
siteRepository = get(),
coordinator = get(), coordinator = get(),
) )
} }

View File

@ -12,7 +12,7 @@ interface InboxMviModel :
} }
data class UiState( data class UiState(
val currentUserId: Int? = null, val isLogged: Boolean? = null,
val section: InboxSection = InboxSection.REPLIES, val section: InboxSection = InboxSection.REPLIES,
val unreadOnly: Boolean = true, val unreadOnly: Boolean = true,
) )

View File

@ -110,7 +110,7 @@ object InboxScreen : Tab {
} }
}, },
actions = { actions = {
if (uiState.currentUserId != null) { if (uiState.isLogged == true) {
Image( Image(
modifier = Modifier.onClick { modifier = Modifier.onClick {
model.reduce(InboxMviModel.Intent.ReadAll) model.reduce(InboxMviModel.Intent.ReadAll)
@ -124,64 +124,70 @@ object InboxScreen : Tab {
) )
}, },
) { paddingValues -> ) { paddingValues ->
if (uiState.currentUserId == null) { when (uiState.isLogged) {
Column( false -> {
modifier = Modifier.padding(paddingValues).padding(horizontal = Spacing.m) Column(
) { modifier = Modifier.padding(paddingValues).padding(horizontal = Spacing.m)
Text( ) {
text = stringResource(MR.strings.inbox_not_logged_message), Text(
) text = stringResource(MR.strings.inbox_not_logged_message),
}
} else {
Column(
modifier = Modifier
.padding(paddingValues)
.nestedScroll(scrollBehavior.nestedScrollConnection),
verticalArrangement = Arrangement.spacedBy(Spacing.s),
) {
SectionSelector(
modifier = Modifier.padding(vertical = Spacing.s),
titles = listOf(
stringResource(MR.strings.inbox_section_replies),
stringResource(MR.strings.inbox_section_mentions),
stringResource(MR.strings.inbox_section_messages),
),
currentSection = when (uiState.section) {
InboxSection.MENTIONS -> 1
InboxSection.MESSAGES -> 2
else -> 0
},
onSectionSelected = {
val section = when (it) {
1 -> InboxSection.MENTIONS
2 -> InboxSection.MESSAGES
else -> InboxSection.REPLIES
}
model.reduce(InboxMviModel.Intent.ChangeSection(section))
},
)
val screens = remember {
listOf(
InboxRepliesScreen(),
InboxMentionsScreen(),
InboxMessagesScreen(),
) )
} }
TabNavigator(screens.first()) { }
CurrentScreen()
val navigator = LocalTabNavigator.current true -> {
LaunchedEffect(model) { Column(
model.uiState.map { it.section }.onEach { section -> modifier = Modifier
val index = when (section) { .padding(paddingValues)
InboxSection.REPLIES -> 0 .nestedScroll(scrollBehavior.nestedScrollConnection),
InboxSection.MENTIONS -> 1 verticalArrangement = Arrangement.spacedBy(Spacing.s),
InboxSection.MESSAGES -> 2 ) {
SectionSelector(
modifier = Modifier.padding(vertical = Spacing.s),
titles = listOf(
stringResource(MR.strings.inbox_section_replies),
stringResource(MR.strings.inbox_section_mentions),
stringResource(MR.strings.inbox_section_messages),
),
currentSection = when (uiState.section) {
InboxSection.MENTIONS -> 1
InboxSection.MESSAGES -> 2
else -> 0
},
onSectionSelected = {
val section = when (it) {
1 -> InboxSection.MENTIONS
2 -> InboxSection.MESSAGES
else -> InboxSection.REPLIES
} }
navigator.current = screens[index] model.reduce(InboxMviModel.Intent.ChangeSection(section))
}.launchIn(this) },
)
val screens = remember {
listOf(
InboxRepliesScreen(),
InboxMentionsScreen(),
InboxMessagesScreen(),
)
}
TabNavigator(screens.first()) {
CurrentScreen()
val navigator = LocalTabNavigator.current
LaunchedEffect(model) {
model.uiState.map { it.section }.onEach { section ->
val index = when (section) {
InboxSection.REPLIES -> 0
InboxSection.MENTIONS -> 1
InboxSection.MESSAGES -> 2
}
navigator.current = screens[index]
}.launchIn(this)
}
} }
} }
} }
else -> Unit
} }
} }
} }

View File

@ -4,17 +4,18 @@ import cafe.adriel.voyager.core.model.ScreenModel
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.InboxCoordinator import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.InboxCoordinator
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class InboxViewModel( class InboxViewModel(
private val mvi: DefaultMviModel<InboxMviModel.Intent, InboxMviModel.UiState, InboxMviModel.Effect>, private val mvi: DefaultMviModel<InboxMviModel.Intent, InboxMviModel.UiState, InboxMviModel.Effect>,
private val identityRepository: IdentityRepository, private val identityRepository: IdentityRepository,
private val siteRepository: SiteRepository,
private val userRepository: UserRepository, private val userRepository: UserRepository,
private val coordinator: InboxCoordinator, private val coordinator: InboxCoordinator,
) : ScreenModel, ) : ScreenModel,
@ -22,11 +23,10 @@ class InboxViewModel(
override fun onStarted() { override fun onStarted() {
mvi.onStarted() mvi.onStarted()
mvi.scope?.launch(Dispatchers.IO) { mvi.scope?.launch {
val auth = identityRepository.authToken.value.orEmpty() identityRepository.authToken.debounce(250).onEach { auth ->
siteRepository.getCurrentUser(auth)?.also { user -> mvi.updateState { it.copy(isLogged = !auth.isNullOrEmpty()) }
mvi.updateState { it.copy(currentUserId = user.id) } }.launchIn(this)
}
} }
} }

View File

@ -98,19 +98,21 @@ internal object ProfileContentScreen : Tab {
ProfileNotLoggedScreen, ProfileNotLoggedScreen,
ProfileLoggedScreen, ProfileLoggedScreen,
) )
// wait until logging status is determined
TabNavigator(ProfileNotLoggedScreen) { if (uiState.logged != null) {
CurrentScreen() TabNavigator(ProfileNotLoggedScreen) {
val navigator = LocalTabNavigator.current CurrentScreen()
LaunchedEffect(model) { val navigator = LocalTabNavigator.current
model.uiState.map { s -> s.logged }.distinctUntilChanged() LaunchedEffect(model) {
.onEach { logged -> model.uiState.map { s -> s.logged }.distinctUntilChanged()
val index = when (logged) { .onEach { logged ->
true -> 1 val index = when (logged) {
else -> 0 true -> 1
} else -> 0
navigator.current = screens[index] }
}.launchIn(this) navigator.current = screens[index]
}.launchIn(this)
}
} }
} }
} }

View File

@ -8,8 +8,10 @@ import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationC
import com.github.diegoberaldin.raccoonforlemmy.core.preferences.KeyStoreKeys import com.github.diegoberaldin.raccoonforlemmy.core.preferences.KeyStoreKeys
import com.github.diegoberaldin.raccoonforlemmy.core.preferences.TemporaryKeyStore import com.github.diegoberaldin.raccoonforlemmy.core.preferences.TemporaryKeyStore
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
class ProfileContentViewModel( class ProfileContentViewModel(
private val mvi: DefaultMviModel<ProfileContentMviModel.Intent, ProfileContentMviModel.UiState, ProfileContentMviModel.Effect>, private val mvi: DefaultMviModel<ProfileContentMviModel.Intent, ProfileContentMviModel.UiState, ProfileContentMviModel.Effect>,
@ -22,8 +24,8 @@ class ProfileContentViewModel(
override fun onStarted() { override fun onStarted() {
mvi.onStarted() mvi.onStarted()
mvi.scope?.apply { mvi.scope?.launch {
identityRepository.authToken.onEach { token -> identityRepository.authToken.debounce(250).onEach { token ->
mvi.updateState { it.copy(logged = !token.isNullOrEmpty()) } mvi.updateState { it.copy(logged = !token.isNullOrEmpty()) }
}.launchIn(this) }.launchIn(this)
} }