chore: remove unnecessary dispatcher switch (#852)

This commit is contained in:
Diego Beraldin 2024-05-15 22:14:14 +02:00 committed by GitHub
parent 9ebf3f7b9e
commit cae9fd4da3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 1582 additions and 1418 deletions

View File

@ -9,8 +9,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.toInboxUnreadOnly
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.inbox.InboxCoordinator
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -25,7 +23,6 @@ class InboxViewModel(
DefaultMviModel<InboxMviModel.Intent, InboxMviModel.UiState, InboxMviModel.Effect>(
initialState = InboxMviModel.UiState(),
) {
init {
screenModelScope.launch {
identityRepository.isLogged.onEach { logged ->
@ -62,9 +59,10 @@ class InboxViewModel(
override fun reduce(intent: InboxMviModel.Intent) {
when (intent) {
is InboxMviModel.Intent.ChangeSection -> updateState {
it.copy(section = intent.value)
}
is InboxMviModel.Intent.ChangeSection ->
updateState {
it.copy(section = intent.value)
}
InboxMviModel.Intent.ReadAll -> markAllRead()
}
@ -78,7 +76,7 @@ class InboxViewModel(
}
private fun markAllRead() {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val auth = identityRepository.authToken.value
userRepository.readAll(auth)
emitEffect(InboxMviModel.Effect.Refresh)

View File

@ -23,8 +23,6 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.ListingType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toInt
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toListingType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -46,7 +44,6 @@ class AdvancedSettingsViewModel(
DefaultMviModel<AdvancedSettingsMviModel.Intent, AdvancedSettingsMviModel.UiState, AdvancedSettingsMviModel.Effect>(
initialState = AdvancedSettingsMviModel.UiState(),
) {
init {
screenModelScope.launch {
themeRepository.navItemTitles.onEach { value ->
@ -155,7 +152,7 @@ class AdvancedSettingsViewModel(
private fun changeNavBarTitlesVisible(value: Boolean) {
themeRepository.changeNavItemTitles(value)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(navigationTitlesVisible = value)
saveSettings(settings)
}
@ -163,7 +160,7 @@ class AdvancedSettingsViewModel(
private fun changeEnableDoubleTapAction(value: Boolean) {
updateState { it.copy(enableDoubleTapAction = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(enableDoubleTapAction = value)
saveSettings(settings)
}
@ -171,7 +168,7 @@ class AdvancedSettingsViewModel(
private fun changeAutoLoadImages(value: Boolean) {
updateState { it.copy(autoLoadImages = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(autoLoadImages = value)
saveSettings(settings)
}
@ -179,7 +176,7 @@ class AdvancedSettingsViewModel(
private fun changeAutoExpandComments(value: Boolean) {
updateState { it.copy(autoExpandComments = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(autoExpandComments = value)
saveSettings(settings)
}
@ -187,7 +184,7 @@ class AdvancedSettingsViewModel(
private fun changeHideNavigationBarWhileScrolling(value: Boolean) {
updateState { it.copy(hideNavigationBarWhileScrolling = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(hideNavigationBarWhileScrolling = value)
saveSettings(settings)
}
@ -195,7 +192,7 @@ class AdvancedSettingsViewModel(
private fun changeMarkAsReadWhileScrolling(value: Boolean) {
updateState { it.copy(markAsReadWhileScrolling = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(markAsReadWhileScrolling = value)
saveSettings(settings)
}
@ -203,7 +200,7 @@ class AdvancedSettingsViewModel(
private fun changeZombieModeInterval(value: Duration) {
updateState { it.copy(zombieModeInterval = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(zombieModeInterval = value)
saveSettings(settings)
}
@ -211,7 +208,7 @@ class AdvancedSettingsViewModel(
private fun changeZombieModeScrollAmount(value: Float) {
updateState { it.copy(zombieModeScrollAmount = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(zombieModeScrollAmount = value)
saveSettings(settings)
}
@ -219,7 +216,7 @@ class AdvancedSettingsViewModel(
private fun changeDefaultInboxUnreadOnly(value: Boolean) {
updateState { it.copy(defaultInboxUnreadOnly = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(defaultInboxType = value.toInboxDefaultType())
saveSettings(settings)
notificationCenter.send(NotificationCenterEvent.ResetInbox)
@ -228,7 +225,7 @@ class AdvancedSettingsViewModel(
private fun changeSearchPostTitleOnly(value: Boolean) {
updateState { it.copy(searchPostTitleOnly = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(searchPostTitleOnly = value)
saveSettings(settings)
}
@ -236,16 +233,15 @@ class AdvancedSettingsViewModel(
private fun changeExploreType(value: ListingType) {
updateState { it.copy(defaultExploreType = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(defaultExploreType = value.toInt())
saveSettings(settings)
}
}
private fun changeEdgeToEdge(value: Boolean) {
updateState { it.copy(edgeToEdge = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(edgeToEdge = value)
saveSettings(settings)
}
@ -253,19 +249,20 @@ class AdvancedSettingsViewModel(
private fun changeInfiniteScrollDisabled(value: Boolean) {
updateState { it.copy(infiniteScrollDisabled = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(infiniteScrollEnabled = !value)
saveSettings(settings)
}
}
private fun changeSystemBarTheme(value: UiBarTheme) {
val opaque = when (value) {
UiBarTheme.Opaque -> true
else -> false
}
val opaque =
when (value) {
UiBarTheme.Opaque -> true
else -> false
}
updateState { it.copy(opaqueSystemBars = opaque) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(opaqueSystemBars = opaque)
saveSettings(settings)
}
@ -273,7 +270,7 @@ class AdvancedSettingsViewModel(
private fun changeImageSourcePath(value: Boolean) {
updateState { it.copy(imageSourcePath = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(imageSourcePath = value)
saveSettings(settings)
}
@ -289,7 +286,7 @@ class AdvancedSettingsViewModel(
private fun changeDefaultLanguageId(value: Long?) {
updateState { it.copy(defaultLanguageId = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(defaultLanguageId = value)
saveSettings(settings)
}
@ -297,7 +294,7 @@ class AdvancedSettingsViewModel(
private fun changeInboxBackgroundCheckPeriod(value: Duration) {
updateState { it.copy(inboxBackgroundCheckPeriod = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(inboxBackgroundCheckPeriod = value)
saveSettings(settings)
}
@ -305,7 +302,7 @@ class AdvancedSettingsViewModel(
private fun changeFadeReadPosts(value: Boolean) {
updateState { it.copy(fadeReadPosts = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(fadeReadPosts = value)
saveSettings(settings)
}
@ -313,7 +310,7 @@ class AdvancedSettingsViewModel(
private fun changeShowUnreadPosts(value: Boolean) {
updateState { it.copy(showUnreadComments = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(showUnreadComments = value)
saveSettings(settings)
}
@ -321,7 +318,7 @@ class AdvancedSettingsViewModel(
private fun changeEnableButtonsToScrollBetweenComments(value: Boolean) {
updateState { it.copy(enableButtonsToScrollBetweenComments = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value.copy(enableButtonsToScrollBetweenComments = value)
saveSettings(settings)
}

View File

@ -15,8 +15,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.SettingsMo
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.AccountRepository
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -32,7 +30,6 @@ class SettingsColorAndFontViewModel(
DefaultMviModel<SettingsColorAndFontMviModel.Intent, SettingsColorAndFontMviModel.UiState, SettingsColorAndFontMviModel.Effect>(
initialState = SettingsColorAndFontMviModel.UiState(),
) {
init {
screenModelScope.launch {
themeRepository.uiTheme.onEach { value ->
@ -112,92 +109,99 @@ class SettingsColorAndFontViewModel(
private fun changeFontFamily(value: UiFontFamily) {
themeRepository.changeUiFontFamily(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
uiFontFamily = value.toInt()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
uiFontFamily = value.toInt(),
)
saveSettings(settings)
}
}
private fun changeUiFontScale(value: Float) {
themeRepository.changeUiFontScale(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
uiFontScale = value
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
uiFontScale = value,
)
saveSettings(settings)
}
}
private fun changeDynamicColors(value: Boolean) {
themeRepository.changeDynamicColors(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
dynamicColors = value
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
dynamicColors = value,
)
saveSettings(settings)
}
}
private fun changeCustomSeedColor(value: Color?) {
themeRepository.changeCustomSeedColor(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
customSeedColor = value?.toArgb()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
customSeedColor = value?.toArgb(),
)
saveSettings(settings)
}
}
private fun changeUpVoteColor(value: Color?) {
themeRepository.changeUpVoteColor(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
upVoteColor = value?.toArgb()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
upVoteColor = value?.toArgb(),
)
saveSettings(settings)
}
}
private fun changeDownVoteColor(value: Color?) {
themeRepository.changeDownVoteColor(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
downVoteColor = value?.toArgb()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
downVoteColor = value?.toArgb(),
)
saveSettings(settings)
}
}
private fun changeReplyColor(value: Color?) {
themeRepository.changeReplyColor(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
replyColor = value?.toArgb()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
replyColor = value?.toArgb(),
)
saveSettings(settings)
}
}
private fun changeSaveColor(value: Color?) {
themeRepository.changeSaveColor(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
saveColor = value?.toArgb()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
saveColor = value?.toArgb(),
)
saveSettings(settings)
}
}
private fun changeCommentBarTheme(value: CommentBarTheme) {
themeRepository.changeCommentBarTheme(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
commentBarTheme = value.toInt()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
commentBarTheme = value.toInt(),
)
saveSettings(settings)
}
}

View File

@ -23,8 +23,6 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toInt
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toListingType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -43,7 +41,6 @@ class SettingsViewModel(
DefaultMviModel<SettingsMviModel.Intent, SettingsMviModel.UiState, SettingsMviModel.Effect>(
initialState = SettingsMviModel.UiState(),
) {
init {
screenModelScope.launch {
themeRepository.uiTheme.onEach { value ->
@ -130,30 +127,33 @@ class SettingsViewModel(
private fun changeTheme(value: UiTheme?) {
themeRepository.changeUiTheme(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
theme = value?.toInt()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
theme = value?.toInt(),
)
saveSettings(settings)
}
}
private fun changeLanguage(value: String) {
l10nManager.changeLanguage(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
locale = value
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
locale = value,
)
saveSettings(settings)
}
}
private fun changeDefaultListingType(value: ListingType) {
updateState { it.copy(defaultListingType = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
defaultListingType = value.toInt()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
defaultListingType = value.toInt(),
)
saveSettings(settings)
notificationCenter.send(NotificationCenterEvent.ResetHome)
}
@ -161,10 +161,11 @@ class SettingsViewModel(
private fun changeDefaultPostSortType(value: SortType) {
updateState { it.copy(defaultPostSortType = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
defaultPostSortType = value.toInt()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
defaultPostSortType = value.toInt(),
)
saveSettings(settings)
notificationCenter.send(NotificationCenterEvent.ResetHome)
}
@ -172,20 +173,22 @@ class SettingsViewModel(
private fun changeDefaultCommentSortType(value: SortType) {
updateState { it.copy(defaultCommentSortType = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
defaultCommentSortType = value.toInt()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
defaultCommentSortType = value.toInt(),
)
saveSettings(settings)
}
}
private fun changeIncludeNsfw(value: Boolean) {
updateState { it.copy(includeNsfw = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
includeNsfw = value
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
includeNsfw = value,
)
saveSettings(settings)
notificationCenter.send(NotificationCenterEvent.ResetHome)
notificationCenter.send(NotificationCenterEvent.ResetExplore)
@ -194,30 +197,33 @@ class SettingsViewModel(
private fun changeBlurNsfw(value: Boolean) {
updateState { it.copy(blurNsfw = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
blurNsfw = value
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
blurNsfw = value,
)
saveSettings(settings)
}
}
private fun changeUrlOpeningMode(value: UrlOpeningMode) {
updateState { it.copy(urlOpeningMode = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
urlOpeningMode = value.toInt()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
urlOpeningMode = value.toInt(),
)
saveSettings(settings)
}
}
private fun changeEnableSwipeActions(value: Boolean) {
updateState { it.copy(enableSwipeActions = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
enableSwipeActions = value
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
enableSwipeActions = value,
)
saveSettings(settings)
}
}
@ -234,7 +240,7 @@ class SettingsViewModel(
}
private fun handleLogout() {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val settings = settingsRepository.getSettings(null)
updateState {
it.copy(

View File

@ -6,8 +6,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.Sett
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.inbox.InboxCoordinator
import com.github.diegoberaldin.raccoonforlemmy.domain.inbox.notification.InboxNotificationChecker
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
@ -23,9 +21,8 @@ class MainViewModel(
DefaultMviModel<MainScreenMviModel.Intent, MainScreenMviModel.UiState, MainScreenMviModel.Effect>(
initialState = MainScreenMviModel.UiState(),
) {
init {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
identityRepository.startup()
inboxCoordinator.totalUnread.onEach { unreadCount ->

View File

@ -11,12 +11,9 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepo
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PrivateMessageRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class InboxChatViewModel(
private val otherUserId: Long,
@ -31,7 +28,6 @@ class InboxChatViewModel(
DefaultMviModel<InboxChatMviModel.Intent, InboxChatMviModel.UiState, InboxChatMviModel.Effect>(
initialState = InboxChatMviModel.UiState(),
) {
private var currentPage: Int = 1
init {
@ -51,24 +47,23 @@ class InboxChatViewModel(
handleLogout()
}.launchIn(this)
withContext(Dispatchers.IO) {
val currentUserId = siteRepository.getCurrentUser(auth)?.id ?: 0
updateState { it.copy(currentUserId = currentUserId) }
val currentUserId = siteRepository.getCurrentUser(auth)?.id ?: 0
updateState { it.copy(currentUserId = currentUserId) }
val user = userRepository.get(
val user =
userRepository.get(
id = otherUserId,
auth = auth,
)
updateState {
it.copy(
otherUserName = user?.name.orEmpty(),
otherUserAvatar = user?.avatar,
)
}
updateState {
it.copy(
otherUserName = user?.name.orEmpty(),
otherUserAvatar = user?.avatar,
)
}
if (uiState.value.messages.isEmpty()) {
refresh(initial = true)
}
if (uiState.value.messages.isEmpty()) {
refresh(initial = true)
}
}
}
@ -127,30 +122,33 @@ class InboxChatViewModel(
updateState { it.copy(loading = true) }
val auth = identityRepository.authToken.value
val refreshing = currentState.refreshing
val itemList = messageRepository.getAll(
creatorId = otherUserId,
auth = auth,
page = currentPage,
unreadOnly = false,
)?.onEach {
if (!it.read) {
markAsRead(true, it.id)
val itemList =
messageRepository.getAll(
creatorId = otherUserId,
auth = auth,
page = currentPage,
unreadOnly = false,
)?.onEach {
if (!it.read) {
markAsRead(true, it.id)
}
}
}
if (!itemList.isNullOrEmpty()) {
currentPage++
}
val itemsToAdd = itemList.orEmpty().filter {
it.creator?.id == otherUserId || it.recipient?.id == otherUserId
}
val itemsToAdd =
itemList.orEmpty().filter {
it.creator?.id == otherUserId || it.recipient?.id == otherUserId
}
val shouldTryNextPage = itemsToAdd.isEmpty() && tryCount < 10
updateState {
val newItems = if (refreshing) {
itemsToAdd
} else {
it.messages + itemsToAdd
}
val newItems =
if (refreshing) {
itemsToAdd
} else {
it.messages + itemsToAdd
}
it.copy(
messages = newItems,
loading = false,
@ -164,14 +162,18 @@ class InboxChatViewModel(
}
}
private fun markAsRead(read: Boolean, messageId: Long) {
private fun markAsRead(
read: Boolean,
messageId: Long,
) {
val auth = identityRepository.authToken.value
screenModelScope.launch {
val newMessage = messageRepository.markAsRead(
read = read,
messageId = messageId,
auth = auth,
)
val newMessage =
messageRepository.markAsRead(
read = read,
messageId = messageId,
auth = auth,
)
if (newMessage != null) {
handleMessageUpdate(newMessage)
}
@ -181,13 +183,14 @@ class InboxChatViewModel(
private fun handleMessageUpdate(newMessage: PrivateMessageModel) {
updateState {
it.copy(
messages = it.messages.map { msg ->
if (msg.id == newMessage.id) {
newMessage
} else {
msg
}
}
messages =
it.messages.map { msg ->
if (msg.id == newMessage.id) {
newMessage
} else {
msg
}
},
)
}
}
@ -225,30 +228,32 @@ class InboxChatViewModel(
if (text.isNotEmpty()) {
screenModelScope.launch {
val auth = identityRepository.authToken.value
val newMessage = if (isEditing) {
messageRepository.edit(
messageId = editedMessageId ?: 0,
message = text,
auth = auth,
)
} else {
messageRepository.create(
message = text,
recipientId = otherUserId,
auth = auth,
)
}
val newMessages = if (isEditing) {
uiState.value.messages.map { msg ->
if (msg.id == newMessage?.id) {
newMessage
} else {
msg
}
val newMessage =
if (isEditing) {
messageRepository.edit(
messageId = editedMessageId ?: 0,
message = text,
auth = auth,
)
} else {
messageRepository.create(
message = text,
recipientId = otherUserId,
auth = auth,
)
}
val newMessages =
if (isEditing) {
uiState.value.messages.map { msg ->
if (msg.id == newMessage?.id) {
newMessage
} else {
msg
}
}
} else {
(newMessage?.let { listOf(it) } ?: emptyList()) + uiState.value.messages
}
} else {
(newMessage?.let { listOf(it) } ?: emptyList()) + uiState.value.messages
}
updateState {
it.copy(
messages = newMessages,

View File

@ -32,9 +32,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortT
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.LemmyItemCache
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.IO
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.debounce
@ -70,7 +68,6 @@ class CommunityDetailViewModel(
DefaultMviModel<CommunityDetailMviModel.Intent, CommunityDetailMviModel.UiState, CommunityDetailMviModel.Effect>(
initialState = CommunityDetailMviModel.UiState(),
) {
private var hideReadPosts = false
private val searchEventChannel = Channel<Unit>()
@ -81,8 +78,9 @@ class CommunityDetailViewModel(
updateState {
it.copy(
community = community,
instance = otherInstance.takeIf { n -> n.isNotEmpty() }
?: apiConfigurationRepository.instance.value,
instance =
otherInstance.takeIf { n -> n.isNotEmpty() }
?: apiConfigurationRepository.instance.value,
)
}
}
@ -133,16 +131,17 @@ class CommunityDetailViewModel(
val newUser = evt.user
updateState {
it.copy(
posts = it.posts.map { p ->
if (p.id == postId) {
p.copy(
creator = newUser,
updateDate = newUser.updateDate,
)
} else {
p
}
},
posts =
it.posts.map { p ->
if (p.id == postId) {
p.copy(
creator = newUser,
updateDate = newUser.updateDate,
)
} else {
p
}
},
)
}
}.launchIn(this)
@ -204,13 +203,15 @@ class CommunityDetailViewModel(
override fun reduce(intent: CommunityDetailMviModel.Intent) {
when (intent) {
CommunityDetailMviModel.Intent.LoadNextPage -> screenModelScope.launch(Dispatchers.IO) {
loadNextPage()
}
CommunityDetailMviModel.Intent.LoadNextPage ->
screenModelScope.launch {
loadNextPage()
}
CommunityDetailMviModel.Intent.Refresh -> screenModelScope.launch(Dispatchers.IO) {
refresh()
}
CommunityDetailMviModel.Intent.Refresh ->
screenModelScope.launch {
refresh()
}
is CommunityDetailMviModel.Intent.DownVotePost -> {
if (intent.feedback) {
@ -274,15 +275,17 @@ class CommunityDetailViewModel(
)
}
is CommunityDetailMviModel.Intent.ModFeaturePost -> uiState.value.posts.firstOrNull { it.id == intent.id }
?.also { post ->
feature(post = post)
}
is CommunityDetailMviModel.Intent.ModFeaturePost ->
uiState.value.posts.firstOrNull { it.id == intent.id }
?.also { post ->
feature(post = post)
}
is CommunityDetailMviModel.Intent.ModLockPost -> uiState.value.posts.firstOrNull { it.id == intent.id }
?.also { post ->
lock(post = post)
}
is CommunityDetailMviModel.Intent.ModLockPost ->
uiState.value.posts.firstOrNull { it.id == intent.id }
?.also { post ->
lock(post = post)
}
is CommunityDetailMviModel.Intent.ModToggleModUser -> {
toggleModeratorStatus(intent.id)
@ -300,9 +303,10 @@ class CommunityDetailViewModel(
}
is CommunityDetailMviModel.Intent.SetSearch -> updateSearchText(intent.value)
is CommunityDetailMviModel.Intent.Copy -> screenModelScope.launch {
emitEffect(CommunityDetailMviModel.Effect.TriggerCopy(intent.value))
}
is CommunityDetailMviModel.Intent.Copy ->
screenModelScope.launch {
emitEffect(CommunityDetailMviModel.Effect.TriggerCopy(intent.value))
}
CommunityDetailMviModel.Intent.WillOpenDetail -> {
val state = postPaginationManager.extractState()
@ -327,22 +331,24 @@ class CommunityDetailViewModel(
otherInstance = otherInstance,
query = currentState.searchText.takeIf { currentState.searching },
includeNsfw = settingsRepository.currentSettings.value.includeNsfw,
)
),
)
updateState { it.copy(canFetchMore = true, refreshing = true) }
val auth = identityRepository.authToken.value
val accountId = accountRepository.getActive()?.id
val isFavorite = favoriteCommunityRepository.getBy(accountId, currentState.community.id) != null
val refreshedCommunity = communityRepository.get(
auth = auth,
name = currentState.community.name,
id = currentState.community.id,
instance = otherInstance,
)?.copy(favorite = isFavorite)
val moderators = communityRepository.getModerators(
auth = auth,
id = currentState.community.id,
)
val refreshedCommunity =
communityRepository.get(
auth = auth,
name = currentState.community.name,
id = currentState.community.id,
instance = otherInstance,
)?.copy(favorite = isFavorite)
val moderators =
communityRepository.getModerators(
auth = auth,
id = currentState.community.id,
)
if (refreshedCommunity != null) {
updateState {
it.copy(
@ -362,7 +368,7 @@ class CommunityDetailViewModel(
return
}
updateState { it.copy(sortType = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
emitEffect(CommunityDetailMviModel.Effect.BackToTop)
delay(50)
refresh()
@ -376,26 +382,27 @@ class CommunityDetailViewModel(
return
}
updateState { it.copy(loading = true) }
val posts = postPaginationManager.loadNextPage().let {
if (!hideReadPosts) {
it
} else {
it.filter { post -> !post.read }
}
}.let {
if (currentState.searching) {
it.filter { post ->
listOf(post.title, post.text).any { s ->
s.contains(
other = currentState.searchText,
ignoreCase = true,
)
}
val posts =
postPaginationManager.loadNextPage().let {
if (!hideReadPosts) {
it
} else {
it.filter { post -> !post.read }
}
}.let {
if (currentState.searching) {
it.filter { post ->
listOf(post.title, post.text).any { s ->
s.contains(
other = currentState.searchText,
ignoreCase = true,
)
}
}
} else {
it
}
} else {
it
}
}
if (uiState.value.autoLoadImages) {
posts.forEach { post ->
post.imageUrl.takeIf { i -> i.isNotEmpty() }?.also { url ->
@ -415,12 +422,13 @@ class CommunityDetailViewModel(
private fun toggleUpVotePost(post: PostModel) {
val newValue = post.myVote <= 0
val newPost = postRepository.asUpVoted(
post = post,
voted = newValue,
)
val newPost =
postRepository.asUpVoted(
post = post,
voted = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.upVote(
@ -444,7 +452,7 @@ class CommunityDetailViewModel(
return
}
val newPost = post.copy(read = true)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.setRead(
@ -462,12 +470,13 @@ class CommunityDetailViewModel(
private fun toggleDownVotePost(post: PostModel) {
val newValue = post.myVote >= 0
val newPost = postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
val newPost =
postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.downVote(
@ -488,12 +497,13 @@ class CommunityDetailViewModel(
private fun toggleSavePost(post: PostModel) {
val newValue = !post.saved
val newPost = postRepository.asSaved(
post = post,
saved = newValue,
)
val newPost =
postRepository.asSaved(
post = post,
saved = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.save(
@ -514,11 +524,12 @@ class CommunityDetailViewModel(
private fun subscribe() {
hapticFeedback.vibrate()
screenModelScope.launch(Dispatchers.IO) {
val community = communityRepository.subscribe(
auth = identityRepository.authToken.value,
id = communityId,
)
screenModelScope.launch {
val community =
communityRepository.subscribe(
auth = identityRepository.authToken.value,
id = communityId,
)
if (community != null) {
updateState { it.copy(community = community) }
notificationCenter.send(NotificationCenterEvent.CommunitySubscriptionChanged(community))
@ -528,11 +539,12 @@ class CommunityDetailViewModel(
private fun unsubscribe() {
hapticFeedback.vibrate()
screenModelScope.launch(Dispatchers.IO) {
val community = communityRepository.unsubscribe(
auth = identityRepository.authToken.value,
id = communityId,
)
screenModelScope.launch {
val community =
communityRepository.unsubscribe(
auth = identityRepository.authToken.value,
id = communityId,
)
if (community != null) {
updateState { it.copy(community = community) }
notificationCenter.send(NotificationCenterEvent.CommunitySubscriptionChanged(community))
@ -543,13 +555,14 @@ class CommunityDetailViewModel(
private fun handlePostUpdate(post: PostModel) {
updateState {
it.copy(
posts = it.posts.map { p ->
if (p.id == post.id) {
post
} else {
p
}
},
posts =
it.posts.map { p ->
if (p.id == post.id) {
post
} else {
p
}
},
)
}
}
@ -560,7 +573,7 @@ class CommunityDetailViewModel(
private fun blockCommunity() {
updateState { it.copy(asyncInProgress = true) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value
communityRepository.block(communityId, true, auth).getOrThrow()
@ -575,7 +588,7 @@ class CommunityDetailViewModel(
private fun blockInstance() {
updateState { it.copy(asyncInProgress = true) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val community = uiState.value.community
val instanceId = community.instanceId
@ -611,13 +624,14 @@ class CommunityDetailViewModel(
}
private fun feature(post: PostModel) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val auth = identityRepository.authToken.value.orEmpty()
val newPost = postRepository.featureInCommunity(
postId = post.id,
auth = auth,
featured = !post.featuredCommunity
)
val newPost =
postRepository.featureInCommunity(
postId = post.id,
auth = auth,
featured = !post.featuredCommunity,
)
if (newPost != null) {
handlePostUpdate(newPost)
}
@ -625,13 +639,14 @@ class CommunityDetailViewModel(
}
private fun lock(post: PostModel) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val auth = identityRepository.authToken.value.orEmpty()
val newPost = postRepository.lock(
postId = post.id,
auth = auth,
locked = !post.locked,
)
val newPost =
postRepository.lock(
postId = post.id,
auth = auth,
locked = !post.locked,
)
if (newPost != null) {
handlePostUpdate(newPost)
}
@ -639,15 +654,16 @@ class CommunityDetailViewModel(
}
private fun toggleModeratorStatus(userId: Long) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val isModerator = uiState.value.moderators.containsId(userId)
val auth = identityRepository.authToken.value.orEmpty()
val newModerators = communityRepository.addModerator(
auth = auth,
communityId = communityId,
added = !isModerator,
userId = userId,
)
val newModerators =
communityRepository.addModerator(
auth = auth,
communityId = communityId,
added = !isModerator,
userId = userId,
)
updateState {
it.copy(moderators = newModerators)
}
@ -655,7 +671,7 @@ class CommunityDetailViewModel(
}
private fun toggleFavorite() {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val accountId = accountRepository.getActive()?.id ?: 0L
val newValue = !uiState.value.community.favorite
if (newValue) {

View File

@ -13,8 +13,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationC
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.SettingsModel
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.AccountRepository
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -29,9 +27,8 @@ class ConfigureContentViewViewModel(
private val notificationCenter: NotificationCenter,
) : ConfigureContentViewMviModel,
DefaultMviModel<ConfigureContentViewMviModel.Intent, ConfigureContentViewMviModel.State, ConfigureContentViewMviModel.Effect>(
initialState = ConfigureContentViewMviModel.State()
initialState = ConfigureContentViewMviModel.State(),
) {
init {
screenModelScope.launch {
themeRepository.postLayout.onEach { value ->
@ -124,114 +121,128 @@ class ConfigureContentViewViewModel(
private fun changePostLayout(value: PostLayout) {
themeRepository.changePostLayout(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
postLayout = value.toInt()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
postLayout = value.toInt(),
)
saveSettings(settings)
}
}
private fun changeVoteFormat(value: VoteFormat) {
updateState { it.copy(voteFormat = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.let {
if (value == VoteFormat.Hidden) {
it.copy(showScores = false)
} else {
it.copy(
voteFormat = value,
showScores = true,
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.let {
if (value == VoteFormat.Hidden) {
it.copy(showScores = false)
} else {
it.copy(
voteFormat = value,
showScores = true,
)
}
}
}
saveSettings(settings)
}
}
private fun changeFullHeightImages(value: Boolean) {
updateState { it.copy(fullHeightImages = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
fullHeightImages = value,
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
fullHeightImages = value,
)
saveSettings(settings)
}
}
private fun changeFullWidthImages(value: Boolean) {
updateState { it.copy(fullWidthImages = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
fullWidthImages = value,
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
fullWidthImages = value,
)
saveSettings(settings)
}
}
private fun changePreferUserNicknames(value: Boolean) {
updateState { it.copy(preferUserNicknames = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
preferUserNicknames = value,
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
preferUserNicknames = value,
)
saveSettings(settings)
}
}
private fun changePostBodyMaxLines(value: Int?) {
updateState { it.copy(postBodyMaxLines = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
postBodyMaxLines = value,
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
postBodyMaxLines = value,
)
saveSettings(settings)
}
}
private fun changeContentFontScale(value: Float, contentClass: ContentFontClass) {
val contentFontScale = themeRepository.contentFontScale.value.let {
when (contentClass) {
ContentFontClass.Title -> it.copy(title = value)
ContentFontClass.Body -> it.copy(body = value)
ContentFontClass.Comment -> it.copy(comment = value)
ContentFontClass.AncillaryText -> it.copy(ancillary = value)
private fun changeContentFontScale(
value: Float,
contentClass: ContentFontClass,
) {
val contentFontScale =
themeRepository.contentFontScale.value.let {
when (contentClass) {
ContentFontClass.Title -> it.copy(title = value)
ContentFontClass.Body -> it.copy(body = value)
ContentFontClass.Comment -> it.copy(comment = value)
ContentFontClass.AncillaryText -> it.copy(ancillary = value)
}
}
}
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
contentFontScale = contentFontScale,
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
contentFontScale = contentFontScale,
)
saveSettings(settings)
}
}
private fun changeContentFontFamily(value: UiFontFamily) {
themeRepository.changeContentFontFamily(value)
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
contentFontFamily = value.toInt()
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
contentFontFamily = value.toInt(),
)
saveSettings(settings)
}
}
private fun changeCommentBarThickness(value: Int) {
updateState { it.copy(commentBarThickness = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
commentBarThickness = value,
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
commentBarThickness = value,
)
saveSettings(settings)
}
}
private fun changeCommentIndentAmount(value: Int) {
updateState { it.copy(commentIndentAmount = value) }
screenModelScope.launch(Dispatchers.IO) {
val settings = settingsRepository.currentSettings.value.copy(
commentIndentAmount = value,
)
screenModelScope.launch {
val settings =
settingsRepository.currentSettings.value.copy(
commentIndentAmount = value,
)
saveSettings(settings)
}
}
@ -241,4 +252,4 @@ class ConfigureContentViewViewModel(
settingsRepository.updateSettings(settings, accountId)
settingsRepository.changeCurrentSettings(settings)
}
}
}

View File

@ -9,8 +9,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.ActionOnSw
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.ActionOnSwipeTarget
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.AccountRepository
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -23,26 +21,28 @@ class ConfigureSwipeActionsViewModel(
DefaultMviModel<ConfigureSwipeActionsMviModel.Intent, ConfigureSwipeActionsMviModel.UiState, ConfigureSwipeActionsMviModel.Effect>(
initialState = ConfigureSwipeActionsMviModel.UiState(),
) {
init {
screenModelScope.launch {
notificationCenter.subscribe(NotificationCenterEvent.ActionsOnSwipeSelected::class)
.onEach { evt ->
when (evt.target) {
ActionOnSwipeTarget.Posts -> addActionPosts(
action = evt.value,
direction = evt.direction,
)
ActionOnSwipeTarget.Posts ->
addActionPosts(
action = evt.value,
direction = evt.direction,
)
ActionOnSwipeTarget.Comments -> addActionComments(
action = evt.value,
direction = evt.direction,
)
ActionOnSwipeTarget.Comments ->
addActionComments(
action = evt.value,
direction = evt.direction,
)
ActionOnSwipeTarget.Inbox -> addActionInbox(
action = evt.value,
direction = evt.direction,
)
ActionOnSwipeTarget.Inbox ->
addActionInbox(
action = evt.value,
direction = evt.direction,
)
}
}.launchIn(this)
}
@ -51,20 +51,23 @@ class ConfigureSwipeActionsViewModel(
override fun reduce(intent: ConfigureSwipeActionsMviModel.Intent) {
when (intent) {
is ConfigureSwipeActionsMviModel.Intent.DeleteActionComments -> removeActionComments(
action = intent.value,
direction = intent.direction,
)
is ConfigureSwipeActionsMviModel.Intent.DeleteActionComments ->
removeActionComments(
action = intent.value,
direction = intent.direction,
)
is ConfigureSwipeActionsMviModel.Intent.DeleteActionInbox -> removeActionInbox(
action = intent.value,
direction = intent.direction,
)
is ConfigureSwipeActionsMviModel.Intent.DeleteActionInbox ->
removeActionInbox(
action = intent.value,
direction = intent.direction,
)
is ConfigureSwipeActionsMviModel.Intent.DeleteActionPosts -> removeActionPosts(
action = intent.value,
direction = intent.direction,
)
is ConfigureSwipeActionsMviModel.Intent.DeleteActionPosts ->
removeActionPosts(
action = intent.value,
direction = intent.direction,
)
ConfigureSwipeActionsMviModel.Intent.ResetActionsComments -> resetActionsComments()
ConfigureSwipeActionsMviModel.Intent.ResetActionsInbox -> resetActionsInbox()
@ -87,28 +90,35 @@ class ConfigureSwipeActionsViewModel(
updateAvailableOptions()
}
private fun addActionPosts(action: ActionOnSwipe, direction: ActionOnSwipeDirection) {
screenModelScope.launch(Dispatchers.IO) {
private fun addActionPosts(
action: ActionOnSwipe,
direction: ActionOnSwipeDirection,
) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value
val accountId = accountRepository.getActive()?.id ?: return@launch
val newActions = when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartPosts + action).toSet().toList()
}
val newActions =
when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartPosts + action).toSet().toList()
}
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndPosts + action).toSet().toList()
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndPosts + action).toSet().toList()
}
}
}
val newSettings = when (direction) {
ActionOnSwipeDirection.ToStart -> settings.copy(
actionsOnSwipeToStartPosts = newActions
)
val newSettings =
when (direction) {
ActionOnSwipeDirection.ToStart ->
settings.copy(
actionsOnSwipeToStartPosts = newActions,
)
ActionOnSwipeDirection.ToEnd -> settings.copy(
actionsOnSwipeToEndPosts = newActions
)
}
ActionOnSwipeDirection.ToEnd ->
settings.copy(
actionsOnSwipeToEndPosts = newActions,
)
}
settingsRepository.updateSettings(settings = newSettings, accountId = accountId)
settingsRepository.changeCurrentSettings(newSettings)
@ -130,28 +140,35 @@ class ConfigureSwipeActionsViewModel(
}
}
private fun removeActionPosts(action: ActionOnSwipe, direction: ActionOnSwipeDirection) {
screenModelScope.launch(Dispatchers.IO) {
private fun removeActionPosts(
action: ActionOnSwipe,
direction: ActionOnSwipeDirection,
) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value
val accountId = accountRepository.getActive()?.id ?: return@launch
val newActions = when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartPosts - action).toSet().toList()
}
val newActions =
when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartPosts - action).toSet().toList()
}
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndPosts - action).toSet().toList()
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndPosts - action).toSet().toList()
}
}
}
val newSettings = when (direction) {
ActionOnSwipeDirection.ToStart -> settings.copy(
actionsOnSwipeToStartPosts = newActions
)
val newSettings =
when (direction) {
ActionOnSwipeDirection.ToStart ->
settings.copy(
actionsOnSwipeToStartPosts = newActions,
)
ActionOnSwipeDirection.ToEnd -> settings.copy(
actionsOnSwipeToEndPosts = newActions
)
}
ActionOnSwipeDirection.ToEnd ->
settings.copy(
actionsOnSwipeToEndPosts = newActions,
)
}
settingsRepository.updateSettings(settings = newSettings, accountId = accountId)
settingsRepository.changeCurrentSettings(newSettings)
@ -173,28 +190,35 @@ class ConfigureSwipeActionsViewModel(
}
}
private fun addActionComments(action: ActionOnSwipe, direction: ActionOnSwipeDirection) {
screenModelScope.launch(Dispatchers.IO) {
private fun addActionComments(
action: ActionOnSwipe,
direction: ActionOnSwipeDirection,
) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value
val accountId = accountRepository.getActive()?.id ?: return@launch
val newActions = when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartComments + action).toSet().toList()
}
val newActions =
when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartComments + action).toSet().toList()
}
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndComments + action).toSet().toList()
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndComments + action).toSet().toList()
}
}
}
val newSettings = when (direction) {
ActionOnSwipeDirection.ToStart -> settings.copy(
actionsOnSwipeToStartComments = newActions
)
val newSettings =
when (direction) {
ActionOnSwipeDirection.ToStart ->
settings.copy(
actionsOnSwipeToStartComments = newActions,
)
ActionOnSwipeDirection.ToEnd -> settings.copy(
actionsOnSwipeToEndComments = newActions
)
}
ActionOnSwipeDirection.ToEnd ->
settings.copy(
actionsOnSwipeToEndComments = newActions,
)
}
settingsRepository.updateSettings(settings = newSettings, accountId = accountId)
settingsRepository.changeCurrentSettings(newSettings)
@ -216,28 +240,35 @@ class ConfigureSwipeActionsViewModel(
}
}
private fun removeActionComments(action: ActionOnSwipe, direction: ActionOnSwipeDirection) {
screenModelScope.launch(Dispatchers.IO) {
private fun removeActionComments(
action: ActionOnSwipe,
direction: ActionOnSwipeDirection,
) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value
val accountId = accountRepository.getActive()?.id ?: return@launch
val newActions = when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartComments - action).toSet().toList()
}
val newActions =
when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartComments - action).toSet().toList()
}
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndComments - action).toSet().toList()
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndComments - action).toSet().toList()
}
}
}
val newSettings = when (direction) {
ActionOnSwipeDirection.ToStart -> settings.copy(
actionsOnSwipeToStartComments = newActions
)
val newSettings =
when (direction) {
ActionOnSwipeDirection.ToStart ->
settings.copy(
actionsOnSwipeToStartComments = newActions,
)
ActionOnSwipeDirection.ToEnd -> settings.copy(
actionsOnSwipeToEndComments = newActions
)
}
ActionOnSwipeDirection.ToEnd ->
settings.copy(
actionsOnSwipeToEndComments = newActions,
)
}
settingsRepository.updateSettings(settings = newSettings, accountId = accountId)
settingsRepository.changeCurrentSettings(newSettings)
@ -259,28 +290,35 @@ class ConfigureSwipeActionsViewModel(
}
}
private fun addActionInbox(action: ActionOnSwipe, direction: ActionOnSwipeDirection) {
screenModelScope.launch(Dispatchers.IO) {
private fun addActionInbox(
action: ActionOnSwipe,
direction: ActionOnSwipeDirection,
) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value
val accountId = accountRepository.getActive()?.id ?: return@launch
val newActions = when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartInbox + action).toSet().toList()
}
val newActions =
when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartInbox + action).toSet().toList()
}
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndInbox + action).toSet().toList()
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndInbox + action).toSet().toList()
}
}
}
val newSettings = when (direction) {
ActionOnSwipeDirection.ToStart -> settings.copy(
actionsOnSwipeToStartInbox = newActions
)
val newSettings =
when (direction) {
ActionOnSwipeDirection.ToStart ->
settings.copy(
actionsOnSwipeToStartInbox = newActions,
)
ActionOnSwipeDirection.ToEnd -> settings.copy(
actionsOnSwipeToEndInbox = newActions
)
}
ActionOnSwipeDirection.ToEnd ->
settings.copy(
actionsOnSwipeToEndInbox = newActions,
)
}
settingsRepository.updateSettings(settings = newSettings, accountId = accountId)
settingsRepository.changeCurrentSettings(newSettings)
@ -302,28 +340,35 @@ class ConfigureSwipeActionsViewModel(
}
}
private fun removeActionInbox(action: ActionOnSwipe, direction: ActionOnSwipeDirection) {
screenModelScope.launch(Dispatchers.IO) {
private fun removeActionInbox(
action: ActionOnSwipe,
direction: ActionOnSwipeDirection,
) {
screenModelScope.launch {
val settings = settingsRepository.currentSettings.value
val accountId = accountRepository.getActive()?.id ?: return@launch
val newActions = when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartInbox - action).toSet().toList()
}
val newActions =
when (direction) {
ActionOnSwipeDirection.ToStart -> {
(settings.actionsOnSwipeToStartInbox - action).toSet().toList()
}
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndInbox - action).toSet().toList()
ActionOnSwipeDirection.ToEnd -> {
(settings.actionsOnSwipeToEndInbox - action).toSet().toList()
}
}
}
val newSettings = when (direction) {
ActionOnSwipeDirection.ToStart -> settings.copy(
actionsOnSwipeToStartInbox = newActions
)
val newSettings =
when (direction) {
ActionOnSwipeDirection.ToStart ->
settings.copy(
actionsOnSwipeToStartInbox = newActions,
)
ActionOnSwipeDirection.ToEnd -> settings.copy(
actionsOnSwipeToEndInbox = newActions
)
}
ActionOnSwipeDirection.ToEnd ->
settings.copy(
actionsOnSwipeToEndInbox = newActions,
)
}
settingsRepository.updateSettings(settings = newSettings, accountId = accountId)
settingsRepository.changeCurrentSettings(newSettings)
@ -347,11 +392,12 @@ class ConfigureSwipeActionsViewModel(
private fun resetActionsPosts() {
val settings = settingsRepository.currentSettings.value
val newSettings = settings.copy(
actionsOnSwipeToStartPosts = ActionOnSwipe.DEFAULT_SWIPE_TO_START_POSTS,
actionsOnSwipeToEndPosts = ActionOnSwipe.DEFAULT_SWIPE_TO_START_POSTS,
)
screenModelScope.launch(Dispatchers.IO) {
val newSettings =
settings.copy(
actionsOnSwipeToStartPosts = ActionOnSwipe.DEFAULT_SWIPE_TO_START_POSTS,
actionsOnSwipeToEndPosts = ActionOnSwipe.DEFAULT_SWIPE_TO_START_POSTS,
)
screenModelScope.launch {
val accountId = accountRepository.getActive()?.id ?: return@launch
settingsRepository.updateSettings(newSettings, accountId)
settingsRepository.changeCurrentSettings(newSettings)
@ -362,11 +408,12 @@ class ConfigureSwipeActionsViewModel(
private fun resetActionsComments() {
val settings = settingsRepository.currentSettings.value
val newSettings = settings.copy(
actionsOnSwipeToStartComments = ActionOnSwipe.DEFAULT_SWIPE_TO_START_COMMENTS,
actionsOnSwipeToEndComments = ActionOnSwipe.DEFAULT_SWIPE_TO_END_COMMENTS,
)
screenModelScope.launch(Dispatchers.IO) {
val newSettings =
settings.copy(
actionsOnSwipeToStartComments = ActionOnSwipe.DEFAULT_SWIPE_TO_START_COMMENTS,
actionsOnSwipeToEndComments = ActionOnSwipe.DEFAULT_SWIPE_TO_END_COMMENTS,
)
screenModelScope.launch {
val accountId = accountRepository.getActive()?.id ?: return@launch
settingsRepository.updateSettings(newSettings, accountId)
settingsRepository.changeCurrentSettings(newSettings)
@ -377,11 +424,12 @@ class ConfigureSwipeActionsViewModel(
private fun resetActionsInbox() {
val settings = settingsRepository.currentSettings.value
val newSettings = settings.copy(
actionsOnSwipeToStartInbox = ActionOnSwipe.DEFAULT_SWIPE_TO_START_INBOX,
actionsOnSwipeToEndInbox = ActionOnSwipe.DEFAULT_SWIPE_TO_END_INBOX,
)
screenModelScope.launch(Dispatchers.IO) {
val newSettings =
settings.copy(
actionsOnSwipeToStartInbox = ActionOnSwipe.DEFAULT_SWIPE_TO_START_INBOX,
actionsOnSwipeToEndInbox = ActionOnSwipe.DEFAULT_SWIPE_TO_END_INBOX,
)
screenModelScope.launch {
val accountId = accountRepository.getActive()?.id ?: return@launch
settingsRepository.updateSettings(newSettings, accountId)
settingsRepository.changeCurrentSettings(newSettings)
@ -390,34 +438,35 @@ class ConfigureSwipeActionsViewModel(
}
}
private fun updateAvailableOptions(
preventActionsOnBothSides: Boolean = false,
) {
private fun updateAvailableOptions(preventActionsOnBothSides: Boolean = false) {
val currentState = uiState.value
val actionsPosts: Set<ActionOnSwipe> = buildSet {
this += ActionOnSwipe.DEFAULT_SWIPE_TO_START_POSTS
this += ActionOnSwipe.DEFAULT_SWIPE_TO_END_POSTS
if (preventActionsOnBothSides) {
this -= currentState.actionsOnSwipeToStartPosts.toSet()
this -= currentState.actionsOnSwipeToEndPosts.toSet()
val actionsPosts: Set<ActionOnSwipe> =
buildSet {
this += ActionOnSwipe.DEFAULT_SWIPE_TO_START_POSTS
this += ActionOnSwipe.DEFAULT_SWIPE_TO_END_POSTS
if (preventActionsOnBothSides) {
this -= currentState.actionsOnSwipeToStartPosts.toSet()
this -= currentState.actionsOnSwipeToEndPosts.toSet()
}
}
}
val actionsComments: Set<ActionOnSwipe> = buildSet {
this += ActionOnSwipe.DEFAULT_SWIPE_TO_START_COMMENTS
this += ActionOnSwipe.DEFAULT_SWIPE_TO_END_COMMENTS
if (preventActionsOnBothSides) {
this -= currentState.actionsOnSwipeToStartComments.toSet()
this -= currentState.actionsOnSwipeToEndComments.toSet()
val actionsComments: Set<ActionOnSwipe> =
buildSet {
this += ActionOnSwipe.DEFAULT_SWIPE_TO_START_COMMENTS
this += ActionOnSwipe.DEFAULT_SWIPE_TO_END_COMMENTS
if (preventActionsOnBothSides) {
this -= currentState.actionsOnSwipeToStartComments.toSet()
this -= currentState.actionsOnSwipeToEndComments.toSet()
}
}
}
val actionsInbox: Set<ActionOnSwipe> = buildSet {
this += ActionOnSwipe.DEFAULT_SWIPE_TO_START_INBOX
this += ActionOnSwipe.DEFAULT_SWIPE_TO_END_INBOX
if (preventActionsOnBothSides) {
this -= currentState.actionsOnSwipeToStartInbox.toSet()
this -= currentState.actionsOnSwipeToEndInbox.toSet()
val actionsInbox: Set<ActionOnSwipe> =
buildSet {
this += ActionOnSwipe.DEFAULT_SWIPE_TO_START_INBOX
this += ActionOnSwipe.DEFAULT_SWIPE_TO_END_INBOX
if (preventActionsOnBothSides) {
this -= currentState.actionsOnSwipeToStartInbox.toSet()
this -= currentState.actionsOnSwipeToEndInbox.toSet()
}
}
}
updateState {
it.copy(
availableOptionsPosts = actionsPosts.toList(),

View File

@ -13,10 +13,8 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.Ident
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.IO
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.channelFlow
@ -28,7 +26,6 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.yield
@ -44,9 +41,8 @@ class ModalDrawerViewModel(
private val notificationCenter: NotificationCenter,
) : ModalDrawerMviModel,
DefaultMviModel<ModalDrawerMviModel.Intent, ModalDrawerMviModel.UiState, ModalDrawerMviModel.Effect>(
initialState = ModalDrawerMviModel.UiState()
initialState = ModalDrawerMviModel.UiState(),
) {
private val searchEventChannel = Channel<Unit>()
init {
@ -85,11 +81,9 @@ class ModalDrawerViewModel(
observeChangesInFavoriteCommunities()
withContext(Dispatchers.IO) {
delay(250)
refreshUser()
refresh()
}
delay(250)
refreshUser()
refresh()
}
}
@ -111,20 +105,22 @@ class ModalDrawerViewModel(
}
}.distinctUntilChanged()
}.onEach { favoriteCommunityIds ->
val newCommunities = uiState.value.communities.map { community ->
community.copy(favorite = community.id in favoriteCommunityIds)
}
.sortedBy { it.name }
.sortedByDescending { it.favorite }
val newCommunities =
uiState.value.communities.map { community ->
community.copy(favorite = community.id in favoriteCommunityIds)
}
.sortedBy { it.name }
.sortedByDescending { it.favorite }
updateState { it.copy(communities = newCommunities) }
}.launchIn(this)
}
override fun reduce(intent: ModalDrawerMviModel.Intent) {
when (intent) {
ModalDrawerMviModel.Intent.Refresh -> screenModelScope.launch {
refresh()
}
ModalDrawerMviModel.Intent.Refresh ->
screenModelScope.launch {
refresh()
}
is ModalDrawerMviModel.Intent.SetSearch -> {
updateState { it.copy(searchText = intent.value) }
@ -166,35 +162,37 @@ class ModalDrawerViewModel(
val favoriteCommunityIds =
favoriteCommunityRepository.getAll(accountId).map { it.communityId }
val searchText = uiState.value.searchText
val communities = communityRepository.getSubscribed(auth)
.let {
if (searchText.isEmpty()) {
it
} else {
it.filter { e ->
listOf(e.name, e.title).any { s -> s.contains(other = searchText, ignoreCase = true) }
}
}
}.map { community ->
community.copy(favorite = community.id in favoriteCommunityIds)
}
.sortedBy { it.name }
.let {
val favorites = it.filter { e -> e.favorite }
val res = it - favorites.toSet()
favorites + res
}
val multiCommunitites = accountId?.let {
multiCommunityRepository.getAll(it)
.let { communities ->
val communities =
communityRepository.getSubscribed(auth)
.let {
if (searchText.isEmpty()) {
communities
it
} else {
communities.filter { c -> c.name.contains(other = searchText, ignoreCase = true) }
it.filter { e ->
listOf(e.name, e.title).any { s -> s.contains(other = searchText, ignoreCase = true) }
}
}
}.map { community ->
community.copy(favorite = community.id in favoriteCommunityIds)
}
.sortedBy { e -> e.name }
}.orEmpty()
.sortedBy { it.name }
.let {
val favorites = it.filter { e -> e.favorite }
val res = it - favorites.toSet()
favorites + res
}
val multiCommunitites =
accountId?.let {
multiCommunityRepository.getAll(it)
.let { communities ->
if (searchText.isEmpty()) {
communities
} else {
communities.filter { c -> c.name.contains(other = searchText, ignoreCase = true) }
}
}
.sortedBy { e -> e.name }
}.orEmpty()
updateState {
it.copy(
isFiltering = searchText.isNotEmpty(),

View File

@ -23,9 +23,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.Communit
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.IO
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.launchIn
@ -51,18 +49,18 @@ class ExploreViewModel(
DefaultMviModel<ExploreMviModel.Intent, ExploreMviModel.UiState, ExploreMviModel.Effect>(
initialState = ExploreMviModel.UiState(),
) {
private var currentPage: Int = 1
private var searchEventChannel = Channel<Unit>()
private val isOnOtherInstance: Boolean get() = otherInstance.isNotEmpty()
private val notificationEventKey: String
get() = buildString {
append("explore")
if (isOnOtherInstance) {
append("-")
append(otherInstance)
get() =
buildString {
append("explore")
if (isOnOtherInstance) {
append("-")
append(otherInstance)
}
}
}
init {
updateState {
@ -152,7 +150,7 @@ class ExploreViewModel(
sortType = sortType,
)
}
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
refresh()
emitEffect(ExploreMviModel.Effect.BackToTop)
}
@ -166,13 +164,13 @@ class ExploreViewModel(
override fun reduce(intent: ExploreMviModel.Intent) {
when (intent) {
ExploreMviModel.Intent.LoadNextPage -> {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
loadNextPage()
}
}
ExploreMviModel.Intent.Refresh -> {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
refresh()
}
}
@ -270,7 +268,7 @@ class ExploreViewModel(
private fun changeListingType(value: ListingType) {
updateState { it.copy(listingType = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
emitEffect(ExploreMviModel.Effect.BackToTop)
refresh()
}
@ -278,7 +276,7 @@ class ExploreViewModel(
private fun changeSortType(value: SortType) {
updateState { it.copy(sortType = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
emitEffect(ExploreMviModel.Effect.BackToTop)
refresh()
}
@ -286,7 +284,7 @@ class ExploreViewModel(
private fun changeResultType(value: SearchResultType) {
updateState { it.copy(resultType = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
emitEffect(ExploreMviModel.Effect.BackToTop)
refresh()
}
@ -318,15 +316,16 @@ class ExploreViewModel(
val sortType = currentState.sortType
val resultType = currentState.resultType
val settings = settingsRepository.currentSettings.value
val itemList = communityRepository.search(
query = searchText,
auth = auth,
resultType = resultType,
page = currentPage,
listingType = listingType,
sortType = sortType,
instance = otherInstance,
)
val itemList =
communityRepository.search(
query = searchText,
auth = auth,
resultType = resultType,
page = currentPage,
listingType = listingType,
sortType = sortType,
instance = otherInstance,
)
val additionalResolvedCommunity =
if (resultType == SearchResultType.All || resultType == SearchResultType.Communities && currentPage == 1) {
communityRepository.getResolved(
@ -348,56 +347,68 @@ class ExploreViewModel(
if (itemList.isNotEmpty()) {
currentPage++
}
val itemsToAdd = itemList.filter { item ->
if (settings.includeNsfw) {
true
} else {
isSafeForWork(item)
}
}.let {
when (resultType) {
SearchResultType.Communities -> {
if (additionalResolvedCommunity != null && it.none { r -> r is SearchResult.Community && r.model.id == additionalResolvedCommunity.id }) {
it + SearchResult.Community(additionalResolvedCommunity)
} else {
it
}
val itemsToAdd =
itemList.filter { item ->
if (settings.includeNsfw) {
true
} else {
isSafeForWork(item)
}
SearchResultType.Users -> {
if (additionalResolvedUser != null && it.none { r -> r is SearchResult.User && r.model.id == additionalResolvedUser.id }) {
it + SearchResult.User(additionalResolvedUser)
} else {
it
}.let {
when (resultType) {
SearchResultType.Communities -> {
if (additionalResolvedCommunity != null &&
it.none {
r ->
r is SearchResult.Community && r.model.id == additionalResolvedCommunity.id
}
) {
it + SearchResult.Community(additionalResolvedCommunity)
} else {
it
}
}
}
SearchResultType.Posts -> {
if (settings.searchPostTitleOnly && searchText.isNotEmpty()) {
// apply the more restrictive title-only search
it.filterIsInstance<SearchResult.Post>()
.filter { r -> r.model.title.contains(other = searchText, ignoreCase = true) }
} else {
it
SearchResultType.Users -> {
if (additionalResolvedUser != null &&
it.none {
r ->
r is SearchResult.User && r.model.id == additionalResolvedUser.id
}
) {
it + SearchResult.User(additionalResolvedUser)
} else {
it
}
}
}
else -> it
SearchResultType.Posts -> {
if (settings.searchPostTitleOnly && searchText.isNotEmpty()) {
// apply the more restrictive title-only search
it.filterIsInstance<SearchResult.Post>()
.filter { r -> r.model.title.contains(other = searchText, ignoreCase = true) }
} else {
it
}
}
else -> it
}
}.filter { item ->
if (refreshing) {
true
} else {
// prevents accidental duplication
currentState.results.none { other -> getItemKey(item) == getItemKey(other) }
}
}
}.filter { item ->
if (refreshing) {
true
} else {
// prevents accidental duplication
currentState.results.none { other -> getItemKey(item) == getItemKey(other) }
}
}
updateState {
val newItems = if (refreshing) {
itemsToAdd
} else {
it.results + itemsToAdd
}
val newItems =
if (refreshing) {
itemsToAdd
} else {
it.results + itemsToAdd
}
it.copy(
results = newItems,
loading = false,
@ -407,13 +418,14 @@ class ExploreViewModel(
}
}
private fun isSafeForWork(element: SearchResult): Boolean = when (element) {
is SearchResult.Community -> !element.model.nsfw
is SearchResult.Post -> !element.model.nsfw
is SearchResult.Comment -> true
is SearchResult.User -> true
else -> false
}
private fun isSafeForWork(element: SearchResult): Boolean =
when (element) {
is SearchResult.Community -> !element.model.nsfw
is SearchResult.Post -> !element.model.nsfw
is SearchResult.Comment -> true
is SearchResult.User -> true
else -> false
}
private fun handleLogout() {
currentPage = 1
@ -429,13 +441,14 @@ class ExploreViewModel(
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
}
},
results =
it.results.map { r ->
if (r is SearchResult.Post && r.model.id == post.id) {
r.copy(model = post)
} else {
r
}
},
)
}
}
@ -443,36 +456,39 @@ class ExploreViewModel(
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
}
},
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,
)
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
}
},
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(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.upVote(
@ -484,14 +500,15 @@ class ExploreViewModel(
e.printStackTrace()
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 = post)
} else {
res
}
},
results =
it.results.map { res ->
if (res !is SearchResult.Post) return@map res
if (res.model.id == post.id) {
res.copy(model = post)
} else {
res
}
},
)
}
}
@ -500,23 +517,25 @@ class ExploreViewModel(
private fun toggleDownVote(post: PostModel) {
val newValue = post.myVote >= 0
val newPost = postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
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
}
},
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(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.downVote(
@ -528,14 +547,15 @@ class ExploreViewModel(
e.printStackTrace()
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 = post)
} else {
res
}
},
results =
it.results.map { res ->
if (res !is SearchResult.Post) return@map res
if (res.model.id == post.id) {
res.copy(model = post)
} else {
res
}
},
)
}
}
@ -544,23 +564,25 @@ class ExploreViewModel(
private fun toggleSave(post: PostModel) {
val newValue = !post.saved
val newPost = postRepository.asSaved(
post = post,
saved = newValue,
)
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
}
},
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(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.save(
@ -572,14 +594,15 @@ class ExploreViewModel(
e.printStackTrace()
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 = post)
} else {
res
}
},
results =
it.results.map { res ->
if (res !is SearchResult.Post) return@map res
if (res.model.id == post.id) {
res.copy(model = post)
} else {
res
}
},
)
}
}
@ -588,23 +611,25 @@ class ExploreViewModel(
private fun toggleUpVoteComment(comment: CommentModel) {
val newValue = comment.myVote <= 0
val newComment = commentRepository.asUpVoted(
comment = comment,
voted = newValue,
)
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
}
},
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(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
commentRepository.upVote(
@ -616,14 +641,15 @@ class ExploreViewModel(
e.printStackTrace()
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 = comment)
} else {
res
}
},
results =
it.results.map { res ->
if (res !is SearchResult.Comment) return@map res
if (res.model.id == comment.id) {
res.copy(model = comment)
} else {
res
}
},
)
}
}
@ -635,17 +661,18 @@ class ExploreViewModel(
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
}
},
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(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
commentRepository.downVote(
@ -657,14 +684,15 @@ class ExploreViewModel(
e.printStackTrace()
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 = comment)
} else {
res
}
},
results =
it.results.map { res ->
if (res !is SearchResult.Comment) return@map res
if (res.model.id == comment.id) {
res.copy(model = comment)
} else {
res
}
},
)
}
}
@ -673,23 +701,25 @@ class ExploreViewModel(
private fun toggleSaveComment(comment: CommentModel) {
val newValue = !comment.saved
val newComment = commentRepository.asSaved(
comment = comment,
saved = newValue,
)
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
}
},
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(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
commentRepository.save(
@ -701,14 +731,15 @@ class ExploreViewModel(
e.printStackTrace()
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 = comment)
} else {
res
}
},
results =
it.results.map { res ->
if (res !is SearchResult.Comment) return@map res
if (res.model.id == comment.id) {
res.copy(model = comment)
} else {
res
}
},
)
}
}
@ -716,29 +747,31 @@ class ExploreViewModel(
}
private fun toggleSubscription(communityId: Long) {
val community = uiState.value.results.firstOrNull {
(it as? SearchResult.Community)?.model?.id == communityId
}.let { (it as? SearchResult.Community)?.model } ?: return
screenModelScope.launch(Dispatchers.IO) {
val newValue = when (community.subscribed) {
true -> {
hapticFeedback.vibrate()
communityRepository.unsubscribe(
auth = identityRepository.authToken.value,
id = communityId,
)
}
val community =
uiState.value.results.firstOrNull {
(it as? SearchResult.Community)?.model?.id == communityId
}.let { (it as? SearchResult.Community)?.model } ?: return
screenModelScope.launch {
val newValue =
when (community.subscribed) {
true -> {
hapticFeedback.vibrate()
communityRepository.unsubscribe(
auth = identityRepository.authToken.value,
id = communityId,
)
}
false -> {
hapticFeedback.vibrate()
communityRepository.subscribe(
auth = identityRepository.authToken.value,
id = communityId,
)
}
false -> {
hapticFeedback.vibrate()
communityRepository.subscribe(
auth = identityRepository.authToken.value,
id = communityId,
)
}
else -> community
}
else -> community
}
if (newValue == null) {
emitEffect(ExploreMviModel.Effect.OperationFailure)
} else {
@ -750,22 +783,24 @@ 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
}
},
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
}
},
)
}
}
}
internal fun getItemKey(result: SearchResult): String = when (result) {
is SearchResult.Post -> "post" + result.model.id.toString() + result.model.updateDate
is SearchResult.Comment -> "comment" + result.model.id.toString() + result.model.updateDate
is SearchResult.User -> "user" + result.model.id.toString()
is SearchResult.Community -> "community" + result.model.id.toString()
}
internal fun getItemKey(result: SearchResult): String =
when (result) {
is SearchResult.Post -> "post" + result.model.id.toString() + result.model.updateDate
is SearchResult.Comment -> "comment" + result.model.id.toString() + result.model.updateDate
is SearchResult.User -> "user" + result.model.id.toString()
is SearchResult.Community -> "community" + result.model.id.toString()
}

View File

@ -7,12 +7,9 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.Ident
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class ManageBanViewModel(
private val identityRepository: IdentityRepository,
@ -24,7 +21,6 @@ class ManageBanViewModel(
DefaultMviModel<ManageBanMviModel.Intent, ManageBanMviModel.UiState, ManageBanMviModel.Effect>(
initialState = ManageBanMviModel.UiState(),
) {
init {
screenModelScope.launch {
settingsRepository.currentSettings.onEach { settings ->
@ -36,10 +32,8 @@ class ManageBanViewModel(
}
}.launchIn(this)
withContext(Dispatchers.IO) {
if (uiState.value.initial) {
refresh()
}
if (uiState.value.initial) {
refresh()
}
}
}
@ -82,7 +76,7 @@ class ManageBanViewModel(
userRepository.block(
id = id,
blocked = false,
auth = auth
auth = auth,
)
updateState {
it.copy(bannedUsers = it.bannedUsers.filter { e -> e.id != id })
@ -98,7 +92,7 @@ class ManageBanViewModel(
communityRepository.block(
id = id,
blocked = false,
auth = auth
auth = auth,
)
updateState {
it.copy(bannedCommunities = it.bannedCommunities.filter { e -> e.id != id })
@ -114,7 +108,7 @@ class ManageBanViewModel(
siteRepository.block(
id = id,
blocked = false,
auth = auth
auth = auth,
)
updateState {
it.copy(bannedInstances = it.bannedInstances.filter { e -> e.id != id })
@ -122,4 +116,4 @@ class ManageBanViewModel(
}
}
}
}
}

View File

@ -14,9 +14,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.vibrate.HapticFeedbac
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.IO
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.launchIn
@ -38,7 +36,6 @@ class ManageSubscriptionsViewModel(
DefaultMviModel<ManageSubscriptionsMviModel.Intent, ManageSubscriptionsMviModel.UiState, ManageSubscriptionsMviModel.Effect>(
initialState = ManageSubscriptionsMviModel.UiState(),
) {
private val searchEventChannel = Channel<Unit>()
init {
@ -81,7 +78,7 @@ class ManageSubscriptionsViewModel(
}
is ManageSubscriptionsMviModel.Intent.DeleteMultiCommunity -> {
uiState.value.multiCommunities.firstOrNull() {
uiState.value.multiCommunities.firstOrNull {
(it.id ?: 0L) == intent.id
}?.also { community ->
deleteMultiCommunity(community)
@ -103,37 +100,39 @@ class ManageSubscriptionsViewModel(
return
}
updateState { it.copy(refreshing = true) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val auth = identityRepository.authToken.value
val accountId = accountRepository.getActive()?.id ?: 0L
val favoriteCommunityIds =
favoriteCommunityRepository.getAll(accountId).map { it.communityId }
val communities = communityRepository.getSubscribed(auth)
.let {
val searchText = uiState.value.searchText
if (searchText.isNotEmpty()) {
it.filter { c ->
c.title.contains(searchText, ignoreCase = true)
|| c.name.contains(searchText, ignoreCase = true)
val communities =
communityRepository.getSubscribed(auth)
.let {
val searchText = uiState.value.searchText
if (searchText.isNotEmpty()) {
it.filter { c ->
c.title.contains(searchText, ignoreCase = true) ||
c.name.contains(searchText, ignoreCase = true)
}
} else {
it
}
} else {
it
}
}.map { community ->
community.copy(favorite = community.id in favoriteCommunityIds)
}.sortedBy { it.name }
val multiCommunitites = multiCommunityRepository.getAll(accountId)
.let {
val searchText = uiState.value.searchText
if (searchText.isNotEmpty()) {
it.filter { c ->
c.name.contains(searchText, ignoreCase = true)
}.map { community ->
community.copy(favorite = community.id in favoriteCommunityIds)
}.sortedBy { it.name }
val multiCommunitites =
multiCommunityRepository.getAll(accountId)
.let {
val searchText = uiState.value.searchText
if (searchText.isNotEmpty()) {
it.filter { c ->
c.name.contains(searchText, ignoreCase = true)
}
} else {
it
}
} else {
it
}
}
.sortedBy { it.name }
.sortedBy { it.name }
updateState {
it.copy(
@ -147,10 +146,11 @@ class ManageSubscriptionsViewModel(
}
private fun unsubscribe(community: CommunityModel) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val auth = identityRepository.authToken.value
communityRepository.unsubscribe(
auth = auth, id = community.id
auth = auth,
id = community.id,
)
updateState {
it.copy(communities = it.communities.filter { c -> c.id != community.id })
@ -159,7 +159,7 @@ class ManageSubscriptionsViewModel(
}
private fun deleteMultiCommunity(community: MultiCommunityModel) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
multiCommunityRepository.delete(community)
updateState {
val newCommunities = it.multiCommunities.filter { c -> c.id != community.id }
@ -170,23 +170,24 @@ 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
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 }
} else {
oldCommunities + community
}.sortedBy { it.name }
updateState { it.copy(multiCommunities = newCommunities) }
}
private fun toggleFavorite(community: CommunityModel) {
val communityId = community.id
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val accountId = accountRepository.getActive()?.id ?: 0L
val newValue = !community.favorite
if (newValue) {
@ -206,13 +207,14 @@ class ManageSubscriptionsViewModel(
private fun handleCommunityUpdate(community: CommunityModel) {
updateState {
it.copy(
communities = it.communities.map { c ->
if (c.id == community.id) {
community
} else {
c
}
},
communities =
it.communities.map { c ->
if (c.id == community.id) {
community
} else {
c
}
},
)
}
}

View File

@ -13,8 +13,6 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PersonMentionM
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SortType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -30,9 +28,8 @@ class InboxMentionsViewModel(
private val notificationCenter: NotificationCenter,
) : InboxMentionsMviModel,
DefaultMviModel<InboxMentionsMviModel.Intent, InboxMentionsMviModel.UiState, InboxMentionsMviModel.Effect>(
initialState = InboxMentionsMviModel.UiState()
initialState = InboxMentionsMviModel.UiState(),
) {
private var currentPage: Int = 1
init {
@ -78,14 +75,16 @@ class InboxMentionsViewModel(
override fun reduce(intent: InboxMentionsMviModel.Intent) {
when (intent) {
InboxMentionsMviModel.Intent.LoadNextPage -> screenModelScope.launch {
loadNextPage()
}
InboxMentionsMviModel.Intent.LoadNextPage ->
screenModelScope.launch {
loadNextPage()
}
InboxMentionsMviModel.Intent.Refresh -> screenModelScope.launch {
refresh()
emitEffect(InboxMentionsMviModel.Effect.BackToTop)
}
InboxMentionsMviModel.Intent.Refresh ->
screenModelScope.launch {
refresh()
emitEffect(InboxMentionsMviModel.Effect.BackToTop)
}
is InboxMentionsMviModel.Intent.MarkAsRead -> {
markAsRead(
@ -138,28 +137,29 @@ class InboxMentionsViewModel(
return
}
updateState { it.copy(loading = true) }
val auth = identityRepository.authToken.value
val refreshing = currentState.refreshing
val unreadOnly = currentState.unreadOnly
val itemList = userRepository.getMentions(
auth = auth,
page = currentPage,
unreadOnly = unreadOnly,
sort = SortType.New,
)?.map {
it.copy(isCommentReply = it.comment.depth > 0)
}
val itemList =
userRepository.getMentions(
auth = auth,
page = currentPage,
unreadOnly = unreadOnly,
sort = SortType.New,
)?.map {
it.copy(isCommentReply = it.comment.depth > 0)
}
if (!itemList.isNullOrEmpty()) {
currentPage++
}
updateState {
val newItems = if (refreshing) {
itemList.orEmpty()
} else {
it.mentions + itemList.orEmpty()
}
val newItems =
if (refreshing) {
itemList.orEmpty()
} else {
it.mentions + itemList.orEmpty()
}
it.copy(
mentions = newItems,
loading = false,
@ -173,18 +173,22 @@ class InboxMentionsViewModel(
private fun handleItemUpdate(item: PersonMentionModel) {
updateState {
it.copy(
mentions = it.mentions.map { i ->
if (i.id == item.id) {
item
} else {
i
}
}
mentions =
it.mentions.map { i ->
if (i.id == item.id) {
item
} else {
i
}
},
)
}
}
private fun markAsRead(read: Boolean, mention: PersonMentionModel) {
private fun markAsRead(
read: Boolean,
mention: PersonMentionModel,
) {
val auth = identityRepository.authToken.value
screenModelScope.launch {
userRepository.setMentionRead(
@ -196,9 +200,10 @@ class InboxMentionsViewModel(
if (read && currentState.unreadOnly) {
updateState {
it.copy(
mentions = currentState.mentions.filter { m ->
m.id != mention.id
}
mentions =
currentState.mentions.filter { m ->
m.id != mention.id
},
)
}
} else {
@ -211,14 +216,16 @@ class InboxMentionsViewModel(
private fun toggleUpVoteComment(mention: PersonMentionModel) {
val newValue = mention.myVote <= 0
val newComment = commentRepository.asUpVoted(
comment = mention.comment,
voted = newValue,
)
val newMention = mention.copy(
myVote = newComment.myVote,
score = newComment.score,
)
val newComment =
commentRepository.asUpVoted(
comment = mention.comment,
voted = newValue,
)
val newMention =
mention.copy(
myVote = newComment.myVote,
score = newComment.score,
)
handleItemUpdate(newMention)
screenModelScope.launch {
try {
@ -237,10 +244,11 @@ class InboxMentionsViewModel(
private fun toggleDownVoteComment(mention: PersonMentionModel) {
val newValue = mention.myVote >= 0
val newComment = commentRepository.asDownVoted(mention.comment, newValue)
val newMention = mention.copy(
myVote = newComment.myVote,
score = newComment.score,
)
val newMention =
mention.copy(
myVote = newComment.myVote,
score = newComment.score,
)
handleItemUpdate(newMention)
screenModelScope.launch {
try {
@ -265,7 +273,7 @@ class InboxMentionsViewModel(
private fun handleLogout() {
updateState { it.copy(mentions = emptyList()) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
refresh(initial = true)
}
}

View File

@ -10,12 +10,9 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.inbox.InboxCoordinator
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.otherUser
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PrivateMessageRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class InboxMessagesViewModel(
private val identityRepository: IdentityRepository,
@ -28,7 +25,6 @@ class InboxMessagesViewModel(
DefaultMviModel<InboxMessagesMviModel.Intent, InboxMessagesMviModel.UiState, InboxMessagesMviModel.Effect>(
initialState = InboxMessagesMviModel.UiState(),
) {
private var currentPage: Int = 1
init {
@ -58,32 +54,31 @@ class InboxMessagesViewModel(
handleLogout()
}.launchIn(this)
withContext(Dispatchers.IO) {
val auth = identityRepository.authToken.value.orEmpty()
val currentUserId = siteRepository.getCurrentUser(auth)?.id ?: 0
updateState { it.copy(currentUserId = currentUserId) }
val auth = identityRepository.authToken.value.orEmpty()
val currentUserId = siteRepository.getCurrentUser(auth)?.id ?: 0
updateState { it.copy(currentUserId = currentUserId) }
if (uiState.value.initial) {
val value = coordinator.unreadOnly.value
changeUnreadOnly(value)
refresh(initial = true)
}
updateUnreadItems()
if (uiState.value.initial) {
val value = coordinator.unreadOnly.value
changeUnreadOnly(value)
refresh(initial = true)
}
updateUnreadItems()
}
}
override fun reduce(intent: InboxMessagesMviModel.Intent) {
when (intent) {
InboxMessagesMviModel.Intent.LoadNextPage -> screenModelScope.launch {
loadNextPage()
}
InboxMessagesMviModel.Intent.LoadNextPage ->
screenModelScope.launch {
loadNextPage()
}
InboxMessagesMviModel.Intent.Refresh -> screenModelScope.launch {
refresh()
emitEffect(InboxMessagesMviModel.Effect.BackToTop)
}
InboxMessagesMviModel.Intent.Refresh ->
screenModelScope.launch {
refresh()
emitEffect(InboxMessagesMviModel.Effect.BackToTop)
}
}
}
@ -123,31 +118,34 @@ class InboxMessagesViewModel(
val auth = identityRepository.authToken.value
val refreshing = currentState.refreshing
val unreadOnly = currentState.unreadOnly
val itemList = messageRepository.getAll(
auth = auth,
page = currentPage,
unreadOnly = unreadOnly,
)?.groupBy {
it.otherUser(currentState.currentUserId)?.id ?: 0
}?.mapNotNull { entry ->
val messages = entry.value.sortedBy { m -> m.publishDate }
messages.lastOrNull()
}
val itemList =
messageRepository.getAll(
auth = auth,
page = currentPage,
unreadOnly = unreadOnly,
)?.groupBy {
it.otherUser(currentState.currentUserId)?.id ?: 0
}?.mapNotNull { entry ->
val messages = entry.value.sortedBy { m -> m.publishDate }
messages.lastOrNull()
}
if (!itemList.isNullOrEmpty()) {
currentPage++
}
updateState {
val newItems = if (refreshing) {
itemList.orEmpty()
} else {
it.chats + itemList.orEmpty().filter { outerChat ->
val outerOtherUser = outerChat.otherUser(currentState.currentUserId)
currentState.chats.none { chat ->
val otherUser = chat.otherUser(currentState.currentUserId)
outerOtherUser == otherUser
}
val newItems =
if (refreshing) {
itemList.orEmpty()
} else {
it.chats +
itemList.orEmpty().filter { outerChat ->
val outerOtherUser = outerChat.otherUser(currentState.currentUserId)
currentState.chats.none { chat ->
val otherUser = chat.otherUser(currentState.currentUserId)
outerOtherUser == otherUser
}
}
}
}
it.copy(
chats = newItems,
loading = false,
@ -167,7 +165,7 @@ class InboxMessagesViewModel(
private fun handleLogout() {
updateState { it.copy(chats = emptyList()) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
refresh(initial = true)
}
}

View File

@ -22,13 +22,10 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class MultiCommunityViewModel(
private val communityId: Long,
@ -47,9 +44,8 @@ class MultiCommunityViewModel(
private val postNavigationManager: PostNavigationManager,
) : MultiCommunityMviModel,
DefaultMviModel<MultiCommunityMviModel.Intent, MultiCommunityMviModel.UiState, MultiCommunityMviModel.Effect>(
initialState = MultiCommunityMviModel.UiState()
initialState = MultiCommunityMviModel.UiState(),
) {
private var hideReadPosts = false
init {
@ -105,18 +101,16 @@ class MultiCommunityViewModel(
val user = siteRepository.getCurrentUser(auth)
updateState { it.copy(currentUserId = user?.id ?: 0) }
}
withContext(Dispatchers.IO) {
if (uiState.value.posts.isEmpty()) {
val settings = settingsRepository.currentSettings.value
val sortTypes = getSortTypesUseCase.getTypesForPosts()
updateState {
it.copy(
sortType = settings.defaultPostSortType.toSortType(),
availableSortTypes = sortTypes,
)
}
refresh(initial = true)
if (uiState.value.posts.isEmpty()) {
val settings = settingsRepository.currentSettings.value
val sortTypes = getSortTypesUseCase.getTypesForPosts()
updateState {
it.copy(
sortType = settings.defaultPostSortType.toSortType(),
availableSortTypes = sortTypes,
)
}
refresh(initial = true)
}
}
}
@ -133,13 +127,15 @@ class MultiCommunityViewModel(
}
MultiCommunityMviModel.Intent.HapticIndication -> hapticFeedback.vibrate()
MultiCommunityMviModel.Intent.LoadNextPage -> screenModelScope.launch {
loadNextPage()
}
MultiCommunityMviModel.Intent.LoadNextPage ->
screenModelScope.launch {
loadNextPage()
}
MultiCommunityMviModel.Intent.Refresh -> screenModelScope.launch {
refresh()
}
MultiCommunityMviModel.Intent.Refresh ->
screenModelScope.launch {
refresh()
}
is MultiCommunityMviModel.Intent.SavePost -> {
if (intent.feedback) {
@ -162,17 +158,20 @@ class MultiCommunityViewModel(
}
MultiCommunityMviModel.Intent.ClearRead -> clearRead()
is MultiCommunityMviModel.Intent.MarkAsRead -> markAsRead(
post = uiState.value.posts.first { it.id == intent.id },
)
is MultiCommunityMviModel.Intent.MarkAsRead ->
markAsRead(
post = uiState.value.posts.first { it.id == intent.id },
)
is MultiCommunityMviModel.Intent.Hide -> hide(
post = uiState.value.posts.first { it.id == intent.id },
)
is MultiCommunityMviModel.Intent.Hide ->
hide(
post = uiState.value.posts.first { it.id == intent.id },
)
is MultiCommunityMviModel.Intent.Copy -> screenModelScope.launch {
emitEffect(MultiCommunityMviModel.Effect.TriggerCopy(intent.value))
}
is MultiCommunityMviModel.Intent.Copy ->
screenModelScope.launch {
emitEffect(MultiCommunityMviModel.Effect.TriggerCopy(intent.value))
}
MultiCommunityMviModel.Intent.WillOpenDetail -> {
val state = postPaginationManager.extractState()
@ -189,7 +188,7 @@ class MultiCommunityViewModel(
communityIds = uiState.value.community.communityIds,
sortType = sortType,
includeNsfw = settingsRepository.currentSettings.value.includeNsfw,
)
),
)
updateState {
it.copy(
@ -211,13 +210,14 @@ class MultiCommunityViewModel(
updateState { it.copy(loading = true) }
val posts = postPaginationManager.loadNextPage().let {
if (!hideReadPosts) {
it
} else {
it.filter { post -> !post.read }
val posts =
postPaginationManager.loadNextPage().let {
if (!hideReadPosts) {
it
} else {
it.filter { post -> !post.read }
}
}
}
val canFetchMore = postPaginationManager.canFetchMore
if (uiState.value.autoLoadImages) {
posts.forEach { post ->
@ -251,12 +251,13 @@ class MultiCommunityViewModel(
private fun toggleUpVote(post: PostModel) {
val newVote = post.myVote <= 0
val newPost = postRepository.asUpVoted(
post = post,
voted = newVote,
)
val newPost =
postRepository.asUpVoted(
post = post,
voted = newVote,
)
handlePostUpdate(newPost)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.upVote(
@ -277,7 +278,7 @@ class MultiCommunityViewModel(
return
}
val newPost = post.copy(read = true)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.setRead(
@ -295,12 +296,13 @@ class MultiCommunityViewModel(
private fun toggleDownVote(post: PostModel) {
val newValue = post.myVote >= 0
val newPost = postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
val newPost =
postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.downVote(
@ -318,12 +320,13 @@ class MultiCommunityViewModel(
private fun toggleSave(post: PostModel) {
val newValue = !post.saved
val newPost = postRepository.asSaved(
post = post,
saved = newValue,
)
val newPost =
postRepository.asSaved(
post = post,
saved = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.save(
@ -342,13 +345,14 @@ class MultiCommunityViewModel(
private fun handlePostUpdate(post: PostModel) {
updateState {
it.copy(
posts = it.posts.map { p ->
if (p.id == post.id) {
post
} else {
p
}
},
posts =
it.posts.map { p ->
if (p.id == post.id) {
post
} else {
p
}
},
)
}
}

View File

@ -12,9 +12,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.ValidationError
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.IO
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.launchIn
@ -33,9 +31,8 @@ class MultiCommunityEditorViewModel(
private val notificationCenter: NotificationCenter,
) : MultiCommunityEditorMviModel,
DefaultMviModel<MultiCommunityEditorMviModel.Intent, MultiCommunityEditorMviModel.UiState, MultiCommunityEditorMviModel.Effect>(
initialState = MultiCommunityEditorMviModel.UiState()
initialState = MultiCommunityEditorMviModel.UiState(),
) {
private var communities: List<Pair<CommunityModel, Boolean>> = emptyList()
private val searchEventChannel = Channel<Unit>()
@ -73,14 +70,16 @@ class MultiCommunityEditorViewModel(
}
private fun populate() {
screenModelScope.launch(Dispatchers.IO) {
val editedCommunity = communityId?.toLong()?.let {
multiCommunityRepository.getById(it)
}
screenModelScope.launch {
val editedCommunity =
communityId?.let {
multiCommunityRepository.getById(it)
}
val auth = identityRepository.authToken.value
communities = communityRepository.getSubscribed(auth).sortedBy { it.name }.map { c ->
c to (editedCommunity?.communityIds?.contains(c.id) == true)
}
communities =
communityRepository.getSubscribed(auth).sortedBy { it.name }.map { c ->
c to (editedCommunity?.communityIds?.contains(c.id) == true)
}
updateState {
val newCommunities = communities
val availableIcons = newCommunities.filter { i -> i.second }.mapNotNull { i -> i.first.icon }
@ -103,36 +102,40 @@ class MultiCommunityEditorViewModel(
private fun filterCommunities(): List<Pair<CommunityModel, Boolean>> {
val searchText = uiState.value.searchText
val res = if (searchText.isNotEmpty()) {
communities.filter { it.first.name.contains(other = searchText, ignoreCase = true) }
} else {
communities
}
val res =
if (searchText.isNotEmpty()) {
communities.filter { it.first.name.contains(other = searchText, ignoreCase = true) }
} else {
communities
}
return res
}
private fun selectImage(index: Int?) {
val image = if (index == null) {
null
} else {
uiState.value.availableIcons[index]
}
val image =
if (index == null) {
null
} else {
uiState.value.availableIcons[index]
}
updateState { it.copy(icon = image) }
}
private fun toggleCommunity(communityId: Long) {
val newCommunities = communities.map { item ->
if (item.first.id == communityId) {
item.first to !item.second
} else {
item
val newCommunities =
communities.map { item ->
if (item.first.id == communityId) {
item.first to !item.second
} else {
item
}
}
val availableIcons =
newCommunities.filter { i ->
i.second
}.mapNotNull { i ->
i.first.icon
}
}
val availableIcons = newCommunities.filter { i ->
i.second
}.mapNotNull { i ->
i.first.icon
}
communities = newCommunities
val filtered = filterCommunities()
updateState { state ->
@ -156,26 +159,28 @@ class MultiCommunityEditorViewModel(
return
}
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val icon = currentState.icon
val communityIds = currentState.communities.filter { it.second }.map { it.first.id }
val editedCommunity = communityId?.toLong()?.let {
multiCommunityRepository.getById(it)
}
val multiCommunity = editedCommunity?.copy(
name = name,
icon = icon,
communityIds = communityIds,
) ?: MultiCommunityModel(
name = name,
icon = icon,
communityIds = communityIds,
)
val editedCommunity =
communityId?.let {
multiCommunityRepository.getById(it)
}
val multiCommunity =
editedCommunity?.copy(
name = name,
icon = icon,
communityIds = communityIds,
) ?: MultiCommunityModel(
name = name,
icon = icon,
communityIds = communityIds,
)
val accountId = accountRepository.getActive()?.id ?: return@launch
if (multiCommunity.id == null) {
val id = multiCommunityRepository.create(multiCommunity, accountId)
notificationCenter.send(
NotificationCenterEvent.MultiCommunityCreated(multiCommunity.copy(id = id))
NotificationCenterEvent.MultiCommunityCreated(multiCommunity.copy(id = id)),
)
} else {
multiCommunityRepository.update(multiCommunity)

View File

@ -21,9 +21,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SortType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.IO
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
@ -32,7 +30,6 @@ import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.yield
@ -51,9 +48,8 @@ class ProfileLoggedViewModel(
private val postNavigationManager: PostNavigationManager,
) : ProfileLoggedMviModel,
DefaultMviModel<ProfileLoggedMviModel.Intent, ProfileLoggedMviModel.UiState, ProfileLoggedMviModel.Effect>(
initialState = ProfileLoggedMviModel.UiState()
initialState = ProfileLoggedMviModel.UiState(),
) {
init {
updateState { it.copy(instance = apiConfigurationRepository.instance.value) }
screenModelScope.launch {
@ -110,14 +106,10 @@ class ProfileLoggedViewModel(
initial = false,
)
}
withContext(Dispatchers.IO) {
refresh(initial = false)
}
refresh(initial = false)
} else {
withContext(Dispatchers.IO) {
refreshUser()
refresh(initial = true)
}
refreshUser()
refresh(initial = true)
}
}
}
@ -128,13 +120,15 @@ class ProfileLoggedViewModel(
is ProfileLoggedMviModel.Intent.ChangeSection -> changeSection(intent.section)
is ProfileLoggedMviModel.Intent.DeleteComment -> deleteComment(intent.id)
is ProfileLoggedMviModel.Intent.DeletePost -> deletePost(intent.id)
ProfileLoggedMviModel.Intent.LoadNextPage -> screenModelScope.launch {
loadNextPage()
}
ProfileLoggedMviModel.Intent.LoadNextPage ->
screenModelScope.launch {
loadNextPage()
}
ProfileLoggedMviModel.Intent.Refresh -> screenModelScope.launch {
refresh()
}
ProfileLoggedMviModel.Intent.Refresh ->
screenModelScope.launch {
refresh()
}
is ProfileLoggedMviModel.Intent.Share -> {
shareHelper.share(intent.url)
@ -228,13 +222,13 @@ class ProfileLoggedViewModel(
PostPaginationSpecification.User(
id = userId,
sortType = SortType.New,
)
),
)
commentPaginationManager.reset(
CommentPaginationSpecification.User(
id = userId,
sortType = SortType.New,
)
),
)
updateState {
it.copy(
@ -268,18 +262,20 @@ class ProfileLoggedViewModel(
val section = currentState.section
if (section == ProfileLoggedSection.Posts) {
coroutineScope {
val posts = async {
postPaginationManager.loadNextPage()
}.await()
val comments = async {
if (currentState.comments.isEmpty() || refreshing) {
// this is needed because otherwise on first selector change
// the lazy column scrolls back to top (it must have an empty data set)
commentPaginationManager.loadNextPage()
} else {
currentState.comments
}
}.await()
val posts =
async {
postPaginationManager.loadNextPage()
}.await()
val comments =
async {
if (currentState.comments.isEmpty() || refreshing) {
// this is needed because otherwise on first selector change
// the lazy column scrolls back to top (it must have an empty data set)
commentPaginationManager.loadNextPage()
} else {
currentState.comments
}
}.await()
updateState {
it.copy(
posts = posts,
@ -307,10 +303,11 @@ class ProfileLoggedViewModel(
private fun toggleUpVotePost(post: PostModel) {
val newVote = post.myVote <= 0
val newPost = postRepository.asUpVoted(
post = post,
voted = newVote,
)
val newPost =
postRepository.asUpVoted(
post = post,
voted = newVote,
)
handlePostUpdate(newPost)
screenModelScope.launch {
try {
@ -329,10 +326,11 @@ class ProfileLoggedViewModel(
private fun toggleDownVotePost(post: PostModel) {
val newValue = post.myVote >= 0
val newPost = postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
val newPost =
postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch {
try {
@ -351,10 +349,11 @@ class ProfileLoggedViewModel(
private fun toggleSavePost(post: PostModel) {
val newValue = !post.saved
val newPost = postRepository.asSaved(
post = post,
saved = newValue,
)
val newPost =
postRepository.asSaved(
post = post,
saved = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch {
try {
@ -373,10 +372,11 @@ class ProfileLoggedViewModel(
private fun toggleUpVoteComment(comment: CommentModel) {
val newValue = comment.myVote <= 0
val newComment = commentRepository.asUpVoted(
comment = comment,
voted = newValue,
)
val newComment =
commentRepository.asUpVoted(
comment = comment,
voted = newValue,
)
handleCommentUpdate(newComment)
screenModelScope.launch {
try {
@ -414,10 +414,11 @@ class ProfileLoggedViewModel(
private fun toggleSaveComment(comment: CommentModel) {
val newValue = !comment.saved
val newComment = commentRepository.asSaved(
comment = comment,
saved = newValue,
)
val newComment =
commentRepository.asSaved(
comment = comment,
saved = newValue,
)
handleCommentUpdate(newComment)
screenModelScope.launch {
try {
@ -437,13 +438,14 @@ class ProfileLoggedViewModel(
private fun handlePostUpdate(post: PostModel) {
updateState {
it.copy(
posts = it.posts.map { p ->
if (p.id == post.id) {
post
} else {
p
}
},
posts =
it.posts.map { p ->
if (p.id == post.id) {
post
} else {
p
}
},
)
}
}
@ -451,13 +453,14 @@ class ProfileLoggedViewModel(
private fun handleCommentUpdate(comment: CommentModel) {
updateState {
it.copy(
comments = it.comments.map { c ->
if (c.id == comment.id) {
comment
} else {
c
}
},
comments =
it.comments.map { c ->
if (c.id == comment.id) {
comment
} else {
c
}
},
)
}
}
@ -467,7 +470,7 @@ class ProfileLoggedViewModel(
}
private fun deletePost(id: Long) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.delete(id = id, auth = auth)
handlePostDelete(id)
@ -475,7 +478,7 @@ class ProfileLoggedViewModel(
}
private fun deleteComment(id: Long) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val auth = identityRepository.authToken.value.orEmpty()
commentRepository.delete(id, auth)
refresh()

View File

@ -26,8 +26,6 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortT
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@ -52,9 +50,8 @@ class PostListViewModel(
private val postNavigationManager: PostNavigationManager,
) : PostListMviModel,
DefaultMviModel<PostListMviModel.Intent, PostListMviModel.UiState, PostListMviModel.Effect>(
initialState = PostListMviModel.UiState()
initialState = PostListMviModel.UiState(),
) {
private var hideReadPosts = false
init {
@ -184,16 +181,18 @@ class PostListViewModel(
override fun reduce(intent: PostListMviModel.Intent) {
when (intent) {
PostListMviModel.Intent.LoadNextPage -> screenModelScope.launch {
loadNextPage()
}
is PostListMviModel.Intent.Refresh -> screenModelScope.launch {
if (intent.hardReset) {
refreshUser()
PostListMviModel.Intent.LoadNextPage ->
screenModelScope.launch {
loadNextPage()
}
is PostListMviModel.Intent.Refresh ->
screenModelScope.launch {
if (intent.hardReset) {
refreshUser()
}
refresh()
}
refresh()
}
is PostListMviModel.Intent.ChangeListing -> applyListingType(intent.value)
is PostListMviModel.Intent.DownVotePost -> {
@ -256,9 +255,10 @@ class PostListViewModel(
)
}
is PostListMviModel.Intent.Copy -> screenModelScope.launch {
emitEffect(PostListMviModel.Effect.TriggerCopy(intent.value))
}
is PostListMviModel.Intent.Copy ->
screenModelScope.launch {
emitEffect(PostListMviModel.Effect.TriggerCopy(intent.value))
}
PostListMviModel.Intent.WillOpenDetail -> {
val state = postPaginationManager.extractState()
@ -277,7 +277,7 @@ class PostListViewModel(
listingType = listingType,
sortType = sortType,
includeNsfw = settingsRepository.currentSettings.value.includeNsfw,
)
),
)
updateState {
it.copy(
@ -301,13 +301,14 @@ class PostListViewModel(
return
}
updateState { it.copy(loading = true) }
val posts = postPaginationManager.loadNextPage().let {
if (!hideReadPosts) {
it
} else {
it.filter { post -> !post.read }
val posts =
postPaginationManager.loadNextPage().let {
if (!hideReadPosts) {
it
} else {
it.filter { post -> !post.read }
}
}
}
if (uiState.value.autoLoadImages) {
posts.forEach { post ->
post.imageUrl.takeIf { i -> i.isNotEmpty() }?.also { url ->
@ -343,7 +344,7 @@ class PostListViewModel(
return
}
updateState { it.copy(listingType = value) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
emitEffect(PostListMviModel.Effect.BackToTop)
delay(50)
refresh()
@ -352,12 +353,13 @@ class PostListViewModel(
private fun toggleUpVote(post: PostModel) {
val newVote = post.myVote <= 0
val newPost = postRepository.asUpVoted(
post = post,
voted = newVote,
)
val newPost =
postRepository.asUpVoted(
post = post,
voted = newVote,
)
handlePostUpdate(newPost)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.upVote(
@ -378,7 +380,7 @@ class PostListViewModel(
return
}
val newPost = post.copy(read = true)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.setRead(
@ -396,12 +398,13 @@ class PostListViewModel(
private fun toggleDownVote(post: PostModel) {
val newValue = post.myVote >= 0
val newPost = postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
val newPost =
postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.downVote(
@ -419,12 +422,13 @@ class PostListViewModel(
private fun toggleSave(post: PostModel) {
val newValue = !post.saved
val newPost = postRepository.asSaved(
post = post,
saved = newValue,
)
val newPost =
postRepository.asSaved(
post = post,
saved = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.save(
@ -443,13 +447,14 @@ class PostListViewModel(
private fun handlePostUpdate(post: PostModel) {
updateState {
it.copy(
posts = it.posts.map { p ->
if (p.id == post.id) {
post
} else {
p
}
},
posts =
it.posts.map { p ->
if (p.id == post.id) {
post
} else {
p
}
},
)
}
}
@ -465,7 +470,7 @@ class PostListViewModel(
}
private fun handlePostDelete(id: Long) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val auth = identityRepository.authToken.value.orEmpty()
postRepository.delete(id = id, auth = auth)
handlePostDelete(id)
@ -491,21 +496,21 @@ class PostListViewModel(
}
private fun blockUser(userId: Long) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val auth = identityRepository.authToken.value
userRepository.block(userId, true, auth)
}
}
private fun blockCommunity(communityId: Long) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val auth = identityRepository.authToken.value
communityRepository.block(communityId, true, auth)
}
}
private fun blockInstance(instanceId: Long) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value
siteRepository.block(instanceId, true, auth)

View File

@ -14,8 +14,6 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SortType
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -34,7 +32,6 @@ class InboxRepliesViewModel(
DefaultMviModel<InboxRepliesMviModel.Intent, InboxRepliesMviModel.UiState, InboxRepliesMviModel.Effect>(
initialState = InboxRepliesMviModel.UiState(),
) {
private var currentPage: Int = 1
private var currentUserId: Long? = null
@ -81,14 +78,16 @@ class InboxRepliesViewModel(
override fun reduce(intent: InboxRepliesMviModel.Intent) {
when (intent) {
InboxRepliesMviModel.Intent.LoadNextPage -> screenModelScope.launch {
loadNextPage()
}
InboxRepliesMviModel.Intent.LoadNextPage ->
screenModelScope.launch {
loadNextPage()
}
InboxRepliesMviModel.Intent.Refresh -> screenModelScope.launch {
refresh()
emitEffect(InboxRepliesMviModel.Effect.BackToTop)
}
InboxRepliesMviModel.Intent.Refresh ->
screenModelScope.launch {
refresh()
emitEffect(InboxRepliesMviModel.Effect.BackToTop)
}
is InboxRepliesMviModel.Intent.MarkAsRead -> {
markAsRead(
@ -97,7 +96,6 @@ class InboxRepliesViewModel(
)
}
InboxRepliesMviModel.Intent.HapticIndication -> hapticFeedback.vibrate()
is InboxRepliesMviModel.Intent.DownVoteComment -> {
toggleDownVoteComment(
@ -149,24 +147,26 @@ class InboxRepliesViewModel(
val auth = identityRepository.authToken.value
val refreshing = currentState.refreshing
val unreadOnly = currentState.unreadOnly
val itemList = userRepository.getReplies(
auth = auth,
page = currentPage,
unreadOnly = unreadOnly,
sort = SortType.New,
)?.map {
it.copy(isCommentReply = it.comment.depth > 0)
}
val itemList =
userRepository.getReplies(
auth = auth,
page = currentPage,
unreadOnly = unreadOnly,
sort = SortType.New,
)?.map {
it.copy(isCommentReply = it.comment.depth > 0)
}
if (!itemList.isNullOrEmpty()) {
currentPage++
}
updateState {
val newItems = if (refreshing) {
itemList.orEmpty()
} else {
it.replies + itemList.orEmpty()
}
val newItems =
if (refreshing) {
itemList.orEmpty()
} else {
it.replies + itemList.orEmpty()
}
it.copy(
replies = newItems,
loading = false,
@ -180,18 +180,22 @@ class InboxRepliesViewModel(
private fun handleItemUpdate(item: PersonMentionModel) {
updateState {
it.copy(
replies = it.replies.map { i ->
if (i.id == item.id) {
item
} else {
i
}
}
replies =
it.replies.map { i ->
if (i.id == item.id) {
item
} else {
i
}
},
)
}
}
private fun markAsRead(read: Boolean, reply: PersonMentionModel) {
private fun markAsRead(
read: Boolean,
reply: PersonMentionModel,
) {
val auth = identityRepository.authToken.value
screenModelScope.launch {
userRepository.setReplyRead(
@ -203,9 +207,10 @@ class InboxRepliesViewModel(
if (read && currentState.unreadOnly) {
updateState {
it.copy(
replies = currentState.replies.filter { r ->
r.id != reply.id
}
replies =
currentState.replies.filter { r ->
r.id != reply.id
},
)
}
} else {
@ -218,10 +223,11 @@ class InboxRepliesViewModel(
private fun toggleUpVoteComment(mention: PersonMentionModel) {
val newValue = mention.myVote <= 0
val newMention = commentRepository.asUpVoted(
mention = mention,
voted = newValue,
)
val newMention =
commentRepository.asUpVoted(
mention = mention,
voted = newValue,
)
handleItemUpdate(newMention)
screenModelScope.launch {
try {
@ -239,10 +245,11 @@ class InboxRepliesViewModel(
private fun toggleDownVoteComment(mention: PersonMentionModel) {
val newValue = mention.myVote >= 0
val newMention = commentRepository.asDownVoted(
mention = mention,
downVoted = newValue
)
val newMention =
commentRepository.asDownVoted(
mention = mention,
downVoted = newValue,
)
handleItemUpdate(newMention)
screenModelScope.launch {
try {
@ -265,7 +272,7 @@ class InboxRepliesViewModel(
private fun handleLogout() {
updateState { it.copy(replies = emptyList()) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
refresh(initial = true)
}
}

View File

@ -12,8 +12,6 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentReportM
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostReportModel
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
@ -34,7 +32,6 @@ class ReportListViewModel(
DefaultMviModel<ReportListMviModel.Intent, ReportListMviModel.UiState, ReportListMviModel.Effect>(
initialState = ReportListMviModel.UiState(),
) {
private val currentPage = mutableMapOf<ReportListSection, Int>()
init {
@ -66,24 +63,28 @@ class ReportListViewModel(
when (intent) {
is ReportListMviModel.Intent.ChangeSection -> changeSection(intent.value)
is ReportListMviModel.Intent.ChangeUnresolvedOnly -> changeUnresolvedOnly(intent.value)
ReportListMviModel.Intent.Refresh -> screenModelScope.launch(Dispatchers.IO) {
refresh()
}
ReportListMviModel.Intent.LoadNextPage -> screenModelScope.launch {
loadNextPage()
}
is ReportListMviModel.Intent.ResolveComment -> uiState.value.commentReports
.firstOrNull { it.id == intent.id }?.also {
resolve(it)
ReportListMviModel.Intent.Refresh ->
screenModelScope.launch {
refresh()
}
is ReportListMviModel.Intent.ResolvePost -> uiState.value.postReports
.firstOrNull { it.id == intent.id }?.also {
resolve(it)
ReportListMviModel.Intent.LoadNextPage ->
screenModelScope.launch {
loadNextPage()
}
is ReportListMviModel.Intent.ResolveComment ->
uiState.value.commentReports
.firstOrNull { it.id == intent.id }?.also {
resolve(it)
}
is ReportListMviModel.Intent.ResolvePost ->
uiState.value.postReports
.firstOrNull { it.id == intent.id }?.also {
resolve(it)
}
ReportListMviModel.Intent.HapticIndication -> hapticFeedback.vibrate()
}
}
@ -100,7 +101,7 @@ class ReportListViewModel(
updateState {
it.copy(unresolvedOnly = value)
}
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
emitEffect(ReportListMviModel.Effect.BackToTop)
delay(50)
refresh(initial = true)
@ -136,34 +137,37 @@ class ReportListViewModel(
if (section == ReportListSection.Posts) {
val page = currentPage[ReportListSection.Posts] ?: 1
coroutineScope {
val itemList = async {
postRepository.getReports(
auth = auth,
communityId = communityId,
page = page,
unresolvedOnly = unresolvedOnly,
)
}.await()
val commentReports = async {
if (page == 1 && (currentState.commentReports.isEmpty() || refreshing)) {
// this is needed because otherwise on first selector change
// the lazy column scrolls back to top (it must have an empty data set)
commentRepository.getReports(
val itemList =
async {
postRepository.getReports(
auth = auth,
communityId = communityId,
page = 1,
page = page,
unresolvedOnly = unresolvedOnly,
).orEmpty()
} else {
currentState.commentReports
}
}.await()
)
}.await()
val commentReports =
async {
if (page == 1 && (currentState.commentReports.isEmpty() || refreshing)) {
// this is needed because otherwise on first selector change
// the lazy column scrolls back to top (it must have an empty data set)
commentRepository.getReports(
auth = auth,
communityId = communityId,
page = 1,
unresolvedOnly = unresolvedOnly,
).orEmpty()
} else {
currentState.commentReports
}
}.await()
updateState {
val postReports = if (refreshing) {
itemList.orEmpty()
} else {
it.postReports + itemList.orEmpty()
}
val postReports =
if (refreshing) {
itemList.orEmpty()
} else {
it.postReports + itemList.orEmpty()
}
it.copy(
postReports = postReports,
commentReports = commentReports,
@ -179,19 +183,21 @@ class ReportListViewModel(
}
} else {
val page = currentPage[ReportListSection.Comments] ?: 1
val itemList = commentRepository.getReports(
auth = auth,
communityId = communityId,
page = page,
unresolvedOnly = unresolvedOnly,
)
val itemList =
commentRepository.getReports(
auth = auth,
communityId = communityId,
page = page,
unresolvedOnly = unresolvedOnly,
)
updateState {
val commentReports = if (refreshing) {
itemList.orEmpty()
} else {
it.commentReports + itemList.orEmpty()
}
val commentReports =
if (refreshing) {
itemList.orEmpty()
} else {
it.commentReports + itemList.orEmpty()
}
it.copy(
commentReports = commentReports,
loading = false,
@ -210,11 +216,12 @@ class ReportListViewModel(
screenModelScope.launch {
updateState { it.copy(asyncInProgress = true) }
val auth = identityRepository.authToken.value.orEmpty()
val newReport = postRepository.resolveReport(
reportId = report.id,
auth = auth,
resolved = !report.resolved
)
val newReport =
postRepository.resolveReport(
reportId = report.id,
auth = auth,
resolved = !report.resolved,
)
updateState { it.copy(asyncInProgress = false) }
if (newReport != null) {
if (uiState.value.unresolvedOnly && newReport.resolved) {
@ -230,11 +237,12 @@ class ReportListViewModel(
screenModelScope.launch {
updateState { it.copy(asyncInProgress = true) }
val auth = identityRepository.authToken.value.orEmpty()
val newReport = commentRepository.resolveReport(
reportId = report.id,
auth = auth,
resolved = !report.resolved
)
val newReport =
commentRepository.resolveReport(
reportId = report.id,
auth = auth,
resolved = !report.resolved,
)
updateState { it.copy(asyncInProgress = false) }
if (newReport != null) {
if (uiState.value.unresolvedOnly && newReport.resolved) {
@ -249,13 +257,14 @@ class ReportListViewModel(
private fun handleReportUpdate(report: PostReportModel) {
updateState {
it.copy(
postReports = it.postReports.map { r ->
if (r.id == report.id) {
report
} else {
r
}
}
postReports =
it.postReports.map { r ->
if (r.id == report.id) {
report
} else {
r
}
},
)
}
}
@ -263,13 +272,14 @@ class ReportListViewModel(
private fun handleReportUpdate(report: CommentReportModel) {
updateState {
it.copy(
commentReports = it.commentReports.map { r ->
if (r.id == report.id) {
report
} else {
r
}
}
commentReports =
it.commentReports.map { r ->
if (r.id == report.id) {
report
} else {
r
}
},
)
}
}
@ -277,7 +287,7 @@ class ReportListViewModel(
private fun handleReporDelete(report: PostReportModel) {
updateState {
it.copy(
postReports = it.postReports.filter { r -> r.id != report.id }
postReports = it.postReports.filter { r -> r.id != report.id },
)
}
}
@ -285,7 +295,7 @@ class ReportListViewModel(
private fun handleReporDelete(report: CommentReportModel) {
updateState {
it.copy(
commentReports = it.commentReports.filter { r -> r.id != report.id }
commentReports = it.commentReports.filter { r -> r.id != report.id },
)
}
}

View File

@ -6,9 +6,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.Inst
import com.github.diegoberaldin.raccoonforlemmy.core.utils.ValidationError
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.ApiConfigurationRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.IO
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.launchIn
@ -24,7 +22,6 @@ class SelectInstanceViewModel(
DefaultMviModel<SelectInstanceMviModel.Intent, SelectInstanceMviModel.State, SelectInstanceMviModel.Effect>(
initialState = SelectInstanceMviModel.State(),
) {
private val saveOperationChannel = Channel<List<String>>()
init {
@ -40,7 +37,7 @@ class SelectInstanceViewModel(
}
if (uiState.value.instances.isEmpty()) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
val instances = instanceRepository.getAll()
updateState { it.copy(instances = instances) }
}
@ -64,7 +61,7 @@ class SelectInstanceViewModel(
}
private fun deleteInstance(value: String) {
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
instanceRepository.remove(value)
val instances = instanceRepository.getAll()
updateState { it.copy(instances = instances) }
@ -83,13 +80,14 @@ class SelectInstanceViewModel(
return
}
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
updateState { it.copy(changeInstanceLoading = true) }
val res = communityRepository.getList(
instance = instanceName,
page = 1,
limit = 1
)
val res =
communityRepository.getList(
instance = instanceName,
page = 1,
limit = 1,
)
if (res.isEmpty()) {
updateState {
it.copy(
@ -115,11 +113,15 @@ class SelectInstanceViewModel(
}
}
private fun swapInstances(from: Int, to: Int) {
val newInstances = uiState.value.instances.toMutableList().apply {
val element = removeAt(from)
add(to, element)
}
private fun swapInstances(
from: Int,
to: Int,
) {
val newInstances =
uiState.value.instances.toMutableList().apply {
val element = removeAt(from)
add(to, element)
}
screenModelScope.launch {
saveOperationChannel.send(newInstances)
updateState {

View File

@ -31,14 +31,12 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepo
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class UserDetailViewModel(
private val userId: Long,
@ -64,12 +62,12 @@ class UserDetailViewModel(
DefaultMviModel<UserDetailMviModel.Intent, UserDetailMviModel.UiState, UserDetailMviModel.Effect>(
initialState = UserDetailMviModel.UiState(),
) {
init {
updateState {
it.copy(
instance = otherInstance.takeIf { n -> n.isNotEmpty() }
?: apiConfigurationRepository.instance.value,
instance =
otherInstance.takeIf { n -> n.isNotEmpty() }
?: apiConfigurationRepository.instance.value,
)
}
screenModelScope.launch {
@ -141,9 +139,7 @@ class UserDetailViewModel(
settingsRepository.currentSettings.value.defaultPostSortType
updateState { it.copy(sortType = defaultPostSortType.toSortType()) }
withContext(Dispatchers.IO) {
refresh(initial = true)
}
refresh(initial = true)
}
}
}
@ -172,13 +168,15 @@ class UserDetailViewModel(
}
UserDetailMviModel.Intent.HapticIndication -> hapticFeedback.vibrate()
UserDetailMviModel.Intent.LoadNextPage -> screenModelScope.launch {
loadNextPage()
}
UserDetailMviModel.Intent.LoadNextPage ->
screenModelScope.launch {
loadNextPage()
}
UserDetailMviModel.Intent.Refresh -> screenModelScope.launch {
refresh()
}
UserDetailMviModel.Intent.Refresh ->
screenModelScope.launch {
refresh()
}
is UserDetailMviModel.Intent.SaveComment -> {
if (intent.feedback) {
@ -222,9 +220,10 @@ class UserDetailViewModel(
UserDetailMviModel.Intent.Block -> blockUser()
UserDetailMviModel.Intent.BlockInstance -> blockInstance()
is UserDetailMviModel.Intent.Copy -> screenModelScope.launch {
emitEffect(UserDetailMviModel.Effect.TriggerCopy(intent.value))
}
is UserDetailMviModel.Intent.Copy ->
screenModelScope.launch {
emitEffect(UserDetailMviModel.Effect.TriggerCopy(intent.value))
}
UserDetailMviModel.Intent.WillOpenDetail -> {
val state = postPaginationManager.extractState()
@ -253,11 +252,12 @@ class UserDetailViewModel(
private fun updateAvailableSortTypes() {
screenModelScope.launch {
val sortTypes = if (uiState.value.section == UserDetailSection.Posts) {
getSortTypesUseCase.getTypesForPosts(otherInstance = otherInstance)
} else {
getSortTypesUseCase.getTypesForComments(otherInstance = otherInstance)
}
val sortTypes =
if (uiState.value.section == UserDetailSection.Posts) {
getSortTypesUseCase.getTypesForPosts(otherInstance = otherInstance)
} else {
getSortTypesUseCase.getTypesForComments(otherInstance = otherInstance)
}
updateState { it.copy(availableSortTypes = sortTypes) }
}
}
@ -269,7 +269,7 @@ class UserDetailViewModel(
name = uiState.value.user.name,
sortType = uiState.value.sortType,
otherInstance = otherInstance,
)
),
)
commentPaginationManager.reset(
CommentPaginationSpecification.User(
@ -277,7 +277,7 @@ class UserDetailViewModel(
name = uiState.value.user.name,
sortType = uiState.value.sortType,
otherInstance = otherInstance,
)
),
)
updateState {
it.copy(
@ -288,12 +288,13 @@ class UserDetailViewModel(
)
}
val auth = identityRepository.authToken.value
val refreshedUser = userRepository.get(
id = userId,
auth = auth,
otherInstance = otherInstance,
username = uiState.value.user.name,
)
val refreshedUser =
userRepository.get(
id = userId,
auth = auth,
otherInstance = otherInstance,
username = uiState.value.user.name,
)
if (refreshedUser != null) {
updateState { it.copy(user = refreshedUser) }
}
@ -311,18 +312,20 @@ class UserDetailViewModel(
val section = currentState.section
if (section == UserDetailSection.Posts) {
coroutineScope {
val posts = async {
postPaginationManager.loadNextPage()
}.await()
val comments = async {
if (currentState.comments.isEmpty() || refreshing) {
// this is needed because otherwise on first selector change
// the lazy column scrolls back to top (it must have an empty data set)
commentPaginationManager.loadNextPage()
} else {
currentState.comments
}
}.await()
val posts =
async {
postPaginationManager.loadNextPage()
}.await()
val comments =
async {
if (currentState.comments.isEmpty() || refreshing) {
// this is needed because otherwise on first selector change
// the lazy column scrolls back to top (it must have an empty data set)
commentPaginationManager.loadNextPage()
} else {
currentState.comments
}
}.await()
updateState {
if (uiState.value.autoLoadImages) {
posts.forEach { post ->
@ -357,10 +360,11 @@ class UserDetailViewModel(
private fun toggleUpVote(post: PostModel) {
val newVote = post.myVote <= 0
val newPost = postRepository.asUpVoted(
post = post,
voted = newVote,
)
val newPost =
postRepository.asUpVoted(
post = post,
voted = newVote,
)
handlePostUpdate(newPost)
screenModelScope.launch {
try {
@ -379,10 +383,11 @@ class UserDetailViewModel(
private fun toggleDownVote(post: PostModel) {
val newValue = post.myVote >= 0
val newPost = postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
val newPost =
postRepository.asDownVoted(
post = post,
downVoted = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch {
try {
@ -401,10 +406,11 @@ class UserDetailViewModel(
private fun toggleSave(post: PostModel) {
val newValue = !post.saved
val newPost = postRepository.asSaved(
post = post,
saved = newValue,
)
val newPost =
postRepository.asSaved(
post = post,
saved = newValue,
)
handlePostUpdate(newPost)
screenModelScope.launch {
try {
@ -423,10 +429,11 @@ class UserDetailViewModel(
private fun toggleUpVoteComment(comment: CommentModel) {
val newValue = comment.myVote <= 0
val newComment = commentRepository.asUpVoted(
comment = comment,
voted = newValue,
)
val newComment =
commentRepository.asUpVoted(
comment = comment,
voted = newValue,
)
handleCommentUpdate(newComment)
screenModelScope.launch {
try {
@ -464,10 +471,11 @@ class UserDetailViewModel(
private fun toggleSaveComment(comment: CommentModel) {
val newValue = !comment.saved
val newComment = commentRepository.asSaved(
comment = comment,
saved = newValue,
)
val newComment =
commentRepository.asSaved(
comment = comment,
saved = newValue,
)
handleCommentUpdate(newComment)
screenModelScope.launch {
try {
@ -487,13 +495,14 @@ class UserDetailViewModel(
private fun handlePostUpdate(post: PostModel) {
updateState {
it.copy(
posts = it.posts.map { p ->
if (p.id == post.id) {
post
} else {
p
}
},
posts =
it.posts.map { p ->
if (p.id == post.id) {
post
} else {
p
}
},
)
}
}
@ -501,20 +510,21 @@ class UserDetailViewModel(
private fun handleCommentUpdate(comment: CommentModel) {
updateState {
it.copy(
comments = it.comments.map { c ->
if (c.id == comment.id) {
comment
} else {
c
}
},
comments =
it.comments.map { c ->
if (c.id == comment.id) {
comment
} else {
c
}
},
)
}
}
private fun blockUser() {
updateState { it.copy(asyncInProgress = true) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val auth = identityRepository.authToken.value
userRepository.block(userId, true, auth).getOrThrow()
@ -529,7 +539,7 @@ class UserDetailViewModel(
private fun blockInstance() {
updateState { it.copy(asyncInProgress = true) }
screenModelScope.launch(Dispatchers.IO) {
screenModelScope.launch {
try {
val user = uiState.value.user
val instanceId = user.instanceId