mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-10-11 00:23:41 +02:00
Separating Note observers into different types to avoid full screen refreshes.
This commit is contained in:
@@ -243,10 +243,12 @@ class Account(
|
|||||||
|
|
||||||
fun joinChannel(idHex: String) {
|
fun joinChannel(idHex: String) {
|
||||||
followingChannels.add(idHex)
|
followingChannels.add(idHex)
|
||||||
|
invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun leaveChannel(idHex: String) {
|
fun leaveChannel(idHex: String) {
|
||||||
followingChannels.remove(idHex)
|
followingChannels.remove(idHex)
|
||||||
|
invalidateData()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideUser(pubkeyHex: String) {
|
fun hideUser(pubkeyHex: String) {
|
||||||
|
@@ -45,7 +45,7 @@ class Note(val idHex: String) {
|
|||||||
this.mentions = mentions
|
this.mentions = mentions
|
||||||
this.replyTo = replyTo
|
this.replyTo = replyTo
|
||||||
|
|
||||||
invalidateData()
|
invalidateData(live)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun formattedDateTime(timestamp: Long): String {
|
fun formattedDateTime(timestamp: Long): String {
|
||||||
@@ -77,22 +77,22 @@ class Note(val idHex: String) {
|
|||||||
|
|
||||||
fun addReply(note: Note) {
|
fun addReply(note: Note) {
|
||||||
if (replies.add(note))
|
if (replies.add(note))
|
||||||
invalidateData()
|
invalidateData(liveReplies)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addBoost(note: Note) {
|
fun addBoost(note: Note) {
|
||||||
if (boosts.add(note))
|
if (boosts.add(note))
|
||||||
invalidateData()
|
invalidateData(liveBoosts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addReaction(note: Note) {
|
fun addReaction(note: Note) {
|
||||||
if (reactions.add(note))
|
if (reactions.add(note))
|
||||||
invalidateData()
|
invalidateData(liveReactions)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addReport(note: Note) {
|
fun addReport(note: Note) {
|
||||||
if (reports.add(note))
|
if (reports.add(note))
|
||||||
invalidateData()
|
invalidateData(liveReports)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isReactedBy(user: User): Boolean {
|
fun isReactedBy(user: User): Boolean {
|
||||||
@@ -110,10 +110,15 @@ class Note(val idHex: String) {
|
|||||||
// Observers line up here.
|
// Observers line up here.
|
||||||
val live: NoteLiveData = NoteLiveData(this)
|
val live: NoteLiveData = NoteLiveData(this)
|
||||||
|
|
||||||
|
val liveReactions: NoteLiveData = NoteLiveData(this)
|
||||||
|
val liveBoosts: NoteLiveData = NoteLiveData(this)
|
||||||
|
val liveReplies: NoteLiveData = NoteLiveData(this)
|
||||||
|
val liveReports: NoteLiveData = NoteLiveData(this)
|
||||||
|
|
||||||
// Refreshes observers in batches.
|
// Refreshes observers in batches.
|
||||||
var handlerWaiting = false
|
var handlerWaiting = false
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun invalidateData() {
|
fun invalidateData(live: NoteLiveData) {
|
||||||
if (handlerWaiting) return
|
if (handlerWaiting) return
|
||||||
|
|
||||||
handlerWaiting = true
|
handlerWaiting = true
|
||||||
|
@@ -14,13 +14,12 @@ import com.vitorpamplona.amethyst.ui.note.toShortenHex
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ClickableNoteTag(
|
fun ClickableNoteTag(
|
||||||
note: Note,
|
baesNote: Note,
|
||||||
navController: NavController
|
navController: NavController
|
||||||
) {
|
) {
|
||||||
val innerNoteState by note.live.observeAsState()
|
|
||||||
ClickableText(
|
ClickableText(
|
||||||
text = AnnotatedString("@${innerNoteState?.note?.id?.toNote()?.toShortenHex()} "),
|
text = AnnotatedString("@${baesNote.id.toNote().toShortenHex()} "),
|
||||||
onClick = { navController.navigate("Note/${innerNoteState?.note?.idHex}") },
|
onClick = { navController.navigate("Note/${baesNote.idHex}") },
|
||||||
style = LocalTextStyle.current.copy(color = MaterialTheme.colors.primary)
|
style = LocalTextStyle.current.copy(color = MaterialTheme.colors.primary)
|
||||||
)
|
)
|
||||||
}
|
}
|
@@ -186,7 +186,7 @@ fun NoteCompose(baseNote: Note, modifier: Modifier = Modifier, isInnerNote: Bool
|
|||||||
RichTextViewer(eventContent, note.event?.tags, navController)
|
RichTextViewer(eventContent, note.event?.tags, navController)
|
||||||
|
|
||||||
if (note.event !is ChannelMessageEvent) {
|
if (note.event !is ChannelMessageEvent) {
|
||||||
ReactionsRowState(note, accountViewModel)
|
ReactionsRow(note, accountViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
Divider(
|
Divider(
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.note
|
package com.vitorpamplona.amethyst.ui.note
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@@ -21,6 +20,7 @@ import androidx.compose.material.icons.outlined.Visibility
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@@ -44,7 +44,19 @@ import com.vitorpamplona.amethyst.ui.actions.NewPostView
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReactionsRow(note: Note, account: Account, accountViewModel: AccountViewModel) {
|
fun ReactionsRow(baseNote: Note, accountViewModel: AccountViewModel) {
|
||||||
|
val accountState by accountViewModel.accountLiveData.observeAsState()
|
||||||
|
val account = accountState?.account ?: return
|
||||||
|
|
||||||
|
val reactionsState by baseNote.liveReactions.observeAsState()
|
||||||
|
val reactedNote = reactionsState?.note
|
||||||
|
|
||||||
|
val boostsState by baseNote.liveBoosts.observeAsState()
|
||||||
|
val boostedNote = boostsState?.note
|
||||||
|
|
||||||
|
val repliesState by baseNote.liveReplies.observeAsState()
|
||||||
|
val replies = repliesState?.note?.replies ?: emptySet()
|
||||||
|
|
||||||
val grayTint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
val grayTint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
|
||||||
|
|
||||||
var popupExpanded by remember { mutableStateOf(false) }
|
var popupExpanded by remember { mutableStateOf(false) }
|
||||||
@@ -65,7 +77,7 @@ fun ReactionsRow(note: Note, account: Account, accountViewModel: AccountViewMode
|
|||||||
) {
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.then(Modifier.size(24.dp)),
|
modifier = Modifier.then(Modifier.size(24.dp)),
|
||||||
onClick = { if (account.isWriteable()) wantsToReplyTo = note }
|
onClick = { if (account.isWriteable()) wantsToReplyTo = baseNote }
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(R.drawable.ic_comment),
|
painter = painterResource(R.drawable.ic_comment),
|
||||||
@@ -76,7 +88,7 @@ fun ReactionsRow(note: Note, account: Account, accountViewModel: AccountViewMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
" ${showCount(note.replies?.size)}",
|
" ${showCount(replies.size)}",
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
color = grayTint,
|
color = grayTint,
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
@@ -84,9 +96,9 @@ fun ReactionsRow(note: Note, account: Account, accountViewModel: AccountViewMode
|
|||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.then(Modifier.size(24.dp)),
|
modifier = Modifier.then(Modifier.size(24.dp)),
|
||||||
onClick = { if (account.isWriteable()) accountViewModel.boost(note) }
|
onClick = { if (account.isWriteable()) accountViewModel.boost(baseNote) }
|
||||||
) {
|
) {
|
||||||
if (note.isBoostedBy(account.userProfile())) {
|
if (boostedNote?.isBoostedBy(account.userProfile()) == true) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(R.drawable.ic_retweeted),
|
painter = painterResource(R.drawable.ic_retweeted),
|
||||||
null,
|
null,
|
||||||
@@ -104,7 +116,7 @@ fun ReactionsRow(note: Note, account: Account, accountViewModel: AccountViewMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
" ${showCount(note.boosts?.size)}",
|
" ${showCount(boostedNote?.boosts?.size)}",
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
@@ -112,9 +124,9 @@ fun ReactionsRow(note: Note, account: Account, accountViewModel: AccountViewMode
|
|||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.then(Modifier.size(24.dp)),
|
modifier = Modifier.then(Modifier.size(24.dp)),
|
||||||
onClick = { if (account.isWriteable()) accountViewModel.reactTo(note) }
|
onClick = { if (account.isWriteable()) accountViewModel.reactTo(baseNote) }
|
||||||
) {
|
) {
|
||||||
if (note.isReactedBy(account.userProfile())) {
|
if (reactedNote?.isReactedBy(account.userProfile()) == true) {
|
||||||
Icon(
|
Icon(
|
||||||
painter = painterResource(R.drawable.ic_liked),
|
painter = painterResource(R.drawable.ic_liked),
|
||||||
null,
|
null,
|
||||||
@@ -132,7 +144,7 @@ fun ReactionsRow(note: Note, account: Account, accountViewModel: AccountViewMode
|
|||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
" ${showCount(note.reactions?.size)}",
|
" ${showCount(reactedNote?.reactions?.size)}",
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
@@ -154,7 +166,7 @@ fun ReactionsRow(note: Note, account: Account, accountViewModel: AccountViewMode
|
|||||||
Row(modifier = Modifier.weight(1f)) {
|
Row(modifier = Modifier.weight(1f)) {
|
||||||
AsyncImage(
|
AsyncImage(
|
||||||
model = ImageRequest.Builder(LocalContext.current)
|
model = ImageRequest.Builder(LocalContext.current)
|
||||||
.data("https://counter.amethyst.social/${note.idHex}.svg?label=+&color=00000000")
|
.data("https://counter.amethyst.social/${baseNote.idHex}.svg?label=+&color=00000000")
|
||||||
.crossfade(true)
|
.crossfade(true)
|
||||||
.diskCachePolicy(CachePolicy.DISABLED)
|
.diskCachePolicy(CachePolicy.DISABLED)
|
||||||
.memoryCachePolicy(CachePolicy.ENABLED)
|
.memoryCachePolicy(CachePolicy.ENABLED)
|
||||||
@@ -179,7 +191,7 @@ fun ReactionsRow(note: Note, account: Account, accountViewModel: AccountViewMode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NoteDropDownMenu(note, popupExpanded, { popupExpanded = false }, accountViewModel)
|
NoteDropDownMenu(baseNote, popupExpanded, { popupExpanded = false }, accountViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showCount(size: Int?): String {
|
fun showCount(size: Int?): String {
|
||||||
|
@@ -1,20 +0,0 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.note
|
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ReactionsRowState(baseNote: Note, accountViewModel: AccountViewModel) {
|
|
||||||
val accountState by accountViewModel.accountLiveData.observeAsState()
|
|
||||||
val account = accountState?.account
|
|
||||||
|
|
||||||
val noteState by baseNote.live.observeAsState()
|
|
||||||
val note = noteState?.note
|
|
||||||
|
|
||||||
if (account == null || note == null) return
|
|
||||||
|
|
||||||
ReactionsRow(note, account, accountViewModel)
|
|
||||||
}
|
|
@@ -40,7 +40,7 @@ import com.vitorpamplona.amethyst.model.Note
|
|||||||
import com.vitorpamplona.amethyst.ui.components.RichTextViewer
|
import com.vitorpamplona.amethyst.ui.components.RichTextViewer
|
||||||
import com.vitorpamplona.amethyst.ui.note.BlankNote
|
import com.vitorpamplona.amethyst.ui.note.BlankNote
|
||||||
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
import com.vitorpamplona.amethyst.ui.note.NoteCompose
|
||||||
import com.vitorpamplona.amethyst.ui.note.ReactionsRowState
|
import com.vitorpamplona.amethyst.ui.note.ReactionsRow
|
||||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||||
import com.vitorpamplona.amethyst.ui.note.timeAgoLong
|
import com.vitorpamplona.amethyst.ui.note.timeAgoLong
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
@@ -205,7 +205,7 @@ fun NoteMaster(baseNote: Note, accountViewModel: AccountViewModel, navController
|
|||||||
if (eventContent != null)
|
if (eventContent != null)
|
||||||
RichTextViewer(eventContent, note.event?.tags, navController)
|
RichTextViewer(eventContent, note.event?.tags, navController)
|
||||||
|
|
||||||
ReactionsRowState(note, accountViewModel)
|
ReactionsRow(note, accountViewModel)
|
||||||
|
|
||||||
Divider(
|
Divider(
|
||||||
modifier = Modifier.padding(top = 10.dp),
|
modifier = Modifier.padding(top = 10.dp),
|
||||||
|
Reference in New Issue
Block a user