mirror of
https://github.com/LiveFastEatTrashRaccoon/RaccoonForLemmy.git
synced 2025-02-08 15:28:42 +01:00
fix: MVI model state update (#879)
This commit is contained in:
parent
aeaff6be61
commit
58e33fccd8
@ -3,6 +3,8 @@ package com.github.diegoberaldin.raccoonforlemmy.core.architecture
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
|
||||
/**
|
||||
* Basic implementation of the MVI model.
|
||||
@ -20,13 +22,14 @@ abstract class DefaultMviModel<Intent, State, Effect>(
|
||||
) : MviModel<Intent, State, Effect> {
|
||||
override val uiState = MutableStateFlow(initialState)
|
||||
override val effects = MutableSharedFlow<Effect>()
|
||||
private val mutex = Mutex()
|
||||
|
||||
/**
|
||||
* Emit an effect (event).
|
||||
*
|
||||
* @param value Value
|
||||
*/
|
||||
suspend fun emitEffect(value: Effect) {
|
||||
protected suspend fun emitEffect(value: Effect) {
|
||||
effects.emit(value)
|
||||
}
|
||||
|
||||
@ -35,8 +38,10 @@ abstract class DefaultMviModel<Intent, State, Effect>(
|
||||
*
|
||||
* @param block Block
|
||||
*/
|
||||
inline fun updateState(block: (State) -> State) {
|
||||
uiState.update { block(uiState.value) }
|
||||
protected suspend fun updateState(block: (State) -> State) {
|
||||
mutex.withLock {
|
||||
uiState.update { block(uiState.value) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun reduce(intent: Intent) {
|
||||
|
@ -30,40 +30,4 @@ class DefaultNotificationCenterTest {
|
||||
expectNoEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenMultipleSubscriptions_whenSendReplayableEvent_thenEventIsReceivedAndReplayed() =
|
||||
runTest {
|
||||
launch {
|
||||
sut.send(NotificationCenterEvent.PostCreated)
|
||||
}
|
||||
|
||||
sut.subscribe(NotificationCenterEvent.PostCreated::class).test {
|
||||
val evt = awaitItem()
|
||||
assertEquals(NotificationCenterEvent.PostCreated, evt)
|
||||
}
|
||||
|
||||
sut.subscribe(NotificationCenterEvent.PostCreated::class).test {
|
||||
val evt = awaitItem()
|
||||
assertEquals(NotificationCenterEvent.PostCreated, evt)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenMultipleSubscriptions_whenResetCache_thenEventIsNotReplayed() =
|
||||
runTest {
|
||||
launch {
|
||||
sut.send(NotificationCenterEvent.PostCreated)
|
||||
}
|
||||
sut.subscribe(NotificationCenterEvent.PostCreated::class).test {
|
||||
val evt = awaitItem()
|
||||
assertEquals(NotificationCenterEvent.PostCreated, evt)
|
||||
}
|
||||
|
||||
sut.resetCache()
|
||||
|
||||
sut.subscribe(NotificationCenterEvent.PostCreated::class).test {
|
||||
expectNoEvents()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package com.github.diegoberaldin.raccoonforlemmy.core.notifications
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
@ -11,49 +10,17 @@ import kotlinx.coroutines.launch
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.safeCast
|
||||
|
||||
private const val REPLAY_EVENT_COUNT = 5
|
||||
|
||||
object DefaultNotificationCenter : NotificationCenter {
|
||||
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
|
||||
private val events = MutableSharedFlow<NotificationCenterEvent>()
|
||||
private val replayedEvents =
|
||||
MutableSharedFlow<NotificationCenterEvent>(
|
||||
replay = REPLAY_EVENT_COUNT,
|
||||
)
|
||||
|
||||
override fun send(event: NotificationCenterEvent) {
|
||||
scope.launch(Dispatchers.Main) {
|
||||
if (isReplayable(event::class)) {
|
||||
replayedEvents.emit(event)
|
||||
} else {
|
||||
events.emit(event)
|
||||
}
|
||||
events.emit(event)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T : NotificationCenterEvent> subscribe(clazz: KClass<T>): Flow<T> {
|
||||
return if (isReplayable(clazz)) {
|
||||
replayedEvents.mapNotNull { clazz.safeCast(it) }
|
||||
} else {
|
||||
events.mapNotNull { clazz.safeCast(it) }
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun resetCache() {
|
||||
replayedEvents.resetReplayCache()
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : NotificationCenterEvent> isReplayable(clazz: KClass<T>): Boolean {
|
||||
return when (clazz) {
|
||||
NotificationCenterEvent.MultiCommunityCreated::class -> true
|
||||
NotificationCenterEvent.PostUpdated::class -> true
|
||||
NotificationCenterEvent.PostCreated::class -> true
|
||||
NotificationCenterEvent.PostDeleted::class -> true
|
||||
NotificationCenterEvent.CommentCreated::class -> true
|
||||
NotificationCenterEvent.UserBannedPost::class -> true
|
||||
NotificationCenterEvent.UserBannedComment::class -> true
|
||||
else -> false
|
||||
return events.mapNotNull { clazz.safeCast(it) }
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,4 @@ interface NotificationCenter {
|
||||
fun send(event: NotificationCenterEvent)
|
||||
|
||||
fun <T : NotificationCenterEvent> subscribe(clazz: KClass<T>): Flow<T>
|
||||
|
||||
fun resetCache()
|
||||
}
|
||||
|
@ -60,8 +60,10 @@ class InboxViewModel(
|
||||
override fun reduce(intent: InboxMviModel.Intent) {
|
||||
when (intent) {
|
||||
is InboxMviModel.Intent.ChangeSection ->
|
||||
updateState {
|
||||
it.copy(section = intent.value)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(section = intent.value)
|
||||
}
|
||||
}
|
||||
|
||||
InboxMviModel.Intent.ReadAll -> markAllRead()
|
||||
@ -69,10 +71,12 @@ class InboxViewModel(
|
||||
}
|
||||
|
||||
private fun changeUnreadOnly(value: Boolean) {
|
||||
updateState {
|
||||
it.copy(unreadOnly = value)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(unreadOnly = value)
|
||||
}
|
||||
coordinator.setUnreadOnly(value)
|
||||
}
|
||||
coordinator.setUnreadOnly(value)
|
||||
}
|
||||
|
||||
private fun markAllRead() {
|
||||
|
@ -80,33 +80,33 @@ class AdvancedSettingsViewModel(
|
||||
}.launchIn(this)
|
||||
|
||||
updateAvailableLanguages()
|
||||
}
|
||||
|
||||
val settings = settingsRepository.currentSettings.value
|
||||
updateState {
|
||||
it.copy(
|
||||
defaultExploreType = settings.defaultExploreType.toListingType(),
|
||||
defaultInboxUnreadOnly = settings.defaultInboxType.toInboxUnreadOnly(),
|
||||
enableDoubleTapAction = settings.enableDoubleTapAction,
|
||||
autoLoadImages = settings.autoLoadImages,
|
||||
autoExpandComments = settings.autoExpandComments,
|
||||
hideNavigationBarWhileScrolling = settings.hideNavigationBarWhileScrolling,
|
||||
zombieModeInterval = settings.zombieModeInterval,
|
||||
zombieModeScrollAmount = settings.zombieModeScrollAmount,
|
||||
markAsReadWhileScrolling = settings.markAsReadWhileScrolling,
|
||||
searchPostTitleOnly = settings.searchPostTitleOnly,
|
||||
edgeToEdge = settings.edgeToEdge,
|
||||
infiniteScrollDisabled = !settings.infiniteScrollEnabled,
|
||||
opaqueSystemBars = settings.opaqueSystemBars,
|
||||
imageSourceSupported = galleryHelper.supportsCustomPath,
|
||||
imageSourcePath = settings.imageSourcePath,
|
||||
defaultLanguageId = settings.defaultLanguageId,
|
||||
appIconChangeSupported = appIconManager.supportsMultipleIcons,
|
||||
fadeReadPosts = settings.fadeReadPosts,
|
||||
showUnreadComments = settings.showUnreadComments,
|
||||
supportSettingsImportExport = fileSystemManager.isSupported,
|
||||
enableButtonsToScrollBetweenComments = settings.enableButtonsToScrollBetweenComments,
|
||||
)
|
||||
val settings = settingsRepository.currentSettings.value
|
||||
updateState {
|
||||
it.copy(
|
||||
defaultExploreType = settings.defaultExploreType.toListingType(),
|
||||
defaultInboxUnreadOnly = settings.defaultInboxType.toInboxUnreadOnly(),
|
||||
enableDoubleTapAction = settings.enableDoubleTapAction,
|
||||
autoLoadImages = settings.autoLoadImages,
|
||||
autoExpandComments = settings.autoExpandComments,
|
||||
hideNavigationBarWhileScrolling = settings.hideNavigationBarWhileScrolling,
|
||||
zombieModeInterval = settings.zombieModeInterval,
|
||||
zombieModeScrollAmount = settings.zombieModeScrollAmount,
|
||||
markAsReadWhileScrolling = settings.markAsReadWhileScrolling,
|
||||
searchPostTitleOnly = settings.searchPostTitleOnly,
|
||||
edgeToEdge = settings.edgeToEdge,
|
||||
infiniteScrollDisabled = !settings.infiniteScrollEnabled,
|
||||
opaqueSystemBars = settings.opaqueSystemBars,
|
||||
imageSourceSupported = galleryHelper.supportsCustomPath,
|
||||
imageSourcePath = settings.imageSourcePath,
|
||||
defaultLanguageId = settings.defaultLanguageId,
|
||||
appIconChangeSupported = appIconManager.supportsMultipleIcons,
|
||||
fadeReadPosts = settings.fadeReadPosts,
|
||||
showUnreadComments = settings.showUnreadComments,
|
||||
supportSettingsImportExport = fileSystemManager.isSupported,
|
||||
enableButtonsToScrollBetweenComments = settings.enableButtonsToScrollBetweenComments,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,64 +153,64 @@ class AdvancedSettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeEnableDoubleTapAction(value: Boolean) {
|
||||
updateState { it.copy(enableDoubleTapAction = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(enableDoubleTapAction = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(enableDoubleTapAction = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeAutoLoadImages(value: Boolean) {
|
||||
updateState { it.copy(autoLoadImages = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(autoLoadImages = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(autoLoadImages = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeAutoExpandComments(value: Boolean) {
|
||||
updateState { it.copy(autoExpandComments = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(autoExpandComments = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(autoExpandComments = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeHideNavigationBarWhileScrolling(value: Boolean) {
|
||||
updateState { it.copy(hideNavigationBarWhileScrolling = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(hideNavigationBarWhileScrolling = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(hideNavigationBarWhileScrolling = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeMarkAsReadWhileScrolling(value: Boolean) {
|
||||
updateState { it.copy(markAsReadWhileScrolling = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(markAsReadWhileScrolling = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(markAsReadWhileScrolling = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeZombieModeInterval(value: Duration) {
|
||||
updateState { it.copy(zombieModeInterval = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(zombieModeInterval = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(zombieModeInterval = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeZombieModeScrollAmount(value: Float) {
|
||||
updateState { it.copy(zombieModeScrollAmount = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(zombieModeScrollAmount = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(zombieModeScrollAmount = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeDefaultInboxUnreadOnly(value: Boolean) {
|
||||
updateState { it.copy(defaultInboxUnreadOnly = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(defaultInboxUnreadOnly = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(defaultInboxType = value.toInboxDefaultType())
|
||||
saveSettings(settings)
|
||||
notificationCenter.send(NotificationCenterEvent.ResetInbox)
|
||||
@ -218,32 +218,32 @@ class AdvancedSettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeSearchPostTitleOnly(value: Boolean) {
|
||||
updateState { it.copy(searchPostTitleOnly = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(searchPostTitleOnly = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(searchPostTitleOnly = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeExploreType(value: ListingType) {
|
||||
updateState { it.copy(defaultExploreType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(defaultExploreType = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(defaultExploreType = value.toInt())
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeEdgeToEdge(value: Boolean) {
|
||||
updateState { it.copy(edgeToEdge = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(edgeToEdge = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(edgeToEdge = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeInfiniteScrollDisabled(value: Boolean) {
|
||||
updateState { it.copy(infiniteScrollDisabled = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(infiniteScrollDisabled = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(infiniteScrollEnabled = !value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
@ -255,16 +255,16 @@ class AdvancedSettingsViewModel(
|
||||
UiBarTheme.Opaque -> true
|
||||
else -> false
|
||||
}
|
||||
updateState { it.copy(opaqueSystemBars = opaque) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(opaqueSystemBars = opaque) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(opaqueSystemBars = opaque)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeImageSourcePath(value: Boolean) {
|
||||
updateState { it.copy(imageSourcePath = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(imageSourcePath = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(imageSourcePath = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
@ -279,40 +279,40 @@ class AdvancedSettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeDefaultLanguageId(value: Long?) {
|
||||
updateState { it.copy(defaultLanguageId = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(defaultLanguageId = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(defaultLanguageId = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeInboxBackgroundCheckPeriod(value: Duration) {
|
||||
updateState { it.copy(inboxBackgroundCheckPeriod = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(inboxBackgroundCheckPeriod = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(inboxBackgroundCheckPeriod = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeFadeReadPosts(value: Boolean) {
|
||||
updateState { it.copy(fadeReadPosts = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(fadeReadPosts = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(fadeReadPosts = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeShowUnreadPosts(value: Boolean) {
|
||||
updateState { it.copy(showUnreadComments = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(showUnreadComments = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(showUnreadComments = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeEnableButtonsToScrollBetweenComments(value: Boolean) {
|
||||
updateState { it.copy(enableButtonsToScrollBetweenComments = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(enableButtonsToScrollBetweenComments = value) }
|
||||
val settings = settingsRepository.currentSettings.value.copy(enableButtonsToScrollBetweenComments = value)
|
||||
saveSettings(settings)
|
||||
}
|
||||
|
@ -96,21 +96,21 @@ class SettingsViewModel(
|
||||
availableSortTypesForComments = availableSortTypesForComments,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val settings = settingsRepository.currentSettings.value
|
||||
updateState {
|
||||
it.copy(
|
||||
defaultListingType = settings.defaultListingType.toListingType(),
|
||||
defaultPostSortType = settings.defaultPostSortType.toSortType(),
|
||||
defaultCommentSortType = settings.defaultCommentSortType.toSortType(),
|
||||
includeNsfw = settings.includeNsfw,
|
||||
blurNsfw = settings.blurNsfw,
|
||||
urlOpeningMode = settings.urlOpeningMode.toUrlOpeningMode(),
|
||||
enableSwipeActions = settings.enableSwipeActions,
|
||||
crashReportEnabled = crashReportConfiguration.isEnabled(),
|
||||
customTabsEnabled = customTabsHelper.isSupported,
|
||||
)
|
||||
val settings = settingsRepository.currentSettings.value
|
||||
updateState {
|
||||
it.copy(
|
||||
defaultListingType = settings.defaultListingType.toListingType(),
|
||||
defaultPostSortType = settings.defaultPostSortType.toSortType(),
|
||||
defaultCommentSortType = settings.defaultCommentSortType.toSortType(),
|
||||
includeNsfw = settings.includeNsfw,
|
||||
blurNsfw = settings.blurNsfw,
|
||||
urlOpeningMode = settings.urlOpeningMode.toUrlOpeningMode(),
|
||||
enableSwipeActions = settings.enableSwipeActions,
|
||||
crashReportEnabled = crashReportConfiguration.isEnabled(),
|
||||
customTabsEnabled = customTabsHelper.isSupported,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,8 +148,8 @@ class SettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeDefaultListingType(value: ListingType) {
|
||||
updateState { it.copy(defaultListingType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(defaultListingType = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
defaultListingType = value.toInt(),
|
||||
@ -160,8 +160,8 @@ class SettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeDefaultPostSortType(value: SortType) {
|
||||
updateState { it.copy(defaultPostSortType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(defaultPostSortType = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
defaultPostSortType = value.toInt(),
|
||||
@ -172,8 +172,8 @@ class SettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeDefaultCommentSortType(value: SortType) {
|
||||
updateState { it.copy(defaultCommentSortType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(defaultCommentSortType = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
defaultCommentSortType = value.toInt(),
|
||||
@ -183,8 +183,8 @@ class SettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeIncludeNsfw(value: Boolean) {
|
||||
updateState { it.copy(includeNsfw = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(includeNsfw = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
includeNsfw = value,
|
||||
@ -196,8 +196,8 @@ class SettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeBlurNsfw(value: Boolean) {
|
||||
updateState { it.copy(blurNsfw = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(blurNsfw = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
blurNsfw = value,
|
||||
@ -207,8 +207,8 @@ class SettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeUrlOpeningMode(value: UrlOpeningMode) {
|
||||
updateState { it.copy(urlOpeningMode = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(urlOpeningMode = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
urlOpeningMode = value.toInt(),
|
||||
@ -218,8 +218,8 @@ class SettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeEnableSwipeActions(value: Boolean) {
|
||||
updateState { it.copy(enableSwipeActions = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(enableSwipeActions = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
enableSwipeActions = value,
|
||||
@ -229,8 +229,10 @@ class SettingsViewModel(
|
||||
}
|
||||
|
||||
private fun changeCrashReportEnabled(value: Boolean) {
|
||||
crashReportConfiguration.setEnabled(value)
|
||||
updateState { it.copy(crashReportEnabled = value) }
|
||||
screenModelScope.launch {
|
||||
crashReportConfiguration.setEnabled(value)
|
||||
updateState { it.copy(crashReportEnabled = value) }
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveSettings(settings: SettingsModel) {
|
||||
|
@ -46,7 +46,9 @@ class MainViewModel(
|
||||
override fun reduce(intent: MainScreenMviModel.Intent) {
|
||||
when (intent) {
|
||||
is MainScreenMviModel.Intent.SetBottomBarOffsetHeightPx -> {
|
||||
updateState { it.copy(bottomBarOffsetHeightPx = intent.value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(bottomBarOffsetHeightPx = intent.value) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,21 @@
|
||||
package com.github.diegoberaldin.raccoonforlemmy.unit.about
|
||||
|
||||
import cafe.adriel.voyager.core.model.screenModelScope
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.debug.AppInfo
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class AboutDialogViewModel : AboutDialogMviModel,
|
||||
DefaultMviModel<AboutDialogMviModel.Intent, AboutDialogMviModel.UiState, AboutDialogMviModel.Effect>(
|
||||
initialState = AboutDialogMviModel.UiState(),
|
||||
) {
|
||||
init {
|
||||
updateState {
|
||||
it.copy(
|
||||
version = AppInfo.versionCode,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
version = AppInfo.versionCode,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,92 +55,112 @@ class AccountSettingsViewModel(
|
||||
override fun reduce(intent: AccountSettingsMviModel.Intent) {
|
||||
when (intent) {
|
||||
is AccountSettingsMviModel.Intent.ChangeDisplayName -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
displayName = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
displayName = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AccountSettingsMviModel.Intent.ChangeEmail -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
email = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
email = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AccountSettingsMviModel.Intent.ChangeMatrixUserId -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
matrixUserId = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
matrixUserId = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AccountSettingsMviModel.Intent.ChangeBio -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
bio = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
bio = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AccountSettingsMviModel.Intent.ChangeBot -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
bot = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
bot = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AccountSettingsMviModel.Intent.ChangeSendNotificationsToEmail -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
sendNotificationsToEmail = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
sendNotificationsToEmail = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AccountSettingsMviModel.Intent.ChangeShowBotAccounts -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
showBotAccounts = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
showBotAccounts = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AccountSettingsMviModel.Intent.ChangeShowNsfw -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
showNsfw = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
showNsfw = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AccountSettingsMviModel.Intent.ChangeShowScores -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
showScores = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
showScores = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is AccountSettingsMviModel.Intent.ChangeShowReadPosts -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
showReadPosts = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
showReadPosts = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,8 +260,8 @@ class AccountSettingsViewModel(
|
||||
showScores = currentState.showScores,
|
||||
showReadPosts = currentState.showReadPosts,
|
||||
) ?: return
|
||||
updateState { it.copy(loading = true) }
|
||||
screenModelScope.launch(Dispatchers.IO) {
|
||||
updateState { it.copy(loading = true) }
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
siteRepository.updateAccountSettings(
|
||||
|
@ -22,8 +22,10 @@ class BanUserViewModel(
|
||||
initialState = BanUserMviModel.UiState(),
|
||||
) {
|
||||
init {
|
||||
updateState {
|
||||
it.copy(targetBanValue = newValue)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(targetBanValue = newValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,21 +33,36 @@ class BanUserViewModel(
|
||||
when (intent) {
|
||||
BanUserMviModel.Intent.IncrementDays -> incrementDays()
|
||||
BanUserMviModel.Intent.DecrementDays -> decrementDays()
|
||||
is BanUserMviModel.Intent.ChangePermanent -> updateState { it.copy(permanent = intent.value) }
|
||||
is BanUserMviModel.Intent.ChangeRemoveData -> updateState { it.copy(removeData = intent.value) }
|
||||
is BanUserMviModel.Intent.SetText -> updateState { it.copy(text = intent.value) }
|
||||
is BanUserMviModel.Intent.ChangePermanent ->
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(permanent = intent.value) }
|
||||
}
|
||||
|
||||
is BanUserMviModel.Intent.ChangeRemoveData ->
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(removeData = intent.value) }
|
||||
}
|
||||
|
||||
is BanUserMviModel.Intent.SetText ->
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(text = intent.value) }
|
||||
}
|
||||
BanUserMviModel.Intent.Submit -> submit()
|
||||
}
|
||||
}
|
||||
|
||||
private fun incrementDays() {
|
||||
val newValue = uiState.value.days + 1
|
||||
updateState { it.copy(days = newValue) }
|
||||
screenModelScope.launch {
|
||||
val newValue = uiState.value.days + 1
|
||||
updateState { it.copy(days = newValue) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun decrementDays() {
|
||||
val newValue = (uiState.value.days - 1).coerceAtLeast(1)
|
||||
updateState { it.copy(days = newValue) }
|
||||
screenModelScope.launch {
|
||||
val newValue = (uiState.value.days - 1).coerceAtLeast(1)
|
||||
updateState { it.copy(days = newValue) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun submit() {
|
||||
@ -57,8 +74,8 @@ class BanUserViewModel(
|
||||
val removeData = currentState.removeData.takeIf { newValue } ?: false
|
||||
val days = currentState.days.toLong().takeIf { newValue }
|
||||
|
||||
updateState { it.copy(loading = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(loading = true) }
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
val newUser =
|
||||
|
@ -181,17 +181,19 @@ class InboxChatViewModel(
|
||||
}
|
||||
|
||||
private fun handleMessageUpdate(newMessage: PrivateMessageModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
messages =
|
||||
it.messages.map { msg ->
|
||||
if (msg.id == newMessage.id) {
|
||||
newMessage
|
||||
} else {
|
||||
msg
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
messages =
|
||||
it.messages.map { msg ->
|
||||
if (msg.id == newMessage.id) {
|
||||
newMessage
|
||||
} else {
|
||||
msg
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,10 +217,12 @@ class InboxChatViewModel(
|
||||
}
|
||||
|
||||
private fun startEditingMessage(message: PrivateMessageModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
editedMessageId = message.id,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
editedMessageId = message.id,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,7 +272,9 @@ class InboxChatViewModel(
|
||||
}
|
||||
|
||||
private fun handleLogout() {
|
||||
updateState { it.copy(messages = emptyList()) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(messages = emptyList()) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteMessage(message: PrivateMessageModel) {
|
||||
|
@ -114,7 +114,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.SortBottomS
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.getScreenModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.di.getNotificationCenter
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.ActionOnSwipe
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsRepository
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||
@ -176,7 +175,6 @@ class CommunityDetailScreen(
|
||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(topAppBarState)
|
||||
val fabNestedScrollConnection = remember { getFabNestedScrollConnection() }
|
||||
val isFabVisible by fabNestedScrollConnection.isFabVisible.collectAsState()
|
||||
val notificationCenter = remember { getNotificationCenter() }
|
||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||
val themeRepository = remember { getThemeRepository() }
|
||||
val upVoteColor by themeRepository.upVoteColor.collectAsState()
|
||||
@ -212,9 +210,6 @@ class CommunityDetailScreen(
|
||||
WindowInsets.statusBars.getTop(this)
|
||||
}
|
||||
|
||||
LaunchedEffect(notificationCenter) {
|
||||
notificationCenter.resetCache()
|
||||
}
|
||||
LaunchedEffect(model) {
|
||||
model.effects.onEach { effect ->
|
||||
when (effect) {
|
||||
|
@ -265,16 +265,20 @@ class CommunityDetailViewModel(
|
||||
}
|
||||
|
||||
CommunityDetailMviModel.Intent.PauseZombieMode -> {
|
||||
updateState { it.copy(zombieModeActive = false) }
|
||||
zombieModeHelper.pause()
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(zombieModeActive = false) }
|
||||
zombieModeHelper.pause()
|
||||
}
|
||||
}
|
||||
|
||||
is CommunityDetailMviModel.Intent.StartZombieMode -> {
|
||||
updateState { it.copy(zombieModeActive = true) }
|
||||
zombieModeHelper.start(
|
||||
initialValue = intent.index,
|
||||
interval = settingsRepository.currentSettings.value.zombieModeInterval,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(zombieModeActive = true) }
|
||||
zombieModeHelper.start(
|
||||
initialValue = intent.index,
|
||||
interval = settingsRepository.currentSettings.value.zombieModeInterval,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is CommunityDetailMviModel.Intent.ModFeaturePost ->
|
||||
@ -298,9 +302,11 @@ class CommunityDetailViewModel(
|
||||
}
|
||||
|
||||
is CommunityDetailMviModel.Intent.ChangeSearching -> {
|
||||
updateState { it.copy(searching = intent.value) }
|
||||
if (!intent.value) {
|
||||
updateSearchText("")
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(searching = intent.value) }
|
||||
if (!intent.value) {
|
||||
updateSearchText("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,8 +381,8 @@ class CommunityDetailViewModel(
|
||||
if (uiState.value.sortType == value) {
|
||||
return
|
||||
}
|
||||
updateState { it.copy(sortType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(sortType = value) }
|
||||
emitEffect(CommunityDetailMviModel.Effect.BackToTop)
|
||||
delay(50)
|
||||
refresh()
|
||||
@ -562,27 +568,31 @@ class CommunityDetailViewModel(
|
||||
}
|
||||
|
||||
private fun handlePostUpdate(post: PostModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlePostDelete(id: Long) {
|
||||
updateState { it.copy(posts = it.posts.filter { post -> post.id != id }) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(posts = it.posts.filter { post -> post.id != id }) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun blockCommunity() {
|
||||
updateState { it.copy(asyncInProgress = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(asyncInProgress = true) }
|
||||
try {
|
||||
val auth = identityRepository.authToken.value
|
||||
communityRepository.block(communityId, true, auth).getOrThrow()
|
||||
@ -596,8 +606,8 @@ class CommunityDetailViewModel(
|
||||
}
|
||||
|
||||
private fun blockInstance() {
|
||||
updateState { it.copy(asyncInProgress = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(asyncInProgress = true) }
|
||||
try {
|
||||
val community = uiState.value.community
|
||||
val instanceId = community.instanceId
|
||||
@ -613,23 +623,27 @@ class CommunityDetailViewModel(
|
||||
}
|
||||
|
||||
private fun clearRead() {
|
||||
hideReadPosts = true
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> !e.read }
|
||||
it.copy(
|
||||
posts = newPosts,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
hideReadPosts = true
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> !e.read }
|
||||
it.copy(
|
||||
posts = newPosts,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hide(post: PostModel) {
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> e.id != post.id }
|
||||
it.copy(
|
||||
posts = newPosts,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> e.id != post.id }
|
||||
it.copy(
|
||||
posts = newPosts,
|
||||
)
|
||||
}
|
||||
markAsRead(post)
|
||||
}
|
||||
markAsRead(post)
|
||||
}
|
||||
|
||||
private fun feature(post: PostModel) {
|
||||
@ -698,8 +712,8 @@ class CommunityDetailViewModel(
|
||||
}
|
||||
|
||||
private fun updateSearchText(value: String) {
|
||||
updateState { it.copy(searchText = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(searchText = value) }
|
||||
searchEventChannel.send(Unit)
|
||||
}
|
||||
}
|
||||
|
@ -137,8 +137,8 @@ class ConfigureContentViewViewModel(
|
||||
}
|
||||
|
||||
private fun changeVoteFormat(value: VoteFormat) {
|
||||
updateState { it.copy(voteFormat = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(voteFormat = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.let {
|
||||
if (value == VoteFormat.Hidden) {
|
||||
@ -155,8 +155,8 @@ class ConfigureContentViewViewModel(
|
||||
}
|
||||
|
||||
private fun changeFullHeightImages(value: Boolean) {
|
||||
updateState { it.copy(fullHeightImages = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(fullHeightImages = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
fullHeightImages = value,
|
||||
@ -166,8 +166,8 @@ class ConfigureContentViewViewModel(
|
||||
}
|
||||
|
||||
private fun changeFullWidthImages(value: Boolean) {
|
||||
updateState { it.copy(fullWidthImages = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(fullWidthImages = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
fullWidthImages = value,
|
||||
@ -177,8 +177,8 @@ class ConfigureContentViewViewModel(
|
||||
}
|
||||
|
||||
private fun changePreferUserNicknames(value: Boolean) {
|
||||
updateState { it.copy(preferUserNicknames = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(preferUserNicknames = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
preferUserNicknames = value,
|
||||
@ -188,8 +188,8 @@ class ConfigureContentViewViewModel(
|
||||
}
|
||||
|
||||
private fun changePostBodyMaxLines(value: Int?) {
|
||||
updateState { it.copy(postBodyMaxLines = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(postBodyMaxLines = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
postBodyMaxLines = value,
|
||||
@ -232,8 +232,8 @@ class ConfigureContentViewViewModel(
|
||||
}
|
||||
|
||||
private fun changeCommentBarThickness(value: Int) {
|
||||
updateState { it.copy(commentBarThickness = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(commentBarThickness = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
commentBarThickness = value,
|
||||
@ -243,8 +243,8 @@ class ConfigureContentViewViewModel(
|
||||
}
|
||||
|
||||
private fun changeCommentIndentAmount(value: Int) {
|
||||
updateState { it.copy(commentIndentAmount = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(commentIndentAmount = value) }
|
||||
val settings =
|
||||
settingsRepository.currentSettings.value.copy(
|
||||
commentIndentAmount = value,
|
||||
|
@ -51,8 +51,9 @@ class ConfigureSwipeActionsViewModel(
|
||||
)
|
||||
}
|
||||
}.launchIn(this)
|
||||
|
||||
refresh()
|
||||
}
|
||||
refresh()
|
||||
}
|
||||
|
||||
override fun reduce(intent: ConfigureSwipeActionsMviModel.Intent) {
|
||||
@ -81,7 +82,7 @@ class ConfigureSwipeActionsViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
private fun refresh() {
|
||||
private suspend fun refresh() {
|
||||
val settings = settingsRepository.currentSettings.value
|
||||
updateState {
|
||||
it.copy(
|
||||
@ -515,12 +516,14 @@ class ConfigureSwipeActionsViewModel(
|
||||
this -= currentState.actionsOnSwipeToEndInbox.toSet()
|
||||
}
|
||||
}
|
||||
updateState {
|
||||
it.copy(
|
||||
availableOptionsPosts = actionsPosts.toList(),
|
||||
availableOptionsComments = actionsComments.toList(),
|
||||
availableOptionsInbox = actionsInbox.toList(),
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
availableOptionsPosts = actionsPosts.toList(),
|
||||
availableOptionsComments = actionsComments.toList(),
|
||||
availableOptionsInbox = actionsInbox.toList(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,9 @@ class CreateCommentViewModel(
|
||||
override fun reduce(intent: CreateCommentMviModel.Intent) {
|
||||
when (intent) {
|
||||
is CreateCommentMviModel.Intent.ChangeSection -> {
|
||||
updateState { it.copy(section = intent.value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(section = intent.value) }
|
||||
}
|
||||
}
|
||||
|
||||
is CreateCommentMviModel.Intent.ImageSelected -> {
|
||||
@ -115,11 +117,15 @@ class CreateCommentViewModel(
|
||||
}
|
||||
|
||||
is CreateCommentMviModel.Intent.ChangeLanguage -> {
|
||||
updateState { it.copy(currentLanguageId = intent.value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(currentLanguageId = intent.value) }
|
||||
}
|
||||
}
|
||||
|
||||
is CreateCommentMviModel.Intent.ChangeTextValue -> {
|
||||
updateState { it.copy(textValue = intent.value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(textValue = intent.value) }
|
||||
}
|
||||
}
|
||||
|
||||
is CreateCommentMviModel.Intent.Send -> submit()
|
||||
@ -133,20 +139,24 @@ class CreateCommentViewModel(
|
||||
return
|
||||
}
|
||||
|
||||
updateState {
|
||||
it.copy(
|
||||
textError = null,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
textError = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
val text = currentState.textValue.text.trim()
|
||||
val languageId = currentState.currentLanguageId
|
||||
|
||||
var valid = true
|
||||
if (text.isEmpty()) {
|
||||
updateState {
|
||||
it.copy(
|
||||
textError = ValidationError.MissingField,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
textError = ValidationError.MissingField,
|
||||
)
|
||||
}
|
||||
}
|
||||
valid = false
|
||||
}
|
||||
@ -154,8 +164,8 @@ class CreateCommentViewModel(
|
||||
return
|
||||
}
|
||||
|
||||
updateState { it.copy(loading = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(loading = true) }
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
if (postId != null) {
|
||||
|
@ -97,20 +97,26 @@ class CreatePostViewModel(
|
||||
}
|
||||
|
||||
is CreatePostMviModel.Intent.SetTitle -> {
|
||||
updateState {
|
||||
it.copy(title = intent.value)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(title = intent.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is CreatePostMviModel.Intent.ChangeNsfw -> {
|
||||
updateState {
|
||||
it.copy(nsfw = intent.value)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(nsfw = intent.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is CreatePostMviModel.Intent.SetUrl -> {
|
||||
updateState {
|
||||
it.copy(url = intent.value)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(url = intent.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,18 +129,23 @@ class CreatePostViewModel(
|
||||
}
|
||||
|
||||
is CreatePostMviModel.Intent.ChangeSection ->
|
||||
updateState {
|
||||
it.copy(section = intent.value)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(section = intent.value)
|
||||
}
|
||||
}
|
||||
|
||||
is CreatePostMviModel.Intent.ChangeLanguage ->
|
||||
updateState {
|
||||
it.copy(currentLanguageId = intent.value)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(currentLanguageId = intent.value)
|
||||
}
|
||||
}
|
||||
|
||||
is CreatePostMviModel.Intent.ChangeBodyValue ->
|
||||
updateState {
|
||||
it.copy(bodyValue = intent.value)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(bodyValue = intent.value)
|
||||
}
|
||||
}
|
||||
|
||||
CreatePostMviModel.Intent.Send -> submit()
|
||||
@ -214,12 +225,14 @@ class CreatePostViewModel(
|
||||
return
|
||||
}
|
||||
|
||||
updateState {
|
||||
it.copy(
|
||||
titleError = null,
|
||||
urlError = null,
|
||||
bodyError = null,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
titleError = null,
|
||||
urlError = null,
|
||||
bodyError = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val communityId = currentState.communityId
|
||||
@ -230,20 +243,26 @@ class CreatePostViewModel(
|
||||
val languageId = currentState.currentLanguageId
|
||||
var valid = true
|
||||
if (title.isEmpty()) {
|
||||
updateState {
|
||||
it.copy(titleError = ValidationError.MissingField)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(titleError = ValidationError.MissingField)
|
||||
}
|
||||
}
|
||||
valid = false
|
||||
}
|
||||
if (!url.isNullOrEmpty() && !url.isValidUrl()) {
|
||||
updateState {
|
||||
it.copy(urlError = ValidationError.InvalidField)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(urlError = ValidationError.InvalidField)
|
||||
}
|
||||
}
|
||||
valid = false
|
||||
}
|
||||
if (communityId == null) {
|
||||
updateState {
|
||||
it.copy(communityError = ValidationError.MissingField)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(communityError = ValidationError.MissingField)
|
||||
}
|
||||
}
|
||||
valid = false
|
||||
}
|
||||
@ -252,8 +271,8 @@ class CreatePostViewModel(
|
||||
return
|
||||
}
|
||||
|
||||
updateState { it.copy(loading = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(loading = true) }
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
when {
|
||||
|
@ -44,8 +44,10 @@ class DraftsViewModel(
|
||||
override fun reduce(intent: DraftsMviModel.Intent) {
|
||||
when (intent) {
|
||||
is DraftsMviModel.Intent.ChangeSection ->
|
||||
updateState {
|
||||
it.copy(section = intent.section)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(section = intent.section)
|
||||
}
|
||||
}
|
||||
|
||||
is DraftsMviModel.Intent.Delete -> deleteDraft(intent.model)
|
||||
@ -54,14 +56,14 @@ class DraftsViewModel(
|
||||
}
|
||||
|
||||
private fun refresh(initial: Boolean = false) {
|
||||
updateState {
|
||||
it.copy(
|
||||
refreshing = !initial,
|
||||
initial = initial,
|
||||
loading = false,
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
refreshing = !initial,
|
||||
initial = initial,
|
||||
loading = false,
|
||||
)
|
||||
}
|
||||
val currentState = uiState.value
|
||||
updateState { it.copy(loading = true) }
|
||||
val refreshing = currentState.refreshing
|
||||
|
@ -123,8 +123,8 @@ class ModalDrawerViewModel(
|
||||
}
|
||||
|
||||
is ModalDrawerMviModel.Intent.SetSearch -> {
|
||||
updateState { it.copy(searchText = intent.value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(searchText = intent.value) }
|
||||
searchEventChannel.send(Unit)
|
||||
}
|
||||
}
|
||||
|
@ -32,38 +32,46 @@ class EditCommunityViewModel(
|
||||
is EditCommunityMviModel.Intent.BannerSelected -> loadImageBanner(intent.value)
|
||||
|
||||
is EditCommunityMviModel.Intent.ChangeDescription -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
description = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
description = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is EditCommunityMviModel.Intent.ChangeTitle -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
title = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
title = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is EditCommunityMviModel.Intent.ChangeNsfw -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
nsfw = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
nsfw = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is EditCommunityMviModel.Intent.ChangePostingRestrictedToMods -> {
|
||||
updateState {
|
||||
it.copy(
|
||||
postingRestrictedToMods = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
postingRestrictedToMods = intent.value,
|
||||
hasUnsavedChanges = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,8 +146,8 @@ class EditCommunityViewModel(
|
||||
private fun submit() {
|
||||
val community = originalCommunity?.copy() ?: return
|
||||
val currentState = uiState.value
|
||||
updateState { it.copy(loading = true) }
|
||||
screenModelScope.launch(Dispatchers.IO) {
|
||||
updateState { it.copy(loading = true) }
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
val newValue =
|
||||
|
@ -65,12 +65,12 @@ class ExploreViewModel(
|
||||
}
|
||||
|
||||
init {
|
||||
updateState {
|
||||
it.copy(
|
||||
instance = apiConfigRepository.instance.value,
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
instance = apiConfigRepository.instance.value,
|
||||
)
|
||||
}
|
||||
identityRepository.isLogged.onEach { isLogged ->
|
||||
updateState {
|
||||
it.copy(isLogged = isLogged ?: false)
|
||||
@ -143,16 +143,16 @@ class ExploreViewModel(
|
||||
}
|
||||
|
||||
private fun onFirstLoad() {
|
||||
val settings = settingsRepository.currentSettings.value
|
||||
val listingType = if (isOnOtherInstance) ListingType.Local else settings.defaultExploreType.toListingType()
|
||||
val sortType = settings.defaultPostSortType.toSortType()
|
||||
updateState {
|
||||
it.copy(
|
||||
listingType = listingType,
|
||||
sortType = sortType,
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
val settings = settingsRepository.currentSettings.value
|
||||
val listingType = if (isOnOtherInstance) ListingType.Local else settings.defaultExploreType.toListingType()
|
||||
val sortType = settings.defaultPostSortType.toSortType()
|
||||
updateState {
|
||||
it.copy(
|
||||
listingType = listingType,
|
||||
sortType = sortType,
|
||||
)
|
||||
}
|
||||
val auth = identityRepository.authToken.value
|
||||
val downVoteEnabled = siteRepository.isDownVoteEnabled(auth)
|
||||
updateState { it.copy(downVoteEnabled = downVoteEnabled) }
|
||||
@ -265,31 +265,31 @@ class ExploreViewModel(
|
||||
}
|
||||
|
||||
private fun setSearch(value: String) {
|
||||
updateState { it.copy(searchText = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(searchText = value) }
|
||||
searchEventChannel.send(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeListingType(value: ListingType) {
|
||||
updateState { it.copy(listingType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(listingType = value) }
|
||||
emitEffect(ExploreMviModel.Effect.BackToTop)
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeSortType(value: SortType) {
|
||||
updateState { it.copy(sortType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(sortType = value) }
|
||||
emitEffect(ExploreMviModel.Effect.BackToTop)
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeResultType(value: SearchResultType) {
|
||||
updateState { it.copy(resultType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(resultType = value) }
|
||||
emitEffect(ExploreMviModel.Effect.BackToTop)
|
||||
refresh()
|
||||
}
|
||||
@ -434,67 +434,73 @@ class ExploreViewModel(
|
||||
}
|
||||
|
||||
private fun handleLogout() {
|
||||
currentPage = 1
|
||||
updateState {
|
||||
it.copy(
|
||||
listingType = ListingType.Local,
|
||||
results = emptyList(),
|
||||
)
|
||||
screenModelScope.launch {
|
||||
currentPage = 1
|
||||
updateState {
|
||||
it.copy(
|
||||
listingType = ListingType.Local,
|
||||
results = emptyList(),
|
||||
)
|
||||
}
|
||||
onFirstLoad()
|
||||
}
|
||||
onFirstLoad()
|
||||
}
|
||||
|
||||
private fun handlePostUpdate(post: PostModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { r ->
|
||||
if (r is SearchResult.Post && r.model.id == post.id) {
|
||||
r.copy(model = post)
|
||||
} else {
|
||||
r
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { r ->
|
||||
if (r is SearchResult.Post && r.model.id == post.id) {
|
||||
r.copy(model = post)
|
||||
} else {
|
||||
r
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCommentUpdate(comment: CommentModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { r ->
|
||||
if (r is SearchResult.Comment && r.model.id == comment.id) {
|
||||
r.copy(model = comment)
|
||||
} else {
|
||||
r
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { r ->
|
||||
if (r is SearchResult.Comment && r.model.id == comment.id) {
|
||||
r.copy(model = comment)
|
||||
} else {
|
||||
r
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleUpVote(post: PostModel) {
|
||||
val newVote = post.myVote <= 0
|
||||
val newPost =
|
||||
postRepository.asUpVoted(
|
||||
post = post,
|
||||
voted = newVote,
|
||||
)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Post) return@map res
|
||||
if (res.model.id == post.id) {
|
||||
res.copy(model = newPost)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
val newVote = post.myVote <= 0
|
||||
val newPost =
|
||||
postRepository.asUpVoted(
|
||||
post = post,
|
||||
voted = newVote,
|
||||
)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Post) return@map res
|
||||
if (res.model.id == post.id) {
|
||||
res.copy(model = newPost)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
postRepository.upVote(
|
||||
@ -522,26 +528,26 @@ class ExploreViewModel(
|
||||
}
|
||||
|
||||
private fun toggleDownVote(post: PostModel) {
|
||||
val newValue = post.myVote >= 0
|
||||
val newPost =
|
||||
postRepository.asDownVoted(
|
||||
post = post,
|
||||
downVoted = newValue,
|
||||
)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Post) return@map res
|
||||
if (res.model.id == post.id) {
|
||||
res.copy(model = newPost)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
val newValue = post.myVote >= 0
|
||||
val newPost =
|
||||
postRepository.asDownVoted(
|
||||
post = post,
|
||||
downVoted = newValue,
|
||||
)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Post) return@map res
|
||||
if (res.model.id == post.id) {
|
||||
res.copy(model = newPost)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
postRepository.downVote(
|
||||
@ -569,26 +575,26 @@ class ExploreViewModel(
|
||||
}
|
||||
|
||||
private fun toggleSave(post: PostModel) {
|
||||
val newValue = !post.saved
|
||||
val newPost =
|
||||
postRepository.asSaved(
|
||||
post = post,
|
||||
saved = newValue,
|
||||
)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Post) return@map res
|
||||
if (res.model.id == post.id) {
|
||||
res.copy(model = newPost)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
val newValue = !post.saved
|
||||
val newPost =
|
||||
postRepository.asSaved(
|
||||
post = post,
|
||||
saved = newValue,
|
||||
)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Post) return@map res
|
||||
if (res.model.id == post.id) {
|
||||
res.copy(model = newPost)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
postRepository.save(
|
||||
@ -616,26 +622,26 @@ class ExploreViewModel(
|
||||
}
|
||||
|
||||
private fun toggleUpVoteComment(comment: CommentModel) {
|
||||
val newValue = comment.myVote <= 0
|
||||
val newComment =
|
||||
commentRepository.asUpVoted(
|
||||
comment = comment,
|
||||
voted = newValue,
|
||||
)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Comment) return@map res
|
||||
if (res.model.id == comment.id) {
|
||||
res.copy(model = newComment)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
val newValue = comment.myVote <= 0
|
||||
val newComment =
|
||||
commentRepository.asUpVoted(
|
||||
comment = comment,
|
||||
voted = newValue,
|
||||
)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Comment) return@map res
|
||||
if (res.model.id == comment.id) {
|
||||
res.copy(model = newComment)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
commentRepository.upVote(
|
||||
@ -663,22 +669,22 @@ class ExploreViewModel(
|
||||
}
|
||||
|
||||
private fun toggleDownVoteComment(comment: CommentModel) {
|
||||
val newValue = comment.myVote >= 0
|
||||
val newComment = commentRepository.asDownVoted(comment, newValue)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Comment) return@map res
|
||||
if (res.model.id == comment.id) {
|
||||
res.copy(model = newComment)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
val newValue = comment.myVote >= 0
|
||||
val newComment = commentRepository.asDownVoted(comment, newValue)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Comment) return@map res
|
||||
if (res.model.id == comment.id) {
|
||||
res.copy(model = newComment)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
commentRepository.downVote(
|
||||
@ -706,26 +712,26 @@ class ExploreViewModel(
|
||||
}
|
||||
|
||||
private fun toggleSaveComment(comment: CommentModel) {
|
||||
val newValue = !comment.saved
|
||||
val newComment =
|
||||
commentRepository.asSaved(
|
||||
comment = comment,
|
||||
saved = newValue,
|
||||
)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Comment) return@map res
|
||||
if (res.model.id == comment.id) {
|
||||
res.copy(model = newComment)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
val newValue = !comment.saved
|
||||
val newComment =
|
||||
commentRepository.asSaved(
|
||||
comment = comment,
|
||||
saved = newValue,
|
||||
)
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Comment) return@map res
|
||||
if (res.model.id == comment.id) {
|
||||
res.copy(model = newComment)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
commentRepository.save(
|
||||
@ -787,18 +793,20 @@ class ExploreViewModel(
|
||||
}
|
||||
|
||||
private fun handleCommunityUpdate(community: CommunityModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Community) return@map res
|
||||
if (res.model.id == community.id) {
|
||||
res.copy(model = community)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
results =
|
||||
it.results.map { res ->
|
||||
if (res !is SearchResult.Community) return@map res
|
||||
if (res.model.id == community.id) {
|
||||
res.copy(model = community)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,10 +47,10 @@ class FilteredContentsViewModel(
|
||||
initialState = FilteredContentsMviModel.State(),
|
||||
) {
|
||||
init {
|
||||
updateState {
|
||||
it.copy(contentsType = contentsType.toFilteredContentsType())
|
||||
}
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(contentsType = contentsType.toFilteredContentsType())
|
||||
}
|
||||
updateState {
|
||||
it.copy(isAdmin = identityRepository.cachedUser?.admin == true)
|
||||
}
|
||||
@ -238,10 +238,10 @@ class FilteredContentsViewModel(
|
||||
}
|
||||
|
||||
private fun changeSection(section: FilteredContentsSection) {
|
||||
updateState {
|
||||
it.copy(
|
||||
section = section,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(section = section)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,17 +408,19 @@ class FilteredContentsViewModel(
|
||||
}
|
||||
|
||||
private fun handlePostUpdate(post: PostModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,23 +505,25 @@ class FilteredContentsViewModel(
|
||||
}
|
||||
|
||||
private fun handleCommentUpdate(comment: CommentModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
comments =
|
||||
it.comments.map { c ->
|
||||
if (c.id == comment.id) {
|
||||
comment
|
||||
} else {
|
||||
c
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
comments =
|
||||
it.comments.map { c ->
|
||||
if (c.id == comment.id) {
|
||||
comment
|
||||
} else {
|
||||
c
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeLiked(value: Boolean) {
|
||||
updateState { it.copy(liked = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(liked = value) }
|
||||
refresh(initial = true)
|
||||
emitEffect(FilteredContentsMviModel.Effect.BackToTop)
|
||||
}
|
||||
|
@ -55,21 +55,23 @@ class InstanceInfoViewModel(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uiState.value.initial) {
|
||||
refresh(initial = true)
|
||||
if (uiState.value.initial) {
|
||||
refresh(initial = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun reduce(intent: InstanceInfoMviModel.Intent) {
|
||||
when (intent) {
|
||||
InstanceInfoMviModel.Intent.LoadNextPage -> loadNextPage()
|
||||
InstanceInfoMviModel.Intent.Refresh -> refresh()
|
||||
InstanceInfoMviModel.Intent.Refresh ->
|
||||
screenModelScope.launch {
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun refresh(initial: Boolean = false) {
|
||||
private suspend fun refresh(initial: Boolean = false) {
|
||||
currentPage = 1
|
||||
updateState {
|
||||
it.copy(
|
||||
@ -85,7 +87,9 @@ class InstanceInfoViewModel(
|
||||
private fun loadNextPage() {
|
||||
val currentState = uiState.value
|
||||
if (!currentState.canFetchMore || currentState.loading) {
|
||||
updateState { it.copy(refreshing = false) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(refreshing = false) }
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -133,8 +137,8 @@ class InstanceInfoViewModel(
|
||||
}
|
||||
|
||||
private fun changeSortType(value: SortType) {
|
||||
updateState { it.copy(sortType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(sortType = value) }
|
||||
emitEffect(InstanceInfoMviModel.Effect.BackToTop)
|
||||
refresh()
|
||||
}
|
||||
|
@ -1,18 +1,22 @@
|
||||
package com.github.diegoberaldin.raccoonforlemmy.unit.licences
|
||||
|
||||
import cafe.adriel.voyager.core.model.screenModelScope
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.licences.models.LicenceItem
|
||||
import com.github.diegoberaldin.raccoonforlemmy.unit.licences.models.LicenceItemType
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class LicencesViewModel : LicencesMviModel,
|
||||
DefaultMviModel<LicencesMviModel.Intent, LicencesMviModel.State, LicencesMviModel.Effect>(
|
||||
initialState = LicencesMviModel.State(),
|
||||
) {
|
||||
init {
|
||||
populate()
|
||||
screenModelScope.launch {
|
||||
populate()
|
||||
}
|
||||
}
|
||||
|
||||
private fun populate() {
|
||||
private suspend fun populate() {
|
||||
updateState {
|
||||
it.copy(
|
||||
items =
|
||||
|
@ -29,8 +29,10 @@ class LoginViewModel(
|
||||
) {
|
||||
init {
|
||||
val instance = apiConfigurationRepository.instance.value
|
||||
updateState {
|
||||
it.copy(instanceName = instance)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(instanceName = instance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,19 +47,27 @@ class LoginViewModel(
|
||||
}
|
||||
|
||||
private fun setInstanceName(value: String) {
|
||||
updateState { it.copy(instanceName = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(instanceName = value) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUsername(value: String) {
|
||||
updateState { it.copy(username = value.trim()) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(username = value.trim()) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun setPassword(value: String) {
|
||||
updateState { it.copy(password = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(password = value) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun setTotp2faToken(value: String) {
|
||||
updateState { it.copy(totp2faToken = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(totp2faToken = value) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun submit() {
|
||||
@ -70,33 +80,41 @@ class LoginViewModel(
|
||||
val username = currentState.username
|
||||
val password = currentState.password
|
||||
val totp2faToken = currentState.totp2faToken
|
||||
updateState {
|
||||
it.copy(
|
||||
instanceNameError = null,
|
||||
usernameError = null,
|
||||
passwordError = null,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
instanceNameError = null,
|
||||
usernameError = null,
|
||||
passwordError = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val valid =
|
||||
when {
|
||||
instance.isEmpty() -> {
|
||||
updateState {
|
||||
it.copy(instanceNameError = ValidationError.MissingField)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(instanceNameError = ValidationError.MissingField)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
username.isEmpty() -> {
|
||||
updateState {
|
||||
it.copy(usernameError = ValidationError.MissingField)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(usernameError = ValidationError.MissingField)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
password.isEmpty() -> {
|
||||
updateState {
|
||||
it.copy(passwordError = ValidationError.MissingField)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(passwordError = ValidationError.MissingField)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ class ManageBanViewModel(
|
||||
override fun reduce(intent: ManageBanMviModel.Intent) {
|
||||
when (intent) {
|
||||
is ManageBanMviModel.Intent.ChangeSection -> {
|
||||
updateState { it.copy(section = intent.section) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(section = intent.section) }
|
||||
}
|
||||
}
|
||||
|
||||
ManageBanMviModel.Intent.Refresh -> {
|
||||
|
@ -99,8 +99,8 @@ class ManageSubscriptionsViewModel(
|
||||
if (uiState.value.refreshing) {
|
||||
return
|
||||
}
|
||||
updateState { it.copy(refreshing = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(refreshing = true) }
|
||||
val auth = identityRepository.authToken.value
|
||||
val accountId = accountRepository.getActive()?.id ?: 0L
|
||||
val favoriteCommunityIds =
|
||||
@ -169,20 +169,22 @@ class ManageSubscriptionsViewModel(
|
||||
}
|
||||
|
||||
private fun handleMultiCommunityCreated(community: MultiCommunityModel) {
|
||||
val oldCommunities = uiState.value.multiCommunities
|
||||
val newCommunities =
|
||||
if (oldCommunities.any { it.id == community.id }) {
|
||||
oldCommunities.map {
|
||||
if (it.id == community.id) {
|
||||
community
|
||||
} else {
|
||||
it
|
||||
screenModelScope.launch {
|
||||
val oldCommunities = uiState.value.multiCommunities
|
||||
val newCommunities =
|
||||
if (oldCommunities.any { it.id == community.id }) {
|
||||
oldCommunities.map {
|
||||
if (it.id == community.id) {
|
||||
community
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
oldCommunities + community
|
||||
}.sortedBy { it.name }
|
||||
updateState { it.copy(multiCommunities = newCommunities) }
|
||||
} else {
|
||||
oldCommunities + community
|
||||
}.sortedBy { it.name }
|
||||
updateState { it.copy(multiCommunities = newCommunities) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleFavorite(community: CommunityModel) {
|
||||
@ -205,23 +207,25 @@ class ManageSubscriptionsViewModel(
|
||||
}
|
||||
|
||||
private fun handleCommunityUpdate(community: CommunityModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
communities =
|
||||
it.communities.map { c ->
|
||||
if (c.id == community.id) {
|
||||
community
|
||||
} else {
|
||||
c
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
communities =
|
||||
it.communities.map { c ->
|
||||
if (c.id == community.id) {
|
||||
community
|
||||
} else {
|
||||
c
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSearchText(value: String) {
|
||||
updateState { it.copy(searchText = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(searchText = value) }
|
||||
searchEventChannel.send(Unit)
|
||||
}
|
||||
}
|
||||
|
@ -126,8 +126,8 @@ class InboxMentionsViewModel(
|
||||
}
|
||||
|
||||
private fun changeUnreadOnly(value: Boolean) {
|
||||
updateState { it.copy(unreadOnly = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(unreadOnly = value) }
|
||||
refresh(initial = true)
|
||||
emitEffect(InboxMentionsMviModel.Effect.BackToTop)
|
||||
}
|
||||
@ -174,17 +174,19 @@ class InboxMentionsViewModel(
|
||||
}
|
||||
|
||||
private fun handleItemUpdate(item: PersonMentionModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
mentions =
|
||||
it.mentions.map { i ->
|
||||
if (i.id == item.id) {
|
||||
item
|
||||
} else {
|
||||
i
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
mentions =
|
||||
it.mentions.map { i ->
|
||||
if (i.id == item.id) {
|
||||
item
|
||||
} else {
|
||||
i
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -287,8 +289,8 @@ class InboxMentionsViewModel(
|
||||
}
|
||||
|
||||
private fun handleLogout() {
|
||||
updateState { it.copy(mentions = emptyList()) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(mentions = emptyList()) }
|
||||
refresh(initial = true)
|
||||
}
|
||||
}
|
||||
|
@ -100,8 +100,8 @@ class InboxMessagesViewModel(
|
||||
if (uiState.value.currentUserId == 0L) {
|
||||
return
|
||||
}
|
||||
updateState { it.copy(unreadOnly = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(unreadOnly = value) }
|
||||
refresh(initial = true)
|
||||
emitEffect(InboxMessagesMviModel.Effect.BackToTop)
|
||||
}
|
||||
@ -168,8 +168,8 @@ class InboxMessagesViewModel(
|
||||
}
|
||||
|
||||
private fun handleLogout() {
|
||||
updateState { it.copy(chats = emptyList()) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(chats = emptyList()) }
|
||||
refresh(initial = true)
|
||||
}
|
||||
}
|
||||
|
@ -22,14 +22,18 @@ class ModerateWithReasonViewModel(
|
||||
initialState = ModerateWithReasonMviModel.UiState(),
|
||||
) {
|
||||
init {
|
||||
updateState { it.copy(action = actionId.toModerateWithReasonAction()) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(action = actionId.toModerateWithReasonAction()) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun reduce(intent: ModerateWithReasonMviModel.Intent) {
|
||||
when (intent) {
|
||||
is ModerateWithReasonMviModel.Intent.SetText -> {
|
||||
updateState {
|
||||
it.copy(text = intent.value)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(text = intent.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,8 +47,8 @@ class ModerateWithReasonViewModel(
|
||||
}
|
||||
val text = uiState.value.text
|
||||
|
||||
updateState { it.copy(loading = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(loading = true) }
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
try {
|
||||
when (uiState.value.action) {
|
||||
|
@ -53,16 +53,16 @@ class ModlogViewModel(
|
||||
}
|
||||
|
||||
private fun refresh(initial: Boolean = false) {
|
||||
currentPage = 1
|
||||
updateState {
|
||||
it.copy(
|
||||
canFetchMore = true,
|
||||
refreshing = !initial,
|
||||
initial = initial,
|
||||
loading = false,
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
currentPage = 1
|
||||
updateState {
|
||||
it.copy(
|
||||
canFetchMore = true,
|
||||
refreshing = !initial,
|
||||
initial = initial,
|
||||
loading = false,
|
||||
)
|
||||
}
|
||||
loadNextPage()
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,9 @@ class ModlogViewModel(
|
||||
private fun loadNextPage() {
|
||||
val currentState = uiState.value
|
||||
if (!currentState.canFetchMore || currentState.loading) {
|
||||
updateState { it.copy(refreshing = false) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(refreshing = false) }
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -247,8 +247,8 @@ class MultiCommunityViewModel(
|
||||
if (uiState.value.sortType == value) {
|
||||
return
|
||||
}
|
||||
updateState { it.copy(sortType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(sortType = value) }
|
||||
emitEffect(MultiCommunityMviModel.Effect.BackToTop)
|
||||
delay(50)
|
||||
refresh()
|
||||
@ -349,35 +349,41 @@ class MultiCommunityViewModel(
|
||||
}
|
||||
|
||||
private fun handlePostUpdate(post: PostModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearRead() {
|
||||
hideReadPosts = true
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> !e.read }
|
||||
it.copy(posts = newPosts)
|
||||
screenModelScope.launch {
|
||||
hideReadPosts = true
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> !e.read }
|
||||
it.copy(posts = newPosts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hide(post: PostModel) {
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> e.id != post.id }
|
||||
it.copy(
|
||||
posts = newPosts,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> e.id != post.id }
|
||||
it.copy(
|
||||
posts = newPosts,
|
||||
)
|
||||
}
|
||||
markAsRead(post)
|
||||
}
|
||||
markAsRead(post)
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,10 @@ class MultiCommunityEditorViewModel(
|
||||
override fun reduce(intent: MultiCommunityEditorMviModel.Intent) {
|
||||
when (intent) {
|
||||
is MultiCommunityEditorMviModel.Intent.SelectImage -> selectImage(intent.index)
|
||||
is MultiCommunityEditorMviModel.Intent.SetName -> updateState { it.copy(name = intent.value) }
|
||||
is MultiCommunityEditorMviModel.Intent.SetName ->
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(name = intent.value) }
|
||||
}
|
||||
is MultiCommunityEditorMviModel.Intent.ToggleCommunity -> toggleCommunity(intent.id)
|
||||
is MultiCommunityEditorMviModel.Intent.SetSearch -> setSearch(intent.value)
|
||||
MultiCommunityEditorMviModel.Intent.Submit -> submit()
|
||||
@ -94,8 +97,8 @@ class MultiCommunityEditorViewModel(
|
||||
}
|
||||
|
||||
private fun setSearch(value: String) {
|
||||
updateState { it.copy(searchText = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(searchText = value) }
|
||||
searchEventChannel.send(Unit)
|
||||
}
|
||||
}
|
||||
@ -112,13 +115,15 @@ class MultiCommunityEditorViewModel(
|
||||
}
|
||||
|
||||
private fun selectImage(index: Int?) {
|
||||
val image =
|
||||
if (index == null) {
|
||||
null
|
||||
} else {
|
||||
uiState.value.availableIcons[index]
|
||||
}
|
||||
updateState { it.copy(icon = image) }
|
||||
screenModelScope.launch {
|
||||
val image =
|
||||
if (index == null) {
|
||||
null
|
||||
} else {
|
||||
uiState.value.availableIcons[index]
|
||||
}
|
||||
updateState { it.copy(icon = image) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleCommunity(communityId: Long) {
|
||||
@ -138,21 +143,27 @@ class MultiCommunityEditorViewModel(
|
||||
}
|
||||
communities = newCommunities
|
||||
val filtered = filterCommunities()
|
||||
updateState { state ->
|
||||
state.copy(
|
||||
communities = filtered,
|
||||
availableIcons = availableIcons,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState { state ->
|
||||
state.copy(
|
||||
communities = filtered,
|
||||
availableIcons = availableIcons,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun submit() {
|
||||
updateState { it.copy(nameError = null) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(nameError = null) }
|
||||
}
|
||||
val currentState = uiState.value
|
||||
var valid = true
|
||||
val name = currentState.name
|
||||
if (name.isEmpty()) {
|
||||
updateState { it.copy(nameError = ValidationError.MissingField) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(nameError = ValidationError.MissingField) }
|
||||
}
|
||||
valid = false
|
||||
}
|
||||
if (!valid) {
|
||||
|
@ -53,8 +53,9 @@ class ProfileLoggedViewModel(
|
||||
initialState = ProfileLoggedMviModel.UiState(),
|
||||
) {
|
||||
init {
|
||||
updateState { it.copy(instance = apiConfigurationRepository.instance.value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(instance = apiConfigurationRepository.instance.value) }
|
||||
|
||||
themeRepository.postLayout.onEach { layout ->
|
||||
updateState { it.copy(postLayout = layout) }
|
||||
}.launchIn(this)
|
||||
@ -253,8 +254,10 @@ class ProfileLoggedViewModel(
|
||||
}
|
||||
|
||||
private fun changeSection(section: ProfileLoggedSection) {
|
||||
updateState {
|
||||
it.copy(section = section)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(section = section)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -444,37 +447,47 @@ class ProfileLoggedViewModel(
|
||||
}
|
||||
|
||||
private fun handlePostUpdate(post: PostModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCommentUpdate(comment: CommentModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
comments =
|
||||
it.comments.map { c ->
|
||||
if (c.id == comment.id) {
|
||||
comment
|
||||
} else {
|
||||
c
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
comments =
|
||||
it.comments.map { c ->
|
||||
if (c.id == comment.id) {
|
||||
comment
|
||||
} else {
|
||||
c
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handlePostDelete(id: Long) {
|
||||
updateState { it.copy(posts = it.posts.filter { post -> post.id != id }) }
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts = it.posts.filter { post -> post.id != id },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun deletePost(id: Long) {
|
||||
|
@ -126,7 +126,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.SortBottomS
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.getScreenModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.di.getNotificationCenter
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.ActionOnSwipe
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsRepository
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||
@ -191,7 +190,6 @@ class PostDetailScreen(
|
||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(topAppBarState)
|
||||
val fabNestedScrollConnection = remember { getFabNestedScrollConnection() }
|
||||
val isFabVisible by fabNestedScrollConnection.isFabVisible.collectAsState()
|
||||
val notificationCenter = remember { getNotificationCenter() }
|
||||
val themeRepository = remember { getThemeRepository() }
|
||||
val upVoteColor by themeRepository.upVoteColor.collectAsState()
|
||||
val downVoteColor by themeRepository.downVoteColor.collectAsState()
|
||||
@ -257,9 +255,6 @@ class PostDetailScreen(
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(notificationCenter) {
|
||||
notificationCenter.resetCache()
|
||||
}
|
||||
LaunchedEffect(model) {
|
||||
model.effects.onEach { effect ->
|
||||
when (effect) {
|
||||
|
@ -74,14 +74,14 @@ class PostDetailViewModel(
|
||||
}
|
||||
|
||||
init {
|
||||
updateState {
|
||||
it.copy(
|
||||
instance =
|
||||
otherInstance.takeIf { n -> n.isNotEmpty() }
|
||||
?: apiConfigurationRepository.instance.value,
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
instance =
|
||||
otherInstance.takeIf { n -> n.isNotEmpty() }
|
||||
?: apiConfigurationRepository.instance.value,
|
||||
)
|
||||
}
|
||||
if (uiState.value.post.id == 0L) {
|
||||
val post = itemCache.getPost(postId) ?: PostModel()
|
||||
val downVoteEnabled = siteRepository.isDownVoteEnabled(identityRepository.authToken.value)
|
||||
@ -371,9 +371,11 @@ class PostDetailViewModel(
|
||||
}
|
||||
|
||||
is PostDetailMviModel.Intent.ChangeSearching -> {
|
||||
updateState { it.copy(searching = intent.value) }
|
||||
if (!intent.value) {
|
||||
updateSearchText("")
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(searching = intent.value) }
|
||||
if (!intent.value) {
|
||||
updateSearchText("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -472,8 +474,8 @@ class PostDetailViewModel(
|
||||
if (uiState.value.sortType == value) {
|
||||
return
|
||||
}
|
||||
updateState { it.copy(sortType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(sortType = value) }
|
||||
emitEffect(PostDetailMviModel.Effect.BackToTop)
|
||||
delay(50)
|
||||
refresh()
|
||||
@ -481,8 +483,10 @@ class PostDetailViewModel(
|
||||
}
|
||||
|
||||
private fun handlePostUpdate(post: PostModel) {
|
||||
updateState {
|
||||
it.copy(post = post)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(post = post)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -546,8 +550,8 @@ class PostDetailViewModel(
|
||||
post = post,
|
||||
voted = newValue,
|
||||
)
|
||||
updateState { it.copy(post = newPost) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(post = newPost) }
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
postRepository.upVote(
|
||||
@ -572,10 +576,10 @@ class PostDetailViewModel(
|
||||
post = post,
|
||||
downVoted = newValue,
|
||||
)
|
||||
updateState {
|
||||
it.copy(post = newPost)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(post = newPost)
|
||||
}
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
postRepository.downVote(
|
||||
@ -600,8 +604,8 @@ class PostDetailViewModel(
|
||||
post = post,
|
||||
saved = newValue,
|
||||
)
|
||||
updateState { it.copy(post = newPost) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(post = newPost) }
|
||||
try {
|
||||
val auth = identityRepository.authToken.value.orEmpty()
|
||||
postRepository.save(
|
||||
@ -620,17 +624,19 @@ class PostDetailViewModel(
|
||||
}
|
||||
|
||||
private fun handleCommentUpdate(comment: CommentModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
comments =
|
||||
it.comments.map { c ->
|
||||
if (c.id == comment.id) {
|
||||
comment
|
||||
} else {
|
||||
c
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
comments =
|
||||
it.comments.map { c ->
|
||||
if (c.id == comment.id) {
|
||||
comment
|
||||
} else {
|
||||
c
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -718,7 +724,9 @@ class PostDetailViewModel(
|
||||
}
|
||||
|
||||
private fun handleCommentDelete(id: Long) {
|
||||
updateState { it.copy(comments = it.comments.filter { comment -> comment.id != id }) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(comments = it.comments.filter { comment -> comment.id != id }) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun deletePost() {
|
||||
@ -833,16 +841,16 @@ class PostDetailViewModel(
|
||||
}
|
||||
|
||||
private fun updateSearchText(value: String) {
|
||||
updateState { it.copy(searchText = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(searchText = value) }
|
||||
searchEventChannel.send(Unit)
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToPreviousPost() {
|
||||
val currentId = uiState.value.post.id
|
||||
updateState { it.copy(loading = true, initial = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(loading = true, initial = true) }
|
||||
postNavigationManager.getPrevious(currentId)?.also { newPost ->
|
||||
loadNewPost(newPost)
|
||||
}
|
||||
@ -851,8 +859,8 @@ class PostDetailViewModel(
|
||||
|
||||
private fun navigateToNextPost() {
|
||||
val currentId = uiState.value.post.id
|
||||
updateState { it.copy(loading = true, initial = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(loading = true, initial = true) }
|
||||
postNavigationManager.getNext(currentId)?.also { newPost ->
|
||||
loadNewPost(newPost)
|
||||
}
|
||||
|
@ -156,14 +156,14 @@ class PostListViewModel(
|
||||
}
|
||||
|
||||
private fun onFirstLoad() {
|
||||
val settings = settingsRepository.currentSettings.value
|
||||
updateState {
|
||||
it.copy(
|
||||
listingType = settings.defaultListingType.toListingType(),
|
||||
sortType = settings.defaultPostSortType.toSortType(),
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
val settings = settingsRepository.currentSettings.value
|
||||
updateState {
|
||||
it.copy(
|
||||
listingType = settings.defaultListingType.toListingType(),
|
||||
sortType = settings.defaultPostSortType.toSortType(),
|
||||
)
|
||||
}
|
||||
refreshUser()
|
||||
refresh(initial = true)
|
||||
emitEffect(PostListMviModel.Effect.BackToTop)
|
||||
@ -251,16 +251,20 @@ class PostListViewModel(
|
||||
}
|
||||
|
||||
PostListMviModel.Intent.PauseZombieMode -> {
|
||||
updateState { it.copy(zombieModeActive = false) }
|
||||
zombieModeHelper.pause()
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(zombieModeActive = false) }
|
||||
zombieModeHelper.pause()
|
||||
}
|
||||
}
|
||||
|
||||
is PostListMviModel.Intent.StartZombieMode -> {
|
||||
updateState { it.copy(zombieModeActive = true) }
|
||||
zombieModeHelper.start(
|
||||
initialValue = intent.index,
|
||||
interval = settingsRepository.currentSettings.value.zombieModeInterval,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(zombieModeActive = true) }
|
||||
zombieModeHelper.start(
|
||||
initialValue = intent.index,
|
||||
interval = settingsRepository.currentSettings.value.zombieModeInterval,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is PostListMviModel.Intent.Copy ->
|
||||
@ -339,8 +343,8 @@ class PostListViewModel(
|
||||
if (uiState.value.sortType == value) {
|
||||
return
|
||||
}
|
||||
updateState { it.copy(sortType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(sortType = value) }
|
||||
emitEffect(PostListMviModel.Effect.BackToTop)
|
||||
delay(50)
|
||||
refresh()
|
||||
@ -351,8 +355,8 @@ class PostListViewModel(
|
||||
if (uiState.value.listingType == value) {
|
||||
return
|
||||
}
|
||||
updateState { it.copy(listingType = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(listingType = value) }
|
||||
emitEffect(PostListMviModel.Effect.BackToTop)
|
||||
delay(50)
|
||||
refresh()
|
||||
@ -453,28 +457,32 @@ class PostListViewModel(
|
||||
}
|
||||
|
||||
private fun handlePostUpdate(post: PostModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleLogout() {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts = emptyList(),
|
||||
isLogged = false,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts = emptyList(),
|
||||
isLogged = false,
|
||||
)
|
||||
}
|
||||
onFirstLoad()
|
||||
}
|
||||
onFirstLoad()
|
||||
}
|
||||
|
||||
private fun handlePostDelete(id: Long) {
|
||||
@ -486,21 +494,25 @@ class PostListViewModel(
|
||||
}
|
||||
|
||||
private fun clearRead() {
|
||||
hideReadPosts = true
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> !e.read }
|
||||
it.copy(posts = newPosts)
|
||||
screenModelScope.launch {
|
||||
hideReadPosts = true
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> !e.read }
|
||||
it.copy(posts = newPosts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun hide(post: PostModel) {
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> e.id != post.id }
|
||||
it.copy(
|
||||
posts = newPosts,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
val newPosts = it.posts.filter { e -> e.id != post.id }
|
||||
it.copy(
|
||||
posts = newPosts,
|
||||
)
|
||||
}
|
||||
markAsRead(post)
|
||||
}
|
||||
markAsRead(post)
|
||||
}
|
||||
|
||||
private fun blockUser(userId: Long) {
|
||||
|
@ -123,8 +123,8 @@ class InboxRepliesViewModel(
|
||||
}
|
||||
|
||||
private fun changeUnreadOnly(value: Boolean) {
|
||||
updateState { it.copy(unreadOnly = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(unreadOnly = value) }
|
||||
refresh(initial = true)
|
||||
emitEffect(InboxRepliesMviModel.Effect.BackToTop)
|
||||
}
|
||||
@ -171,17 +171,19 @@ class InboxRepliesViewModel(
|
||||
}
|
||||
|
||||
private fun handleItemUpdate(item: PersonMentionModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
replies =
|
||||
it.replies.map { i ->
|
||||
if (i.id == item.id) {
|
||||
item
|
||||
} else {
|
||||
i
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
replies =
|
||||
it.replies.map { i ->
|
||||
if (i.id == item.id) {
|
||||
item
|
||||
} else {
|
||||
i
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,8 +284,8 @@ class InboxRepliesViewModel(
|
||||
}
|
||||
|
||||
private fun handleLogout() {
|
||||
updateState { it.copy(replies = emptyList()) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(replies = emptyList()) }
|
||||
refresh(initial = true)
|
||||
}
|
||||
}
|
||||
|
@ -90,18 +90,20 @@ class ReportListViewModel(
|
||||
}
|
||||
|
||||
private fun changeSection(section: ReportListSection) {
|
||||
updateState {
|
||||
it.copy(
|
||||
section = section,
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
section = section,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeUnresolvedOnly(value: Boolean) {
|
||||
updateState {
|
||||
it.copy(unresolvedOnly = value)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(unresolvedOnly = value)
|
||||
}
|
||||
emitEffect(ReportListMviModel.Effect.BackToTop)
|
||||
delay(50)
|
||||
refresh(initial = true)
|
||||
@ -255,48 +257,56 @@ class ReportListViewModel(
|
||||
}
|
||||
|
||||
private fun handleReportUpdate(report: PostReportModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
postReports =
|
||||
it.postReports.map { r ->
|
||||
if (r.id == report.id) {
|
||||
report
|
||||
} else {
|
||||
r
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
postReports =
|
||||
it.postReports.map { r ->
|
||||
if (r.id == report.id) {
|
||||
report
|
||||
} else {
|
||||
r
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleReportUpdate(report: CommentReportModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
commentReports =
|
||||
it.commentReports.map { r ->
|
||||
if (r.id == report.id) {
|
||||
report
|
||||
} else {
|
||||
r
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
commentReports =
|
||||
it.commentReports.map { r ->
|
||||
if (r.id == report.id) {
|
||||
report
|
||||
} else {
|
||||
r
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleReporDelete(report: PostReportModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
postReports = it.postReports.filter { r -> r.id != report.id },
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
postReports = it.postReports.filter { r -> r.id != report.id },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleReporDelete(report: CommentReportModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
commentReports = it.commentReports.filter { r -> r.id != report.id },
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
commentReports = it.commentReports.filter { r -> r.id != report.id },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,8 +58,8 @@ class SelectCommunityViewModel(
|
||||
}
|
||||
|
||||
private fun setSearch(value: String) {
|
||||
updateState { it.copy(searchText = value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(searchText = value) }
|
||||
searchEventChannel.send(Unit)
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,9 @@ class SelectInstanceViewModel(
|
||||
}
|
||||
|
||||
is SelectInstanceMviModel.Intent.ChangeInstanceName -> {
|
||||
updateState { it.copy(changeInstanceName = intent.value) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(changeInstanceName = intent.value) }
|
||||
}
|
||||
}
|
||||
|
||||
is SelectInstanceMviModel.Intent.SubmitChangeInstanceDialog -> submitChangeInstance()
|
||||
@ -69,11 +71,15 @@ class SelectInstanceViewModel(
|
||||
}
|
||||
|
||||
private fun submitChangeInstance() {
|
||||
updateState { it.copy(changeInstanceNameError = null) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(changeInstanceNameError = null) }
|
||||
}
|
||||
var valid = true
|
||||
val instanceName = uiState.value.changeInstanceName
|
||||
if (instanceName.isEmpty()) {
|
||||
updateState { it.copy(changeInstanceNameError = ValidationError.MissingField) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(changeInstanceNameError = ValidationError.MissingField) }
|
||||
}
|
||||
valid = false
|
||||
}
|
||||
if (!valid) {
|
||||
|
@ -98,7 +98,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.SortBottomS
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.l10n.LocalXmlStrings
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.getScreenModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.di.getNotificationCenter
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.ActionOnSwipe
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsRepository
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||
@ -152,7 +151,6 @@ class UserDetailScreen(
|
||||
val otherInstanceName = remember { otherInstance }
|
||||
val topAppBarState = rememberTopAppBarState()
|
||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(topAppBarState)
|
||||
val notificationCenter = remember { getNotificationCenter() }
|
||||
val fabNestedScrollConnection = remember { getFabNestedScrollConnection() }
|
||||
val isFabVisible by fabNestedScrollConnection.isFabVisible.collectAsState()
|
||||
val themeRepository = remember { getThemeRepository() }
|
||||
@ -171,9 +169,6 @@ class UserDetailScreen(
|
||||
val detailOpener = remember { getDetailOpener() }
|
||||
val clipboardManager = LocalClipboardManager.current
|
||||
|
||||
LaunchedEffect(notificationCenter) {
|
||||
notificationCenter.resetCache()
|
||||
}
|
||||
LaunchedEffect(model) {
|
||||
model.effects.onEach { effect ->
|
||||
when (effect) {
|
||||
|
@ -63,14 +63,15 @@ class UserDetailViewModel(
|
||||
initialState = UserDetailMviModel.UiState(),
|
||||
) {
|
||||
init {
|
||||
updateState {
|
||||
it.copy(
|
||||
instance =
|
||||
otherInstance.takeIf { n -> n.isNotEmpty() }
|
||||
?: apiConfigurationRepository.instance.value,
|
||||
)
|
||||
}
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
instance =
|
||||
otherInstance.takeIf { n -> n.isNotEmpty() }
|
||||
?: apiConfigurationRepository.instance.value,
|
||||
)
|
||||
}
|
||||
|
||||
if (uiState.value.user.id == 0L) {
|
||||
val user = itemCache.getUser(userId) ?: UserModel()
|
||||
updateState {
|
||||
@ -238,8 +239,8 @@ class UserDetailViewModel(
|
||||
if (uiState.value.sortType == value) {
|
||||
return
|
||||
}
|
||||
updateState { it.copy(sortType = value) }
|
||||
screenModelScope.launch(Dispatchers.Main) {
|
||||
updateState { it.copy(sortType = value) }
|
||||
emitEffect(UserDetailMviModel.Effect.BackToTop)
|
||||
delay(50)
|
||||
refresh()
|
||||
@ -247,8 +248,10 @@ class UserDetailViewModel(
|
||||
}
|
||||
|
||||
private fun changeSection(section: UserDetailSection) {
|
||||
updateState {
|
||||
it.copy(section = section)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(section = section)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,38 +498,42 @@ class UserDetailViewModel(
|
||||
}
|
||||
|
||||
private fun handlePostUpdate(post: PostModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
posts =
|
||||
it.posts.map { p ->
|
||||
if (p.id == post.id) {
|
||||
post
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCommentUpdate(comment: CommentModel) {
|
||||
updateState {
|
||||
it.copy(
|
||||
comments =
|
||||
it.comments.map { c ->
|
||||
if (c.id == comment.id) {
|
||||
comment
|
||||
} else {
|
||||
c
|
||||
}
|
||||
},
|
||||
)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(
|
||||
comments =
|
||||
it.comments.map { c ->
|
||||
if (c.id == comment.id) {
|
||||
comment
|
||||
} else {
|
||||
c
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun blockUser() {
|
||||
updateState { it.copy(asyncInProgress = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(asyncInProgress = true) }
|
||||
try {
|
||||
val auth = identityRepository.authToken.value
|
||||
userRepository.block(userId, true, auth).getOrThrow()
|
||||
@ -540,8 +547,8 @@ class UserDetailViewModel(
|
||||
}
|
||||
|
||||
private fun blockInstance() {
|
||||
updateState { it.copy(asyncInProgress = true) }
|
||||
screenModelScope.launch {
|
||||
updateState { it.copy(asyncInProgress = true) }
|
||||
try {
|
||||
val user = uiState.value.user
|
||||
val instanceId = user.instanceId
|
||||
|
@ -125,8 +125,10 @@ class ZoomableImageViewModel(
|
||||
|
||||
private fun changeContentScale(contentScale: ContentScale) {
|
||||
imagePreloadManager.remove(url)
|
||||
updateState {
|
||||
it.copy(contentScale = contentScale)
|
||||
screenModelScope.launch {
|
||||
updateState {
|
||||
it.copy(contentScale = contentScale)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user