refactor: screen params (state restoration) (#402)
* chore: add local cache * chore: remove possibility to disable bottom sheet gestures * chore: add cache to detail opener and create entry points * chore: add query by id to multi-community * chore: update community detail * chore: update community info * chore: update create comment * chore: update create post * chore: update multi-community screens * chore: update user detail * chore: update user info * chore: update post detail * chore: update post list * chore: update modal drawer * chore: update subscription management * chore: update profile * chore: update saved items * chore: remove JavaSerializable closes #316
This commit is contained in:
parent
d28f843a51
commit
e206de2e16
@ -1,6 +1,7 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.detailopener.api
|
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.detailopener.api
|
||||||
|
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||||
@ -23,4 +24,17 @@ interface DetailOpener {
|
|||||||
highlightCommentId: Int? = null,
|
highlightCommentId: Int? = null,
|
||||||
isMod: Boolean = false,
|
isMod: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun openReply(
|
||||||
|
originalPost: PostModel? = null,
|
||||||
|
originalComment: CommentModel? = null,
|
||||||
|
editedComment: CommentModel? = null,
|
||||||
|
initialText: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun openCreatePost(
|
||||||
|
editedPost: PostModel? = null,
|
||||||
|
crossPost: PostModel? = null,
|
||||||
|
communityId: Int? = null,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,15 @@ kotlin {
|
|||||||
|
|
||||||
implementation(projects.core.navigation)
|
implementation(projects.core.navigation)
|
||||||
implementation(projects.core.commonui.detailopenerApi)
|
implementation(projects.core.commonui.detailopenerApi)
|
||||||
|
|
||||||
|
implementation(projects.domain.lemmy.data)
|
||||||
|
implementation(projects.domain.lemmy.repository)
|
||||||
|
|
||||||
implementation(projects.unit.postdetail)
|
implementation(projects.unit.postdetail)
|
||||||
implementation(projects.unit.communitydetail)
|
implementation(projects.unit.communitydetail)
|
||||||
implementation(projects.unit.userdetail)
|
implementation(projects.unit.userdetail)
|
||||||
|
implementation(projects.unit.createpost)
|
||||||
implementation(projects.domain.lemmy.data)
|
implementation(projects.unit.createcomment)
|
||||||
|
|
||||||
implementation(projects.resources)
|
implementation(projects.resources)
|
||||||
}
|
}
|
||||||
|
@ -2,33 +2,50 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.detailopener.impl
|
|||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.detailopener.api.DetailOpener
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.detailopener.api.DetailOpener
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.NavigationCoordinator
|
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.NavigationCoordinator
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.LemmyItemCache
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.communitydetail.CommunityDetailScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.communitydetail.CommunityDetailScreen
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.unit.createcomment.CreateCommentScreen
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.unit.createpost.CreatePostScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.postdetail.PostDetailScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.postdetail.PostDetailScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.userdetail.UserDetailScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.userdetail.UserDetailScreen
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class DefaultDetailOpener(
|
class DefaultDetailOpener(
|
||||||
private val navigationCoordinator: NavigationCoordinator,
|
private val navigationCoordinator: NavigationCoordinator,
|
||||||
|
private val itemCache: LemmyItemCache,
|
||||||
) : DetailOpener {
|
) : DetailOpener {
|
||||||
|
|
||||||
|
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
|
||||||
|
|
||||||
override fun openCommunityDetail(community: CommunityModel, otherInstance: String) {
|
override fun openCommunityDetail(community: CommunityModel, otherInstance: String) {
|
||||||
navigationCoordinator.pushScreen(
|
scope.launch {
|
||||||
CommunityDetailScreen(
|
itemCache.putCommunity(community)
|
||||||
community = community,
|
navigationCoordinator.pushScreen(
|
||||||
otherInstance = otherInstance,
|
CommunityDetailScreen(
|
||||||
),
|
communityId = community.id,
|
||||||
)
|
otherInstance = otherInstance,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openUserDetail(user: UserModel, otherInstance: String) {
|
override fun openUserDetail(user: UserModel, otherInstance: String) {
|
||||||
navigationCoordinator.pushScreen(
|
scope.launch {
|
||||||
UserDetailScreen(
|
itemCache.putUser(user)
|
||||||
user = user,
|
navigationCoordinator.pushScreen(
|
||||||
otherInstance = otherInstance,
|
UserDetailScreen(
|
||||||
),
|
userId = user.id,
|
||||||
)
|
otherInstance = otherInstance,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun openPostDetail(
|
override fun openPostDetail(
|
||||||
@ -37,13 +54,63 @@ class DefaultDetailOpener(
|
|||||||
highlightCommentId: Int?,
|
highlightCommentId: Int?,
|
||||||
isMod: Boolean,
|
isMod: Boolean,
|
||||||
) {
|
) {
|
||||||
navigationCoordinator.pushScreen(
|
scope.launch {
|
||||||
PostDetailScreen(
|
itemCache.putPost(post)
|
||||||
post = post,
|
navigationCoordinator.pushScreen(
|
||||||
highlightCommentId = highlightCommentId,
|
PostDetailScreen(
|
||||||
otherInstance = otherInstance,
|
postId = post.id,
|
||||||
isMod = isMod,
|
highlightCommentId = highlightCommentId,
|
||||||
),
|
otherInstance = otherInstance,
|
||||||
)
|
isMod = isMod,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun openReply(
|
||||||
|
originalPost: PostModel?,
|
||||||
|
originalComment: CommentModel?,
|
||||||
|
editedComment: CommentModel?,
|
||||||
|
initialText: String?,
|
||||||
|
) {
|
||||||
|
scope.launch {
|
||||||
|
if (originalPost != null) {
|
||||||
|
itemCache.putPost(originalPost)
|
||||||
|
}
|
||||||
|
if (originalComment != null) {
|
||||||
|
itemCache.putComment(originalComment)
|
||||||
|
}
|
||||||
|
if (editedComment != null) {
|
||||||
|
itemCache.putComment(editedComment)
|
||||||
|
}
|
||||||
|
val screen = CreateCommentScreen(
|
||||||
|
originalPostId = originalPost?.id,
|
||||||
|
originalCommentId = originalComment?.id,
|
||||||
|
editedCommentId = editedComment?.id,
|
||||||
|
initialText = initialText,
|
||||||
|
)
|
||||||
|
navigationCoordinator.pushScreen(screen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun openCreatePost(
|
||||||
|
editedPost: PostModel?,
|
||||||
|
crossPost: PostModel?,
|
||||||
|
communityId: Int?,
|
||||||
|
) {
|
||||||
|
scope.launch {
|
||||||
|
if (editedPost != null) {
|
||||||
|
itemCache.putPost(editedPost)
|
||||||
|
}
|
||||||
|
if (crossPost != null) {
|
||||||
|
itemCache.putPost(crossPost)
|
||||||
|
}
|
||||||
|
val screen = CreatePostScreen(
|
||||||
|
editedPostId = editedPost?.id,
|
||||||
|
crossPostId = crossPost?.id,
|
||||||
|
communityId = communityId,
|
||||||
|
)
|
||||||
|
navigationCoordinator.pushScreen(screen)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -40,7 +40,6 @@ internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
|||||||
override val inboxUnread = MutableStateFlow(0)
|
override val inboxUnread = MutableStateFlow(0)
|
||||||
override val canPop = MutableStateFlow(false)
|
override val canPop = MutableStateFlow(false)
|
||||||
override val exitMessageVisible = MutableStateFlow(false)
|
override val exitMessageVisible = MutableStateFlow(false)
|
||||||
override val bottomSheetGesturesEnabled = MutableStateFlow(true)
|
|
||||||
|
|
||||||
private var connection: NestedScrollConnection? = null
|
private var connection: NestedScrollConnection? = null
|
||||||
private var navigator: Navigator? = null
|
private var navigator: Navigator? = null
|
||||||
@ -72,7 +71,6 @@ internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
|||||||
|
|
||||||
NavigationEvent.Hide -> {
|
NavigationEvent.Hide -> {
|
||||||
bottomNavigator?.hide()
|
bottomNavigator?.hide()
|
||||||
setBottomSheetGesturesEnabled(true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
@ -175,10 +173,6 @@ internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
|||||||
exitMessageVisible.value = value
|
exitMessageVisible.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setBottomSheetGesturesEnabled(value: Boolean) {
|
|
||||||
bottomSheetGesturesEnabled.value = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTabNavigator(value: TabNavigator) {
|
override fun setTabNavigator(value: TabNavigator) {
|
||||||
tabNavigator = value
|
tabNavigator = value
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ interface NavigationCoordinator {
|
|||||||
val deepLinkUrl: Flow<String?>
|
val deepLinkUrl: Flow<String?>
|
||||||
val canPop: StateFlow<Boolean>
|
val canPop: StateFlow<Boolean>
|
||||||
val exitMessageVisible: StateFlow<Boolean>
|
val exitMessageVisible: StateFlow<Boolean>
|
||||||
val bottomSheetGesturesEnabled: StateFlow<Boolean>
|
|
||||||
|
|
||||||
fun setCurrentSection(section: TabNavigationSection)
|
fun setCurrentSection(section: TabNavigationSection)
|
||||||
fun submitDeeplink(url: String)
|
fun submitDeeplink(url: String)
|
||||||
@ -43,7 +42,6 @@ interface NavigationCoordinator {
|
|||||||
fun pushScreen(screen: Screen)
|
fun pushScreen(screen: Screen)
|
||||||
fun popScreen()
|
fun popScreen()
|
||||||
fun setExitMessageVisible(value: Boolean)
|
fun setExitMessageVisible(value: Boolean)
|
||||||
fun setBottomSheetGesturesEnabled(value: Boolean)
|
|
||||||
fun setTabNavigator(value: TabNavigator)
|
fun setTabNavigator(value: TabNavigator)
|
||||||
fun changeTab(value: Tab)
|
fun changeTab(value: Tab)
|
||||||
}
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.persistence.data
|
package com.github.diegoberaldin.raccoonforlemmy.core.persistence.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class AccountModel(
|
data class AccountModel(
|
||||||
val id: Long? = null,
|
val id: Long? = null,
|
||||||
@ -9,4 +8,4 @@ data class AccountModel(
|
|||||||
val instance: String,
|
val instance: String,
|
||||||
val jwt: String,
|
val jwt: String,
|
||||||
val active: Boolean = false,
|
val active: Boolean = false,
|
||||||
) : JavaSerializable
|
)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.persistence.data
|
package com.github.diegoberaldin.raccoonforlemmy.core.persistence.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class FavoriteCommunityModel(
|
data class FavoriteCommunityModel(
|
||||||
val id: Long? = null,
|
val id: Long? = null,
|
||||||
val communityId: Int? = null,
|
val communityId: Int? = null,
|
||||||
) : JavaSerializable
|
)
|
@ -1,10 +1,8 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.persistence.data
|
package com.github.diegoberaldin.raccoonforlemmy.core.persistence.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class MultiCommunityModel(
|
data class MultiCommunityModel(
|
||||||
val id: Long? = null,
|
val id: Long? = null,
|
||||||
val name: String = "",
|
val name: String = "",
|
||||||
val communityIds: List<Int> = emptyList(),
|
val communityIds: List<Int> = emptyList(),
|
||||||
val icon: String? = null,
|
val icon: String? = null,
|
||||||
) : JavaSerializable
|
)
|
@ -1,7 +1,6 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.persistence.data
|
package com.github.diegoberaldin.raccoonforlemmy.core.persistence.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.VoteFormat
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.VoteFormat
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
@ -40,4 +39,4 @@ data class SettingsModel(
|
|||||||
val replyColor: Int? = null,
|
val replyColor: Int? = null,
|
||||||
val searchPostTitleOnly: Boolean = false,
|
val searchPostTitleOnly: Boolean = false,
|
||||||
val edgeToEdge: Boolean = true,
|
val edgeToEdge: Boolean = true,
|
||||||
) : JavaSerializable
|
)
|
||||||
|
@ -13,12 +13,17 @@ internal class DefaultMultiCommunityRepository(
|
|||||||
|
|
||||||
private val db = provider.getDatabase()
|
private val db = provider.getDatabase()
|
||||||
|
|
||||||
override suspend fun getAll(accountId: Long?): List<MultiCommunityModel> =
|
override suspend fun getAll(accountId: Long): List<MultiCommunityModel> =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
db.multicommunitiesQueries.getAll(accountId)
|
db.multicommunitiesQueries.getAll(accountId)
|
||||||
.executeAsList().map { it.toModel() }
|
.executeAsList().map { it.toModel() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getById(id: Long): MultiCommunityModel? =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
db.multicommunitiesQueries.getById(id).executeAsOneOrNull()?.toModel()
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun create(model: MultiCommunityModel, accountId: Long): Long =
|
override suspend fun create(model: MultiCommunityModel, accountId: Long): Long =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
db.multicommunitiesQueries.create(
|
db.multicommunitiesQueries.create(
|
||||||
|
@ -3,7 +3,8 @@ package com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
||||||
|
|
||||||
interface MultiCommunityRepository {
|
interface MultiCommunityRepository {
|
||||||
suspend fun getAll(accountId: Long?): List<MultiCommunityModel>
|
suspend fun getById(id: Long): MultiCommunityModel?
|
||||||
|
suspend fun getAll(accountId: Long): List<MultiCommunityModel>
|
||||||
|
|
||||||
suspend fun create(model: MultiCommunityModel, accountId: Long): Long
|
suspend fun create(model: MultiCommunityModel, accountId: Long): Long
|
||||||
|
|
||||||
|
@ -18,6 +18,11 @@ SELECT *
|
|||||||
FROM MultiCommunityEntity
|
FROM MultiCommunityEntity
|
||||||
WHERE name = ? AND account_id = ?;
|
WHERE name = ? AND account_id = ?;
|
||||||
|
|
||||||
|
getById:
|
||||||
|
SELECT *
|
||||||
|
FROM MultiCommunityEntity
|
||||||
|
WHERE id = ?;
|
||||||
|
|
||||||
create:
|
create:
|
||||||
INSERT OR IGNORE INTO MultiCommunityEntity (
|
INSERT OR IGNORE INTO MultiCommunityEntity (
|
||||||
name,
|
name,
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.utils
|
|
||||||
|
|
||||||
actual typealias JavaSerializable = java.io.Serializable
|
|
@ -1,3 +0,0 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.utils
|
|
||||||
|
|
||||||
expect interface JavaSerializable
|
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.github.diegoberaldin.raccoonforlemmy.core.utils.cache
|
||||||
|
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
|
||||||
|
internal class DefaultLruCache<T>(val size: Int) : LruCache<T> {
|
||||||
|
|
||||||
|
private val values: MutableMap<Int, T> = mutableMapOf()
|
||||||
|
private var lastUsedIds: List<Int> = listOf()
|
||||||
|
private val mutex = Mutex()
|
||||||
|
|
||||||
|
override suspend fun get(key: Int): T? = mutex.withLock {
|
||||||
|
val res = values[key]
|
||||||
|
if (res != null) {
|
||||||
|
moveAtTheBeginning(key)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun put(value: T, key: Int) = mutex.withLock {
|
||||||
|
val old = values[key]
|
||||||
|
if (old != null) {
|
||||||
|
// already existing element
|
||||||
|
moveAtTheBeginning(key)
|
||||||
|
} else {
|
||||||
|
// new element
|
||||||
|
values[key] = value
|
||||||
|
lastUsedIds = buildList {
|
||||||
|
this += key
|
||||||
|
this += lastUsedIds
|
||||||
|
}
|
||||||
|
if (lastUsedIds.size > size) {
|
||||||
|
dropOldest()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun dropOldest() {
|
||||||
|
lastUsedIds.lastOrNull()?.also { oldest ->
|
||||||
|
values.remove(oldest)
|
||||||
|
lastUsedIds = lastUsedIds - oldest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun moveAtTheBeginning(key: Int) {
|
||||||
|
lastUsedIds = buildList {
|
||||||
|
this += key
|
||||||
|
this += (lastUsedIds - key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.github.diegoberaldin.raccoonforlemmy.core.utils.cache
|
||||||
|
|
||||||
|
interface LruCache<T> {
|
||||||
|
suspend fun get(key: Int): T?
|
||||||
|
|
||||||
|
suspend fun put(value: T, key: Int)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun <T> factory(size: Int): LruCache<T> = DefaultLruCache(size)
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.utils
|
|
||||||
|
|
||||||
actual interface JavaSerializable
|
|
@ -1,9 +1,7 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class AccountBansModel(
|
data class AccountBansModel(
|
||||||
val users: List<UserModel> = emptyList(),
|
val users: List<UserModel> = emptyList(),
|
||||||
val communities: List<CommunityModel> = emptyList(),
|
val communities: List<CommunityModel> = emptyList(),
|
||||||
val instances: List<InstanceModel> = emptyList(),
|
val instances: List<InstanceModel> = emptyList(),
|
||||||
) : JavaSerializable
|
)
|
@ -1,7 +1,5 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class AccountSettingsModel(
|
data class AccountSettingsModel(
|
||||||
val avatar: String? = null,
|
val avatar: String? = null,
|
||||||
val banner: String? = null,
|
val banner: String? = null,
|
||||||
@ -16,4 +14,4 @@ data class AccountSettingsModel(
|
|||||||
val showNsfw: Boolean? = null,
|
val showNsfw: Boolean? = null,
|
||||||
val defaultListingType: ListingType? = null,
|
val defaultListingType: ListingType? = null,
|
||||||
val defaultSortType: SortType? = null,
|
val defaultSortType: SortType? = null,
|
||||||
) : JavaSerializable
|
)
|
@ -1,6 +1,5 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
import kotlin.jvm.Transient
|
import kotlin.jvm.Transient
|
||||||
|
|
||||||
data class CommentModel(
|
data class CommentModel(
|
||||||
@ -27,7 +26,7 @@ data class CommentModel(
|
|||||||
@Transient
|
@Transient
|
||||||
val loadMoreButtonVisible: Boolean = false,
|
val loadMoreButtonVisible: Boolean = false,
|
||||||
val languageId: Int = 0,
|
val languageId: Int = 0,
|
||||||
) : JavaSerializable {
|
) {
|
||||||
val depth: Int get() = (path.split(".").size - 2).coerceAtLeast(0)
|
val depth: Int get() = (path.split(".").size - 2).coerceAtLeast(0)
|
||||||
val parentId: String?
|
val parentId: String?
|
||||||
get() = path.split(".")
|
get() = path.split(".")
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class CommentReportModel(
|
data class CommentReportModel(
|
||||||
val id: Int = 0,
|
val id: Int = 0,
|
||||||
val creator: UserModel? = null,
|
val creator: UserModel? = null,
|
||||||
@ -13,4 +11,4 @@ data class CommentReportModel(
|
|||||||
val resolver: UserModel? = null,
|
val resolver: UserModel? = null,
|
||||||
val publishDate: String? = null,
|
val publishDate: String? = null,
|
||||||
val updateDate: String? = null,
|
val updateDate: String? = null,
|
||||||
) : JavaSerializable
|
)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
import kotlin.jvm.Transient
|
import kotlin.jvm.Transient
|
||||||
|
|
||||||
data class CommunityModel(
|
data class CommunityModel(
|
||||||
@ -23,4 +22,4 @@ data class CommunityModel(
|
|||||||
val comments: Int = 0,
|
val comments: Int = 0,
|
||||||
val creationDate: String? = null,
|
val creationDate: String? = null,
|
||||||
@Transient val favorite: Boolean = false,
|
@Transient val favorite: Boolean = false,
|
||||||
) : JavaSerializable
|
)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class InstanceModel(
|
data class InstanceModel(
|
||||||
val id: Int = 0,
|
val id: Int = 0,
|
||||||
val domain: String = "",
|
val domain: String = "",
|
||||||
) : JavaSerializable
|
)
|
@ -5,11 +5,10 @@ import androidx.compose.material.icons.filled.Book
|
|||||||
import androidx.compose.material.icons.filled.Cottage
|
import androidx.compose.material.icons.filled.Cottage
|
||||||
import androidx.compose.material.icons.filled.Public
|
import androidx.compose.material.icons.filled.Public
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import dev.icerock.moko.resources.compose.stringResource
|
import dev.icerock.moko.resources.compose.stringResource
|
||||||
|
|
||||||
sealed interface ListingType : JavaSerializable {
|
sealed interface ListingType {
|
||||||
data object All : ListingType
|
data object All : ListingType
|
||||||
data object Subscribed : ListingType
|
data object Subscribed : ListingType
|
||||||
data object Local : ListingType
|
data object Local : ListingType
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class MetadataModel(
|
data class MetadataModel(
|
||||||
val title: String = "",
|
val title: String = "",
|
||||||
val description: String = "",
|
val description: String = "",
|
||||||
) : JavaSerializable
|
)
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
sealed class ModlogItem(
|
sealed class ModlogItem(
|
||||||
val type: ModlogItemType,
|
val type: ModlogItemType,
|
||||||
) : JavaSerializable {
|
) {
|
||||||
|
|
||||||
abstract val id: Int
|
abstract val id: Int
|
||||||
abstract val date: String?
|
abstract val date: String?
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
sealed interface ModlogItemType {
|
||||||
|
|
||||||
sealed interface ModlogItemType : JavaSerializable {
|
|
||||||
data object All : ModlogItemType
|
data object All : ModlogItemType
|
||||||
data object ModRemovePost : ModlogItemType
|
data object ModRemovePost : ModlogItemType
|
||||||
data object ModLockPost : ModlogItemType
|
data object ModLockPost : ModlogItemType
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class PersonMentionModel(
|
data class PersonMentionModel(
|
||||||
val id: Int = 0,
|
val id: Int = 0,
|
||||||
val post: PostModel,
|
val post: PostModel,
|
||||||
@ -16,4 +14,4 @@ data class PersonMentionModel(
|
|||||||
val isOwnPost: Boolean = false,
|
val isOwnPost: Boolean = false,
|
||||||
val publishDate: String? = null,
|
val publishDate: String? = null,
|
||||||
val read: Boolean = false,
|
val read: Boolean = false,
|
||||||
) : JavaSerializable
|
)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.looksLikeAnImage
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.looksLikeAnImage
|
||||||
|
|
||||||
data class PostModel(
|
data class PostModel(
|
||||||
@ -28,7 +27,7 @@ data class PostModel(
|
|||||||
val removed: Boolean = false,
|
val removed: Boolean = false,
|
||||||
val locked: Boolean = false,
|
val locked: Boolean = false,
|
||||||
val languageId: Int = 0,
|
val languageId: Int = 0,
|
||||||
) : JavaSerializable
|
)
|
||||||
|
|
||||||
val PostModel.imageUrl: String
|
val PostModel.imageUrl: String
|
||||||
get() = url?.takeIf { it.looksLikeAnImage }?.takeIf { it.isNotEmpty() } ?: run {
|
get() = url?.takeIf { it.looksLikeAnImage }?.takeIf { it.isNotEmpty() } ?: run {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.looksLikeAnImage
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.looksLikeAnImage
|
||||||
|
|
||||||
data class PostReportModel(
|
data class PostReportModel(
|
||||||
@ -16,7 +15,7 @@ data class PostReportModel(
|
|||||||
val resolver: UserModel? = null,
|
val resolver: UserModel? = null,
|
||||||
val publishDate: String? = null,
|
val publishDate: String? = null,
|
||||||
val updateDate: String? = null,
|
val updateDate: String? = null,
|
||||||
) : JavaSerializable
|
)
|
||||||
|
|
||||||
val PostReportModel.imageUrl: String
|
val PostReportModel.imageUrl: String
|
||||||
get() = originalUrl?.takeIf { it.looksLikeAnImage }?.takeIf { it.isNotEmpty() } ?: run {
|
get() = originalUrl?.takeIf { it.looksLikeAnImage }?.takeIf { it.isNotEmpty() } ?: run {
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class PrivateMessageModel(
|
data class PrivateMessageModel(
|
||||||
val id: Int = 0,
|
val id: Int = 0,
|
||||||
val content: String? = null,
|
val content: String? = null,
|
||||||
@ -10,7 +8,7 @@ data class PrivateMessageModel(
|
|||||||
val publishDate: String? = null,
|
val publishDate: String? = null,
|
||||||
val updateDate: String? = null,
|
val updateDate: String? = null,
|
||||||
val read: Boolean = false,
|
val read: Boolean = false,
|
||||||
) : JavaSerializable
|
)
|
||||||
|
|
||||||
fun PrivateMessageModel.otherUser(currentUserId: Int): UserModel? = when (currentUserId) {
|
fun PrivateMessageModel.otherUser(currentUserId: Int): UserModel? = when (currentUserId) {
|
||||||
creator?.id -> recipient
|
creator?.id -> recipient
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
sealed interface SearchResult {
|
||||||
|
|
||||||
sealed interface SearchResult : JavaSerializable {
|
|
||||||
data class Post(val model: PostModel) : SearchResult
|
data class Post(val model: PostModel) : SearchResult
|
||||||
data class Comment(val model: CommentModel) : SearchResult
|
data class Comment(val model: CommentModel) : SearchResult
|
||||||
data class User(val model: UserModel) : SearchResult
|
data class User(val model: UserModel) : SearchResult
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
sealed interface SearchResultType {
|
||||||
|
|
||||||
sealed interface SearchResultType : JavaSerializable {
|
|
||||||
data object All : SearchResultType
|
data object All : SearchResultType
|
||||||
data object Posts : SearchResultType
|
data object Posts : SearchResultType
|
||||||
data object Comments : SearchResultType
|
data object Comments : SearchResultType
|
||||||
|
@ -12,11 +12,10 @@ import androidx.compose.material.icons.filled.Thunderstorm
|
|||||||
import androidx.compose.material.icons.filled.TrendingUp
|
import androidx.compose.material.icons.filled.TrendingUp
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import dev.icerock.moko.resources.compose.stringResource
|
import dev.icerock.moko.resources.compose.stringResource
|
||||||
|
|
||||||
sealed interface SortType : JavaSerializable {
|
sealed interface SortType {
|
||||||
data object Active : SortType
|
data object Active : SortType
|
||||||
data object Hot : SortType
|
data object Hot : SortType
|
||||||
data object New : SortType
|
data object New : SortType
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class UserModel(
|
data class UserModel(
|
||||||
val id: Int = 0,
|
val id: Int = 0,
|
||||||
val instanceId: Int = 0,
|
val instanceId: Int = 0,
|
||||||
@ -17,6 +15,6 @@ data class UserModel(
|
|||||||
val banned: Boolean = false,
|
val banned: Boolean = false,
|
||||||
val updateDate: String? = null,
|
val updateDate: String? = null,
|
||||||
val admin: Boolean = false,
|
val admin: Boolean = false,
|
||||||
) : JavaSerializable
|
)
|
||||||
|
|
||||||
fun List<UserModel>.containsId(value: Int?): Boolean = any { it.id == value }
|
fun List<UserModel>.containsId(value: Int?): Boolean = any { it.id == value }
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.JavaSerializable
|
|
||||||
|
|
||||||
data class UserScoreModel(
|
data class UserScoreModel(
|
||||||
val postScore: Int = 0,
|
val postScore: Int = 0,
|
||||||
val commentScore: Int = 0,
|
val commentScore: Int = 0,
|
||||||
) : JavaSerializable
|
)
|
@ -29,7 +29,10 @@ kotlin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(libs.koin.core)
|
implementation(libs.koin.core)
|
||||||
implementation(libs.ktorfit.lib)
|
implementation(libs.ktorfit.lib)
|
||||||
|
|
||||||
implementation(projects.core.api)
|
implementation(projects.core.api)
|
||||||
|
implementation(projects.core.utils)
|
||||||
|
|
||||||
implementation(projects.domain.lemmy.data)
|
implementation(projects.domain.lemmy.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository
|
||||||
|
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.cache.LruCache
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||||
|
|
||||||
|
internal class DefaultLemmyItemCache(
|
||||||
|
private val postCache: LruCache<PostModel>,
|
||||||
|
private val communityCache: LruCache<CommunityModel>,
|
||||||
|
private val commentCache: LruCache<CommentModel>,
|
||||||
|
private val userCache: LruCache<UserModel>,
|
||||||
|
) : LemmyItemCache {
|
||||||
|
|
||||||
|
override suspend fun putPost(value: PostModel) {
|
||||||
|
postCache.put(value = value, key = value.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getPost(id: Int): PostModel? = postCache.get(id)
|
||||||
|
|
||||||
|
override suspend fun putComment(value: CommentModel) {
|
||||||
|
commentCache.put(value = value, key = value.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getComment(id: Int): CommentModel? = commentCache.get(id)
|
||||||
|
|
||||||
|
override suspend fun putCommunity(value: CommunityModel) {
|
||||||
|
communityCache.put(value = value, key = value.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getCommunity(id: Int): CommunityModel? = communityCache.get(id)
|
||||||
|
|
||||||
|
override suspend fun putUser(value: UserModel) {
|
||||||
|
userCache.put(value = value, key = value.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getUser(id: Int): UserModel? = userCache.get(id)
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository
|
||||||
|
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||||
|
|
||||||
|
interface LemmyItemCache {
|
||||||
|
suspend fun putPost(value: PostModel)
|
||||||
|
suspend fun getPost(id: Int): PostModel?
|
||||||
|
|
||||||
|
suspend fun putComment(value: CommentModel)
|
||||||
|
suspend fun getComment(id: Int): CommentModel?
|
||||||
|
|
||||||
|
suspend fun putCommunity(value: CommunityModel)
|
||||||
|
suspend fun getCommunity(id: Int): CommunityModel?
|
||||||
|
|
||||||
|
suspend fun putUser(value: UserModel)
|
||||||
|
suspend fun getUser(id: Int): UserModel?
|
||||||
|
}
|
@ -1,16 +1,19 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.di
|
package com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.di
|
||||||
|
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.cache.LruCache
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultCommentRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultCommentRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultCommunityRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultCommunityRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultGetSortTypesUseCase
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultGetSortTypesUseCase
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultLemmyItemCache
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultModlogRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultModlogRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultPostRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultPostRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultPrivateMessageRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultPrivateMessageRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultSiteRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultSiteRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultUserRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.DefaultUserRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.LemmyItemCache
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.ModlogRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.ModlogRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PrivateMessageRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PrivateMessageRepository
|
||||||
@ -65,4 +68,12 @@ val repositoryModule = module {
|
|||||||
services = get(named("default")),
|
services = get(named("default")),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
single<LemmyItemCache> {
|
||||||
|
DefaultLemmyItemCache(
|
||||||
|
postCache = LruCache.factory(5),
|
||||||
|
commentCache = LruCache.factory(5),
|
||||||
|
communityCache = LruCache.factory(5),
|
||||||
|
userCache = LruCache.factory(5),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,6 @@ fun App(onLoadingFinished: () -> Unit = {}) {
|
|||||||
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
|
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
|
||||||
val drawerCoordinator = remember { getDrawerCoordinator() }
|
val drawerCoordinator = remember { getDrawerCoordinator() }
|
||||||
val drawerGesturesEnabled by drawerCoordinator.gesturesEnabled.collectAsState()
|
val drawerGesturesEnabled by drawerCoordinator.gesturesEnabled.collectAsState()
|
||||||
val bottomSheetGesturesEnabled by navigationCoordinator.bottomSheetGesturesEnabled.collectAsState()
|
|
||||||
val detailOpener = remember { getDetailOpener() }
|
val detailOpener = remember { getDetailOpener() }
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
@ -203,7 +202,9 @@ fun App(onLoadingFinished: () -> Unit = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is DrawerEvent.OpenMultiCommunity -> {
|
is DrawerEvent.OpenMultiCommunity -> {
|
||||||
navigationCoordinator.pushScreen(MultiCommunityScreen(evt.community))
|
evt.community.id?.toInt()?.also {
|
||||||
|
navigationCoordinator.pushScreen(MultiCommunityScreen(it))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerEvent.ManageSubscriptions -> {
|
DrawerEvent.ManageSubscriptions -> {
|
||||||
@ -240,7 +241,6 @@ fun App(onLoadingFinished: () -> Unit = {}) {
|
|||||||
topEnd = CornerSize.xl
|
topEnd = CornerSize.xl
|
||||||
),
|
),
|
||||||
sheetBackgroundColor = MaterialTheme.colorScheme.background,
|
sheetBackgroundColor = MaterialTheme.colorScheme.background,
|
||||||
sheetGesturesEnabled = bottomSheetGesturesEnabled,
|
|
||||||
) { bottomNavigator ->
|
) { bottomNavigator ->
|
||||||
navigationCoordinator.setBottomNavigator(bottomNavigator)
|
navigationCoordinator.setBottomNavigator(bottomNavigator)
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ internal val internalSharedModule = module {
|
|||||||
single<DetailOpener> {
|
single<DetailOpener> {
|
||||||
DefaultDetailOpener(
|
DefaultDetailOpener(
|
||||||
navigationCoordinator = get(),
|
navigationCoordinator = get(),
|
||||||
|
itemCache = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -101,15 +101,12 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.keepscreenon.rememberKeepScreenOn
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.keepscreenon.rememberKeepScreenOn
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.containsId
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.containsId
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.ban.BanUserScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.ban.BanUserScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.communityinfo.CommunityInfoScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.communityinfo.CommunityInfoScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createcomment.CreateCommentScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createpost.CreatePostScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.instanceinfo.InstanceInfoScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.instanceinfo.InstanceInfoScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.modlog.ModlogScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.modlog.ModlogScreen
|
||||||
@ -125,21 +122,21 @@ import kotlinx.coroutines.launch
|
|||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
class CommunityDetailScreen(
|
class CommunityDetailScreen(
|
||||||
private val community: CommunityModel,
|
private val communityId: Int,
|
||||||
private val otherInstance: String = "",
|
private val otherInstance: String = "",
|
||||||
) : Screen {
|
) : Screen {
|
||||||
|
|
||||||
override val key: ScreenKey
|
override val key: ScreenKey
|
||||||
get() = super.key + community.id.toString()
|
get() = super.key + communityId.toString()
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val model = getScreenModel<CommunityDetailMviModel>(
|
val model = getScreenModel<CommunityDetailMviModel>(
|
||||||
tag = community.id.toString() + community.name,
|
tag = communityId.toString(),
|
||||||
parameters = { parametersOf(community, otherInstance) },
|
parameters = { parametersOf(communityId, otherInstance) },
|
||||||
)
|
)
|
||||||
model.bindToLifecycle(key + community.id.toString())
|
model.bindToLifecycle(key + communityId.toString())
|
||||||
val uiState by model.uiState.collectAsState()
|
val uiState by model.uiState.collectAsState()
|
||||||
val lazyListState = rememberLazyListState()
|
val lazyListState = rememberLazyListState()
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
@ -366,7 +363,7 @@ class CommunityDetailScreen(
|
|||||||
|
|
||||||
OptionId.Info -> {
|
OptionId.Info -> {
|
||||||
navigationCoordinator.showBottomSheet(
|
navigationCoordinator.showBottomSheet(
|
||||||
CommunityInfoScreen(uiState.community),
|
CommunityInfoScreen(uiState.community.id),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,13 +472,9 @@ class CommunityDetailScreen(
|
|||||||
icon = Icons.Default.Create,
|
icon = Icons.Default.Create,
|
||||||
text = stringResource(MR.strings.action_create_post),
|
text = stringResource(MR.strings.action_create_post),
|
||||||
onSelected = rememberCallback {
|
onSelected = rememberCallback {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openCreatePost(
|
||||||
setBottomSheetGesturesEnabled(false)
|
communityId = uiState.community.id,
|
||||||
val screen = CreatePostScreen(
|
)
|
||||||
communityId = uiState.community.id,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen = screen)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -612,13 +605,9 @@ class CommunityDetailScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onSecondDismissToStart = rememberCallback(model) {
|
onSecondDismissToStart = rememberCallback(model) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = post,
|
||||||
val screen = CreateCommentScreen(
|
)
|
||||||
originalPost = post,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDismissToEnd = rememberCallback(model) {
|
onDismissToEnd = rememberCallback(model) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -808,12 +797,7 @@ class CommunityDetailScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openCreatePost(editedPost = post)
|
||||||
setBottomSheetGesturesEnabled(false)
|
|
||||||
showBottomSheet(
|
|
||||||
CreatePostScreen(editedPost = post),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
@ -823,12 +807,7 @@ class CommunityDetailScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionId.CrossPost -> {
|
OptionId.CrossPost -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openCreatePost(crossPost = post)
|
||||||
setBottomSheetGesturesEnabled(false)
|
|
||||||
showBottomSheet(
|
|
||||||
CreatePostScreen(crossPost = post),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.SeeRaw -> {
|
OptionId.SeeRaw -> {
|
||||||
@ -943,7 +922,8 @@ class CommunityDetailScreen(
|
|||||||
if (rawContent != null) {
|
if (rawContent != null) {
|
||||||
when (val content = rawContent) {
|
when (val content = rawContent) {
|
||||||
is PostModel -> {
|
is PostModel -> {
|
||||||
RawContentDialog(title = content.title,
|
RawContentDialog(
|
||||||
|
title = content.title,
|
||||||
publishDate = content.publishDate,
|
publishDate = content.publishDate,
|
||||||
updateDate = content.updateDate,
|
updateDate = content.updateDate,
|
||||||
url = content.url,
|
url = content.url,
|
||||||
@ -954,20 +934,17 @@ class CommunityDetailScreen(
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = content,
|
||||||
val screen = CreateCommentScreen(
|
initialText = buildString {
|
||||||
originalPost = content,
|
append("> ")
|
||||||
initialText = buildString {
|
append(quotation)
|
||||||
append("> ")
|
append("\n\n")
|
||||||
append(quotation)
|
},
|
||||||
append("\n\n")
|
)
|
||||||
},
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is CommentModel -> {
|
is CommentModel -> {
|
||||||
@ -981,16 +958,14 @@ class CommunityDetailScreen(
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalComment = content,
|
||||||
val screen = CreateCommentScreen(originalComment = content,
|
initialText = buildString {
|
||||||
initialText = buildString {
|
append("> ")
|
||||||
append("> ")
|
append(quotation)
|
||||||
append(quotation)
|
append("\n\n")
|
||||||
append("\n\n")
|
},
|
||||||
})
|
)
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -23,6 +23,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.imageUrl
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
|
||||||
|
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.PostRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -33,7 +34,7 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
class CommunityDetailViewModel(
|
class CommunityDetailViewModel(
|
||||||
private val mvi: DefaultMviModel<CommunityDetailMviModel.Intent, CommunityDetailMviModel.UiState, CommunityDetailMviModel.Effect>,
|
private val mvi: DefaultMviModel<CommunityDetailMviModel.Intent, CommunityDetailMviModel.UiState, CommunityDetailMviModel.Effect>,
|
||||||
private val community: CommunityModel,
|
private val communityId: Int,
|
||||||
private val otherInstance: String,
|
private val otherInstance: String,
|
||||||
private val identityRepository: IdentityRepository,
|
private val identityRepository: IdentityRepository,
|
||||||
private val apiConfigurationRepository: ApiConfigurationRepository,
|
private val apiConfigurationRepository: ApiConfigurationRepository,
|
||||||
@ -50,6 +51,7 @@ class CommunityDetailViewModel(
|
|||||||
private val imagePreloadManager: ImagePreloadManager,
|
private val imagePreloadManager: ImagePreloadManager,
|
||||||
private val getSortTypesUseCase: GetSortTypesUseCase,
|
private val getSortTypesUseCase: GetSortTypesUseCase,
|
||||||
private val notificationCenter: NotificationCenter,
|
private val notificationCenter: NotificationCenter,
|
||||||
|
private val itemCache: LemmyItemCache,
|
||||||
) : CommunityDetailMviModel,
|
) : CommunityDetailMviModel,
|
||||||
MviModel<CommunityDetailMviModel.Intent, CommunityDetailMviModel.UiState, CommunityDetailMviModel.Effect> by mvi {
|
MviModel<CommunityDetailMviModel.Intent, CommunityDetailMviModel.UiState, CommunityDetailMviModel.Effect> by mvi {
|
||||||
|
|
||||||
@ -59,16 +61,18 @@ class CommunityDetailViewModel(
|
|||||||
|
|
||||||
override fun onStarted() {
|
override fun onStarted() {
|
||||||
mvi.onStarted()
|
mvi.onStarted()
|
||||||
|
|
||||||
mvi.updateState {
|
|
||||||
it.copy(
|
|
||||||
community = it.community.takeIf { c -> c.id != 0 } ?: community,
|
|
||||||
instance = otherInstance.takeIf { n -> n.isNotEmpty() }
|
|
||||||
?: apiConfigurationRepository.instance.value,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
mvi.scope?.launch {
|
mvi.scope?.launch {
|
||||||
|
if (uiState.value.community.id == 0) {
|
||||||
|
val community = itemCache.getCommunity(communityId) ?: CommunityModel()
|
||||||
|
mvi.updateState {
|
||||||
|
it.copy(
|
||||||
|
community = community,
|
||||||
|
instance = otherInstance.takeIf { n -> n.isNotEmpty() }
|
||||||
|
?: apiConfigurationRepository.instance.value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
themeRepository.postLayout.onEach { layout ->
|
themeRepository.postLayout.onEach { layout ->
|
||||||
mvi.updateState { it.copy(postLayout = layout) }
|
mvi.updateState { it.copy(postLayout = layout) }
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
@ -252,6 +256,7 @@ class CommunityDetailViewModel(
|
|||||||
pageCursor = null
|
pageCursor = null
|
||||||
hideReadPosts = false
|
hideReadPosts = false
|
||||||
mvi.updateState { it.copy(canFetchMore = true, refreshing = true) }
|
mvi.updateState { it.copy(canFetchMore = true, refreshing = true) }
|
||||||
|
val community = uiState.value.community
|
||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
val accountId = accountRepository.getActive()?.id
|
val accountId = accountRepository.getActive()?.id
|
||||||
val isFavorite = favoriteCommunityRepository.getBy(accountId, community.id) != null
|
val isFavorite = favoriteCommunityRepository.getBy(accountId, community.id) != null
|
||||||
@ -298,11 +303,11 @@ class CommunityDetailViewModel(
|
|||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
val refreshing = currentState.refreshing
|
val refreshing = currentState.refreshing
|
||||||
val sort = currentState.sortType
|
val sort = currentState.sortType
|
||||||
val communityId = currentState.community.id
|
val community = currentState.community
|
||||||
val (itemList, nextPage) = postRepository.getAll(
|
val (itemList, nextPage) = postRepository.getAll(
|
||||||
auth = auth,
|
auth = auth,
|
||||||
otherInstance = otherInstance,
|
otherInstance = otherInstance,
|
||||||
communityId = communityId,
|
communityId = community.id,
|
||||||
communityName = community.name,
|
communityName = community.name,
|
||||||
page = currentPage,
|
page = currentPage,
|
||||||
pageCursor = pageCursor,
|
pageCursor = pageCursor,
|
||||||
@ -459,7 +464,7 @@ class CommunityDetailViewModel(
|
|||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
communityRepository.subscribe(
|
communityRepository.subscribe(
|
||||||
auth = identityRepository.authToken.value,
|
auth = identityRepository.authToken.value,
|
||||||
id = community.id,
|
id = communityId,
|
||||||
)
|
)
|
||||||
// the first response isn't immediately true, simulate here
|
// the first response isn't immediately true, simulate here
|
||||||
mvi.updateState { it.copy(community = it.community.copy(subscribed = true)) }
|
mvi.updateState { it.copy(community = it.community.copy(subscribed = true)) }
|
||||||
@ -471,7 +476,7 @@ class CommunityDetailViewModel(
|
|||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
val community = communityRepository.unsubscribe(
|
val community = communityRepository.unsubscribe(
|
||||||
auth = identityRepository.authToken.value,
|
auth = identityRepository.authToken.value,
|
||||||
id = community.id,
|
id = communityId,
|
||||||
)
|
)
|
||||||
if (community != null) {
|
if (community != null) {
|
||||||
mvi.updateState { it.copy(community = community) }
|
mvi.updateState { it.copy(community = community) }
|
||||||
@ -501,7 +506,6 @@ class CommunityDetailViewModel(
|
|||||||
mvi.updateState { it.copy(asyncInProgress = true) }
|
mvi.updateState { it.copy(asyncInProgress = true) }
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val communityId = community.id
|
|
||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
communityRepository.block(communityId, true, auth).getOrThrow()
|
communityRepository.block(communityId, true, auth).getOrThrow()
|
||||||
mvi.emitEffect(CommunityDetailMviModel.Effect.BlockSuccess)
|
mvi.emitEffect(CommunityDetailMviModel.Effect.BlockSuccess)
|
||||||
@ -517,6 +521,7 @@ class CommunityDetailViewModel(
|
|||||||
mvi.updateState { it.copy(asyncInProgress = true) }
|
mvi.updateState { it.copy(asyncInProgress = true) }
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
|
val community = uiState.value.community
|
||||||
val instanceId = community.instanceId
|
val instanceId = community.instanceId
|
||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
siteRepository.block(instanceId, true, auth).getOrThrow()
|
siteRepository.block(instanceId, true, auth).getOrThrow()
|
||||||
@ -583,7 +588,7 @@ class CommunityDetailViewModel(
|
|||||||
val auth = identityRepository.authToken.value.orEmpty()
|
val auth = identityRepository.authToken.value.orEmpty()
|
||||||
val newModerators = communityRepository.addModerator(
|
val newModerators = communityRepository.addModerator(
|
||||||
auth = auth,
|
auth = auth,
|
||||||
communityId = community.id,
|
communityId = communityId,
|
||||||
added = !isModerator,
|
added = !isModerator,
|
||||||
userId = userId,
|
userId = userId,
|
||||||
)
|
)
|
||||||
@ -594,10 +599,9 @@ class CommunityDetailViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleFavorite() {
|
private fun toggleFavorite() {
|
||||||
val communityId = community.id
|
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
val accountId = accountRepository.getActive()?.id ?: 0L
|
val accountId = accountRepository.getActive()?.id ?: 0L
|
||||||
val newValue = !community.favorite
|
val newValue = !uiState.value.community.favorite
|
||||||
if (newValue) {
|
if (newValue) {
|
||||||
val model = FavoriteCommunityModel(communityId = communityId)
|
val model = FavoriteCommunityModel(communityId = communityId)
|
||||||
favoriteCommunityRepository.create(model, accountId)
|
favoriteCommunityRepository.create(model, accountId)
|
||||||
|
@ -9,7 +9,7 @@ val communityDetailModule = module {
|
|||||||
factory<CommunityDetailMviModel> { params ->
|
factory<CommunityDetailMviModel> { params ->
|
||||||
CommunityDetailViewModel(
|
CommunityDetailViewModel(
|
||||||
mvi = DefaultMviModel(CommunityDetailMviModel.UiState()),
|
mvi = DefaultMviModel(CommunityDetailMviModel.UiState()),
|
||||||
community = params[0],
|
communityId = params[0],
|
||||||
otherInstance = params[1],
|
otherInstance = params[1],
|
||||||
identityRepository = get(),
|
identityRepository = get(),
|
||||||
apiConfigurationRepository = get(),
|
apiConfigurationRepository = get(),
|
||||||
@ -26,6 +26,7 @@ val communityDetailModule = module {
|
|||||||
getSortTypesUseCase = get(),
|
getSortTypesUseCase = get(),
|
||||||
accountRepository = get(),
|
accountRepository = get(),
|
||||||
favoriteCommunityRepository = get(),
|
favoriteCommunityRepository = get(),
|
||||||
|
itemCache = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,7 +32,6 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.getScreenModel
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
|
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.BottomSheetHandle
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.BottomSheetHandle
|
||||||
@ -41,10 +40,10 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.detailopener.api.g
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.DetailInfoItem
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.DetailInfoItem
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.PostCardBody
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.PostCardBody
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
|
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.getScreenModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.prettifyDate
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.prettifyDate
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.getPrettyNumber
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.getPrettyNumber
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.communityinfo.components.ModeratorCell
|
import com.github.diegoberaldin.raccoonforlemmy.unit.communityinfo.components.ModeratorCell
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
||||||
@ -55,14 +54,14 @@ import kotlinx.coroutines.launch
|
|||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
class CommunityInfoScreen(
|
class CommunityInfoScreen(
|
||||||
private val community: CommunityModel,
|
private val communityId: Int,
|
||||||
) : Screen {
|
) : Screen {
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val model = getScreenModel<CommunityInfoMviModel>(
|
val model = getScreenModel<CommunityInfoMviModel>(
|
||||||
tag = community.id.toString() + community.name,
|
tag = communityId.toString(),
|
||||||
parameters = { parametersOf(community) },
|
parameters = { parametersOf(communityId) },
|
||||||
)
|
)
|
||||||
model.bindToLifecycle(key)
|
model.bindToLifecycle(key)
|
||||||
val uiState by model.uiState.collectAsState()
|
val uiState by model.uiState.collectAsState()
|
||||||
|
@ -5,30 +5,35 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.LemmyItemCache
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class CommunityInfoViewModel(
|
class CommunityInfoViewModel(
|
||||||
private val mvi: DefaultMviModel<CommunityInfoMviModel.Intent, CommunityInfoMviModel.UiState, CommunityInfoMviModel.Effect>,
|
private val mvi: DefaultMviModel<CommunityInfoMviModel.Intent, CommunityInfoMviModel.UiState, CommunityInfoMviModel.Effect>,
|
||||||
private val community: CommunityModel,
|
private val communityId: Int,
|
||||||
private val communityRepository: CommunityRepository,
|
private val communityRepository: CommunityRepository,
|
||||||
private val settingsRepository: SettingsRepository,
|
private val settingsRepository: SettingsRepository,
|
||||||
|
private val itemCache: LemmyItemCache,
|
||||||
) : CommunityInfoMviModel,
|
) : CommunityInfoMviModel,
|
||||||
MviModel<CommunityInfoMviModel.Intent, CommunityInfoMviModel.UiState, CommunityInfoMviModel.Effect> by mvi {
|
MviModel<CommunityInfoMviModel.Intent, CommunityInfoMviModel.UiState, CommunityInfoMviModel.Effect> by mvi {
|
||||||
|
|
||||||
override fun onStarted() {
|
override fun onStarted() {
|
||||||
mvi.onStarted()
|
mvi.onStarted()
|
||||||
mvi.updateState { it.copy(community = community) }
|
|
||||||
|
|
||||||
mvi.scope?.launch {
|
mvi.scope?.launch {
|
||||||
|
if (uiState.value.community.id == 0) {
|
||||||
|
val community = itemCache.getCommunity(communityId) ?: CommunityModel()
|
||||||
|
mvi.updateState { it.copy(community = community) }
|
||||||
|
}
|
||||||
settingsRepository.currentSettings.onEach {
|
settingsRepository.currentSettings.onEach {
|
||||||
mvi.updateState { it.copy(autoLoadImages = it.autoLoadImages) }
|
mvi.updateState { it.copy(autoLoadImages = it.autoLoadImages) }
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
|
|
||||||
if (uiState.value.moderators.isEmpty()) {
|
if (uiState.value.moderators.isEmpty()) {
|
||||||
val moderators = communityRepository.getModerators(
|
val moderators = communityRepository.getModerators(
|
||||||
id = community.id
|
id = communityId
|
||||||
)
|
)
|
||||||
mvi.updateState { it.copy(moderators = moderators) }
|
mvi.updateState { it.copy(moderators = moderators) }
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,10 @@ val communityInfoModule = module {
|
|||||||
factory<CommunityInfoMviModel> { params ->
|
factory<CommunityInfoMviModel> { params ->
|
||||||
CommunityInfoViewModel(
|
CommunityInfoViewModel(
|
||||||
mvi = DefaultMviModel(CommunityInfoMviModel.UiState()),
|
mvi = DefaultMviModel(CommunityInfoMviModel.UiState()),
|
||||||
community = params[0],
|
communityId = params[0],
|
||||||
communityRepository = get(),
|
communityRepository = get(),
|
||||||
settingsRepository = get(),
|
settingsRepository = get(),
|
||||||
|
itemCache = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,9 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.VoteFormat
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.VoteFormat
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.CreatePostSection
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.CreatePostSection
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.LanguageModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.LanguageModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
import dev.icerock.moko.resources.desc.StringDesc
|
import dev.icerock.moko.resources.desc.StringDesc
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
@ -37,6 +39,9 @@ interface CreateCommentMviModel :
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class UiState(
|
data class UiState(
|
||||||
|
val originalPost: PostModel? = null,
|
||||||
|
val originalComment: CommentModel? = null,
|
||||||
|
val editedComment: CommentModel? = null,
|
||||||
val postLayout: PostLayout = PostLayout.Card,
|
val postLayout: PostLayout = PostLayout.Card,
|
||||||
val fullHeightImages: Boolean = true,
|
val fullHeightImages: Boolean = true,
|
||||||
val voteFormat: VoteFormat = VoteFormat.Aggregated,
|
val voteFormat: VoteFormat = VoteFormat.Aggregated,
|
||||||
|
@ -82,9 +82,9 @@ import kotlinx.coroutines.flow.onEach
|
|||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
class CreateCommentScreen(
|
class CreateCommentScreen(
|
||||||
private val originalPost: PostModel? = null,
|
private val originalPostId: Int? = null,
|
||||||
private val originalComment: CommentModel? = null,
|
private val originalCommentId: Int? = null,
|
||||||
private val editedComment: CommentModel? = null,
|
private val editedCommentId: Int? = null,
|
||||||
private val initialText: String? = null,
|
private val initialText: String? = null,
|
||||||
) : Screen {
|
) : Screen {
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@ -92,9 +92,9 @@ class CreateCommentScreen(
|
|||||||
override fun Content() {
|
override fun Content() {
|
||||||
val model = getScreenModel<CreateCommentMviModel> {
|
val model = getScreenModel<CreateCommentMviModel> {
|
||||||
parametersOf(
|
parametersOf(
|
||||||
originalPost?.id,
|
originalPostId,
|
||||||
originalComment?.id,
|
originalCommentId,
|
||||||
editedComment?.id,
|
editedCommentId,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
model.bindToLifecycle(key)
|
model.bindToLifecycle(key)
|
||||||
@ -109,7 +109,7 @@ class CreateCommentScreen(
|
|||||||
var textFieldValue by remember {
|
var textFieldValue by remember {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
TextFieldValue(
|
TextFieldValue(
|
||||||
text = (initialText ?: editedComment?.text).orEmpty()
|
text = (initialText ?: uiState.editedComment?.text).orEmpty()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -122,7 +122,7 @@ class CreateCommentScreen(
|
|||||||
var selectLanguageDialogOpen by remember { mutableStateOf(false) }
|
var selectLanguageDialogOpen by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
LaunchedEffect(model) {
|
LaunchedEffect(model) {
|
||||||
if (editedComment != null) {
|
uiState.editedComment?.also { editedComment ->
|
||||||
model.reduce(CreateCommentMviModel.Intent.ChangeLanguage(editedComment.languageId))
|
model.reduce(CreateCommentMviModel.Intent.ChangeLanguage(editedComment.languageId))
|
||||||
}
|
}
|
||||||
model.effects.onEach { effect ->
|
model.effects.onEach { effect ->
|
||||||
@ -133,7 +133,7 @@ class CreateCommentScreen(
|
|||||||
|
|
||||||
is CreateCommentMviModel.Effect.Success -> {
|
is CreateCommentMviModel.Effect.Success -> {
|
||||||
notificationCenter.send(event = NotificationCenterEvent.CommentCreated)
|
notificationCenter.send(event = NotificationCenterEvent.CommentCreated)
|
||||||
if (originalPost != null) {
|
uiState.originalPost?.also { originalPost ->
|
||||||
notificationCenter.send(
|
notificationCenter.send(
|
||||||
event = NotificationCenterEvent.PostUpdated(
|
event = NotificationCenterEvent.PostUpdated(
|
||||||
originalPost.copy(
|
originalPost.copy(
|
||||||
@ -146,7 +146,7 @@ class CreateCommentScreen(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
navigationCoordinator.hideBottomSheet()
|
navigationCoordinator.popScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
is CreateCommentMviModel.Effect.AddImageToText -> {
|
is CreateCommentMviModel.Effect.AddImageToText -> {
|
||||||
@ -167,7 +167,7 @@ class CreateCommentScreen(
|
|||||||
Image(
|
Image(
|
||||||
modifier = Modifier.padding(start = Spacing.s).onClick(
|
modifier = Modifier.padding(start = Spacing.s).onClick(
|
||||||
onClick = rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.hideBottomSheet()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.Close,
|
imageVector = Icons.Default.Close,
|
||||||
@ -189,7 +189,7 @@ class CreateCommentScreen(
|
|||||||
BottomSheetHandle()
|
BottomSheetHandle()
|
||||||
Text(
|
Text(
|
||||||
text = when {
|
text = when {
|
||||||
editedComment != null -> {
|
uiState.editedComment != null -> {
|
||||||
stringResource(MR.strings.edit_comment_title)
|
stringResource(MR.strings.edit_comment_title)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,57 +345,55 @@ class CreateCommentScreen(
|
|||||||
modifier = Modifier.padding(padding),
|
modifier = Modifier.padding(padding),
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
when {
|
val originalComment = uiState.originalComment
|
||||||
originalComment != null -> {
|
val originalPost = uiState.originalPost
|
||||||
CommentCard(
|
if (originalComment != null) {
|
||||||
modifier = referenceModifier,
|
CommentCard(
|
||||||
comment = originalComment,
|
modifier = referenceModifier,
|
||||||
hideIndent = true,
|
comment = originalComment,
|
||||||
voteFormat = uiState.voteFormat,
|
hideIndent = true,
|
||||||
autoLoadImages = uiState.autoLoadImages,
|
voteFormat = uiState.voteFormat,
|
||||||
options = buildList {
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
add(
|
options = buildList {
|
||||||
Option(
|
add(
|
||||||
OptionId.SeeRaw,
|
Option(
|
||||||
stringResource(MR.strings.post_action_see_raw)
|
OptionId.SeeRaw,
|
||||||
)
|
stringResource(MR.strings.post_action_see_raw)
|
||||||
)
|
)
|
||||||
},
|
)
|
||||||
onOptionSelected = {
|
},
|
||||||
rawContent = originalComment
|
onOptionSelected = {
|
||||||
},
|
rawContent = originalComment
|
||||||
)
|
},
|
||||||
Divider()
|
)
|
||||||
}
|
Divider()
|
||||||
|
} else if (originalPost != null) {
|
||||||
originalPost != null -> {
|
PostCard(
|
||||||
PostCard(
|
modifier = referenceModifier,
|
||||||
modifier = referenceModifier,
|
postLayout = if (uiState.postLayout == PostLayout.Card) {
|
||||||
postLayout = if (uiState.postLayout == PostLayout.Card) {
|
uiState.postLayout
|
||||||
uiState.postLayout
|
} else {
|
||||||
} else {
|
PostLayout.Full
|
||||||
PostLayout.Full
|
},
|
||||||
},
|
fullHeightImage = uiState.fullHeightImages,
|
||||||
fullHeightImage = uiState.fullHeightImages,
|
post = originalPost,
|
||||||
post = originalPost,
|
limitBodyHeight = true,
|
||||||
limitBodyHeight = true,
|
blurNsfw = false,
|
||||||
blurNsfw = false,
|
includeFullBody = true,
|
||||||
includeFullBody = true,
|
voteFormat = uiState.voteFormat,
|
||||||
voteFormat = uiState.voteFormat,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
autoLoadImages = uiState.autoLoadImages,
|
options = buildList {
|
||||||
options = buildList {
|
add(
|
||||||
add(
|
Option(
|
||||||
Option(
|
OptionId.SeeRaw,
|
||||||
OptionId.SeeRaw,
|
stringResource(MR.strings.post_action_see_raw)
|
||||||
stringResource(MR.strings.post_action_see_raw)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
},
|
)
|
||||||
onOptionSelected = {
|
},
|
||||||
rawContent = originalPost
|
onOptionSelected = {
|
||||||
},
|
rawContent = originalPost
|
||||||
)
|
},
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationC
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
|
||||||
|
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.PostRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR.strings.message_missing_field
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR.strings.message_missing_field
|
||||||
@ -30,15 +31,28 @@ class CreateCommentViewModel(
|
|||||||
private val themeRepository: ThemeRepository,
|
private val themeRepository: ThemeRepository,
|
||||||
private val settingsRepository: SettingsRepository,
|
private val settingsRepository: SettingsRepository,
|
||||||
private val notificationCenter: NotificationCenter,
|
private val notificationCenter: NotificationCenter,
|
||||||
|
private val itemCache: LemmyItemCache,
|
||||||
) : CreateCommentMviModel,
|
) : CreateCommentMviModel,
|
||||||
MviModel<CreateCommentMviModel.Intent, CreateCommentMviModel.UiState, CreateCommentMviModel.Effect> by mvi {
|
MviModel<CreateCommentMviModel.Intent, CreateCommentMviModel.UiState, CreateCommentMviModel.Effect> by mvi {
|
||||||
|
|
||||||
override fun onStarted() {
|
override fun onStarted() {
|
||||||
mvi.onStarted()
|
mvi.onStarted()
|
||||||
mvi.scope?.launch {
|
mvi.scope?.launch {
|
||||||
|
val originalPost = postId?.let { itemCache.getPost(it) }
|
||||||
|
val originalComment = parentId?.let { itemCache.getComment(it) }
|
||||||
|
val editedComment = editedCommentId?.let { itemCache.getComment(it) }
|
||||||
|
mvi.updateState {
|
||||||
|
it.copy(
|
||||||
|
originalPost = originalPost,
|
||||||
|
originalComment = originalComment,
|
||||||
|
editedComment = editedComment,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
themeRepository.postLayout.onEach { layout ->
|
themeRepository.postLayout.onEach { layout ->
|
||||||
mvi.updateState { it.copy(postLayout = layout) }
|
mvi.updateState { it.copy(postLayout = layout) }
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
|
|
||||||
if (uiState.value.currentUser.isEmpty()) {
|
if (uiState.value.currentUser.isEmpty()) {
|
||||||
val auth = identityRepository.authToken.value.orEmpty()
|
val auth = identityRepository.authToken.value.orEmpty()
|
||||||
val currentUser = siteRepository.getCurrentUser(auth)
|
val currentUser = siteRepository.getCurrentUser(auth)
|
||||||
|
@ -19,6 +19,7 @@ val createCommentModule = module {
|
|||||||
themeRepository = get(),
|
themeRepository = get(),
|
||||||
settingsRepository = get(),
|
settingsRepository = get(),
|
||||||
notificationCenter = get(),
|
notificationCenter = get(),
|
||||||
|
itemCache = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.CreatePostSection
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.CreatePostSection
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.LanguageModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.LanguageModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
import dev.icerock.moko.resources.desc.StringDesc
|
import dev.icerock.moko.resources.desc.StringDesc
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
@ -57,6 +58,8 @@ interface CreatePostMviModel :
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class UiState(
|
data class UiState(
|
||||||
|
val editedPost: PostModel? = null,
|
||||||
|
val crossPost: PostModel? = null,
|
||||||
val communityInfo: String = "",
|
val communityInfo: String = "",
|
||||||
val communityId: Int? = null,
|
val communityId: Int? = null,
|
||||||
val communityError: StringDesc? = null,
|
val communityError: StringDesc? = null,
|
||||||
|
@ -87,14 +87,14 @@ import org.koin.core.parameter.parametersOf
|
|||||||
|
|
||||||
class CreatePostScreen(
|
class CreatePostScreen(
|
||||||
private val communityId: Int? = null,
|
private val communityId: Int? = null,
|
||||||
private val editedPost: PostModel? = null,
|
private val editedPostId: Int? = null,
|
||||||
private val crossPost: PostModel? = null,
|
private val crossPostId: Int? = null,
|
||||||
) : Screen {
|
) : Screen {
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val model = getScreenModel<CreatePostMviModel> {
|
val model = getScreenModel<CreatePostMviModel> {
|
||||||
parametersOf(editedPost?.id)
|
parametersOf(editedPostId, crossPostId)
|
||||||
}
|
}
|
||||||
model.bindToLifecycle(key)
|
model.bindToLifecycle(key)
|
||||||
val uiState by model.uiState.collectAsState()
|
val uiState by model.uiState.collectAsState()
|
||||||
@ -103,22 +103,21 @@ class CreatePostScreen(
|
|||||||
val notificationCenter = remember { getNotificationCenter() }
|
val notificationCenter = remember { getNotificationCenter() }
|
||||||
val galleryHelper = remember { getGalleryHelper() }
|
val galleryHelper = remember { getGalleryHelper() }
|
||||||
val crossPostText = stringResource(MR.strings.create_post_cross_post_text)
|
val crossPostText = stringResource(MR.strings.create_post_cross_post_text)
|
||||||
|
val crossPost = uiState.crossPost
|
||||||
|
val editedPost = uiState.editedPost
|
||||||
var bodyTextFieldValue by remember {
|
var bodyTextFieldValue by remember {
|
||||||
val text = when {
|
val text = buildString {
|
||||||
crossPost != null -> buildString {
|
if (crossPost != null) {
|
||||||
append(crossPostText)
|
append(crossPostText)
|
||||||
append(" ")
|
append(" ")
|
||||||
append(crossPost.originalUrl)
|
append(crossPost.originalUrl)
|
||||||
|
} else if (editedPost != null) {
|
||||||
|
append(editedPost.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
editedPost != null -> {
|
|
||||||
editedPost.text
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> ""
|
|
||||||
}
|
}
|
||||||
mutableStateOf(TextFieldValue(text = text))
|
mutableStateOf(TextFieldValue(text = text))
|
||||||
}
|
}
|
||||||
|
|
||||||
val bodyFocusRequester = remember { FocusRequester() }
|
val bodyFocusRequester = remember { FocusRequester() }
|
||||||
val urlFocusRequester = remember { FocusRequester() }
|
val urlFocusRequester = remember { FocusRequester() }
|
||||||
val focusManager = LocalFocusManager.current
|
val focusManager = LocalFocusManager.current
|
||||||
@ -137,6 +136,7 @@ class CreatePostScreen(
|
|||||||
model.reduce(CreatePostMviModel.Intent.InsertImageInBody(bytes))
|
model.reduce(CreatePostMviModel.Intent.InsertImageInBody(bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var openSelectCommunity by remember { mutableStateOf(false) }
|
var openSelectCommunity by remember { mutableStateOf(false) }
|
||||||
val topAppBarState = rememberTopAppBarState()
|
val topAppBarState = rememberTopAppBarState()
|
||||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(topAppBarState)
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(topAppBarState)
|
||||||
@ -146,7 +146,7 @@ class CreatePostScreen(
|
|||||||
var selectLanguageDialogOpen by remember { mutableStateOf(false) }
|
var selectLanguageDialogOpen by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
LaunchedEffect(model) {
|
LaunchedEffect(model) {
|
||||||
val referencePost = editedPost ?: crossPost
|
val referencePost = uiState.editedPost ?: uiState.crossPost
|
||||||
model.reduce(CreatePostMviModel.Intent.SetTitle(referencePost?.title.orEmpty()))
|
model.reduce(CreatePostMviModel.Intent.SetTitle(referencePost?.title.orEmpty()))
|
||||||
model.reduce(CreatePostMviModel.Intent.SetUrl(referencePost?.url.orEmpty()))
|
model.reduce(CreatePostMviModel.Intent.SetUrl(referencePost?.url.orEmpty()))
|
||||||
if (editedPost != null) {
|
if (editedPost != null) {
|
||||||
@ -178,7 +178,7 @@ class CreatePostScreen(
|
|||||||
notificationCenter.send(
|
notificationCenter.send(
|
||||||
event = NotificationCenterEvent.PostCreated,
|
event = NotificationCenterEvent.PostCreated,
|
||||||
)
|
)
|
||||||
navigationCoordinator.hideBottomSheet()
|
navigationCoordinator.popScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
is CreatePostMviModel.Effect.AddImageToBody -> {
|
is CreatePostMviModel.Effect.AddImageToBody -> {
|
||||||
@ -189,7 +189,8 @@ class CreatePostScreen(
|
|||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
}
|
}
|
||||||
LaunchedEffect(notificationCenter) {
|
LaunchedEffect(notificationCenter)
|
||||||
|
{
|
||||||
notificationCenter.subscribe(NotificationCenterEvent.SelectCommunity::class)
|
notificationCenter.subscribe(NotificationCenterEvent.SelectCommunity::class)
|
||||||
.onEach { evt ->
|
.onEach { evt ->
|
||||||
model.reduce(CreatePostMviModel.Intent.SetCommunity(evt.model))
|
model.reduce(CreatePostMviModel.Intent.SetCommunity(evt.model))
|
||||||
@ -211,7 +212,7 @@ class CreatePostScreen(
|
|||||||
Image(
|
Image(
|
||||||
modifier = Modifier.padding(start = Spacing.s).onClick(
|
modifier = Modifier.padding(start = Spacing.s).onClick(
|
||||||
onClick = rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.hideBottomSheet()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.Close,
|
imageVector = Icons.Default.Close,
|
||||||
@ -232,7 +233,6 @@ class CreatePostScreen(
|
|||||||
Text(
|
Text(
|
||||||
text = when {
|
text = when {
|
||||||
editedPost != null -> stringResource(MR.strings.edit_post_title)
|
editedPost != null -> stringResource(MR.strings.edit_post_title)
|
||||||
|
|
||||||
else -> stringResource(MR.strings.create_post_title)
|
else -> stringResource(MR.strings.create_post_title)
|
||||||
},
|
},
|
||||||
style = MaterialTheme.typography.titleLarge,
|
style = MaterialTheme.typography.titleLarge,
|
||||||
@ -254,7 +254,8 @@ class CreatePostScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}, snackbarHost = {
|
}, snackbarHost =
|
||||||
|
{
|
||||||
SnackbarHost(snackbarHostState) { data ->
|
SnackbarHost(snackbarHostState) { data ->
|
||||||
Snackbar(
|
Snackbar(
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
@ -262,7 +263,8 @@ class CreatePostScreen(
|
|||||||
snackbarData = data,
|
snackbarData = data,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}) { padding ->
|
})
|
||||||
|
{ padding ->
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(padding).verticalScroll(rememberScrollState()),
|
modifier = Modifier.padding(padding).verticalScroll(rememberScrollState()),
|
||||||
) {
|
) {
|
||||||
|
@ -6,6 +6,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.StringUtils.isValidUrl
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.StringUtils.isValidUrl
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.LemmyItemCache
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepository
|
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.SiteRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR.strings.message_invalid_field
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR.strings.message_invalid_field
|
||||||
@ -18,19 +19,29 @@ import kotlinx.coroutines.flow.onEach
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class CreatePostViewModel(
|
class CreatePostViewModel(
|
||||||
private val editedPostId: Int?,
|
|
||||||
private val mvi: DefaultMviModel<CreatePostMviModel.Intent, CreatePostMviModel.UiState, CreatePostMviModel.Effect>,
|
private val mvi: DefaultMviModel<CreatePostMviModel.Intent, CreatePostMviModel.UiState, CreatePostMviModel.Effect>,
|
||||||
|
private val editedPostId: Int?,
|
||||||
|
private val crossPostId: Int?,
|
||||||
private val identityRepository: IdentityRepository,
|
private val identityRepository: IdentityRepository,
|
||||||
private val postRepository: PostRepository,
|
private val postRepository: PostRepository,
|
||||||
private val siteRepository: SiteRepository,
|
private val siteRepository: SiteRepository,
|
||||||
private val themeRepository: ThemeRepository,
|
private val themeRepository: ThemeRepository,
|
||||||
private val settingsRepository: SettingsRepository,
|
private val settingsRepository: SettingsRepository,
|
||||||
|
private val itemCache: LemmyItemCache,
|
||||||
) : CreatePostMviModel,
|
) : CreatePostMviModel,
|
||||||
MviModel<CreatePostMviModel.Intent, CreatePostMviModel.UiState, CreatePostMviModel.Effect> by mvi {
|
MviModel<CreatePostMviModel.Intent, CreatePostMviModel.UiState, CreatePostMviModel.Effect> by mvi {
|
||||||
|
|
||||||
override fun onStarted() {
|
override fun onStarted() {
|
||||||
mvi.onStarted()
|
mvi.onStarted()
|
||||||
mvi.scope?.launch {
|
mvi.scope?.launch {
|
||||||
|
val editedPost = editedPostId?.let {
|
||||||
|
itemCache.getPost(it)
|
||||||
|
}
|
||||||
|
val crossPost = crossPostId?.let {
|
||||||
|
itemCache.getPost(it)
|
||||||
|
}
|
||||||
|
mvi.updateState { it.copy(editedPost = editedPost, crossPost = crossPost) }
|
||||||
|
|
||||||
themeRepository.postLayout.onEach { layout ->
|
themeRepository.postLayout.onEach { layout ->
|
||||||
mvi.updateState { it.copy(postLayout = layout) }
|
mvi.updateState { it.copy(postLayout = layout) }
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
|
@ -10,11 +10,13 @@ val createPostModule = module {
|
|||||||
CreatePostViewModel(
|
CreatePostViewModel(
|
||||||
mvi = DefaultMviModel(CreatePostMviModel.UiState()),
|
mvi = DefaultMviModel(CreatePostMviModel.UiState()),
|
||||||
editedPostId = params[0],
|
editedPostId = params[0],
|
||||||
|
crossPostId = params[1],
|
||||||
identityRepository = get(),
|
identityRepository = get(),
|
||||||
postRepository = get(),
|
postRepository = get(),
|
||||||
siteRepository = get(),
|
siteRepository = get(),
|
||||||
themeRepository = get(),
|
themeRepository = get(),
|
||||||
settingsRepository = get(),
|
settingsRepository = get(),
|
||||||
|
itemCache = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -152,8 +152,9 @@ class ModalDrawerViewModel(
|
|||||||
val res = it - favorites.toSet()
|
val res = it - favorites.toSet()
|
||||||
favorites + res
|
favorites + res
|
||||||
}
|
}
|
||||||
val multiCommunitites = multiCommunityRepository.getAll(accountId).sortedBy { it.name }
|
val multiCommunitites = accountId?.let {
|
||||||
|
multiCommunityRepository.getAll(it).sortedBy { e -> e.name }
|
||||||
|
}.orEmpty()
|
||||||
mvi.updateState {
|
mvi.updateState {
|
||||||
it.copy(
|
it.copy(
|
||||||
refreshing = false,
|
refreshing = false,
|
||||||
|
@ -190,9 +190,11 @@ class ManageSubscriptionsScreen : Screen {
|
|||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
.background(MaterialTheme.colorScheme.background).onClick(
|
.background(MaterialTheme.colorScheme.background).onClick(
|
||||||
onClick = rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigatorCoordinator.pushScreen(
|
community.id?.toInt()?.also {
|
||||||
MultiCommunityScreen(community),
|
navigatorCoordinator.pushScreen(
|
||||||
)
|
MultiCommunityScreen(it),
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
community = community,
|
community = community,
|
||||||
@ -211,7 +213,7 @@ class ManageSubscriptionsScreen : Screen {
|
|||||||
when (optionId) {
|
when (optionId) {
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
navigatorCoordinator.pushScreen(
|
navigatorCoordinator.pushScreen(
|
||||||
MultiCommunityEditorScreen(community),
|
MultiCommunityEditorScreen(community.id?.toInt()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import cafe.adriel.voyager.core.model.ScreenModel
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.VoteFormat
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.VoteFormat
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
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.data.SortType
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ interface MultiCommunityMviModel :
|
|||||||
val instance: String = "",
|
val instance: String = "",
|
||||||
val isLogged: Boolean = false,
|
val isLogged: Boolean = false,
|
||||||
val sortType: SortType? = null,
|
val sortType: SortType? = null,
|
||||||
|
val community: MultiCommunityModel = MultiCommunityModel(),
|
||||||
val posts: List<PostModel> = emptyList(),
|
val posts: List<PostModel> = emptyList(),
|
||||||
val blurNsfw: Boolean = true,
|
val blurNsfw: Boolean = true,
|
||||||
val swipeActionsEnabled: Boolean = true,
|
val swipeActionsEnabled: Boolean = true,
|
||||||
|
@ -75,7 +75,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.di.getFabN
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.ShareBottomSheet
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.ShareBottomSheet
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.SortBottomSheet
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.SortBottomSheet
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
|
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsRepository
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
||||||
@ -83,7 +82,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.getAdditionalLabel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.getAdditionalLabel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createcomment.CreateCommentScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.zoomableimage.ZoomableImageScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.zoomableimage.ZoomableImageScreen
|
||||||
@ -91,15 +89,18 @@ import dev.icerock.moko.resources.compose.stringResource
|
|||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
class MultiCommunityScreen(
|
class MultiCommunityScreen(
|
||||||
private val community: MultiCommunityModel,
|
private val communityId: Int,
|
||||||
) : Screen {
|
) : Screen {
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val model = getScreenModel<MultiCommunityMviModel>()
|
val model = getScreenModel<MultiCommunityMviModel>(parameters = {
|
||||||
|
parametersOf(communityId)
|
||||||
|
})
|
||||||
model.bindToLifecycle(key)
|
model.bindToLifecycle(key)
|
||||||
val uiState by model.uiState.collectAsState()
|
val uiState by model.uiState.collectAsState()
|
||||||
val topAppBarState = rememberTopAppBarState()
|
val topAppBarState = rememberTopAppBarState()
|
||||||
@ -136,7 +137,7 @@ class MultiCommunityScreen(
|
|||||||
},
|
},
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = community.name,
|
text = uiState.community.name,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
@ -302,13 +303,9 @@ class MultiCommunityScreen(
|
|||||||
model.reduce(MultiCommunityMviModel.Intent.UpVotePost(post.id))
|
model.reduce(MultiCommunityMviModel.Intent.UpVotePost(post.id))
|
||||||
},
|
},
|
||||||
onSecondDismissToStart = rememberCallback(model) {
|
onSecondDismissToStart = rememberCallback(model) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = post,
|
||||||
val screen = CreateCommentScreen(
|
)
|
||||||
originalPost = post,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDismissToEnd = {
|
onDismissToEnd = {
|
||||||
model.reduce(MultiCommunityMviModel.Intent.DownVotePost(post.id))
|
model.reduce(MultiCommunityMviModel.Intent.DownVotePost(post.id))
|
||||||
|
@ -6,11 +6,11 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenter
|
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenter
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenterEvent
|
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenterEvent
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.MultiCommunityRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.imagepreload.ImagePreloadManager
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.share.ShareHelper
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.share.ShareHelper
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.vibrate.HapticFeedback
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.ApiConfigurationRepository
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository.IdentityRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
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.data.SortType
|
||||||
@ -25,13 +25,14 @@ import kotlinx.coroutines.IO
|
|||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class MultiCommunityViewModel(
|
class MultiCommunityViewModel(
|
||||||
private val mvi: DefaultMviModel<MultiCommunityMviModel.Intent, MultiCommunityMviModel.UiState, MultiCommunityMviModel.Effect>,
|
private val mvi: DefaultMviModel<MultiCommunityMviModel.Intent, MultiCommunityMviModel.UiState, MultiCommunityMviModel.Effect>,
|
||||||
private val community: MultiCommunityModel,
|
private val communityId: Int,
|
||||||
private val postRepository: PostRepository,
|
private val postRepository: PostRepository,
|
||||||
private val identityRepository: IdentityRepository,
|
private val identityRepository: IdentityRepository,
|
||||||
private val apiConfigurationRepository: ApiConfigurationRepository,
|
private val multiCommunityRepository: MultiCommunityRepository,
|
||||||
private val siteRepository: SiteRepository,
|
private val siteRepository: SiteRepository,
|
||||||
private val themeRepository: ThemeRepository,
|
private val themeRepository: ThemeRepository,
|
||||||
private val shareHelper: ShareHelper,
|
private val shareHelper: ShareHelper,
|
||||||
@ -49,6 +50,11 @@ class MultiCommunityViewModel(
|
|||||||
override fun onStarted() {
|
override fun onStarted() {
|
||||||
mvi.onStarted()
|
mvi.onStarted()
|
||||||
mvi.scope?.launch {
|
mvi.scope?.launch {
|
||||||
|
if ((uiState.value.community.id ?: 0) == 0L) {
|
||||||
|
val community =
|
||||||
|
multiCommunityRepository.getById(communityId.toLong()) ?: MultiCommunityModel()
|
||||||
|
mvi.updateState { it.copy(community = community) }
|
||||||
|
}
|
||||||
themeRepository.postLayout.onEach { layout ->
|
themeRepository.postLayout.onEach { layout ->
|
||||||
mvi.updateState { it.copy(postLayout = layout) }
|
mvi.updateState { it.copy(postLayout = layout) }
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
@ -80,20 +86,19 @@ class MultiCommunityViewModel(
|
|||||||
val user = siteRepository.getCurrentUser(auth)
|
val user = siteRepository.getCurrentUser(auth)
|
||||||
mvi.updateState { it.copy(currentUserId = user?.id ?: 0) }
|
mvi.updateState { it.copy(currentUserId = user?.id ?: 0) }
|
||||||
}
|
}
|
||||||
}
|
withContext(Dispatchers.IO) {
|
||||||
|
if (uiState.value.posts.isEmpty()) {
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
val settings = settingsRepository.currentSettings.value
|
||||||
if (uiState.value.posts.isEmpty()) {
|
val sortTypes = getSortTypesUseCase.getTypesForPosts()
|
||||||
val settings = settingsRepository.currentSettings.value
|
mvi.updateState {
|
||||||
val sortTypes = getSortTypesUseCase.getTypesForPosts()
|
it.copy(
|
||||||
mvi.updateState {
|
sortType = settings.defaultPostSortType.toSortType(),
|
||||||
it.copy(
|
availableSortTypes = sortTypes,
|
||||||
sortType = settings.defaultPostSortType.toSortType(),
|
)
|
||||||
availableSortTypes = sortTypes,
|
}
|
||||||
)
|
paginator.setCommunities(uiState.value.community.communityIds)
|
||||||
|
refresh()
|
||||||
}
|
}
|
||||||
paginator.setCommunities(community.communityIds)
|
|
||||||
refresh()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,9 @@ val multiCommunityModule = module {
|
|||||||
factory<MultiCommunityMviModel> { params ->
|
factory<MultiCommunityMviModel> { params ->
|
||||||
MultiCommunityViewModel(
|
MultiCommunityViewModel(
|
||||||
mvi = DefaultMviModel(MultiCommunityMviModel.UiState()),
|
mvi = DefaultMviModel(MultiCommunityMviModel.UiState()),
|
||||||
community = params[0],
|
communityId = params[0],
|
||||||
postRepository = get(),
|
postRepository = get(),
|
||||||
identityRepository = get(),
|
identityRepository = get(),
|
||||||
apiConfigurationRepository = get(),
|
|
||||||
siteRepository = get(),
|
siteRepository = get(),
|
||||||
themeRepository = get(),
|
themeRepository = get(),
|
||||||
shareHelper = get(),
|
shareHelper = get(),
|
||||||
@ -26,6 +25,7 @@ val multiCommunityModule = module {
|
|||||||
paginator = get(),
|
paginator = get(),
|
||||||
imagePreloadManager = get(),
|
imagePreloadManager = get(),
|
||||||
getSortTypesUseCase = get(),
|
getSortTypesUseCase = get(),
|
||||||
|
multiCommunityRepository = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
factory<MultiCommunityPaginator> {
|
factory<MultiCommunityPaginator> {
|
||||||
@ -36,7 +36,7 @@ val multiCommunityModule = module {
|
|||||||
factory<MultiCommunityEditorMviModel> { params ->
|
factory<MultiCommunityEditorMviModel> { params ->
|
||||||
MultiCommunityEditorViewModel(
|
MultiCommunityEditorViewModel(
|
||||||
mvi = DefaultMviModel(MultiCommunityEditorMviModel.UiState()),
|
mvi = DefaultMviModel(MultiCommunityEditorMviModel.UiState()),
|
||||||
editedCommunity = params[0],
|
communityId = params[0],
|
||||||
identityRepository = get(),
|
identityRepository = get(),
|
||||||
communityRepository = get(),
|
communityRepository = get(),
|
||||||
accountRepository = get(),
|
accountRepository = get(),
|
||||||
|
@ -60,7 +60,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycl
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CustomImage
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CustomImage
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.CommunityItem
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.lemmyui.CommunityItem
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
|
import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.data.MultiCommunityModel
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
@ -71,13 +70,13 @@ import kotlinx.coroutines.flow.onEach
|
|||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
class MultiCommunityEditorScreen(
|
class MultiCommunityEditorScreen(
|
||||||
private val editedCommunity: MultiCommunityModel? = null,
|
private val communityId: Int? = null,
|
||||||
) : Screen {
|
) : Screen {
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val model = getScreenModel<MultiCommunityEditorMviModel> { parametersOf(editedCommunity) }
|
val model = getScreenModel<MultiCommunityEditorMviModel> { parametersOf(communityId) }
|
||||||
model.bindToLifecycle(key)
|
model.bindToLifecycle(key)
|
||||||
val uiState by model.uiState.collectAsState()
|
val uiState by model.uiState.collectAsState()
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
|
@ -23,7 +23,7 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
class MultiCommunityEditorViewModel(
|
class MultiCommunityEditorViewModel(
|
||||||
private val mvi: DefaultMviModel<MultiCommunityEditorMviModel.Intent, MultiCommunityEditorMviModel.UiState, MultiCommunityEditorMviModel.Effect>,
|
private val mvi: DefaultMviModel<MultiCommunityEditorMviModel.Intent, MultiCommunityEditorMviModel.UiState, MultiCommunityEditorMviModel.Effect>,
|
||||||
private val editedCommunity: MultiCommunityModel? = null,
|
private val communityId: Int?,
|
||||||
private val identityRepository: IdentityRepository,
|
private val identityRepository: IdentityRepository,
|
||||||
private val communityRepository: CommunityRepository,
|
private val communityRepository: CommunityRepository,
|
||||||
private val multiCommunityRepository: MultiCommunityRepository,
|
private val multiCommunityRepository: MultiCommunityRepository,
|
||||||
@ -60,6 +60,9 @@ class MultiCommunityEditorViewModel(
|
|||||||
|
|
||||||
private fun populate() {
|
private fun populate() {
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
|
val editedCommunity = communityId?.toLong()?.let {
|
||||||
|
multiCommunityRepository.getById(it)
|
||||||
|
}
|
||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
communities = communityRepository.getSubscribed(auth).sortedBy { it.name }.map { c ->
|
communities = communityRepository.getSubscribed(auth).sortedBy { it.name }.map { c ->
|
||||||
c to (editedCommunity?.communityIds?.contains(c.id) == true)
|
c to (editedCommunity?.communityIds?.contains(c.id) == true)
|
||||||
@ -145,19 +148,21 @@ class MultiCommunityEditorViewModel(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val icon = currentState.icon
|
|
||||||
val communityIds = currentState.communities.filter { it.second }.map { it.first.id }
|
|
||||||
val multiCommunity = editedCommunity?.copy(
|
|
||||||
name = name,
|
|
||||||
icon = icon,
|
|
||||||
communityIds = communityIds,
|
|
||||||
) ?: MultiCommunityModel(
|
|
||||||
name = name,
|
|
||||||
icon = icon,
|
|
||||||
communityIds = communityIds,
|
|
||||||
)
|
|
||||||
|
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
|
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 accountId = accountRepository.getActive()?.id ?: return@launch
|
val accountId = accountRepository.getActive()?.id ?: return@launch
|
||||||
if (multiCommunity.id == null) {
|
if (multiCommunity.id == null) {
|
||||||
val id = multiCommunityRepository.create(multiCommunity, accountId)
|
val id = multiCommunityRepository.create(multiCommunity, accountId)
|
||||||
|
@ -58,8 +58,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createcomment.CreateCommentScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createpost.CreatePostScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.zoomableimage.ZoomableImageScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.zoomableimage.ZoomableImageScreen
|
||||||
@ -259,14 +257,9 @@ object ProfileLoggedScreen : Tab {
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openCreatePost(
|
||||||
setBottomSheetGesturesEnabled(false)
|
editedPost = post,
|
||||||
showBottomSheet(
|
)
|
||||||
CreatePostScreen(
|
|
||||||
editedPost = post,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.SeeRaw -> {
|
OptionId.SeeRaw -> {
|
||||||
@ -327,8 +320,7 @@ object ProfileLoggedScreen : Tab {
|
|||||||
items = uiState.comments,
|
items = uiState.comments,
|
||||||
key = { it.id.toString() + it.updateDate },
|
key = { it.id.toString() + it.updateDate },
|
||||||
) { comment ->
|
) { comment ->
|
||||||
CommentCard(
|
CommentCard(modifier = Modifier.background(MaterialTheme.colorScheme.background),
|
||||||
modifier = Modifier.background(MaterialTheme.colorScheme.background),
|
|
||||||
comment = comment,
|
comment = comment,
|
||||||
voteFormat = uiState.voteFormat,
|
voteFormat = uiState.voteFormat,
|
||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
@ -396,12 +388,9 @@ object ProfileLoggedScreen : Tab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
editedComment = comment,
|
||||||
showBottomSheet(
|
)
|
||||||
CreateCommentScreen(editedComment = comment)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.SeeRaw -> {
|
OptionId.SeeRaw -> {
|
||||||
@ -410,8 +399,7 @@ object ProfileLoggedScreen : Tab {
|
|||||||
|
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
|
||||||
Divider(
|
Divider(
|
||||||
modifier = Modifier.padding(vertical = Spacing.xxxs),
|
modifier = Modifier.padding(vertical = Spacing.xxxs),
|
||||||
thickness = 0.25.dp
|
thickness = 0.25.dp
|
||||||
@ -466,8 +454,7 @@ object ProfileLoggedScreen : Tab {
|
|||||||
if (rawContent != null) {
|
if (rawContent != null) {
|
||||||
when (val content = rawContent) {
|
when (val content = rawContent) {
|
||||||
is PostModel -> {
|
is PostModel -> {
|
||||||
RawContentDialog(
|
RawContentDialog(title = content.title,
|
||||||
title = content.title,
|
|
||||||
publishDate = content.publishDate,
|
publishDate = content.publishDate,
|
||||||
updateDate = content.updateDate,
|
updateDate = content.updateDate,
|
||||||
url = content.url,
|
url = content.url,
|
||||||
@ -478,27 +465,20 @@ object ProfileLoggedScreen : Tab {
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = content,
|
||||||
val screen =
|
initialText = buildString {
|
||||||
CreateCommentScreen(
|
append("> ")
|
||||||
originalPost = content,
|
append(quotation)
|
||||||
initialText = buildString {
|
append("\n\n")
|
||||||
append("> ")
|
},
|
||||||
append(quotation)
|
)
|
||||||
append("\n\n")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is CommentModel -> {
|
is CommentModel -> {
|
||||||
RawContentDialog(
|
RawContentDialog(text = content.text,
|
||||||
text = content.text,
|
|
||||||
publishDate = content.publishDate,
|
publishDate = content.publishDate,
|
||||||
updateDate = content.updateDate,
|
updateDate = content.updateDate,
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
@ -507,21 +487,16 @@ object ProfileLoggedScreen : Tab {
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalComment = content,
|
||||||
val screen = CreateCommentScreen(
|
initialText = buildString {
|
||||||
originalComment = content,
|
append("> ")
|
||||||
initialText = buildString {
|
append(quotation)
|
||||||
append("> ")
|
append("\n\n")
|
||||||
append(quotation)
|
},
|
||||||
append("\n\n")
|
)
|
||||||
}
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,8 +100,6 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.containsId
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.ban.BanUserScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.ban.BanUserScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createcomment.CreateCommentScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createpost.CreatePostScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.remove.RemoveScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.remove.RemoveScreen
|
||||||
@ -114,14 +112,14 @@ import kotlinx.coroutines.launch
|
|||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
class PostDetailScreen(
|
class PostDetailScreen(
|
||||||
private val post: PostModel,
|
private val postId: Int,
|
||||||
private val otherInstance: String = "",
|
private val otherInstance: String = "",
|
||||||
private val highlightCommentId: Int? = null,
|
private val highlightCommentId: Int? = null,
|
||||||
private val isMod: Boolean = false,
|
private val isMod: Boolean = false,
|
||||||
) : Screen {
|
) : Screen {
|
||||||
|
|
||||||
override val key: ScreenKey
|
override val key: ScreenKey
|
||||||
get() = super.key + post.id.toString()
|
get() = super.key + postId.toString()
|
||||||
|
|
||||||
@OptIn(
|
@OptIn(
|
||||||
ExperimentalMaterial3Api::class,
|
ExperimentalMaterial3Api::class,
|
||||||
@ -131,17 +129,16 @@ class PostDetailScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val model = getScreenModel<PostDetailMviModel>(
|
val model = getScreenModel<PostDetailMviModel>(
|
||||||
tag = post.id.toString() + highlightCommentId.toString(),
|
tag = postId.toString() + highlightCommentId.toString(),
|
||||||
parameters = {
|
parameters = {
|
||||||
parametersOf(
|
parametersOf(
|
||||||
post,
|
postId,
|
||||||
otherInstance,
|
otherInstance,
|
||||||
highlightCommentId,
|
highlightCommentId,
|
||||||
isMod,
|
isMod,
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
)
|
model.bindToLifecycle(key + postId.toString())
|
||||||
model.bindToLifecycle(key + post.id.toString())
|
|
||||||
val uiState by model.uiState.collectAsState()
|
val uiState by model.uiState.collectAsState()
|
||||||
val isOnOtherInstance = remember { otherInstance.isNotEmpty() }
|
val isOnOtherInstance = remember { otherInstance.isNotEmpty() }
|
||||||
val otherInstanceName = remember { otherInstance }
|
val otherInstanceName = remember { otherInstance }
|
||||||
@ -169,9 +166,6 @@ class PostDetailScreen(
|
|||||||
LaunchedEffect(notificationCenter) {
|
LaunchedEffect(notificationCenter) {
|
||||||
notificationCenter.resetCache()
|
notificationCenter.resetCache()
|
||||||
}
|
}
|
||||||
LaunchedEffect(navigationCoordinator) {
|
|
||||||
navigationCoordinator.setBottomSheetGesturesEnabled(true)
|
|
||||||
}
|
|
||||||
LaunchedEffect(model) {
|
LaunchedEffect(model) {
|
||||||
model.effects.onEach { evt ->
|
model.effects.onEach { evt ->
|
||||||
when (evt) {
|
when (evt) {
|
||||||
@ -193,8 +187,7 @@ class PostDetailScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier
|
modifier = Modifier.background(MaterialTheme.colorScheme.background)
|
||||||
.background(MaterialTheme.colorScheme.background)
|
|
||||||
.padding(Spacing.xs),
|
.padding(Spacing.xs),
|
||||||
topBar = {
|
topBar = {
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
@ -268,13 +261,9 @@ class PostDetailScreen(
|
|||||||
icon = Icons.Default.Reply,
|
icon = Icons.Default.Reply,
|
||||||
text = stringResource(MR.strings.action_reply),
|
text = stringResource(MR.strings.action_reply),
|
||||||
onSelected = rememberCallback {
|
onSelected = rememberCallback {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = uiState.post,
|
||||||
val screen = CreateCommentScreen(
|
)
|
||||||
originalPost = uiState.post,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -297,8 +286,7 @@ class PostDetailScreen(
|
|||||||
} else {
|
} else {
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
}.nestedScroll(fabNestedScrollConnection)
|
}.nestedScroll(fabNestedScrollConnection).pullRefresh(pullRefreshState),
|
||||||
.pullRefresh(pullRefreshState),
|
|
||||||
) {
|
) {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = lazyListState
|
state = lazyListState
|
||||||
@ -357,13 +345,9 @@ class PostDetailScreen(
|
|||||||
},
|
},
|
||||||
onReply = rememberCallback {
|
onReply = rememberCallback {
|
||||||
if (uiState.isLogged && !isOnOtherInstance) {
|
if (uiState.isLogged && !isOnOtherInstance) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = uiState.post,
|
||||||
val screen = CreateCommentScreen(
|
)
|
||||||
originalPost = uiState.post,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
options = buildList {
|
options = buildList {
|
||||||
@ -441,12 +425,7 @@ class PostDetailScreen(
|
|||||||
OptionId.Delete -> model.reduce(PostDetailMviModel.Intent.DeletePost)
|
OptionId.Delete -> model.reduce(PostDetailMviModel.Intent.DeletePost)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openCreatePost(editedPost = uiState.post)
|
||||||
setBottomSheetGesturesEnabled(false)
|
|
||||||
showBottomSheet(
|
|
||||||
CreatePostScreen(editedPost = uiState.post),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
@ -456,12 +435,7 @@ class PostDetailScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionId.CrossPost -> {
|
OptionId.CrossPost -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openCreatePost(crossPost = uiState.post)
|
||||||
setBottomSheetGesturesEnabled(false)
|
|
||||||
showBottomSheet(
|
|
||||||
CreatePostScreen(crossPost = uiState.post),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.SeeRaw -> {
|
OptionId.SeeRaw -> {
|
||||||
@ -649,14 +623,10 @@ class PostDetailScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onSecondDismissToStart = rememberCallback(model) {
|
onSecondDismissToStart = rememberCallback(model) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = uiState.post,
|
||||||
val screen = CreateCommentScreen(
|
originalComment = comment,
|
||||||
originalPost = uiState.post,
|
)
|
||||||
originalComment = comment,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDismissToEnd = rememberCallback(model) {
|
onDismissToEnd = rememberCallback(model) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -762,14 +732,10 @@ class PostDetailScreen(
|
|||||||
},
|
},
|
||||||
onReply = rememberCallback {
|
onReply = rememberCallback {
|
||||||
if (uiState.isLogged && !isOnOtherInstance) {
|
if (uiState.isLogged && !isOnOtherInstance) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = uiState.post,
|
||||||
val screen = CreateCommentScreen(
|
originalComment = comment,
|
||||||
originalPost = uiState.post,
|
)
|
||||||
originalComment = comment,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs { user, instance ->
|
onOpenCreator = rememberCallbackArgs { user, instance ->
|
||||||
@ -777,8 +743,7 @@ class PostDetailScreen(
|
|||||||
},
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs { community, instance ->
|
onOpenCommunity = rememberCallbackArgs { community, instance ->
|
||||||
detailOpener.openCommunityDetail(
|
detailOpener.openCommunityDetail(
|
||||||
community,
|
community, instance
|
||||||
instance
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenPost = rememberCallbackArgs { p, instance ->
|
onOpenPost = rememberCallbackArgs { p, instance ->
|
||||||
@ -862,16 +827,9 @@ class PostDetailScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(
|
editedComment = comment,
|
||||||
false,
|
)
|
||||||
)
|
|
||||||
showBottomSheet(
|
|
||||||
CreateCommentScreen(
|
|
||||||
editedComment = comment,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
@ -979,14 +937,10 @@ class PostDetailScreen(
|
|||||||
},
|
},
|
||||||
onReply = rememberCallback(model) {
|
onReply = rememberCallback(model) {
|
||||||
if (uiState.isLogged && !isOnOtherInstance) {
|
if (uiState.isLogged && !isOnOtherInstance) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = uiState.post,
|
||||||
val screen = CreateCommentScreen(
|
originalComment = comment,
|
||||||
originalPost = uiState.post,
|
)
|
||||||
originalComment = comment,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
onOpenCreator = rememberCallbackArgs { user ->
|
||||||
@ -1058,14 +1012,9 @@ class PostDetailScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
editedComment = comment,
|
||||||
showBottomSheet(
|
)
|
||||||
CreateCommentScreen(
|
|
||||||
editedComment = comment,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
@ -1174,8 +1123,7 @@ class PostDetailScreen(
|
|||||||
Column {
|
Column {
|
||||||
if (uiState.post.comments == 0) {
|
if (uiState.post.comments == 0) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(top = Spacing.xs),
|
.padding(top = Spacing.xs),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
text = stringResource(MR.strings.message_empty_comments),
|
text = stringResource(MR.strings.message_empty_comments),
|
||||||
@ -1184,8 +1132,7 @@ class PostDetailScreen(
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(top = Spacing.xs),
|
.padding(top = Spacing.xs),
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
text = stringResource(MR.strings.message_error_loading_comments),
|
text = stringResource(MR.strings.message_error_loading_comments),
|
||||||
@ -1240,18 +1187,14 @@ class PostDetailScreen(
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = content,
|
||||||
val screen = CreateCommentScreen(
|
initialText = buildString {
|
||||||
originalPost = content,
|
append("> ")
|
||||||
initialText = buildString {
|
append(quotation)
|
||||||
append("> ")
|
append("\n\n")
|
||||||
append(quotation)
|
},
|
||||||
append("\n\n")
|
)
|
||||||
},
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -1268,19 +1211,15 @@ class PostDetailScreen(
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = uiState.post,
|
||||||
val screen = CreateCommentScreen(
|
originalComment = content,
|
||||||
originalPost = uiState.post,
|
initialText = buildString {
|
||||||
originalComment = content,
|
append("> ")
|
||||||
initialText = buildString {
|
append(quotation)
|
||||||
append("> ")
|
append("\n\n")
|
||||||
append(quotation)
|
},
|
||||||
append("\n\n")
|
)
|
||||||
},
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -18,6 +18,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommunityRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
|
||||||
|
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.PostRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -28,7 +29,7 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
class PostDetailViewModel(
|
class PostDetailViewModel(
|
||||||
private val mvi: DefaultMviModel<PostDetailMviModel.Intent, PostDetailMviModel.UiState, PostDetailMviModel.Effect>,
|
private val mvi: DefaultMviModel<PostDetailMviModel.Intent, PostDetailMviModel.UiState, PostDetailMviModel.Effect>,
|
||||||
private val post: PostModel,
|
private val postId: Int,
|
||||||
private val otherInstance: String,
|
private val otherInstance: String,
|
||||||
private val highlightCommentId: Int?,
|
private val highlightCommentId: Int?,
|
||||||
private val isModerator: Boolean,
|
private val isModerator: Boolean,
|
||||||
@ -44,6 +45,7 @@ class PostDetailViewModel(
|
|||||||
private val notificationCenter: NotificationCenter,
|
private val notificationCenter: NotificationCenter,
|
||||||
private val hapticFeedback: HapticFeedback,
|
private val hapticFeedback: HapticFeedback,
|
||||||
private val getSortTypesUseCase: GetSortTypesUseCase,
|
private val getSortTypesUseCase: GetSortTypesUseCase,
|
||||||
|
private val itemCache: LemmyItemCache,
|
||||||
) : PostDetailMviModel,
|
) : PostDetailMviModel,
|
||||||
MviModel<PostDetailMviModel.Intent, PostDetailMviModel.UiState, PostDetailMviModel.Effect> by mvi {
|
MviModel<PostDetailMviModel.Intent, PostDetailMviModel.UiState, PostDetailMviModel.Effect> by mvi {
|
||||||
|
|
||||||
@ -60,6 +62,15 @@ class PostDetailViewModel(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
mvi.scope?.launch {
|
mvi.scope?.launch {
|
||||||
|
if (uiState.value.post.id == 0) {
|
||||||
|
val post = itemCache.getPost(postId) ?: PostModel()
|
||||||
|
mvi.updateState {
|
||||||
|
it.copy(
|
||||||
|
post = post,
|
||||||
|
isModerator = isModerator,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
notificationCenter.subscribe(NotificationCenterEvent.PostUpdated::class).onEach { evt ->
|
notificationCenter.subscribe(NotificationCenterEvent.PostUpdated::class).onEach { evt ->
|
||||||
handlePostUpdate(evt.model)
|
handlePostUpdate(evt.model)
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
@ -121,12 +132,11 @@ class PostDetailViewModel(
|
|||||||
notificationCenter.subscribe(NotificationCenterEvent.Share::class).onEach { evt ->
|
notificationCenter.subscribe(NotificationCenterEvent.Share::class).onEach { evt ->
|
||||||
shareHelper.share(evt.url)
|
shareHelper.share(evt.url)
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
}
|
|
||||||
|
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
|
||||||
identityRepository.isLogged.onEach { logged ->
|
identityRepository.isLogged.onEach { logged ->
|
||||||
mvi.updateState { it.copy(isLogged = logged ?: false) }
|
mvi.updateState { it.copy(isLogged = logged ?: false) }
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
|
|
||||||
if (uiState.value.currentUserId == null) {
|
if (uiState.value.currentUserId == null) {
|
||||||
val auth = identityRepository.authToken.value.orEmpty()
|
val auth = identityRepository.authToken.value.orEmpty()
|
||||||
val user = siteRepository.getCurrentUser(auth)
|
val user = siteRepository.getCurrentUser(auth)
|
||||||
@ -135,16 +145,9 @@ class PostDetailViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mvi.updateState {
|
|
||||||
it.copy(
|
|
||||||
post = post,
|
|
||||||
isModerator = isModerator,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
val updatedPost = postRepository.get(
|
val updatedPost = postRepository.get(
|
||||||
id = post.id,
|
id = postId,
|
||||||
auth = auth,
|
auth = auth,
|
||||||
instance = otherInstance,
|
instance = otherInstance,
|
||||||
)
|
)
|
||||||
@ -163,7 +166,7 @@ class PostDetailViewModel(
|
|||||||
highlightCommentPath = comment?.path
|
highlightCommentPath = comment?.path
|
||||||
}
|
}
|
||||||
if (isModerator) {
|
if (isModerator) {
|
||||||
post.community?.id?.also { communityId ->
|
uiState.value.post.community?.id?.also { communityId ->
|
||||||
val moderators = communityRepository.getModerators(
|
val moderators = communityRepository.getModerators(
|
||||||
auth = auth,
|
auth = auth,
|
||||||
id = communityId
|
id = communityId
|
||||||
@ -174,7 +177,7 @@ class PostDetailViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (post.text.isEmpty() && post.title.isEmpty()) {
|
if (uiState.value.post.text.isEmpty() && uiState.value.post.title.isEmpty()) {
|
||||||
refreshPost()
|
refreshPost()
|
||||||
}
|
}
|
||||||
if (mvi.uiState.value.comments.isEmpty()) {
|
if (mvi.uiState.value.comments.isEmpty()) {
|
||||||
@ -315,10 +318,10 @@ class PostDetailViewModel(
|
|||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
val updatedPost = postRepository.get(
|
val updatedPost = postRepository.get(
|
||||||
id = post.id,
|
id = postId,
|
||||||
auth = auth,
|
auth = auth,
|
||||||
instance = otherInstance,
|
instance = otherInstance,
|
||||||
) ?: post
|
) ?: uiState.value.post
|
||||||
mvi.updateState {
|
mvi.updateState {
|
||||||
it.copy(post = updatedPost)
|
it.copy(post = updatedPost)
|
||||||
}
|
}
|
||||||
@ -345,7 +348,7 @@ class PostDetailViewModel(
|
|||||||
val sort = currentState.sortType
|
val sort = currentState.sortType
|
||||||
val itemList = commentRepository.getAll(
|
val itemList = commentRepository.getAll(
|
||||||
auth = auth,
|
auth = auth,
|
||||||
postId = post.id,
|
postId = postId,
|
||||||
instance = otherInstance,
|
instance = otherInstance,
|
||||||
page = currentPage,
|
page = currentPage,
|
||||||
sort = sort,
|
sort = sort,
|
||||||
@ -633,9 +636,9 @@ class PostDetailViewModel(
|
|||||||
private fun deletePost() {
|
private fun deletePost() {
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
val auth = identityRepository.authToken.value.orEmpty()
|
val auth = identityRepository.authToken.value.orEmpty()
|
||||||
postRepository.delete(id = post.id, auth = auth)
|
postRepository.delete(id = postId, auth = auth)
|
||||||
notificationCenter.send(
|
notificationCenter.send(
|
||||||
event = NotificationCenterEvent.PostDeleted(post),
|
event = NotificationCenterEvent.PostDeleted(uiState.value.post),
|
||||||
)
|
)
|
||||||
mvi.emitEffect(PostDetailMviModel.Effect.Close)
|
mvi.emitEffect(PostDetailMviModel.Effect.Close)
|
||||||
}
|
}
|
||||||
@ -719,6 +722,7 @@ class PostDetailViewModel(
|
|||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
val isModerator = uiState.value.moderators.containsId(userId)
|
val isModerator = uiState.value.moderators.containsId(userId)
|
||||||
val auth = identityRepository.authToken.value.orEmpty()
|
val auth = identityRepository.authToken.value.orEmpty()
|
||||||
|
val post = uiState.value.post
|
||||||
val communityId = post.community?.id
|
val communityId = post.community?.id
|
||||||
if (communityId != null) {
|
if (communityId != null) {
|
||||||
val newModerators = communityRepository.addModerator(
|
val newModerators = communityRepository.addModerator(
|
||||||
|
@ -9,7 +9,7 @@ val postDetailModule = module {
|
|||||||
factory<PostDetailMviModel> { params ->
|
factory<PostDetailMviModel> { params ->
|
||||||
PostDetailViewModel(
|
PostDetailViewModel(
|
||||||
mvi = DefaultMviModel(PostDetailMviModel.UiState()),
|
mvi = DefaultMviModel(PostDetailMviModel.UiState()),
|
||||||
post = params[0],
|
postId = params[0],
|
||||||
otherInstance = params[1],
|
otherInstance = params[1],
|
||||||
highlightCommentId = params[2],
|
highlightCommentId = params[2],
|
||||||
isModerator = params[3],
|
isModerator = params[3],
|
||||||
@ -25,6 +25,7 @@ val postDetailModule = module {
|
|||||||
notificationCenter = get(),
|
notificationCenter = get(),
|
||||||
hapticFeedback = get(),
|
hapticFeedback = get(),
|
||||||
getSortTypesUseCase = get(),
|
getSortTypesUseCase = get(),
|
||||||
|
itemCache = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -80,8 +80,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.keepscreenon.rememberKeepScreenOn
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.keepscreenon.rememberKeepScreenOn
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createcomment.CreateCommentScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createpost.CreatePostScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
||||||
@ -345,13 +343,9 @@ class PostListScreen : Screen {
|
|||||||
model.reduce(PostListMviModel.Intent.UpVotePost(post.id))
|
model.reduce(PostListMviModel.Intent.UpVotePost(post.id))
|
||||||
},
|
},
|
||||||
onSecondDismissToStart = rememberCallback(model) {
|
onSecondDismissToStart = rememberCallback(model) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = post,
|
||||||
val screen = CreateCommentScreen(
|
)
|
||||||
originalPost = post,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDismissToEnd = rememberCallback(model) {
|
onDismissToEnd = rememberCallback(model) {
|
||||||
model.reduce(PostListMviModel.Intent.DownVotePost(post.id))
|
model.reduce(PostListMviModel.Intent.DownVotePost(post.id))
|
||||||
@ -518,12 +512,7 @@ class PostListScreen : Screen {
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openCreatePost(editedPost = post)
|
||||||
setBottomSheetGesturesEnabled(false)
|
|
||||||
showBottomSheet(
|
|
||||||
CreatePostScreen(editedPost = post),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
@ -533,12 +522,7 @@ class PostListScreen : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionId.CrossPost -> {
|
OptionId.CrossPost -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openCreatePost(crossPost = post)
|
||||||
setBottomSheetGesturesEnabled(false)
|
|
||||||
showBottomSheet(
|
|
||||||
CreatePostScreen(crossPost = post),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.SeeRaw -> {
|
OptionId.SeeRaw -> {
|
||||||
@ -668,19 +652,14 @@ class PostListScreen : Screen {
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = content,
|
||||||
val screen =
|
initialText = buildString {
|
||||||
CreateCommentScreen(
|
append("> ")
|
||||||
originalPost = content,
|
append(quotation)
|
||||||
initialText = buildString {
|
append("\n\n")
|
||||||
append("> ")
|
},
|
||||||
append(quotation)
|
)
|
||||||
append("\n\n")
|
|
||||||
},
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -69,7 +69,6 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createcomment.CreateCommentScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
||||||
@ -373,14 +372,11 @@ class SavedItemsScreen : Screen {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onReply = {
|
onReply = {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = PostModel(id = comment.postId),
|
||||||
val screen = CreateCommentScreen(
|
originalComment = comment,
|
||||||
originalPost = PostModel(id = comment.postId),
|
)
|
||||||
originalComment = comment,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
options = buildList {
|
options = buildList {
|
||||||
add(
|
add(
|
||||||
@ -475,18 +471,14 @@ class SavedItemsScreen : Screen {
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = content,
|
||||||
val screen = CreateCommentScreen(
|
initialText = buildString {
|
||||||
originalPost = content,
|
append("> ")
|
||||||
initialText = buildString {
|
append(quotation)
|
||||||
append("> ")
|
append("\n\n")
|
||||||
append(quotation)
|
},
|
||||||
append("\n\n")
|
)
|
||||||
},
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -503,18 +495,14 @@ class SavedItemsScreen : Screen {
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalComment = content,
|
||||||
val screen = CreateCommentScreen(
|
initialText = buildString {
|
||||||
originalComment = content,
|
append("> ")
|
||||||
initialText = buildString {
|
append(quotation)
|
||||||
append("> ")
|
append("\n\n")
|
||||||
append(quotation)
|
},
|
||||||
append("\n\n")
|
)
|
||||||
},
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -100,12 +100,9 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallb
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toIcon
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.chat.InboxChatScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.chat.InboxChatScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createcomment.CreateCommentScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createpost.CreatePostScreen
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.createreport.CreateReportScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
import com.github.diegoberaldin.raccoonforlemmy.unit.rawcontent.RawContentDialog
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.userinfo.UserInfoScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.userinfo.UserInfoScreen
|
||||||
@ -118,21 +115,19 @@ import kotlinx.coroutines.launch
|
|||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
class UserDetailScreen(
|
class UserDetailScreen(
|
||||||
private val user: UserModel,
|
private val userId: Int,
|
||||||
private val otherInstance: String = "",
|
private val otherInstance: String = "",
|
||||||
) : Screen {
|
) : Screen {
|
||||||
|
|
||||||
override val key: ScreenKey
|
override val key: ScreenKey
|
||||||
get() = super.key + user.id.toString()
|
get() = super.key + userId.toString()
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val model = getScreenModel<UserDetailMviModel>(
|
val model = getScreenModel<UserDetailMviModel>(tag = userId.toString(),
|
||||||
tag = user.id.toString(),
|
parameters = { parametersOf(userId, otherInstance) })
|
||||||
parameters = { parametersOf(user, otherInstance) }
|
model.bindToLifecycle(key + userId.toString())
|
||||||
)
|
|
||||||
model.bindToLifecycle(key + user.id.toString())
|
|
||||||
val uiState by model.uiState.collectAsState()
|
val uiState by model.uiState.collectAsState()
|
||||||
val lazyListState = rememberLazyListState()
|
val lazyListState = rememberLazyListState()
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
@ -181,194 +176,185 @@ class UserDetailScreen(
|
|||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(modifier = Modifier.background(MaterialTheme.colorScheme.background)
|
||||||
modifier = Modifier
|
.padding(Spacing.xs), topBar = {
|
||||||
.background(MaterialTheme.colorScheme.background)
|
val userName = uiState.user.name
|
||||||
.padding(Spacing.xs),
|
val userHost = uiState.user.host
|
||||||
topBar = {
|
val maxTopInset = Dimensions.topBarHeight.value.toInt()
|
||||||
val userName = user.name
|
var topInset by remember { mutableStateOf(maxTopInset) }
|
||||||
val userHost = user.host
|
snapshotFlow { topAppBarState.collapsedFraction }.onEach {
|
||||||
val maxTopInset = Dimensions.topBarHeight.value.toInt()
|
topInset = (maxTopInset * (1 - it)).toInt()
|
||||||
var topInset by remember { mutableStateOf(maxTopInset) }
|
}.launchIn(scope)
|
||||||
snapshotFlow { topAppBarState.collapsedFraction }.onEach {
|
|
||||||
topInset = (maxTopInset * (1 - it)).toInt()
|
|
||||||
}.launchIn(scope)
|
|
||||||
|
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
windowInsets = if (settings.edgeToEdge) {
|
windowInsets = if (settings.edgeToEdge) {
|
||||||
WindowInsets(0, topInset, 0, 0)
|
WindowInsets(0, topInset, 0, 0)
|
||||||
} else {
|
} else {
|
||||||
TopAppBarDefaults.windowInsets
|
TopAppBarDefaults.windowInsets
|
||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.padding(horizontal = Spacing.s),
|
modifier = Modifier.padding(horizontal = Spacing.s),
|
||||||
text = buildString {
|
text = buildString {
|
||||||
append(userName)
|
append(userName)
|
||||||
if (userHost.isNotEmpty()) {
|
if (userHost.isNotEmpty()) {
|
||||||
append("@$userHost")
|
append("@$userHost")
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
actions = {
|
||||||
|
// sort button
|
||||||
|
Image(
|
||||||
|
modifier = Modifier.onClick(
|
||||||
|
onClick = rememberCallback {
|
||||||
|
val sheet = SortBottomSheet(
|
||||||
|
sheetKey = key,
|
||||||
|
values = uiState.availableSortTypes,
|
||||||
|
comments = false,
|
||||||
|
expandTop = true,
|
||||||
|
)
|
||||||
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
maxLines = 1,
|
),
|
||||||
overflow = TextOverflow.Ellipsis,
|
imageVector = uiState.sortType.toIcon(),
|
||||||
|
contentDescription = null,
|
||||||
|
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
||||||
|
)
|
||||||
|
|
||||||
|
// options menu
|
||||||
|
Box {
|
||||||
|
val options = listOf(
|
||||||
|
Option(
|
||||||
|
OptionId.Info, stringResource(MR.strings.user_detail_info)
|
||||||
|
),
|
||||||
|
Option(
|
||||||
|
OptionId.Block,
|
||||||
|
stringResource(MR.strings.community_detail_block)
|
||||||
|
),
|
||||||
|
Option(
|
||||||
|
OptionId.BlockInstance,
|
||||||
|
stringResource(MR.strings.community_detail_block_instance)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
},
|
var optionsExpanded by remember { mutableStateOf(false) }
|
||||||
actions = {
|
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
||||||
// sort button
|
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onGloballyPositioned {
|
||||||
|
optionsOffset = it.positionInParent()
|
||||||
|
}.padding(start = Spacing.s).onClick(
|
||||||
onClick = rememberCallback {
|
onClick = rememberCallback {
|
||||||
val sheet = SortBottomSheet(
|
optionsExpanded = true
|
||||||
sheetKey = key,
|
|
||||||
values = uiState.availableSortTypes,
|
|
||||||
comments = false,
|
|
||||||
expandTop = true,
|
|
||||||
)
|
|
||||||
navigationCoordinator.showBottomSheet(sheet)
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = uiState.sortType.toIcon(),
|
imageVector = Icons.Default.MoreVert,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
||||||
)
|
)
|
||||||
|
CustomDropDown(
|
||||||
|
expanded = optionsExpanded,
|
||||||
|
onDismiss = {
|
||||||
|
optionsExpanded = false
|
||||||
|
},
|
||||||
|
offset = DpOffset(
|
||||||
|
x = optionsOffset.x.toLocalDp(),
|
||||||
|
y = optionsOffset.y.toLocalDp(),
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
options.forEach { option ->
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(
|
||||||
|
horizontal = Spacing.m,
|
||||||
|
vertical = Spacing.s,
|
||||||
|
).onClick(
|
||||||
|
onClick = rememberCallback {
|
||||||
|
optionsExpanded = false
|
||||||
|
when (option.id) {
|
||||||
|
OptionId.BlockInstance -> model.reduce(
|
||||||
|
UserDetailMviModel.Intent.BlockInstance
|
||||||
|
)
|
||||||
|
|
||||||
// options menu
|
OptionId.Block -> model.reduce(
|
||||||
Box {
|
UserDetailMviModel.Intent.Block
|
||||||
val options = listOf(
|
)
|
||||||
Option(
|
|
||||||
OptionId.Info,
|
OptionId.Info -> {
|
||||||
stringResource(MR.strings.user_detail_info)
|
navigationCoordinator.showBottomSheet(
|
||||||
),
|
UserInfoScreen(uiState.user.id),
|
||||||
Option(
|
|
||||||
OptionId.Block,
|
|
||||||
stringResource(MR.strings.community_detail_block)
|
|
||||||
),
|
|
||||||
Option(
|
|
||||||
OptionId.BlockInstance,
|
|
||||||
stringResource(MR.strings.community_detail_block_instance)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
var optionsExpanded by remember { mutableStateOf(false) }
|
|
||||||
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
|
||||||
Image(
|
|
||||||
modifier = Modifier.onGloballyPositioned {
|
|
||||||
optionsOffset = it.positionInParent()
|
|
||||||
}.padding(start = Spacing.s).onClick(
|
|
||||||
onClick = rememberCallback {
|
|
||||||
optionsExpanded = true
|
|
||||||
},
|
|
||||||
),
|
|
||||||
imageVector = Icons.Default.MoreVert,
|
|
||||||
contentDescription = null,
|
|
||||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
|
||||||
)
|
|
||||||
CustomDropDown(
|
|
||||||
expanded = optionsExpanded,
|
|
||||||
onDismiss = {
|
|
||||||
optionsExpanded = false
|
|
||||||
},
|
|
||||||
offset = DpOffset(
|
|
||||||
x = optionsOffset.x.toLocalDp(),
|
|
||||||
y = optionsOffset.y.toLocalDp(),
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
options.forEach { option ->
|
|
||||||
Text(
|
|
||||||
modifier = Modifier.padding(
|
|
||||||
horizontal = Spacing.m,
|
|
||||||
vertical = Spacing.s,
|
|
||||||
).onClick(
|
|
||||||
onClick = rememberCallback {
|
|
||||||
optionsExpanded = false
|
|
||||||
when (option.id) {
|
|
||||||
OptionId.BlockInstance -> model.reduce(
|
|
||||||
UserDetailMviModel.Intent.BlockInstance
|
|
||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Block -> model.reduce(
|
|
||||||
UserDetailMviModel.Intent.Block
|
|
||||||
)
|
|
||||||
|
|
||||||
OptionId.Info -> {
|
|
||||||
navigationCoordinator.showBottomSheet(
|
|
||||||
UserInfoScreen(uiState.user),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> Unit
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
),
|
else -> Unit
|
||||||
text = option.text,
|
}
|
||||||
)
|
},
|
||||||
}
|
),
|
||||||
}
|
text = option.text,
|
||||||
}
|
|
||||||
},
|
|
||||||
navigationIcon = {
|
|
||||||
if (navigationCoordinator.canPop.value) {
|
|
||||||
Image(
|
|
||||||
modifier = Modifier.onClick(
|
|
||||||
onClick = rememberCallback {
|
|
||||||
navigationCoordinator.popScreen()
|
|
||||||
},
|
|
||||||
),
|
|
||||||
imageVector = Icons.Default.ArrowBack,
|
|
||||||
contentDescription = null,
|
|
||||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
floatingActionButton = {
|
|
||||||
AnimatedVisibility(
|
|
||||||
visible = isFabVisible,
|
|
||||||
enter = slideInVertically(
|
|
||||||
initialOffsetY = { it * 2 },
|
|
||||||
),
|
|
||||||
exit = slideOutVertically(
|
|
||||||
targetOffsetY = { it * 2 },
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
FloatingActionButtonMenu(
|
|
||||||
items = buildList {
|
|
||||||
this += FloatingActionButtonMenuItem(
|
|
||||||
icon = Icons.Default.ExpandLess,
|
|
||||||
text = stringResource(MR.strings.action_back_to_top),
|
|
||||||
onSelected = rememberCallback {
|
|
||||||
scope.launch {
|
|
||||||
lazyListState.scrollToItem(0)
|
|
||||||
topAppBarState.heightOffset = 0f
|
|
||||||
topAppBarState.contentOffset = 0f
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if (uiState.isLogged && !isOnOtherInstance) {
|
|
||||||
this += FloatingActionButtonMenuItem(
|
|
||||||
icon = Icons.Default.Chat,
|
|
||||||
text = stringResource(MR.strings.action_chat),
|
|
||||||
onSelected = rememberCallback {
|
|
||||||
val screen = InboxChatScreen(otherUserId = user.id)
|
|
||||||
navigationCoordinator.pushScreen(screen)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
if (navigationCoordinator.canPop.value) {
|
||||||
|
Image(
|
||||||
|
modifier = Modifier.onClick(
|
||||||
|
onClick = rememberCallback {
|
||||||
|
navigationCoordinator.popScreen()
|
||||||
|
},
|
||||||
|
),
|
||||||
|
imageVector = Icons.Default.ArrowBack,
|
||||||
|
contentDescription = null,
|
||||||
|
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}, floatingActionButton = {
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = isFabVisible,
|
||||||
|
enter = slideInVertically(
|
||||||
|
initialOffsetY = { it * 2 },
|
||||||
|
),
|
||||||
|
exit = slideOutVertically(
|
||||||
|
targetOffsetY = { it * 2 },
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
FloatingActionButtonMenu(items = buildList {
|
||||||
|
this += FloatingActionButtonMenuItem(
|
||||||
|
icon = Icons.Default.ExpandLess,
|
||||||
|
text = stringResource(MR.strings.action_back_to_top),
|
||||||
|
onSelected = rememberCallback {
|
||||||
|
scope.launch {
|
||||||
|
lazyListState.scrollToItem(0)
|
||||||
|
topAppBarState.heightOffset = 0f
|
||||||
|
topAppBarState.contentOffset = 0f
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
if (uiState.isLogged && !isOnOtherInstance) {
|
||||||
},
|
this += FloatingActionButtonMenuItem(
|
||||||
snackbarHost = {
|
icon = Icons.Default.Chat,
|
||||||
SnackbarHost(snackbarHostState) { data ->
|
text = stringResource(MR.strings.action_chat),
|
||||||
Snackbar(
|
onSelected = rememberCallback {
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
val screen = InboxChatScreen(otherUserId = userId)
|
||||||
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
navigationCoordinator.pushScreen(screen)
|
||||||
snackbarData = data,
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
) { padding ->
|
}, snackbarHost = {
|
||||||
|
SnackbarHost(snackbarHostState) { data ->
|
||||||
|
Snackbar(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
snackbarData = data,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}) { padding ->
|
||||||
val pullRefreshState = rememberPullRefreshState(
|
val pullRefreshState = rememberPullRefreshState(
|
||||||
refreshing = uiState.refreshing,
|
refreshing = uiState.refreshing,
|
||||||
onRefresh = rememberCallback(model) {
|
onRefresh = rememberCallback(model) {
|
||||||
@ -376,17 +362,13 @@ class UserDetailScreen(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.padding(padding).let {
|
||||||
.padding(padding)
|
if (settings.hideNavigationBarWhileScrolling) {
|
||||||
.let {
|
it.nestedScroll(scrollBehavior.nestedScrollConnection)
|
||||||
if (settings.hideNavigationBarWhileScrolling) {
|
} else {
|
||||||
it.nestedScroll(scrollBehavior.nestedScrollConnection)
|
it
|
||||||
} else {
|
|
||||||
it
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.nestedScroll(fabNestedScrollConnection)
|
}.nestedScroll(fabNestedScrollConnection).pullRefresh(pullRefreshState),
|
||||||
.pullRefresh(pullRefreshState),
|
|
||||||
) {
|
) {
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = lazyListState,
|
state = lazyListState,
|
||||||
@ -506,13 +488,9 @@ class UserDetailScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onSecondDismissToStart = rememberCallback(model) {
|
onSecondDismissToStart = rememberCallback(model) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = post,
|
||||||
val screen = CreateCommentScreen(
|
)
|
||||||
originalPost = post,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDismissToEnd = rememberCallback(model) {
|
onDismissToEnd = rememberCallback(model) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -642,12 +620,7 @@ class UserDetailScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionId.CrossPost -> {
|
OptionId.CrossPost -> {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openCreatePost(crossPost = post)
|
||||||
setBottomSheetGesturesEnabled(false)
|
|
||||||
showBottomSheet(
|
|
||||||
CreatePostScreen(crossPost = post),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.SeeRaw -> {
|
OptionId.SeeRaw -> {
|
||||||
@ -773,14 +746,10 @@ class UserDetailScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onSecondDismissToStart = rememberCallback(model) {
|
onSecondDismissToStart = rememberCallback(model) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = PostModel(id = comment.postId),
|
||||||
val screen = CreateCommentScreen(
|
originalComment = comment,
|
||||||
originalPost = PostModel(id = comment.postId),
|
)
|
||||||
originalComment = comment,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDismissToEnd = rememberCallback(model) {
|
onDismissToEnd = rememberCallback(model) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -855,14 +824,10 @@ class UserDetailScreen(
|
|||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
rememberCallback {
|
rememberCallback {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = PostModel(id = comment.postId),
|
||||||
val screen = CreateCommentScreen(
|
originalComment = comment,
|
||||||
originalPost = PostModel(id = comment.postId),
|
)
|
||||||
originalComment = comment,
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs { community, instance ->
|
onOpenCommunity = rememberCallbackArgs { community, instance ->
|
||||||
@ -982,26 +947,21 @@ class UserDetailScreen(
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalPost = content,
|
||||||
val screen = CreateCommentScreen(
|
initialText = buildString {
|
||||||
originalPost = content,
|
append("> ")
|
||||||
initialText = buildString {
|
append(quotation)
|
||||||
append("> ")
|
append("\n\n")
|
||||||
append(quotation)
|
},
|
||||||
append("\n\n")
|
)
|
||||||
},
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is CommentModel -> {
|
is CommentModel -> {
|
||||||
RawContentDialog(
|
RawContentDialog(text = content.text,
|
||||||
text = content.text,
|
|
||||||
publishDate = content.publishDate,
|
publishDate = content.publishDate,
|
||||||
updateDate = content.updateDate,
|
updateDate = content.updateDate,
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
@ -1010,21 +970,16 @@ class UserDetailScreen(
|
|||||||
onQuote = rememberCallbackArgs { quotation ->
|
onQuote = rememberCallbackArgs { quotation ->
|
||||||
rawContent = null
|
rawContent = null
|
||||||
if (quotation != null) {
|
if (quotation != null) {
|
||||||
with(navigationCoordinator) {
|
detailOpener.openReply(
|
||||||
setBottomSheetGesturesEnabled(false)
|
originalComment = content,
|
||||||
val screen = CreateCommentScreen(
|
initialText = buildString {
|
||||||
originalComment = content,
|
append("> ")
|
||||||
initialText = buildString {
|
append(quotation)
|
||||||
append("> ")
|
append("\n\n")
|
||||||
append(quotation)
|
},
|
||||||
append("\n\n")
|
)
|
||||||
},
|
|
||||||
)
|
|
||||||
showBottomSheet(screen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.imageUrl
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.toSortType
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.GetSortTypesUseCase
|
||||||
|
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.PostRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
|
||||||
@ -34,7 +35,7 @@ import kotlinx.coroutines.withContext
|
|||||||
|
|
||||||
class UserDetailViewModel(
|
class UserDetailViewModel(
|
||||||
private val mvi: DefaultMviModel<UserDetailMviModel.Intent, UserDetailMviModel.UiState, UserDetailMviModel.Effect>,
|
private val mvi: DefaultMviModel<UserDetailMviModel.Intent, UserDetailMviModel.UiState, UserDetailMviModel.Effect>,
|
||||||
private val user: UserModel,
|
private val userId: Int,
|
||||||
private val otherInstance: String = "",
|
private val otherInstance: String = "",
|
||||||
private val identityRepository: IdentityRepository,
|
private val identityRepository: IdentityRepository,
|
||||||
private val apiConfigurationRepository: ApiConfigurationRepository,
|
private val apiConfigurationRepository: ApiConfigurationRepository,
|
||||||
@ -49,6 +50,7 @@ class UserDetailViewModel(
|
|||||||
private val notificationCenter: NotificationCenter,
|
private val notificationCenter: NotificationCenter,
|
||||||
private val imagePreloadManager: ImagePreloadManager,
|
private val imagePreloadManager: ImagePreloadManager,
|
||||||
private val getSortTypesUseCase: GetSortTypesUseCase,
|
private val getSortTypesUseCase: GetSortTypesUseCase,
|
||||||
|
private val itemCache: LemmyItemCache,
|
||||||
) : UserDetailMviModel,
|
) : UserDetailMviModel,
|
||||||
MviModel<UserDetailMviModel.Intent, UserDetailMviModel.UiState, UserDetailMviModel.Effect> by mvi {
|
MviModel<UserDetailMviModel.Intent, UserDetailMviModel.UiState, UserDetailMviModel.Effect> by mvi {
|
||||||
|
|
||||||
@ -63,6 +65,12 @@ class UserDetailViewModel(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
mvi.scope?.launch {
|
mvi.scope?.launch {
|
||||||
|
if (uiState.value.user.id == 0) {
|
||||||
|
val user = itemCache.getUser(userId) ?: UserModel()
|
||||||
|
mvi.updateState {
|
||||||
|
it.copy(user = user)
|
||||||
|
}
|
||||||
|
}
|
||||||
themeRepository.postLayout.onEach { layout ->
|
themeRepository.postLayout.onEach { layout ->
|
||||||
mvi.updateState { it.copy(postLayout = layout) }
|
mvi.updateState { it.copy(postLayout = layout) }
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
@ -77,11 +85,7 @@ class UserDetailViewModel(
|
|||||||
shareHelper.share(evt.url)
|
shareHelper.share(evt.url)
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
}
|
}
|
||||||
mvi.updateState {
|
|
||||||
it.copy(
|
|
||||||
user = it.user.takeIf { u -> u.id != 0 } ?: user,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
mvi.scope?.launch {
|
mvi.scope?.launch {
|
||||||
settingsRepository.currentSettings.onEach { settings ->
|
settingsRepository.currentSettings.onEach { settings ->
|
||||||
mvi.updateState {
|
mvi.updateState {
|
||||||
@ -236,10 +240,10 @@ class UserDetailViewModel(
|
|||||||
}
|
}
|
||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
val refreshedUser = userRepository.get(
|
val refreshedUser = userRepository.get(
|
||||||
id = user.id,
|
id = userId,
|
||||||
auth = auth,
|
auth = auth,
|
||||||
otherInstance = otherInstance,
|
otherInstance = otherInstance,
|
||||||
username = user.name,
|
username = uiState.value.user.name,
|
||||||
)
|
)
|
||||||
if (refreshedUser != null) {
|
if (refreshedUser != null) {
|
||||||
mvi.updateState { it.copy(user = refreshedUser) }
|
mvi.updateState { it.copy(user = refreshedUser) }
|
||||||
@ -266,7 +270,7 @@ class UserDetailViewModel(
|
|||||||
id = userId,
|
id = userId,
|
||||||
page = currentPage,
|
page = currentPage,
|
||||||
sort = currentState.sortType,
|
sort = currentState.sortType,
|
||||||
username = user.name,
|
username = uiState.value.user.name,
|
||||||
otherInstance = otherInstance,
|
otherInstance = otherInstance,
|
||||||
)
|
)
|
||||||
}.await()
|
}.await()
|
||||||
@ -279,7 +283,7 @@ class UserDetailViewModel(
|
|||||||
id = userId,
|
id = userId,
|
||||||
page = currentPage,
|
page = currentPage,
|
||||||
sort = currentState.sortType,
|
sort = currentState.sortType,
|
||||||
username = user.name,
|
username = uiState.value.user.name,
|
||||||
otherInstance = otherInstance,
|
otherInstance = otherInstance,
|
||||||
).orEmpty()
|
).orEmpty()
|
||||||
} else {
|
} else {
|
||||||
@ -502,7 +506,6 @@ class UserDetailViewModel(
|
|||||||
mvi.updateState { it.copy(asyncInProgress = true) }
|
mvi.updateState { it.copy(asyncInProgress = true) }
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val userId = user.id
|
|
||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
userRepository.block(userId, true, auth).getOrThrow()
|
userRepository.block(userId, true, auth).getOrThrow()
|
||||||
mvi.emitEffect(UserDetailMviModel.Effect.BlockSuccess)
|
mvi.emitEffect(UserDetailMviModel.Effect.BlockSuccess)
|
||||||
@ -518,6 +521,7 @@ class UserDetailViewModel(
|
|||||||
mvi.updateState { it.copy(asyncInProgress = true) }
|
mvi.updateState { it.copy(asyncInProgress = true) }
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.scope?.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
|
val user = uiState.value.user
|
||||||
val instanceId = user.instanceId
|
val instanceId = user.instanceId
|
||||||
val auth = identityRepository.authToken.value
|
val auth = identityRepository.authToken.value
|
||||||
siteRepository.block(instanceId, true, auth).getOrThrow()
|
siteRepository.block(instanceId, true, auth).getOrThrow()
|
||||||
|
@ -9,7 +9,7 @@ val userDetailModule = module {
|
|||||||
factory<UserDetailMviModel> { params ->
|
factory<UserDetailMviModel> { params ->
|
||||||
UserDetailViewModel(
|
UserDetailViewModel(
|
||||||
mvi = DefaultMviModel(UserDetailMviModel.UiState()),
|
mvi = DefaultMviModel(UserDetailMviModel.UiState()),
|
||||||
user = params[0],
|
userId = params[0],
|
||||||
otherInstance = params[1],
|
otherInstance = params[1],
|
||||||
identityRepository = get(),
|
identityRepository = get(),
|
||||||
apiConfigurationRepository = get(),
|
apiConfigurationRepository = get(),
|
||||||
@ -24,6 +24,7 @@ val userDetailModule = module {
|
|||||||
notificationCenter = get(),
|
notificationCenter = get(),
|
||||||
imagePreloadManager = get(),
|
imagePreloadManager = get(),
|
||||||
getSortTypesUseCase = get(),
|
getSortTypesUseCase = get(),
|
||||||
|
itemCache = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -46,7 +46,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigation
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.prettifyDate
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.prettifyDate
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.getPrettyNumber
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.getPrettyNumber
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.userinfo.components.ModeratedCommunityCell
|
import com.github.diegoberaldin.raccoonforlemmy.unit.userinfo.components.ModeratedCommunityCell
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
import com.github.diegoberaldin.raccoonforlemmy.unit.web.WebViewScreen
|
||||||
@ -57,12 +56,12 @@ import kotlinx.coroutines.launch
|
|||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
class UserInfoScreen(
|
class UserInfoScreen(
|
||||||
private val user: UserModel,
|
private val userId: Int,
|
||||||
) : Screen {
|
) : Screen {
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val model = getScreenModel<UserInfoMviModel> { parametersOf(user) }
|
val model = getScreenModel<UserInfoMviModel> { parametersOf(userId) }
|
||||||
model.bindToLifecycle(key)
|
model.bindToLifecycle(key)
|
||||||
val uiState by model.uiState.collectAsState()
|
val uiState by model.uiState.collectAsState()
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
|
@ -4,27 +4,29 @@ import com.github.diegoberaldin.raccoonforlemmy.core.architecture.DefaultMviMode
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.MviModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.repository.SettingsRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.LemmyItemCache
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
|
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.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class UserInfoViewModel(
|
class UserInfoViewModel(
|
||||||
private val mvi: DefaultMviModel<UserInfoMviModel.Intent, UserInfoMviModel.UiState, UserInfoMviModel.Effect>,
|
private val mvi: DefaultMviModel<UserInfoMviModel.Intent, UserInfoMviModel.UiState, UserInfoMviModel.Effect>,
|
||||||
private val user: UserModel,
|
private val userId: Int,
|
||||||
private val userRepository: UserRepository,
|
private val userRepository: UserRepository,
|
||||||
private val settingsRepository: SettingsRepository,
|
private val settingsRepository: SettingsRepository,
|
||||||
|
private val itemCache: LemmyItemCache,
|
||||||
) : UserInfoMviModel,
|
) : UserInfoMviModel,
|
||||||
MviModel<UserInfoMviModel.Intent, UserInfoMviModel.UiState, UserInfoMviModel.Effect> by mvi {
|
MviModel<UserInfoMviModel.Intent, UserInfoMviModel.UiState, UserInfoMviModel.Effect> by mvi {
|
||||||
|
|
||||||
override fun onStarted() {
|
override fun onStarted() {
|
||||||
mvi.onStarted()
|
mvi.onStarted()
|
||||||
mvi.updateState {
|
|
||||||
it.copy(user = user)
|
mvi.scope?.launch {
|
||||||
}
|
val user = itemCache.getUser(userId) ?: UserModel()
|
||||||
mvi.scope?.launch(Dispatchers.IO) {
|
mvi.updateState {
|
||||||
|
it.copy(user = user)
|
||||||
|
}
|
||||||
settingsRepository.currentSettings.onEach {
|
settingsRepository.currentSettings.onEach {
|
||||||
mvi.updateState { it.copy(autoLoadImages = it.autoLoadImages) }
|
mvi.updateState { it.copy(autoLoadImages = it.autoLoadImages) }
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
|
@ -9,9 +9,10 @@ val userInfoModule = module {
|
|||||||
factory<UserInfoMviModel> { params ->
|
factory<UserInfoMviModel> { params ->
|
||||||
UserInfoViewModel(
|
UserInfoViewModel(
|
||||||
mvi = DefaultMviModel(UserInfoMviModel.UiState()),
|
mvi = DefaultMviModel(UserInfoMviModel.UiState()),
|
||||||
user = params[0],
|
userId = params[0],
|
||||||
userRepository = get(),
|
userRepository = get(),
|
||||||
settingsRepository = get(),
|
settingsRepository = get(),
|
||||||
|
itemCache = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user