Skip to content

Commit

Permalink
Comment tree rework 1 (#162)
Browse files Browse the repository at this point in the history
* Trying to rework comment tree v1.

* Fixing tree UI triggering.
  • Loading branch information
dessalines authored Apr 19, 2022
1 parent a1fd106 commit 2975bb7
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 14 deletions.
7 changes: 5 additions & 2 deletions app/src/main/java/com/jerboa/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import android.widget.Toast
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.material.ScaffoldState
import androidx.compose.runtime.Stable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color
Expand Down Expand Up @@ -95,7 +97,8 @@ fun newVote(currentVote: Int?, voteType: VoteType): Int {

data class CommentNodeData(
val commentView: CommentView,
val children: MutableList<CommentNodeData>?,
// Must use a SnapshotStateList and not a MutableList here, otherwise changes in the tree children won't trigger a UI update
val children: SnapshotStateList<CommentNodeData>?,
var depth: Int?,
)

Expand All @@ -114,7 +117,7 @@ fun buildCommentsTree(
comments?.forEach { cv ->
val node = CommentNodeData(
commentView = cv,
children = mutableListOf(),
children = mutableStateListOf(),
depth = null,
)
map[cv.comment.id] = node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package com.jerboa.ui.components.comment
import android.content.Context
import android.util.Log
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.focus.FocusManager
import androidx.navigation.NavController
import com.jerboa.CommentNodeData
import com.jerboa.VoteType
import com.jerboa.api.*
import com.jerboa.datatypes.CommentView
Expand All @@ -24,6 +27,7 @@ import kotlinx.coroutines.launch
fun likeCommentRoutine(
commentView: MutableState<CommentView?>,
comments: MutableList<CommentView>? = null,
commentTree: SnapshotStateList<CommentNodeData>? = null,
voteType: VoteType,
account: Account,
ctx: Context,
Expand All @@ -39,13 +43,17 @@ fun likeCommentRoutine(
comments?.also {
findAndUpdateComment(comments, updatedCommentView)
}
commentTree?.also {
findAndUpdateCommentInTree(commentTree, updatedCommentView)
}
}
}
}

fun saveCommentRoutine(
commentView: MutableState<CommentView?>,
comments: MutableList<CommentView>? = null,
commentTree: SnapshotStateList<CommentNodeData>? = null,
account: Account,
ctx: Context,
scope: CoroutineScope,
Expand All @@ -61,6 +69,9 @@ fun saveCommentRoutine(
comments?.also {
findAndUpdateComment(comments, updatedCommentView)
}
commentTree?.also {
findAndUpdateCommentInTree(commentTree, updatedCommentView)
}
}
}
}
Expand Down Expand Up @@ -138,7 +149,7 @@ fun createCommentRoutine(

// Add to all the views which might have your comment
if (commentView != null) {
addCommentToMutableList(postViewModel.comments, commentView)
insertCommentIntoTree(postViewModel.commentTree, commentView)

// Maybe a back button would view this page.
if (account.id == personProfileViewModel.personId.value) {
Expand Down Expand Up @@ -185,7 +196,7 @@ fun editCommentRoutine(

// Update all the views which might have your comment
findAndUpdateComment(personProfileViewModel.comments, commentView.value)
findAndUpdateComment(postViewModel.comments, commentView.value)
findAndUpdateCommentInTree(postViewModel.commentTree, commentView.value)
findAndUpdateComment(inboxViewModel.replies, commentView.value)

navController.navigateUp()
Expand All @@ -196,6 +207,7 @@ fun editCommentRoutine(
fun deleteCommentRoutine(
commentView: MutableState<CommentView?>,
comments: MutableList<CommentView>? = null,
commentTree: SnapshotStateList<CommentNodeData>? = null,
account: Account,
ctx: Context,
scope: CoroutineScope,
Expand All @@ -212,6 +224,9 @@ fun deleteCommentRoutine(
comments?.also {
findAndUpdateComment(comments, deletedCommentView)
}
commentTree?.also {
findAndUpdateCommentInTree(commentTree, deletedCommentView)
}
}
}
}
Expand Down Expand Up @@ -249,6 +264,63 @@ fun findAndUpdateComment(
}
}

fun insertCommentIntoTree(
commentTree: MutableList<CommentNodeData>,
cv: CommentView
) {
var nodeData = CommentNodeData(
commentView = cv,
children = null,
depth = null,
)
cv.comment.parent_id?.also { parentId ->
val foundIndex = commentTree.indexOfFirst {
it.commentView.comment.id == parentId
}

if (foundIndex != -1) {
val parent = commentTree[foundIndex]
nodeData.depth = parent.depth?.plus(1) ?: 0

parent.children?.also { children ->
children.add(0, nodeData)
} ?: run {
commentTree[foundIndex] = parent.copy(children = mutableStateListOf(nodeData))
}
} else {
commentTree.forEach { node ->
node.children?.also { children ->
insertCommentIntoTree(children, cv)
}
}
}
} ?: run {
commentTree.add(0, nodeData)
}
}

fun findAndUpdateCommentInTree(
commentTree: SnapshotStateList<CommentNodeData>,
cv: CommentView?
) {
cv?.also {
val foundIndex = commentTree.indexOfFirst {
it.commentView.comment.id == cv.comment.id
}

if (foundIndex != -1) {
val updatedComment = commentTree[foundIndex].copy(commentView = cv)
commentTree[foundIndex] = updatedComment
} else {
commentTree.forEach { node ->
node.children?.also { children ->
findAndUpdateCommentInTree(children, cv)
}
}
}
}
}

fun addCommentToMutableList(
comments: MutableList<CommentView>,
newCommentView: CommentView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ import androidx.compose.material.LinearProgressIndicator
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Surface
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavController
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import com.jerboa.VoteType
import com.jerboa.buildCommentsTree
import com.jerboa.datatypes.SortType
import com.jerboa.db.AccountViewModel
import com.jerboa.isModerator
import com.jerboa.openLink
Expand Down Expand Up @@ -57,7 +56,6 @@ fun PostActivity(
val ctx = LocalContext.current

val account = getCurrentAccount(accountViewModel = accountViewModel)
val commentNodes = buildCommentsTree(postViewModel.comments, SortType.Hot)

val swipeRefreshState = rememberSwipeRefreshState(
isRefreshing = postViewModel.loading && postViewModel
Expand Down Expand Up @@ -200,7 +198,7 @@ fun PostActivity(
)
}
// Can't really do scrolling well here either because of tree
items(commentNodes) { node ->
items(postViewModel.commentTree) { node ->
CommentNode(
node = node,
onUpvoteClick = { commentView ->
Expand Down
15 changes: 9 additions & 6 deletions app/src/main/java/com/jerboa/ui/components/post/PostViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.jerboa.CommentNodeData
import com.jerboa.VoteType
import com.jerboa.api.API
import com.jerboa.api.retrofitErrorHandler
import com.jerboa.buildCommentsTree
import com.jerboa.datatypes.CommentView
import com.jerboa.datatypes.CommunityModeratorView
import com.jerboa.datatypes.PersonSafe
import com.jerboa.datatypes.PostView
import com.jerboa.datatypes.SortType
import com.jerboa.datatypes.api.GetPost
import com.jerboa.datatypes.api.GetPostResponse
import com.jerboa.db.Account
Expand All @@ -33,7 +36,7 @@ class PostViewModel : ViewModel() {
private set
var postView = mutableStateOf<PostView?>(null)
private set
var comments = mutableStateListOf<CommentView>()
var commentTree = mutableStateListOf<CommentNodeData>()
private set
var moderators = mutableStateListOf<CommunityModeratorView>()
private set
Expand Down Expand Up @@ -64,8 +67,8 @@ class PostViewModel : ViewModel() {
val out = retrofitErrorHandler(api.getPost(form = form.serializeToMap()))
res = out
postView.value = out.post_view
comments.clear()
comments.addAll(out.comments)
commentTree.clear()
commentTree.addAll(buildCommentsTree(out.comments, SortType.Hot))
moderators.clear()
moderators.addAll(out.moderators)
} catch (e: Exception) {
Expand All @@ -85,7 +88,7 @@ class PostViewModel : ViewModel() {
likeCommentRoutine(
commentView = mutableStateOf(commentView),
voteType = voteType,
comments = comments,
commentTree = commentTree,
account = account,
ctx = ctx,
scope = viewModelScope,
Expand All @@ -95,7 +98,7 @@ class PostViewModel : ViewModel() {
fun deleteComment(commentView: CommentView, account: Account, ctx: Context) {
deleteCommentRoutine(
commentView = mutableStateOf(commentView),
comments = comments, // TODO should this be here?
commentTree = commentTree,
account = account,
ctx = ctx,
scope = viewModelScope,
Expand Down Expand Up @@ -125,7 +128,7 @@ class PostViewModel : ViewModel() {
) {
saveCommentRoutine(
commentView = mutableStateOf(commentView),
comments = comments,
commentTree = commentTree,
account = account,
ctx = ctx,
scope = viewModelScope,
Expand Down

0 comments on commit 2975bb7

Please sign in to comment.