feat: implement support for persisting read comments

Fixes #358
This commit is contained in:
Harsh Shandilya 2023-01-12 01:01:29 +05:30
parent 1345709450
commit a59b6411b1
No known key found for this signature in database
3 changed files with 27 additions and 6 deletions

View file

@ -217,6 +217,8 @@ fun LobstersApp(
postId = postId, postId = postId,
postActions = postActions, postActions = postActions,
htmlConverter = htmlConverter, htmlConverter = htmlConverter,
getSeenComments = viewModel::getSeenComments,
markSeenComments = viewModel::markSeenComments,
) )
} }
composable( composable(

View file

@ -28,14 +28,20 @@ internal data class CommentNode(
} }
} }
internal fun createListNode(comments: List<Comment>): MutableList<CommentNode> { internal fun createListNode(
comments: List<Comment>,
commentState: PostComments?
): MutableList<CommentNode> {
val commentNodes = mutableListOf<CommentNode>() val commentNodes = mutableListOf<CommentNode>()
val isUnread = { id: String -> commentState?.commentIds?.contains(id) == false }
for (i in comments.indices) { for (i in comments.indices) {
if (comments[i].indentLevel == 1) { if (comments[i].indentLevel == 1) {
commentNodes.add(CommentNode(comment = comments[i])) commentNodes.add(CommentNode(comment = comments[i], isUnread = isUnread(comments[i].shortId)))
} else { } else {
commentNodes.last().addChild(CommentNode(comment = comments[i])) commentNodes
.last()
.addChild(CommentNode(comment = comments[i], isUnread = isUnread(comments[i].shortId)))
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright © 2021-2022 Harsh Shandilya. * Copyright © 2021-2023 Harsh Shandilya.
* Use of this source code is governed by an MIT-style * Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at * license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT. * https://opensource.org/licenses/MIT.
@ -16,6 +16,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState import androidx.compose.runtime.produceState
import androidx.compose.runtime.toMutableStateList import androidx.compose.runtime.toMutableStateList
@ -31,16 +32,22 @@ import dev.msfjarvis.claw.common.NetworkState.Success
import dev.msfjarvis.claw.common.posts.PostActions import dev.msfjarvis.claw.common.posts.PostActions
import dev.msfjarvis.claw.common.ui.NetworkError import dev.msfjarvis.claw.common.ui.NetworkError
import dev.msfjarvis.claw.common.ui.ProgressBar import dev.msfjarvis.claw.common.ui.ProgressBar
import dev.msfjarvis.claw.database.local.PostComments
import dev.msfjarvis.claw.model.Comment
import dev.msfjarvis.claw.model.LobstersPostDetails import dev.msfjarvis.claw.model.LobstersPostDetails
@Suppress("LongParameterList")
@Composable @Composable
private fun CommentsPageInternal( private fun CommentsPageInternal(
details: LobstersPostDetails, details: LobstersPostDetails,
postActions: PostActions, postActions: PostActions,
htmlConverter: HTMLConverter, htmlConverter: HTMLConverter,
commentState: PostComments?,
markSeenComments: (String, List<Comment>) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val commentNodes = createListNode(details.comments).toMutableStateList() val commentNodes = createListNode(details.comments, commentState).toMutableStateList()
LaunchedEffect(key1 = commentNodes) { markSeenComments(details.shortId, details.comments) }
Surface(color = MaterialTheme.colorScheme.surfaceVariant) { Surface(color = MaterialTheme.colorScheme.surfaceVariant) {
LazyColumn(modifier = modifier, contentPadding = PaddingValues(bottom = 24.dp)) { LazyColumn(modifier = modifier, contentPadding = PaddingValues(bottom = 24.dp)) {
@ -90,12 +97,14 @@ private fun CommentsPageInternal(
} }
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST", "LongParameterList")
@Composable @Composable
fun CommentsPage( fun CommentsPage(
postId: String, postId: String,
postActions: PostActions, postActions: PostActions,
htmlConverter: HTMLConverter, htmlConverter: HTMLConverter,
getSeenComments: suspend (String) -> PostComments?,
markSeenComments: (String, List<Comment>) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val postDetails by val postDetails by
@ -106,6 +115,8 @@ fun CommentsPage(
onFailure = { value = Error(error = it, description = "Failed to load comments") } onFailure = { value = Error(error = it, description = "Failed to load comments") }
) )
} }
val commentState by
produceState<PostComments?>(initialValue = null) { value = getSeenComments(postId) }
when (postDetails) { when (postDetails) {
is Success<*> -> { is Success<*> -> {
@ -113,6 +124,8 @@ fun CommentsPage(
details = (postDetails as Success<LobstersPostDetails>).data, details = (postDetails as Success<LobstersPostDetails>).data,
postActions = postActions, postActions = postActions,
htmlConverter = htmlConverter, htmlConverter = htmlConverter,
commentState = commentState,
markSeenComments = markSeenComments,
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
) )
} }