- Solves infinite Quotation issue.

- Restructures NoteCompose for performance
- Restructures markAsRead to minimize threading cost.
This commit is contained in:
Vitor Pamplona 2024-03-18 15:26:49 -04:00
parent ac56d02b9d
commit d83acab84b
42 changed files with 443 additions and 558 deletions

View File

@ -31,6 +31,7 @@ import com.vitorpamplona.quartz.events.ImmutableListOfLists
fun TranslatableRichTextViewer(
content: String,
canPreview: Boolean,
quotesLeft: Int,
modifier: Modifier = Modifier,
tags: ImmutableListOfLists<String>,
backgroundColor: MutableState<Color>,
@ -40,6 +41,7 @@ fun TranslatableRichTextViewer(
) = ExpandableRichTextViewer(
content,
canPreview,
quotesLeft,
modifier,
tags,
backgroundColor,

View File

@ -268,6 +268,7 @@ fun EditPostView(
makeItShort = true,
unPackReply = false,
isQuotedNote = true,
quotesLeft = 1,
modifier = MaterialTheme.colorScheme.replyModifier,
accountViewModel = accountViewModel,
nav = nav,
@ -312,11 +313,12 @@ fun EditPostView(
val backgroundColor = remember { mutableStateOf(bgColor) }
BechLink(
myUrlPreview,
true,
backgroundColor,
accountViewModel,
nav,
word = myUrlPreview,
canPreview = true,
quotesLeft = 1,
backgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
} else if (RichTextParser.isUrlWithoutScheme(myUrlPreview)) {
LoadUrlPreview("https://$myUrlPreview", myUrlPreview, accountViewModel)

View File

@ -336,6 +336,7 @@ fun NewPostView(
makeItShort = true,
unPackReply = false,
isQuotedNote = true,
quotesLeft = 1,
modifier = MaterialTheme.colorScheme.replyModifier,
accountViewModel = accountViewModel,
nav = nav,
@ -413,11 +414,12 @@ fun NewPostView(
val backgroundColor = remember { mutableStateOf(bgColor) }
BechLink(
myUrlPreview,
true,
backgroundColor,
accountViewModel,
nav,
word = myUrlPreview,
canPreview = true,
quotesLeft = 1,
backgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
} else if (RichTextParser.isUrlWithoutScheme(myUrlPreview)) {
LoadUrlPreview("https://$myUrlPreview", myUrlPreview, accountViewModel)

View File

@ -65,6 +65,7 @@ fun NotifyRequestDialog(
TranslatableRichTextViewer(
textContent,
canPreview = true,
quotesLeft = 1,
Modifier.fillMaxWidth(),
EmptyTagList,
background,

View File

@ -26,13 +26,18 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.text.AnnotatedString
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.ui.navigation.routeFor
import com.vitorpamplona.amethyst.ui.note.toShortenHex
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@Composable
fun ClickableNoteTag(
baseNote: Note,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
val route = routeFor(baseNote, accountViewModel.userProfile())
ClickableText(
text = AnnotatedString("@${baseNote.idNote().toShortenHex()}"),
onClick = { nav("Note/${baseNote.idHex}") },

View File

@ -60,6 +60,7 @@ object ShowFullTextCache {
fun ExpandableRichTextViewer(
content: String,
canPreview: Boolean,
quotesLeft: Int,
modifier: Modifier,
tags: ImmutableListOfLists<String>,
backgroundColor: MutableState<Color>,
@ -94,6 +95,7 @@ fun ExpandableRichTextViewer(
RichTextViewer(
text,
canPreview,
quotesLeft,
modifier.align(Alignment.TopStart),
tags,
backgroundColor,

View File

@ -129,6 +129,7 @@ fun isMarkdown(content: String): Boolean {
fun RichTextViewer(
content: String,
canPreview: Boolean,
quotesLeft: Int,
modifier: Modifier,
tags: ImmutableListOfLists<String>,
backgroundColor: MutableState<Color>,
@ -139,7 +140,7 @@ fun RichTextViewer(
if (remember(content) { isMarkdown(content) }) {
RenderContentAsMarkdown(content, tags, accountViewModel, nav)
} else {
RenderRegular(content, tags, canPreview, backgroundColor, accountViewModel, nav)
RenderRegular(content, tags, canPreview, quotesLeft, backgroundColor, accountViewModel, nav)
}
}
}
@ -277,6 +278,7 @@ private fun RenderRegular(
content: String,
tags: ImmutableListOfLists<String>,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -287,6 +289,7 @@ private fun RenderRegular(
word,
state,
backgroundColor,
quotesLeft,
accountViewModel,
nav,
)
@ -394,10 +397,10 @@ private fun RenderWordWithoutPreview(
is CashuSegment -> Text(word.segmentText)
is EmailSegment -> ClickableEmail(word.segmentText)
is PhoneSegment -> ClickablePhone(word.segmentText)
is BechSegment -> BechLink(word.segmentText, false, backgroundColor, accountViewModel, nav)
is BechSegment -> BechLink(word.segmentText, false, 0, backgroundColor, accountViewModel, nav)
is HashTagSegment -> HashTag(word, nav)
is HashIndexUserSegment -> TagLink(word, accountViewModel, nav)
is HashIndexEventSegment -> TagLink(word, false, backgroundColor, accountViewModel, nav)
is HashIndexEventSegment -> TagLink(word, false, 0, backgroundColor, accountViewModel, nav)
is SchemelessUrlSegment -> NoProtocolUrlRenderer(word)
is RegularTextSegment -> Text(word.segmentText)
}
@ -408,6 +411,7 @@ private fun RenderWordWithPreview(
word: Segment,
state: RichTextViewerState,
backgroundColor: MutableState<Color>,
quotesLeft: Int,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
@ -420,10 +424,10 @@ private fun RenderWordWithPreview(
is CashuSegment -> CashuPreview(word.segmentText, accountViewModel)
is EmailSegment -> ClickableEmail(word.segmentText)
is PhoneSegment -> ClickablePhone(word.segmentText)
is BechSegment -> BechLink(word.segmentText, true, backgroundColor, accountViewModel, nav)
is BechSegment -> BechLink(word.segmentText, true, quotesLeft, backgroundColor, accountViewModel, nav)
is HashTagSegment -> HashTag(word, nav)
is HashIndexUserSegment -> TagLink(word, accountViewModel, nav)
is HashIndexEventSegment -> TagLink(word, true, backgroundColor, accountViewModel, nav)
is HashIndexEventSegment -> TagLink(word, true, quotesLeft, backgroundColor, accountViewModel, nav)
is SchemelessUrlSegment -> NoProtocolUrlRenderer(word)
is RegularTextSegment -> Text(word.segmentText)
}
@ -643,6 +647,7 @@ private fun ObserveUser(
fun BechLink(
word: String,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -655,14 +660,17 @@ fun BechLink(
}
}
if (canPreview && loadedLink?.baseNote != null) {
val baseNote = loadedLink?.baseNote
if (canPreview && quotesLeft > 0 && baseNote != null) {
Row {
DisplayFullNote(
loadedLink?.baseNote!!,
accountViewModel,
backgroundColor,
nav,
loadedLink?.nip19?.additionalChars?.ifBlank { null },
note = baseNote,
extraChars = loadedLink?.nip19?.additionalChars?.ifBlank { null },
quotesLeft = quotesLeft,
backgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
}
} else if (loadedLink?.nip19 != null) {
@ -683,17 +691,19 @@ fun BechLink(
@Composable
private fun DisplayFullNote(
it: Note,
accountViewModel: AccountViewModel,
backgroundColor: MutableState<Color>,
nav: (String) -> Unit,
note: Note,
extraChars: String?,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
NoteCompose(
baseNote = it,
baseNote = note,
accountViewModel = accountViewModel,
modifier = MaterialTheme.colorScheme.innerPostModifier,
parentBackgroundColor = backgroundColor,
quotesLeft = quotesLeft - 1,
isQuotedNote = true,
nav = nav,
)
@ -806,6 +816,7 @@ fun LoadNote(
fun TagLink(
word: HashIndexEventSegment,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -819,6 +830,7 @@ fun TagLink(
it,
word.extras,
canPreview,
quotesLeft,
accountViewModel,
backgroundColor,
nav,
@ -833,21 +845,23 @@ private fun DisplayNoteFromTag(
baseNote: Note,
addedChars: String?,
canPreview: Boolean,
quotesLeft: Int,
accountViewModel: AccountViewModel,
backgroundColor: MutableState<Color>,
nav: (String) -> Unit,
) {
if (canPreview) {
if (canPreview && quotesLeft > 0) {
NoteCompose(
baseNote = baseNote,
accountViewModel = accountViewModel,
modifier = MaterialTheme.colorScheme.innerPostModifier,
parentBackgroundColor = backgroundColor,
isQuotedNote = true,
quotesLeft = quotesLeft - 1,
nav = nav,
)
} else {
ClickableNoteTag(baseNote, nav)
ClickableNoteTag(baseNote, accountViewModel, nav)
}
addedChars?.ifBlank { null }?.let { Text(text = it) }

View File

@ -32,13 +32,11 @@ import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MilitaryTech
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
@ -46,8 +44,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@ -55,11 +51,10 @@ import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.ui.navigation.routeFor
import com.vitorpamplona.amethyst.ui.note.elements.NoteDropDownMenu
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
import com.vitorpamplona.amethyst.ui.screen.BadgeCard
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.Size15Modifier
import com.vitorpamplona.amethyst.ui.theme.newItemBackgroundColor
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import kotlinx.coroutines.launch
@ -86,24 +81,12 @@ fun BadgeCompose(
if (note == null) {
BlankNote(Modifier, !isInnerNote)
} else {
val defaultBackgroundColor = MaterialTheme.colorScheme.background
val backgroundColor = remember { mutableStateOf<Color>(defaultBackgroundColor) }
val newItemColor = MaterialTheme.colorScheme.newItemBackgroundColor
LaunchedEffect(key1 = likeSetCard) {
accountViewModel.loadAndMarkAsRead(routeForLastRead, likeSetCard.createdAt()) { isNew ->
val newBackgroundColor =
if (isNew) {
newItemColor.compositeOver(defaultBackgroundColor)
} else {
defaultBackgroundColor
}
if (backgroundColor.value != newBackgroundColor) {
backgroundColor.value = newBackgroundColor
}
}
}
val backgroundColor =
calculateBackgroundColor(
createdAt = likeSetCard.createdAt(),
routeForLastRead = routeForLastRead,
accountViewModel = accountViewModel,
)
Column(
modifier =
@ -173,21 +156,8 @@ fun BadgeCompose(
}
note.replyTo?.firstOrNull()?.let {
NoteCompose(
baseNote = it,
routeForLastRead = null,
isBoostedNote = true,
showHidden = showHidden,
parentBackgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
BadgeDisplay(baseNote = it)
}
HorizontalDivider(
modifier = Modifier.padding(top = 10.dp),
thickness = DividerThickness,
)
}
}
}

View File

@ -121,13 +121,12 @@ fun HiddenNote(
isHiddenAuthor: Boolean,
accountViewModel: AccountViewModel,
modifier: Modifier = Modifier,
isQuote: Boolean = false,
nav: (String) -> Unit,
onClick: () -> Unit,
) {
Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
Row(
modifier = Modifier.padding(start = if (!isQuote) 30.dp else 25.dp, end = 20.dp),
modifier = Modifier.padding(horizontal = 20.dp),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
) {

View File

@ -56,7 +56,6 @@ import androidx.compose.ui.Alignment.Companion.TopEnd
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
@ -91,7 +90,6 @@ import com.vitorpamplona.amethyst.ui.theme.Size5dp
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.StdPadding
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
import com.vitorpamplona.amethyst.ui.theme.newItemBackgroundColor
import com.vitorpamplona.amethyst.ui.theme.placeholderText
import com.vitorpamplona.quartz.events.ChannelCreateEvent
import com.vitorpamplona.quartz.events.ClassifiedsEvent
@ -258,7 +256,6 @@ fun RenderChannelCardReportState(
state.isHiddenAuthor,
accountViewModel,
modifier,
false,
nav,
onClick = { showReportedNote = true },
)
@ -307,41 +304,13 @@ private fun CheckNewAndRenderChannelCard(
showPopup: () -> Unit,
nav: (String) -> Unit,
) {
val newItemColor = MaterialTheme.colorScheme.newItemBackgroundColor
val defaultBackgroundColor = MaterialTheme.colorScheme.background
val backgroundColor =
remember {
mutableStateOf<Color>(
parentBackgroundColor?.value ?: defaultBackgroundColor,
)
}
LaunchedEffect(key1 = routeForLastRead, key2 = parentBackgroundColor?.value) {
routeForLastRead?.let {
accountViewModel.loadAndMarkAsRead(routeForLastRead, baseNote.createdAt()) { isNew ->
val newBackgroundColor =
if (isNew) {
if (parentBackgroundColor != null) {
newItemColor.compositeOver(parentBackgroundColor.value)
} else {
newItemColor.compositeOver(defaultBackgroundColor)
}
} else {
parentBackgroundColor?.value ?: defaultBackgroundColor
}
if (newBackgroundColor != backgroundColor.value) {
launch(Dispatchers.Main) { backgroundColor.value = newBackgroundColor }
}
}
}
?: run {
val newBackgroundColor = parentBackgroundColor?.value ?: defaultBackgroundColor
if (newBackgroundColor != backgroundColor.value) {
launch(Dispatchers.Main) { backgroundColor.value = newBackgroundColor }
}
}
}
calculateBackgroundColor(
createdAt = baseNote.createdAt(),
routeForLastRead = routeForLastRead,
parentBackgroundColor = parentBackgroundColor,
accountViewModel = accountViewModel,
)
ClickableNote(
baseNote = baseNote,

View File

@ -77,8 +77,6 @@ import com.vitorpamplona.quartz.events.ChannelCreateEvent
import com.vitorpamplona.quartz.events.ChannelMetadataEvent
import com.vitorpamplona.quartz.events.ChatroomKey
import com.vitorpamplona.quartz.events.ChatroomKeyable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@Composable
fun ChatroomHeaderCompose(
@ -408,11 +406,8 @@ private fun WatchNotificationChanges(
onNewStatus: (Boolean) -> Unit,
) {
LaunchedEffect(key1 = note, accountViewModel.accountMarkAsReadUpdates.intValue) {
launch(Dispatchers.IO) {
note.event?.createdAt()?.let {
val lastTime = accountViewModel.account.loadLastRead(route)
onNewStatus(it > lastTime)
}
note.event?.createdAt()?.let {
onNewStatus(it > accountViewModel.account.loadLastRead(route))
}
}
}

View File

@ -204,7 +204,6 @@ fun LoadedChatMessageCompose(
state.isHiddenAuthor,
accountViewModel,
Modifier,
innerQuote,
nav,
onClick = { showReportedNote = true },
)
@ -290,7 +289,7 @@ fun NormalChatNote(
if (routeForLastRead != null) {
LaunchedEffect(key1 = routeForLastRead) {
accountViewModel.loadAndMarkAsRead(routeForLastRead, note.createdAt()) {}
accountViewModel.loadAndMarkAsRead(routeForLastRead, note.createdAt())
}
}
@ -445,6 +444,7 @@ private fun MessageBubbleLines(
NoteRow(
note = baseNote,
canPreview = canPreview,
innerQuote = innerQuote,
backgroundBubbleColor = backgroundBubbleColor,
accountViewModel = accountViewModel,
nav = nav,
@ -528,6 +528,7 @@ private fun RenderReply(
private fun NoteRow(
note: Note,
canPreview: Boolean,
innerQuote: Boolean,
backgroundBubbleColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -544,6 +545,7 @@ private fun NoteRow(
RenderRegularTextNote(
note,
canPreview,
innerQuote,
backgroundBubbleColor,
accountViewModel,
nav,
@ -640,6 +642,7 @@ fun ChatTimeAgo(baseNote: Note) {
private fun RenderRegularTextNote(
note: Note,
canPreview: Boolean,
innerQuote: Boolean,
backgroundBubbleColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -655,6 +658,7 @@ private fun RenderRegularTextNote(
TranslatableRichTextViewer(
content = eventContent,
canPreview = canPreview,
quotesLeft = if (innerQuote) 0 else 1,
modifier = HalfTopPadding,
tags = tags,
backgroundColor = backgroundBubbleColor,
@ -667,6 +671,7 @@ private fun RenderRegularTextNote(
TranslatableRichTextViewer(
content = stringResource(id = R.string.could_not_decrypt_the_message),
canPreview = true,
quotesLeft = 0,
modifier = HalfTopPadding,
tags = EmptyTagList,
backgroundColor = backgroundBubbleColor,

View File

@ -30,24 +30,17 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.ui.navigation.routeFor
import com.vitorpamplona.amethyst.ui.note.elements.NoteDropDownMenu
import com.vitorpamplona.amethyst.ui.screen.MessageSetCard
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.newItemBackgroundColor
import kotlinx.coroutines.launch
@OptIn(ExperimentalFoundationApi::class)
@ -66,24 +59,12 @@ fun MessageSetCompose(
val scope = rememberCoroutineScope()
val defaultBackgroundColor = MaterialTheme.colorScheme.background
val backgroundColor = remember { mutableStateOf<Color>(defaultBackgroundColor) }
val newItemColor = MaterialTheme.colorScheme.newItemBackgroundColor
LaunchedEffect(key1 = messageSetCard) {
accountViewModel.loadAndMarkAsRead(routeForLastRead, messageSetCard.createdAt()) { isNew ->
val newBackgroundColor =
if (isNew) {
newItemColor.compositeOver(defaultBackgroundColor)
} else {
defaultBackgroundColor
}
if (backgroundColor.value != newBackgroundColor) {
backgroundColor.value = newBackgroundColor
}
}
}
val backgroundColor =
calculateBackgroundColor(
createdAt = messageSetCard.createdAt(),
routeForLastRead = routeForLastRead,
accountViewModel = accountViewModel,
)
val columnModifier =
remember(backgroundColor.value) {
@ -125,6 +106,7 @@ fun MessageSetCompose(
isBoostedNote = true,
addMarginTop = false,
showHidden = showHidden,
quotesLeft = 1,
parentBackgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,
@ -133,9 +115,5 @@ fun MessageSetCompose(
NoteDropDownMenu(baseNote, popupExpanded, null, accountViewModel, nav)
}
}
HorizontalDivider(
thickness = DividerThickness,
)
}
}

View File

@ -36,7 +36,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -54,7 +53,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
@ -74,7 +72,6 @@ import com.vitorpamplona.amethyst.ui.note.elements.NoteDropDownMenu
import com.vitorpamplona.amethyst.ui.screen.CombinedZap
import com.vitorpamplona.amethyst.ui.screen.MultiSetCard
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.HalfTopPadding
import com.vitorpamplona.amethyst.ui.theme.NotificationIconModifier
import com.vitorpamplona.amethyst.ui.theme.NotificationIconModifierSmaller
@ -88,14 +85,12 @@ import com.vitorpamplona.amethyst.ui.theme.StdStartPadding
import com.vitorpamplona.amethyst.ui.theme.WidthAuthorPictureModifier
import com.vitorpamplona.amethyst.ui.theme.WidthAuthorPictureModifierWithPadding
import com.vitorpamplona.amethyst.ui.theme.bitcoinColor
import com.vitorpamplona.amethyst.ui.theme.newItemBackgroundColor
import com.vitorpamplona.amethyst.ui.theme.overPictureBackground
import com.vitorpamplona.amethyst.ui.theme.profile35dpModifier
import com.vitorpamplona.quartz.encoders.Nip30CustomEmoji
import com.vitorpamplona.quartz.events.EmptyTagList
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlin.time.ExperimentalTime
@ -115,24 +110,12 @@ fun MultiSetCompose(
val scope = rememberCoroutineScope()
val defaultBackgroundColor = MaterialTheme.colorScheme.background
val backgroundColor = remember { mutableStateOf<Color>(defaultBackgroundColor) }
val newItemColor = MaterialTheme.colorScheme.newItemBackgroundColor
LaunchedEffect(key1 = multiSetCard) {
accountViewModel.loadAndMarkAsRead(routeForLastRead, multiSetCard.maxCreatedAt) { isNew ->
val newBackgroundColor =
if (isNew) {
newItemColor.compositeOver(defaultBackgroundColor)
} else {
defaultBackgroundColor
}
if (backgroundColor.value != newBackgroundColor) {
launch(Dispatchers.Main) { backgroundColor.value = newBackgroundColor }
}
}
}
val backgroundColor =
calculateBackgroundColor(
createdAt = multiSetCard.maxCreatedAt,
routeForLastRead = routeForLastRead,
accountViewModel = accountViewModel,
)
val columnModifier =
remember(backgroundColor.value) {
@ -163,6 +146,7 @@ fun MultiSetCompose(
modifier = HalfTopPadding,
isBoostedNote = true,
showHidden = showHidden,
quotesLeft = 1,
parentBackgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,
@ -170,10 +154,6 @@ fun MultiSetCompose(
NoteDropDownMenu(baseNote, popupExpanded, null, accountViewModel, nav)
}
HorizontalDivider(
thickness = DividerThickness,
)
}
}
@ -471,6 +451,7 @@ fun CrossfadeToDisplayComment(
TranslatableRichTextViewer(
content = comment,
canPreview = true,
quotesLeft = 1,
tags = EmptyTagList,
modifier = textBoxModifier,
backgroundColor = backgroundColor,

View File

@ -31,7 +31,6 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@ -56,7 +55,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.map
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.AddressableNote
import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.FeatureSetType
import com.vitorpamplona.amethyst.model.Note
@ -78,8 +76,6 @@ import com.vitorpamplona.amethyst.ui.note.elements.MoreOptionsButton
import com.vitorpamplona.amethyst.ui.note.elements.Reward
import com.vitorpamplona.amethyst.ui.note.elements.ShowForkInformation
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgo
import com.vitorpamplona.amethyst.ui.note.types.BadgeDisplay
import com.vitorpamplona.amethyst.ui.note.types.CommunityHeader
import com.vitorpamplona.amethyst.ui.note.types.DisplayPeopleList
import com.vitorpamplona.amethyst.ui.note.types.DisplayRelaySet
import com.vitorpamplona.amethyst.ui.note.types.EditState
@ -110,7 +106,6 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderWikiContent
import com.vitorpamplona.amethyst.ui.note.types.VideoDisplay
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ChannelHeader
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
import com.vitorpamplona.amethyst.ui.theme.HalfDoubleVertSpacer
@ -137,7 +132,6 @@ import com.vitorpamplona.quartz.events.AppDefinitionEvent
import com.vitorpamplona.quartz.events.AudioHeaderEvent
import com.vitorpamplona.quartz.events.AudioTrackEvent
import com.vitorpamplona.quartz.events.BadgeAwardEvent
import com.vitorpamplona.quartz.events.BadgeDefinitionEvent
import com.vitorpamplona.quartz.events.BaseTextNoteEvent
import com.vitorpamplona.quartz.events.ChannelCreateEvent
import com.vitorpamplona.quartz.events.ChannelMessageEvent
@ -172,10 +166,8 @@ import com.vitorpamplona.quartz.events.VideoVerticalEvent
import com.vitorpamplona.quartz.events.WikiNoteEvent
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun NoteCompose(
baseNote: Note,
@ -187,16 +179,27 @@ fun NoteCompose(
makeItShort: Boolean = false,
addMarginTop: Boolean = true,
showHidden: Boolean = false,
quotesLeft: Int,
parentBackgroundColor: MutableState<Color>? = null,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
Crossfade(targetState = hasEvent, label = "Event presence") {
if (it) {
CheckHiddenNoteCompose(
note = baseNote,
WatchNoteEvent(
baseNote = baseNote,
accountViewModel = accountViewModel,
showDivider = !isBoostedNote && !isQuotedNote,
modifier,
) {
CheckHiddenNoteCompose(
note = baseNote,
modifier = modifier,
showHidden = showHidden,
showHiddenWarning = isQuotedNote || isBoostedNote,
accountViewModel = accountViewModel,
nav = nav,
) { canPreview ->
NormalNote(
baseNote = baseNote,
routeForLastRead = routeForLastRead,
modifier = modifier,
isBoostedNote = isBoostedNote,
@ -204,22 +207,46 @@ fun NoteCompose(
unPackReply = unPackReply,
makeItShort = makeItShort,
addMarginTop = addMarginTop,
showHidden = showHidden,
canPreview = canPreview,
quotesLeft = quotesLeft,
parentBackgroundColor = parentBackgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
} else {
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
BlankNote(
remember {
modifier.combinedClickable(
onClick = {},
onLongClick = showPopup,
)
},
!isBoostedNote && !isQuotedNote,
)
}
}
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun WatchNoteEvent(
baseNote: Note,
accountViewModel: AccountViewModel,
showDivider: Boolean,
modifier: Modifier = Modifier,
onNoteEventFound: @Composable () -> Unit,
) {
if (baseNote.event != null) {
onNoteEventFound()
} else {
// avoid observing costs if already has an event.
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
Crossfade(targetState = hasEvent, label = "Event presence") {
if (it) {
onNoteEventFound()
} else {
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
BlankNote(
remember {
modifier.combinedClickable(
onClick = {},
onLongClick = showPopup,
)
},
showDivider,
)
}
}
}
}
@ -228,93 +255,64 @@ fun NoteCompose(
@Composable
fun CheckHiddenNoteCompose(
note: Note,
routeForLastRead: String? = null,
modifier: Modifier = Modifier,
isBoostedNote: Boolean = false,
isQuotedNote: Boolean = false,
unPackReply: Boolean = true,
makeItShort: Boolean = false,
addMarginTop: Boolean = true,
showHiddenWarning: Boolean,
showHidden: Boolean = false,
parentBackgroundColor: MutableState<Color>? = null,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
normalNote: @Composable (canPreview: Boolean) -> Unit,
) {
if (showHidden) {
// Ignores reports as well
val state by
remember(note) {
mutableStateOf(
AccountViewModel.NoteComposeReportState(),
)
}
RenderReportState(
state = state,
note = note,
routeForLastRead = routeForLastRead,
modifier = modifier,
isBoostedNote = isBoostedNote,
isQuotedNote = isQuotedNote,
unPackReply = unPackReply,
makeItShort = makeItShort,
addMarginTop = addMarginTop,
parentBackgroundColor = parentBackgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
normalNote(true)
} else {
val isHidden by
remember(note) {
accountViewModel.account.liveHiddenUsers
.map { note.isHiddenFor(it) }
.distinctUntilChanged()
}
.observeAsState(accountViewModel.isNoteHidden(note))
val showAnyway =
remember {
mutableStateOf(false)
}
Crossfade(targetState = isHidden, label = "CheckHiddenNoteCompose") {
if (!it || showAnyway.value) {
LoadedNoteCompose(
note = note,
routeForLastRead = routeForLastRead,
modifier = modifier,
isBoostedNote = isBoostedNote,
isQuotedNote = isQuotedNote,
unPackReply = unPackReply,
makeItShort = makeItShort,
addMarginTop = addMarginTop,
parentBackgroundColor = parentBackgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
} else if (isQuotedNote || isBoostedNote) {
HiddenNoteByMe(
isQuote = true,
onClick = { showAnyway.value = true },
)
WatchIsHidden(note, showHiddenWarning, accountViewModel) {
LoadReportsNoteCompose(note, modifier, accountViewModel, nav) { canPreview ->
normalNote(canPreview)
}
}
}
}
@Composable
fun LoadedNoteCompose(
fun WatchIsHidden(
note: Note,
showHiddenWarning: Boolean,
accountViewModel: AccountViewModel,
notHiddenNote: @Composable () -> Unit,
) {
val isHidden by remember(note) {
accountViewModel.account.liveHiddenUsers
.map { note.isHiddenFor(it) }
.distinctUntilChanged()
}
.observeAsState(accountViewModel.isNoteHidden(note))
val showAnyway =
remember {
mutableStateOf(false)
}
Crossfade(targetState = isHidden, label = "CheckHiddenNoteCompose") {
if (!it || showAnyway.value) {
notHiddenNote()
} else if (showHiddenWarning) {
// if it is a quoted or boosted note, how the hidden warning.
HiddenNoteByMe(
isQuote = true,
onClick = { showAnyway.value = true },
)
}
}
}
@Composable
fun LoadReportsNoteCompose(
note: Note,
routeForLastRead: String? = null,
modifier: Modifier = Modifier,
isBoostedNote: Boolean = false,
isQuotedNote: Boolean = false,
unPackReply: Boolean = true,
makeItShort: Boolean = false,
addMarginTop: Boolean = true,
parentBackgroundColor: MutableState<Color>? = null,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
normalNote: @Composable (canPreview: Boolean) -> Unit,
) {
var state by
remember(note) {
@ -330,20 +328,9 @@ fun LoadedNoteCompose(
}
Crossfade(targetState = state, label = "LoadedNoteCompose") {
RenderReportState(
it,
note,
routeForLastRead,
modifier,
isBoostedNote,
isQuotedNote,
unPackReply,
makeItShort,
addMarginTop,
parentBackgroundColor,
accountViewModel,
nav,
)
RenderReportState(state = it, note = note, modifier = modifier, accountViewModel = accountViewModel, nav = nav) { canPreview ->
normalNote(canPreview)
}
}
}
@ -351,16 +338,10 @@ fun LoadedNoteCompose(
fun RenderReportState(
state: AccountViewModel.NoteComposeReportState,
note: Note,
routeForLastRead: String? = null,
modifier: Modifier = Modifier,
isBoostedNote: Boolean = false,
isQuotedNote: Boolean = false,
unPackReply: Boolean = true,
makeItShort: Boolean = false,
addMarginTop: Boolean = true,
parentBackgroundColor: MutableState<Color>? = null,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
normalNote: @Composable (canPreview: Boolean) -> Unit,
) {
var showReportedNote by remember(note) { mutableStateOf(false) }
@ -371,27 +352,13 @@ fun RenderReportState(
state.isHiddenAuthor,
accountViewModel,
modifier,
isBoostedNote,
nav,
onClick = { showReportedNote = true },
)
} else {
val canPreview = (!state.isAcceptable && showReportedNote) || state.canPreview
NormalNote(
baseNote = note,
routeForLastRead = routeForLastRead,
modifier = modifier,
isBoostedNote = isBoostedNote,
isQuotedNote = isQuotedNote,
unPackReply = unPackReply,
makeItShort = makeItShort,
addMarginTop = addMarginTop,
canPreview = canPreview,
parentBackgroundColor = parentBackgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
normalNote(canPreview)
}
}
}
@ -422,6 +389,7 @@ fun NormalNote(
makeItShort: Boolean = false,
addMarginTop: Boolean = true,
canPreview: Boolean = true,
quotesLeft: Int,
parentBackgroundColor: MutableState<Color>? = null,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -439,35 +407,25 @@ fun NormalNote(
accountViewModel = accountViewModel,
nav = nav,
)
is CommunityDefinitionEvent ->
(baseNote as? AddressableNote)?.let {
CommunityHeader(
baseNote = it,
showBottomDiviser = true,
sendToCommunity = true,
accountViewModel = accountViewModel,
nav = nav,
)
}
is BadgeDefinitionEvent -> BadgeDisplay(baseNote = baseNote)
else ->
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) {
showPopup,
->
CheckNewAndRenderNote(
baseNote,
routeForLastRead,
modifier,
isBoostedNote,
isQuotedNote,
unPackReply,
makeItShort,
addMarginTop,
canPreview,
parentBackgroundColor,
accountViewModel,
showPopup,
nav,
baseNote = baseNote,
routeForLastRead = routeForLastRead,
modifier = modifier,
isBoostedNote = isBoostedNote,
isQuotedNote = isQuotedNote,
unPackReply = unPackReply,
makeItShort = makeItShort,
addMarginTop = addMarginTop,
canPreview = canPreview,
quotesLeft = quotesLeft,
parentBackgroundColor = parentBackgroundColor,
accountViewModel = accountViewModel,
showPopup = showPopup,
nav = nav,
)
}
}
@ -484,17 +442,6 @@ fun NormalNote(
accountViewModel = accountViewModel,
nav = nav,
)
is CommunityDefinitionEvent ->
(baseNote as? AddressableNote)?.let {
CommunityHeader(
baseNote = it,
showBottomDiviser = true,
sendToCommunity = true,
accountViewModel = accountViewModel,
nav = nav,
)
}
is BadgeDefinitionEvent -> BadgeDisplay(baseNote = baseNote)
is FileHeaderEvent -> FileHeaderDisplay(baseNote, false, accountViewModel)
is FileStorageHeaderEvent -> FileStorageHeaderDisplay(baseNote, false, accountViewModel)
else ->
@ -511,6 +458,7 @@ fun NormalNote(
makeItShort = makeItShort,
addMarginTop = addMarginTop,
canPreview = canPreview,
quotesLeft = quotesLeft,
parentBackgroundColor = parentBackgroundColor,
accountViewModel = accountViewModel,
showPopup = showPopup,
@ -521,6 +469,36 @@ fun NormalNote(
}
}
@Composable
fun calculateBackgroundColor(
createdAt: Long?,
routeForLastRead: String? = null,
parentBackgroundColor: MutableState<Color>? = null,
accountViewModel: AccountViewModel,
): MutableState<Color> {
val defaultBackgroundColor = MaterialTheme.colorScheme.background
val newItemColor = MaterialTheme.colorScheme.newItemBackgroundColor
return remember(createdAt) {
mutableStateOf<Color>(
if (routeForLastRead != null) {
val isNew = accountViewModel.loadAndMarkAsRead(routeForLastRead, createdAt)
if (isNew) {
if (parentBackgroundColor != null) {
newItemColor.compositeOver(parentBackgroundColor.value)
} else {
newItemColor.compositeOver(defaultBackgroundColor)
}
} else {
parentBackgroundColor?.value ?: defaultBackgroundColor
}
} else {
parentBackgroundColor?.value ?: defaultBackgroundColor
},
)
}
}
@Composable
private fun CheckNewAndRenderNote(
baseNote: Note,
@ -532,45 +510,19 @@ private fun CheckNewAndRenderNote(
makeItShort: Boolean = false,
addMarginTop: Boolean = true,
canPreview: Boolean = true,
quotesLeft: Int,
parentBackgroundColor: MutableState<Color>? = null,
accountViewModel: AccountViewModel,
showPopup: () -> Unit,
nav: (String) -> Unit,
) {
val newItemColor = MaterialTheme.colorScheme.newItemBackgroundColor
val defaultBackgroundColor = MaterialTheme.colorScheme.background
val backgroundColor =
remember(baseNote) {
mutableStateOf<Color>(parentBackgroundColor?.value ?: defaultBackgroundColor)
}
LaunchedEffect(key1 = routeForLastRead, key2 = parentBackgroundColor?.value) {
routeForLastRead?.let {
accountViewModel.loadAndMarkAsRead(it, baseNote.createdAt()) { isNew ->
val newBackgroundColor =
if (isNew) {
if (parentBackgroundColor != null) {
newItemColor.compositeOver(parentBackgroundColor.value)
} else {
newItemColor.compositeOver(defaultBackgroundColor)
}
} else {
parentBackgroundColor?.value ?: defaultBackgroundColor
}
if (newBackgroundColor != backgroundColor.value) {
launch(Dispatchers.Main) { backgroundColor.value = newBackgroundColor }
}
}
}
?: run {
val newBackgroundColor = parentBackgroundColor?.value ?: defaultBackgroundColor
if (newBackgroundColor != backgroundColor.value) {
launch(Dispatchers.Main) { backgroundColor.value = newBackgroundColor }
}
}
}
calculateBackgroundColor(
baseNote.createdAt(),
routeForLastRead,
parentBackgroundColor,
accountViewModel,
)
ClickableNote(
baseNote = baseNote,
@ -589,6 +541,7 @@ private fun CheckNewAndRenderNote(
unPackReply = unPackReply,
makeItShort = makeItShort,
canPreview = canPreview,
quotesLeft = quotesLeft,
accountViewModel = accountViewModel,
nav = nav,
)
@ -641,6 +594,7 @@ fun InnerNoteWithReactions(
unPackReply: Boolean,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
@ -675,6 +629,7 @@ fun InnerNoteWithReactions(
makeItShort = makeItShort,
canPreview = canPreview,
showSecondRow = showSecondRow,
quotesLeft = quotesLeft,
backgroundColor = backgroundColor,
editState = editState,
accountViewModel = accountViewModel,
@ -701,12 +656,6 @@ fun InnerNoteWithReactions(
)
}
}
if (notBoostedNorQuote) {
HorizontalDivider(
thickness = DividerThickness,
)
}
}
@Composable
@ -717,6 +666,7 @@ fun NoteBody(
makeItShort: Boolean = false,
canPreview: Boolean = true,
showSecondRow: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
editState: State<GenericLoadable<EditState>>,
accountViewModel: AccountViewModel,
@ -758,6 +708,7 @@ fun NoteBody(
makeItShort = makeItShort,
canPreview = canPreview,
editState = editState,
quotesLeft = quotesLeft,
accountViewModel = accountViewModel,
nav = nav,
)
@ -776,6 +727,7 @@ private fun RenderNoteRow(
backgroundColor: MutableState<Color>,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
editState: State<GenericLoadable<EditState>>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -792,16 +744,16 @@ private fun RenderNoteRow(
RenderAudioHeader(baseNote, accountViewModel, nav)
}
is ReactionEvent -> {
RenderReaction(baseNote, backgroundColor, accountViewModel, nav)
RenderReaction(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
}
is RepostEvent -> {
RenderRepost(baseNote, backgroundColor, accountViewModel, nav)
RenderRepost(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
}
is GenericRepostEvent -> {
RenderRepost(baseNote, backgroundColor, accountViewModel, nav)
RenderRepost(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
}
is ReportEvent -> {
RenderReport(baseNote, backgroundColor, accountViewModel, nav)
RenderReport(baseNote, quotesLeft, backgroundColor, accountViewModel, nav)
}
is LongTextNoteEvent -> {
RenderLongFormContent(baseNote, accountViewModel, nav)
@ -838,6 +790,7 @@ private fun RenderNoteRow(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
@ -848,6 +801,7 @@ private fun RenderNoteRow(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
@ -858,6 +812,7 @@ private fun RenderNoteRow(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
@ -876,6 +831,7 @@ private fun RenderNoteRow(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
@ -886,6 +842,7 @@ private fun RenderNoteRow(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
@ -906,8 +863,7 @@ private fun RenderNoteRow(
is CommunityPostApprovalEvent -> {
RenderPostApproval(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
@ -918,6 +874,7 @@ private fun RenderNoteRow(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
@ -928,6 +885,7 @@ private fun RenderNoteRow(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
editState,
accountViewModel,
@ -940,18 +898,18 @@ private fun RenderNoteRow(
@Composable
fun RenderRepost(
note: Note,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
val boostedNote = remember { note.replyTo?.lastOrNull() }
boostedNote?.let {
note.replyTo?.lastOrNull()?.let {
NoteCompose(
it,
modifier = Modifier,
isBoostedNote = true,
unPackReply = false,
quotesLeft = quotesLeft - 1,
parentBackgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,
@ -1048,21 +1006,19 @@ private fun ReplyNoteComposition(
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
val replyBackgroundColor = remember { mutableStateOf(backgroundColor.value) }
val defaultReplyBackground = MaterialTheme.colorScheme.replyBackground
LaunchedEffect(key1 = backgroundColor.value, key2 = defaultReplyBackground) {
launch(Dispatchers.Default) {
val newReplyBackgroundColor = defaultReplyBackground.compositeOver(backgroundColor.value)
if (replyBackgroundColor.value != newReplyBackgroundColor) {
replyBackgroundColor.value = newReplyBackgroundColor
}
val replyBackgroundColor =
remember {
mutableStateOf(
defaultReplyBackground.compositeOver(backgroundColor.value),
)
}
}
NoteCompose(
baseNote = replyingDirectlyTo,
isQuotedNote = true,
quotesLeft = 0,
modifier = MaterialTheme.colorScheme.replyModifier,
unPackReply = false,
makeItShort = true,

View File

@ -76,6 +76,7 @@ import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
import com.vitorpamplona.amethyst.ui.navigation.routeToMessage
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.StringToastMsg
import com.vitorpamplona.amethyst.ui.theme.BigPadding
import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange
import com.vitorpamplona.amethyst.ui.theme.ButtonBorder
import com.vitorpamplona.amethyst.ui.theme.Font14SP
@ -271,6 +272,7 @@ private fun RenderOptionAfterVote(
TranslatableRichTextViewer(
poolOption.descriptor,
canPreview,
quotesLeft = 1,
Modifier,
tags,
backgroundColor,
@ -303,14 +305,15 @@ private fun RenderOptionBeforeVote(
),
) {
TranslatableRichTextViewer(
description,
canPreview,
remember { Modifier.padding(15.dp) },
tags,
backgroundColor,
content = description,
canPreview = canPreview,
quotesLeft = 1,
modifier = BigPadding,
tags = tags,
backgroundColor = backgroundColor,
id = description,
accountViewModel,
nav,
accountViewModel = accountViewModel,
nav = nav,
)
}
}

View File

@ -29,25 +29,17 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.ui.screen.ZapUserSetCard
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
import com.vitorpamplona.amethyst.ui.theme.Size25dp
import com.vitorpamplona.amethyst.ui.theme.Size55Modifier
import com.vitorpamplona.amethyst.ui.theme.Size55dp
import com.vitorpamplona.amethyst.ui.theme.newItemBackgroundColor
@Composable
fun ZapUserSetCompose(
@ -57,24 +49,12 @@ fun ZapUserSetCompose(
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
val defaultBackgroundColor = MaterialTheme.colorScheme.background
val backgroundColor = remember { mutableStateOf<Color>(defaultBackgroundColor) }
val newItemColor = MaterialTheme.colorScheme.newItemBackgroundColor
LaunchedEffect(key1 = zapSetCard.createdAt()) {
accountViewModel.loadAndMarkAsRead(routeForLastRead, zapSetCard.createdAt) { isNew ->
val newBackgroundColor =
if (isNew) {
newItemColor.compositeOver(defaultBackgroundColor)
} else {
defaultBackgroundColor
}
if (backgroundColor.value != newBackgroundColor) {
backgroundColor.value = newBackgroundColor
}
}
}
val backgroundColor =
calculateBackgroundColor(
createdAt = zapSetCard.createdAt,
routeForLastRead = routeForLastRead,
accountViewModel = accountViewModel,
)
Column(
modifier =
@ -131,9 +111,5 @@ fun ZapUserSetCompose(
Spacer(DoubleVertSpacer)
}
}
HorizontalDivider(
thickness = DividerThickness,
)
}
}

View File

@ -232,6 +232,7 @@ fun RenderAppDefinition(
TranslatableRichTextViewer(
content = it,
canPreview = false,
quotesLeft = 1,
tags = tags,
backgroundColor = backgroundColor,
id = note.idHex,

View File

@ -216,6 +216,7 @@ fun AudioHeader(
TranslatableRichTextViewer(
content = it,
canPreview = true,
quotesLeft = 1,
tags = tags,
backgroundColor = background,
id = note.idHex,

View File

@ -62,7 +62,6 @@ import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
import com.vitorpamplona.amethyst.ui.note.NoteCompose
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.Size35dp
import com.vitorpamplona.amethyst.ui.theme.mediumImportanceLink
@ -219,15 +218,6 @@ fun RenderBadgeAward(
}
note.replyTo?.firstOrNull()?.let {
NoteCompose(
it,
modifier = Modifier,
isBoostedNote = false,
isQuotedNote = true,
unPackReply = false,
parentBackgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
BadgeDisplay(baseNote = it)
}
}

View File

@ -180,6 +180,7 @@ fun LongCommunityHeader(
TranslatableRichTextViewer(
content = summary ?: stringResource(id = R.string.community_no_descriptor),
canPreview = false,
quotesLeft = 1,
tags = EmptyTagList,
backgroundColor = background,
id = baseNote.idHex,

View File

@ -74,6 +74,7 @@ fun RenderGitPatchEvent(
baseNote: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -85,6 +86,7 @@ fun RenderGitPatchEvent(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
@ -129,6 +131,7 @@ private fun RenderGitPatchEvent(
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -180,6 +183,7 @@ private fun RenderGitPatchEvent(
TranslatableRichTextViewer(
content = eventContent,
canPreview = canPreview && !makeItShort,
quotesLeft = quotesLeft,
modifier = modifier,
tags = tags,
backgroundColor = backgroundColor,
@ -205,6 +209,7 @@ fun RenderGitIssueEvent(
baseNote: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -216,6 +221,7 @@ fun RenderGitIssueEvent(
baseNote,
makeItShort,
canPreview,
quotesLeft,
backgroundColor,
accountViewModel,
nav,
@ -228,6 +234,7 @@ private fun RenderGitIssueEvent(
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -279,6 +286,7 @@ private fun RenderGitIssueEvent(
TranslatableRichTextViewer(
content = eventContent,
canPreview = canPreview && !makeItShort,
quotesLeft = quotesLeft,
modifier = modifier,
tags = tags,
backgroundColor = backgroundColor,

View File

@ -62,6 +62,7 @@ fun RenderHighlight(
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -78,6 +79,7 @@ fun RenderHighlight(
postAddress = postHex,
makeItShort = makeItShort,
canPreview = canPreview,
quotesLeft = quotesLeft,
backgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,
@ -92,6 +94,7 @@ fun DisplayHighlight(
postAddress: ATag?,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -104,7 +107,8 @@ fun DisplayHighlight(
TranslatableRichTextViewer(
quote,
canPreview = canPreview && !makeItShort,
remember { Modifier.fillMaxWidth() },
quotesLeft,
Modifier.fillMaxWidth(),
EmptyTagList,
backgroundColor,
id = quote,

View File

@ -105,6 +105,7 @@ fun RenderPinListEvent(
TranslatableRichTextViewer(
content = pin,
canPreview = true,
quotesLeft = 1,
tags = EmptyTagList,
backgroundColor = backgroundColor,
id = baseNote.idHex,

View File

@ -46,6 +46,7 @@ fun RenderPoll(
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -70,7 +71,8 @@ fun RenderPoll(
TranslatableRichTextViewer(
content = eventContent,
canPreview = canPreview && !makeItShort,
modifier = remember { Modifier.fillMaxWidth() },
quotesLeft = quotesLeft,
modifier = Modifier.fillMaxWidth(),
tags = tags,
backgroundColor = backgroundColor,
id = note.idHex,

View File

@ -50,6 +50,7 @@ fun RenderPrivateMessage(
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -81,6 +82,7 @@ fun RenderPrivateMessage(
TranslatableRichTextViewer(
content = eventContent,
canPreview = canPreview && !makeItShort,
quotesLeft = quotesLeft,
modifier = modifier,
tags = tags,
backgroundColor = backgroundColor,
@ -109,12 +111,13 @@ fun RenderPrivateMessage(
"@$recipient",
),
canPreview = !makeItShort,
Modifier.fillMaxWidth(),
EmptyTagList,
backgroundColor,
quotesLeft = 0,
modifier = Modifier.fillMaxWidth(),
tags = EmptyTagList,
backgroundColor = backgroundColor,
id = note.idHex,
accountViewModel,
nav,
accountViewModel = accountViewModel,
nav = nav,
)
}
}

View File

@ -32,6 +32,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@Composable
fun RenderReaction(
note: Note,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -42,6 +43,7 @@ fun RenderReaction(
modifier = Modifier,
isBoostedNote = true,
unPackReply = false,
quotesLeft = quotesLeft - 1,
parentBackgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,

View File

@ -45,8 +45,7 @@ import com.vitorpamplona.quartz.events.CommunityPostApprovalEvent
@Composable
fun RenderPostApproval(
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -56,12 +55,13 @@ fun RenderPostApproval(
val noteEvent = note.event as? CommunityPostApprovalEvent ?: return
Column(Modifier.fillMaxWidth()) {
noteEvent.communities().forEach {
LoadAddressableNote(it, accountViewModel) {
it?.let {
NoteCompose(
it,
parentBackgroundColor = backgroundColor,
noteEvent.communities().forEach { tag ->
LoadAddressableNote(tag, accountViewModel) { baseNote ->
baseNote?.let {
CommunityHeader(
baseNote = it,
showBottomDiviser = false,
sendToCommunity = true,
accountViewModel = accountViewModel,
nav = nav,
)
@ -88,6 +88,7 @@ fun RenderPostApproval(
unPackReply = false,
makeItShort = true,
isQuotedNote = true,
quotesLeft = quotesLeft - 1,
parentBackgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,

View File

@ -20,31 +20,26 @@
*/
package com.vitorpamplona.amethyst.ui.note.types
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
import com.vitorpamplona.amethyst.ui.note.NoteCompose
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
import com.vitorpamplona.amethyst.ui.theme.replyModifier
import com.vitorpamplona.quartz.events.EmptyTagList
import com.vitorpamplona.quartz.events.ReportEvent
@Composable
fun RenderReport(
note: Note,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -81,6 +76,7 @@ fun RenderReport(
tags = EmptyTagList,
backgroundColor = backgroundColor,
id = note.idHex,
quotesLeft = 1,
accountViewModel = accountViewModel,
nav = nav,
)
@ -89,18 +85,10 @@ fun RenderReport(
NoteCompose(
baseNote = it,
isQuotedNote = true,
modifier =
Modifier
.padding(top = 5.dp)
.fillMaxWidth()
.clip(shape = QuoteBorder)
.border(
1.dp,
MaterialTheme.colorScheme.subtleBorder,
QuoteBorder,
),
modifier = MaterialTheme.colorScheme.replyModifier,
unPackReply = false,
makeItShort = true,
quotesLeft = quotesLeft - 1,
parentBackgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,

View File

@ -51,6 +51,7 @@ fun RenderTextEvent(
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
editState: State<GenericLoadable<EditState>>,
accountViewModel: AccountViewModel,
@ -103,6 +104,7 @@ fun RenderTextEvent(
TranslatableRichTextViewer(
content = eventContent,
canPreview = canPreview && !makeItShort,
quotesLeft = quotesLeft,
modifier = modifier,
tags = tags,
backgroundColor = backgroundColor,

View File

@ -67,6 +67,7 @@ fun RenderTextModificationEvent(
note: Note,
makeItShort: Boolean,
canPreview: Boolean,
quotesLeft: Int,
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
@ -113,6 +114,7 @@ fun RenderTextModificationEvent(
TranslatableRichTextViewer(
content = it,
canPreview = canPreview && !makeItShort,
quotesLeft = quotesLeft,
modifier = Modifier.fillMaxWidth(),
tags = EmptyTagList,
backgroundColor = backgroundColor,
@ -182,6 +184,7 @@ fun RenderTextModificationEvent(
makeItShort = false,
canPreview = true,
showSecondRow = false,
quotesLeft = quotesLeft,
backgroundColor = backgroundColor,
editState = editState,
accountViewModel = accountViewModel,

View File

@ -163,6 +163,7 @@ fun VideoDisplay(
TranslatableRichTextViewer(
content = it,
canPreview = canPreview && !makeItShort,
quotesLeft = 1,
modifier = Modifier.fillMaxWidth(),
tags = tags,
backgroundColor = backgroundColor,

View File

@ -31,6 +31,7 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.pullrefresh.PullRefreshIndicator
import androidx.compose.material3.pullrefresh.pullRefresh
import androidx.compose.material3.pullrefresh.rememberPullRefreshState
@ -55,6 +56,7 @@ import com.vitorpamplona.amethyst.ui.note.NoteCompose
import com.vitorpamplona.amethyst.ui.note.ZapTheDevsCard
import com.vitorpamplona.amethyst.ui.note.ZapUserSetCompose
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
@Composable
@ -196,6 +198,9 @@ private fun FeedLoaded(
nav,
)
}
HorizontalDivider(
thickness = DividerThickness,
)
}
}
}
@ -302,6 +307,7 @@ fun NoteCardCompose(
makeItShort = makeItShort,
addMarginTop = addMarginTop,
showHidden = showHidden,
quotesLeft = 3,
parentBackgroundColor = parentBackgroundColor,
accountViewModel = accountViewModel,
nav = nav,

View File

@ -38,6 +38,7 @@ import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.Button
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.material3.pullrefresh.PullRefreshIndicator
@ -56,6 +57,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.ui.note.NoteCompose
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
@ -227,24 +229,15 @@ private fun FeedLoaded(
modifier = Modifier,
isBoostedNote = false,
showHidden = state.showHidden.value,
quotesLeft = 3,
accountViewModel = accountViewModel,
nav = nav,
)
}
/*var see by
remember {
mutableStateOf(false)
}
if (see) {
} else {
Row(defaultModifier) {
Button(onClick = { see = true }) {
Text("Show")
}
}
}*/
HorizontalDivider(
thickness = DividerThickness,
)
}
}
}

View File

@ -263,34 +263,35 @@ fun ThreadFeedView(
)
}
} else {
Column {
Row {
val selectedNoteColor = MaterialTheme.colorScheme.selectedNote
val background =
remember {
if (item.idHex == noteId) mutableStateOf(selectedNoteColor) else null
}
NoteCompose(
item,
modifier =
Modifier.drawReplyLevel(
item.replyLevel(),
MaterialTheme.colorScheme.placeholderText,
if (item.idHex == noteId) {
MaterialTheme.colorScheme.lessImportantLink
} else {
MaterialTheme.colorScheme.placeholderText
},
),
parentBackgroundColor = background,
isBoostedNote = false,
unPackReply = false,
accountViewModel = accountViewModel,
nav = nav,
)
val selectedNoteColor = MaterialTheme.colorScheme.selectedNote
val background =
remember {
if (item.idHex == noteId) mutableStateOf(selectedNoteColor) else null
}
}
NoteCompose(
item,
modifier =
Modifier.drawReplyLevel(
item.replyLevel(),
MaterialTheme.colorScheme.placeholderText,
if (item.idHex == noteId) {
MaterialTheme.colorScheme.lessImportantLink
} else {
MaterialTheme.colorScheme.placeholderText
},
),
parentBackgroundColor = background,
isBoostedNote = false,
unPackReply = false,
quotesLeft = 3,
accountViewModel = accountViewModel,
nav = nav,
)
HorizontalDivider(
thickness = DividerThickness,
)
}
}
}
@ -376,7 +377,6 @@ fun NoteMaster(
note.author?.let { account.isHidden(it) } ?: false,
accountViewModel,
Modifier,
false,
nav,
onClick = { showHiddenNote = true },
)
@ -522,8 +522,7 @@ fun NoteMaster(
} else if (noteEvent is CommunityPostApprovalEvent) {
RenderPostApproval(
baseNote,
false,
true,
quotesLeft = 3,
backgroundColor,
accountViewModel,
nav,
@ -554,9 +553,9 @@ fun NoteMaster(
} else if (noteEvent is GitRepositoryEvent) {
RenderGitRepositoryEvent(baseNote, accountViewModel, nav)
} else if (noteEvent is GitPatchEvent) {
RenderGitPatchEvent(baseNote, false, true, backgroundColor, accountViewModel, nav)
RenderGitPatchEvent(baseNote, false, true, quotesLeft = 3, backgroundColor, accountViewModel, nav)
} else if (noteEvent is GitIssueEvent) {
RenderGitIssueEvent(baseNote, false, true, backgroundColor, accountViewModel, nav)
RenderGitIssueEvent(baseNote, false, true, quotesLeft = 3, backgroundColor, accountViewModel, nav)
} else if (noteEvent is AppDefinitionEvent) {
RenderAppDefinition(baseNote, accountViewModel, nav)
} else if (noteEvent is HighlightEvent) {
@ -567,17 +566,19 @@ fun NoteMaster(
noteEvent.inPost(),
false,
true,
quotesLeft = 3,
backgroundColor,
accountViewModel,
nav,
)
} else if (noteEvent is RepostEvent || noteEvent is GenericRepostEvent) {
RenderRepost(baseNote, backgroundColor, accountViewModel, nav)
RenderRepost(baseNote, quotesLeft = 3, backgroundColor, accountViewModel, nav)
} else if (noteEvent is TextNoteModificationEvent) {
RenderTextModificationEvent(
note = baseNote,
makeItShort = false,
canPreview = true,
quotesLeft = 3,
backgroundColor,
accountViewModel,
nav,
@ -592,6 +593,7 @@ fun NoteMaster(
baseNote,
false,
canPreview,
quotesLeft = 3,
backgroundColor,
accountViewModel,
nav,
@ -606,6 +608,7 @@ fun NoteMaster(
baseNote,
false,
canPreview,
quotesLeft = 3,
backgroundColor,
editState,
accountViewModel,
@ -885,6 +888,7 @@ private fun RenderWikiHeaderForThreadPreview() {
baseNote!!,
false,
true,
quotesLeft = 3,
backgroundColor,
editState,
accountViewModel,

View File

@ -681,41 +681,42 @@ class AccountViewModel(val account: Account, val settings: SettingsState) : View
val relevantReports: ImmutableSet<Note> = persistentSetOf(),
)
fun isNoteAcceptable(
suspend fun isNoteAcceptable(
note: Note,
onReady: (NoteComposeReportState) -> Unit,
) {
viewModelScope.launch(Dispatchers.IO) {
val isFromLoggedIn = note.author?.pubkeyHex == userProfile().pubkeyHex
val isFromLoggedInFollow = note.author?.let { userProfile().isFollowingCached(it) } ?: true
val newState =
withContext(Dispatchers.IO) {
val isFromLoggedIn = note.author?.pubkeyHex == userProfile().pubkeyHex
val isFromLoggedInFollow = note.author?.let { userProfile().isFollowingCached(it) } ?: true
if (isFromLoggedIn || isFromLoggedInFollow) {
// No need to process if from trusted people
onReady(NoteComposeReportState(true, true, false, persistentSetOf()))
} else if (note.author?.let { account.isHidden(it) } == true) {
onReady(NoteComposeReportState(false, false, true, persistentSetOf()))
} else {
val newCanPreview = !note.hasAnyReports()
val newIsAcceptable = account.isAcceptable(note)
if (newCanPreview && newIsAcceptable) {
// No need to process reports if nothing is wrong
onReady(NoteComposeReportState(true, true, false, persistentSetOf()))
if (isFromLoggedIn || isFromLoggedInFollow) {
// No need to process if from trusted people
NoteComposeReportState(true, true, false, persistentSetOf())
} else if (note.author?.let { account.isHidden(it) } == true) {
NoteComposeReportState(false, false, true, persistentSetOf())
} else {
val newRelevantReports = account.getRelevantReports(note)
val newCanPreview = !note.hasAnyReports()
val newIsAcceptable = account.isAcceptable(note)
if (newCanPreview && newIsAcceptable) {
// No need to process reports if nothing is wrong
NoteComposeReportState(true, true, false, persistentSetOf())
} else {
val newRelevantReports = account.getRelevantReports(note)
onReady(
NoteComposeReportState(
newIsAcceptable,
newCanPreview,
false,
newRelevantReports.toImmutableSet(),
),
)
)
}
}
}
}
onReady(newState)
}
fun unwrap(
@ -1067,20 +1068,22 @@ class AccountViewModel(val account: Account, val settings: SettingsState) : View
fun loadAndMarkAsRead(
routeForLastRead: String,
createdAt: Long?,
onIsNew: (Boolean) -> Unit,
) {
viewModelScope.launch(Dispatchers.IO) {
val lastTime = account.loadLastRead(routeForLastRead)
): Boolean {
if (createdAt == null) return false
if (createdAt != null) {
val lastTime = account.loadLastRead(routeForLastRead)
val onIsNew = createdAt > lastTime
if (onIsNew) {
viewModelScope.launch(Dispatchers.IO) {
if (account.markAsRead(routeForLastRead, createdAt)) {
refreshMarkAsReadObservers()
}
onIsNew(createdAt > lastTime)
} else {
onIsNew(false)
}
}
return onIsNew
}
fun markAllAsRead(

View File

@ -809,6 +809,7 @@ fun LongChannelHeader(
TranslatableRichTextViewer(
content = summary ?: stringResource(id = R.string.groups_no_descriptor),
canPreview = false,
quotesLeft = 1,
tags = tags,
backgroundColor = background,
id = baseChannel.idHex,

View File

@ -1103,6 +1103,7 @@ private fun DrawAdditionalInfo(
TranslatableRichTextViewer(
content = it,
canPreview = false,
quotesLeft = 1,
tags = EmptyTagList,
backgroundColor = background,
id = it,

View File

@ -411,9 +411,14 @@ private fun DisplaySearchResults(
) { _, item ->
NoteCompose(
item,
quotesLeft = 1,
accountViewModel = accountViewModel,
nav = nav,
)
HorizontalDivider(
thickness = DividerThickness,
)
}
}
}

View File

@ -303,7 +303,6 @@ fun RenderReportState(
state.isHiddenAuthor,
accountViewModel,
Modifier.fillMaxWidth(),
false,
nav,
onClick = { showReportedNote = true },
)

View File

@ -99,6 +99,7 @@ val HalfTopPadding = Modifier.padding(top = 5.dp)
val HalfPadding = Modifier.padding(5.dp)
val StdPadding = Modifier.padding(10.dp)
val BigPadding = Modifier.padding(15.dp)
val HalfHorzPadding = Modifier.padding(horizontal = 5.dp)
val HalfVertPadding = Modifier.padding(vertical = 5.dp)

View File

@ -71,6 +71,7 @@ import java.util.Locale
fun TranslatableRichTextViewer(
content: String,
canPreview: Boolean,
quotesLeft: Int,
modifier: Modifier = Modifier,
tags: ImmutableListOfLists<String>,
backgroundColor: MutableState<Color>,
@ -93,15 +94,16 @@ fun TranslatableRichTextViewer(
Crossfade(targetState = translatedTextState) {
RenderText(
it,
content,
canPreview,
modifier,
tags,
backgroundColor,
id,
accountViewModel,
nav,
translatedTextState = it,
content = content,
canPreview = canPreview,
quotesLeft = quotesLeft,
modifier = modifier,
tags = tags,
backgroundColor = backgroundColor,
id = id,
accountViewModel = accountViewModel,
nav = nav,
)
}
}
@ -111,6 +113,7 @@ private fun RenderText(
translatedTextState: TranslationConfig,
content: String,
canPreview: Boolean,
quotesLeft: Int,
modifier: Modifier,
tags: ImmutableListOfLists<String>,
backgroundColor: MutableState<Color>,
@ -130,6 +133,7 @@ private fun RenderText(
ExpandableRichTextViewer(
toBeViewed,
canPreview,
quotesLeft,
modifier,
tags,
backgroundColor,