mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-11-11 03:56:43 +01:00
Faster calculation of uncited hashtags.
This commit is contained in:
@@ -28,13 +28,16 @@ import com.vitorpamplona.quartz.events.ImmutableListOfLists
|
|||||||
object CachedRichTextParser {
|
object CachedRichTextParser {
|
||||||
val richTextCache = LruCache<String, RichTextViewerState>(50)
|
val richTextCache = LruCache<String, RichTextViewerState>(50)
|
||||||
|
|
||||||
|
fun getCached(content: String): RichTextViewerState? = richTextCache[content]
|
||||||
|
|
||||||
fun parseText(
|
fun parseText(
|
||||||
content: String,
|
content: String,
|
||||||
tags: ImmutableListOfLists<String>,
|
tags: ImmutableListOfLists<String>,
|
||||||
callbackUri: String? = null,
|
callbackUri: String? = null,
|
||||||
): RichTextViewerState {
|
): RichTextViewerState {
|
||||||
return if (richTextCache[content] != null) {
|
val cached = richTextCache[content]
|
||||||
richTextCache[content]
|
return if (cached != null) {
|
||||||
|
cached
|
||||||
} else {
|
} else {
|
||||||
val newUrls = RichTextParser().parseText(content, tags, callbackUri)
|
val newUrls = RichTextParser().parseText(content, tags, callbackUri)
|
||||||
richTextCache.put(content, newUrls)
|
richTextCache.put(content, newUrls)
|
||||||
|
|||||||
@@ -26,23 +26,75 @@ import androidx.compose.foundation.text.ClickableText
|
|||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
|
import com.vitorpamplona.amethyst.commons.richtext.HashTagSegment
|
||||||
|
import com.vitorpamplona.amethyst.service.CachedRichTextParser
|
||||||
import com.vitorpamplona.amethyst.ui.theme.HalfTopPadding
|
import com.vitorpamplona.amethyst.ui.theme.HalfTopPadding
|
||||||
import com.vitorpamplona.amethyst.ui.theme.lessImportantLink
|
import com.vitorpamplona.amethyst.ui.theme.lessImportantLink
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import com.vitorpamplona.quartz.events.Event
|
||||||
|
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DisplayUncitedHashtags(
|
||||||
|
event: Event,
|
||||||
|
nav: (String) -> Unit,
|
||||||
|
) {
|
||||||
|
DisplayUncitedHashtags(event, event.content, nav)
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun DisplayUncitedHashtags(
|
fun DisplayUncitedHashtags(
|
||||||
hashtags: ImmutableList<String>,
|
event: Event,
|
||||||
eventContent: String,
|
content: String,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
val unusedHashtags =
|
val unusedHashtags by
|
||||||
remember(eventContent) { hashtags.filter { !eventContent.contains(it, true) } }
|
produceState(initialValue = emptyList<String>()) {
|
||||||
|
withContext(Dispatchers.Default) {
|
||||||
|
val state = CachedRichTextParser.parseText(content, event.tags.toImmutableListOfLists())
|
||||||
|
|
||||||
|
val tagsInEvent = event.hashtags()
|
||||||
|
|
||||||
|
if (tagsInEvent.isEmpty()) return@withContext
|
||||||
|
|
||||||
|
val tagsInContent =
|
||||||
|
state
|
||||||
|
.paragraphs
|
||||||
|
.map {
|
||||||
|
it.words.mapNotNull {
|
||||||
|
if (it is HashTagSegment) {
|
||||||
|
it.hashtag
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.flatten()
|
||||||
|
|
||||||
|
val unusedHashtags =
|
||||||
|
tagsInEvent.filterNot { eventTag ->
|
||||||
|
tagsInContent.any { contentTag ->
|
||||||
|
eventTag.equals(contentTag, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unusedHashtags.isNotEmpty()) {
|
||||||
|
value = unusedHashtags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (unusedHashtags.isNotEmpty()) {
|
if (unusedHashtags.isNotEmpty()) {
|
||||||
|
val style =
|
||||||
|
LocalTextStyle.current.copy(
|
||||||
|
color = MaterialTheme.colorScheme.lessImportantLink,
|
||||||
|
)
|
||||||
|
|
||||||
FlowRow(
|
FlowRow(
|
||||||
modifier = HalfTopPadding,
|
modifier = HalfTopPadding,
|
||||||
) {
|
) {
|
||||||
@@ -50,10 +102,7 @@ fun DisplayUncitedHashtags(
|
|||||||
ClickableText(
|
ClickableText(
|
||||||
text = remember { AnnotatedString("#$hashtag ") },
|
text = remember { AnnotatedString("#$hashtag ") },
|
||||||
onClick = { nav("Hashtag/$hashtag") },
|
onClick = { nav("Hashtag/$hashtag") },
|
||||||
style =
|
style = style,
|
||||||
LocalTextStyle.current.copy(
|
|
||||||
color = MaterialTheme.colorScheme.lessImportantLink,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,8 +240,7 @@ fun AudioHeader(
|
|||||||
|
|
||||||
if (noteEvent.hasHashtags()) {
|
if (noteEvent.hasHashtags()) {
|
||||||
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
||||||
val hashtags = remember(noteEvent) { noteEvent.hashtags().toImmutableList() }
|
DisplayUncitedHashtags(noteEvent, nav)
|
||||||
DisplayUncitedHashtags(hashtags, content ?: "", nav)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ import com.vitorpamplona.quartz.events.EmptyTagList
|
|||||||
import com.vitorpamplona.quartz.events.Participant
|
import com.vitorpamplona.quartz.events.Participant
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -90,9 +89,10 @@ fun RenderCommunity(
|
|||||||
) {
|
) {
|
||||||
if (baseNote is AddressableNote) {
|
if (baseNote is AddressableNote) {
|
||||||
Row(
|
Row(
|
||||||
MaterialTheme.colorScheme.innerPostModifier.clickable {
|
MaterialTheme.colorScheme.innerPostModifier
|
||||||
routeFor(baseNote, accountViewModel.userProfile())?.let { nav(it) }
|
.clickable {
|
||||||
}.padding(Size10dp),
|
routeFor(baseNote, accountViewModel.userProfile())?.let { nav(it) }
|
||||||
|
}.padding(Size10dp),
|
||||||
) {
|
) {
|
||||||
ShortCommunityHeader(
|
ShortCommunityHeader(
|
||||||
baseNote = baseNote,
|
baseNote = baseNote,
|
||||||
@@ -160,8 +160,8 @@ fun LongCommunityHeader(
|
|||||||
|
|
||||||
if (summary != null && noteEvent.hasHashtags()) {
|
if (summary != null && noteEvent.hasHashtags()) {
|
||||||
DisplayUncitedHashtags(
|
DisplayUncitedHashtags(
|
||||||
hashtags = remember(key1 = noteEvent) { noteEvent.hashtags().toImmutableList() },
|
event = noteEvent,
|
||||||
eventContent = summary,
|
content = summary,
|
||||||
nav = nav,
|
nav = nav,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -361,8 +361,7 @@ fun WatchAddressableNoteFollows(
|
|||||||
accountViewModel.userFollows
|
accountViewModel.userFollows
|
||||||
.map { it.user.latestContactList?.isTaggedAddressableNote(note.idHex) ?: false }
|
.map { it.user.latestContactList?.isTaggedAddressableNote(note.idHex) ?: false }
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
}
|
}.observeAsState(false)
|
||||||
.observeAsState(false)
|
|
||||||
|
|
||||||
onFollowChanges(showFollowingMark)
|
onFollowChanges(showFollowingMark)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,8 +66,6 @@ import com.vitorpamplona.quartz.events.GitPatchEvent
|
|||||||
import com.vitorpamplona.quartz.events.GitRepositoryEvent
|
import com.vitorpamplona.quartz.events.GitRepositoryEvent
|
||||||
import com.vitorpamplona.quartz.events.TextNoteEvent
|
import com.vitorpamplona.quartz.events.TextNoteEvent
|
||||||
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RenderGitPatchEvent(
|
fun RenderGitPatchEvent(
|
||||||
@@ -195,11 +193,11 @@ private fun RenderGitPatchEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (note.event?.hasHashtags() == true) {
|
if (note.event?.hasHashtags() == true) {
|
||||||
val hashtags =
|
DisplayUncitedHashtags(
|
||||||
remember(note.event) {
|
event = noteEvent,
|
||||||
note.event?.hashtags()?.toImmutableList() ?: persistentListOf()
|
content = eventContent,
|
||||||
}
|
nav = nav,
|
||||||
DisplayUncitedHashtags(hashtags, eventContent, nav)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,11 +297,7 @@ private fun RenderGitIssueEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (note.event?.hasHashtags() == true) {
|
if (note.event?.hasHashtags() == true) {
|
||||||
val hashtags =
|
DisplayUncitedHashtags(noteEvent, eventContent, nav)
|
||||||
remember(note.event) {
|
|
||||||
note.event?.hashtags()?.toImmutableList() ?: persistentListOf()
|
|
||||||
}
|
|
||||||
DisplayUncitedHashtags(hashtags, eventContent, nav)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.note.types
|
package com.vitorpamplona.amethyst.ui.note.types
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
@@ -35,17 +34,12 @@ import com.vitorpamplona.amethyst.ui.components.GenericLoadable
|
|||||||
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
|
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
|
||||||
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
||||||
import com.vitorpamplona.amethyst.ui.note.LoadDecryptedContent
|
import com.vitorpamplona.amethyst.ui.note.LoadDecryptedContent
|
||||||
import com.vitorpamplona.amethyst.ui.note.ReplyNoteComposition
|
|
||||||
import com.vitorpamplona.amethyst.ui.note.elements.DisplayUncitedHashtags
|
import com.vitorpamplona.amethyst.ui.note.elements.DisplayUncitedHashtags
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
|
||||||
import com.vitorpamplona.quartz.events.BaseTextNoteEvent
|
|
||||||
import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
|
|
||||||
import com.vitorpamplona.quartz.events.EmptyTagList
|
import com.vitorpamplona.quartz.events.EmptyTagList
|
||||||
|
import com.vitorpamplona.quartz.events.Event
|
||||||
import com.vitorpamplona.quartz.events.TextNoteEvent
|
import com.vitorpamplona.quartz.events.TextNoteEvent
|
||||||
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RenderNIP90ContentDiscoveryResponse(
|
fun RenderNIP90ContentDiscoveryResponse(
|
||||||
@@ -59,39 +53,7 @@ fun RenderNIP90ContentDiscoveryResponse(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
val noteEvent = note.event
|
val noteEvent = note.event as? Event ?: return
|
||||||
|
|
||||||
val showReply by
|
|
||||||
remember(note) {
|
|
||||||
derivedStateOf {
|
|
||||||
noteEvent is BaseTextNoteEvent && !makeItShort && unPackReply && (note.replyTo != null || noteEvent.hasAnyTaggedUser())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showReply) {
|
|
||||||
val replyingDirectlyTo =
|
|
||||||
remember(note) {
|
|
||||||
if (noteEvent is BaseTextNoteEvent) {
|
|
||||||
val replyingTo = noteEvent.replyingToAddressOrEvent()
|
|
||||||
if (replyingTo != null) {
|
|
||||||
val newNote = accountViewModel.getNoteIfExists(replyingTo)
|
|
||||||
if (newNote != null && newNote.channelHex() == null && newNote.event?.kind() != CommunityDefinitionEvent.KIND) {
|
|
||||||
newNote
|
|
||||||
} else {
|
|
||||||
note.replyTo?.lastOrNull { it.event?.kind() != CommunityDefinitionEvent.KIND }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
note.replyTo?.lastOrNull { it.event?.kind() != CommunityDefinitionEvent.KIND }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
note.replyTo?.lastOrNull { it.event?.kind() != CommunityDefinitionEvent.KIND }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (replyingDirectlyTo != null && unPackReply) {
|
|
||||||
ReplyNoteComposition(replyingDirectlyTo, backgroundColor, accountViewModel, nav)
|
|
||||||
Spacer(modifier = StdVertSpacer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadDecryptedContent(
|
LoadDecryptedContent(
|
||||||
note,
|
note,
|
||||||
@@ -118,9 +80,6 @@ fun RenderNIP90ContentDiscoveryResponse(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val isAuthorTheLoggedUser =
|
|
||||||
remember(note.event) { accountViewModel.isLoggedUser(note.author) }
|
|
||||||
|
|
||||||
SensitivityWarning(
|
SensitivityWarning(
|
||||||
note = note,
|
note = note,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
@@ -143,12 +102,8 @@ fun RenderNIP90ContentDiscoveryResponse(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note.event?.hasHashtags() == true) {
|
if (noteEvent.hasHashtags()) {
|
||||||
val hashtags =
|
DisplayUncitedHashtags(noteEvent, eventContent, nav)
|
||||||
remember(note.event) {
|
|
||||||
note.event?.hashtags()?.toImmutableList() ?: persistentListOf()
|
|
||||||
}
|
|
||||||
DisplayUncitedHashtags(hashtags, eventContent, nav)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
|
|||||||
import com.vitorpamplona.quartz.events.EmptyTagList
|
import com.vitorpamplona.quartz.events.EmptyTagList
|
||||||
import com.vitorpamplona.quartz.events.PollNoteEvent
|
import com.vitorpamplona.quartz.events.PollNoteEvent
|
||||||
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RenderPoll(
|
fun RenderPoll(
|
||||||
@@ -126,8 +125,7 @@ fun RenderPoll(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (noteEvent.hasHashtags()) {
|
if (noteEvent.hasHashtags()) {
|
||||||
val hashtags = remember { noteEvent.hashtags().toImmutableList() }
|
DisplayUncitedHashtags(noteEvent, eventContent, nav)
|
||||||
DisplayUncitedHashtags(hashtags, eventContent, nav)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ import com.vitorpamplona.quartz.events.ChatroomKeyable
|
|||||||
import com.vitorpamplona.quartz.events.EmptyTagList
|
import com.vitorpamplona.quartz.events.EmptyTagList
|
||||||
import com.vitorpamplona.quartz.events.PrivateDmEvent
|
import com.vitorpamplona.quartz.events.PrivateDmEvent
|
||||||
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RenderPrivateMessage(
|
fun RenderPrivateMessage(
|
||||||
@@ -122,11 +120,7 @@ fun RenderPrivateMessage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (noteEvent.hasHashtags()) {
|
if (noteEvent.hasHashtags()) {
|
||||||
val hashtags =
|
DisplayUncitedHashtags(noteEvent, eventContent, nav)
|
||||||
remember(note.event?.id()) {
|
|
||||||
note.event?.hashtags()?.toImmutableList() ?: persistentListOf()
|
|
||||||
}
|
|
||||||
DisplayUncitedHashtags(hashtags, eventContent, nav)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,10 +46,9 @@ import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
|||||||
import com.vitorpamplona.quartz.events.BaseTextNoteEvent
|
import com.vitorpamplona.quartz.events.BaseTextNoteEvent
|
||||||
import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
|
import com.vitorpamplona.quartz.events.CommunityDefinitionEvent
|
||||||
import com.vitorpamplona.quartz.events.EmptyTagList
|
import com.vitorpamplona.quartz.events.EmptyTagList
|
||||||
|
import com.vitorpamplona.quartz.events.Event
|
||||||
import com.vitorpamplona.quartz.events.TextNoteEvent
|
import com.vitorpamplona.quartz.events.TextNoteEvent
|
||||||
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RenderTextEvent(
|
fun RenderTextEvent(
|
||||||
@@ -63,7 +62,7 @@ fun RenderTextEvent(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
) {
|
) {
|
||||||
val noteEvent = note.event
|
val noteEvent = note.event as? Event ?: return
|
||||||
|
|
||||||
val showReply by
|
val showReply by
|
||||||
remember(note) {
|
remember(note) {
|
||||||
@@ -137,7 +136,6 @@ fun RenderTextEvent(
|
|||||||
note = note,
|
note = note,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
) {
|
) {
|
||||||
val modifier = remember(note) { Modifier.fillMaxWidth() }
|
|
||||||
val tags =
|
val tags =
|
||||||
remember(note) { note.event?.tags()?.toImmutableListOfLists() ?: EmptyTagList }
|
remember(note) { note.event?.tags()?.toImmutableListOfLists() ?: EmptyTagList }
|
||||||
|
|
||||||
@@ -145,7 +143,7 @@ fun RenderTextEvent(
|
|||||||
content = eventContent,
|
content = eventContent,
|
||||||
canPreview = canPreview && !makeItShort,
|
canPreview = canPreview && !makeItShort,
|
||||||
quotesLeft = quotesLeft,
|
quotesLeft = quotesLeft,
|
||||||
modifier = modifier,
|
modifier = Modifier.fillMaxWidth(),
|
||||||
tags = tags,
|
tags = tags,
|
||||||
backgroundColor = backgroundColor,
|
backgroundColor = backgroundColor,
|
||||||
id = note.idHex,
|
id = note.idHex,
|
||||||
@@ -155,12 +153,8 @@ fun RenderTextEvent(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note.event?.hasHashtags() == true) {
|
if (noteEvent.hasHashtags()) {
|
||||||
val hashtags =
|
DisplayUncitedHashtags(noteEvent, eventContent, nav)
|
||||||
remember(note.event) {
|
|
||||||
note.event?.hashtags()?.toImmutableList() ?: persistentListOf()
|
|
||||||
}
|
|
||||||
DisplayUncitedHashtags(hashtags, eventContent, nav)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ import com.vitorpamplona.amethyst.ui.theme.imageModifier
|
|||||||
import com.vitorpamplona.quartz.events.EmptyTagList
|
import com.vitorpamplona.quartz.events.EmptyTagList
|
||||||
import com.vitorpamplona.quartz.events.VideoEvent
|
import com.vitorpamplona.quartz.events.VideoEvent
|
||||||
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
import com.vitorpamplona.quartz.events.toImmutableListOfLists
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun VideoDisplay(
|
fun VideoDisplay(
|
||||||
@@ -178,17 +177,13 @@ fun VideoDisplay(
|
|||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
nav = nav,
|
nav = nav,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
if (event.hasHashtags()) {
|
if (event.hasHashtags()) {
|
||||||
Row(
|
Row(
|
||||||
Modifier.fillMaxWidth(),
|
Modifier.fillMaxWidth(),
|
||||||
) {
|
) {
|
||||||
DisplayUncitedHashtags(
|
DisplayUncitedHashtags(event, summary, nav)
|
||||||
remember(event) { event.hashtags().toImmutableList() },
|
}
|
||||||
summary ?: "",
|
|
||||||
nav,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -710,8 +710,7 @@ fun ShowVideoStreaming(
|
|||||||
.map {
|
.map {
|
||||||
val activity = it.channel as? LiveActivitiesChannel
|
val activity = it.channel as? LiveActivitiesChannel
|
||||||
activity?.info
|
activity?.info
|
||||||
}
|
}.distinctUntilChanged()
|
||||||
.distinctUntilChanged()
|
|
||||||
.observeAsState(baseChannel.info)
|
.observeAsState(baseChannel.info)
|
||||||
|
|
||||||
streamingInfo?.let { event ->
|
streamingInfo?.let { event ->
|
||||||
@@ -869,12 +868,12 @@ fun LongChannelHeader(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (baseChannel is LiveActivitiesChannel && baseChannel.info?.hasHashtags() == true) {
|
if (baseChannel is LiveActivitiesChannel && summary != null) {
|
||||||
val hashtags =
|
baseChannel.info?.let {
|
||||||
remember(baseChannel.info) {
|
if (it.hasHashtags()) {
|
||||||
baseChannel.info?.hashtags()?.toImmutableList() ?: persistentListOf()
|
DisplayUncitedHashtags(it, summary, nav)
|
||||||
}
|
}
|
||||||
DisplayUncitedHashtags(hashtags, summary ?: "", nav)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -938,8 +937,7 @@ fun LongChannelHeader(
|
|||||||
?.participants()
|
?.participants()
|
||||||
?.mapNotNull { part ->
|
?.mapNotNull { part ->
|
||||||
LocalCache.checkGetOrCreateUser(part.key)?.let { Pair(part, it) }
|
LocalCache.checkGetOrCreateUser(part.key)?.let { Pair(part, it) }
|
||||||
}
|
}?.toImmutableList()
|
||||||
?.toImmutableList()
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
newParticipantUsers != null && !equalImmutableLists(newParticipantUsers, participantUsers)
|
newParticipantUsers != null && !equalImmutableLists(newParticipantUsers, participantUsers)
|
||||||
@@ -1155,10 +1153,11 @@ fun OfflineFlag() {
|
|||||||
fun ScheduledFlag(starts: Long?) {
|
fun ScheduledFlag(starts: Long?) {
|
||||||
val startsIn =
|
val startsIn =
|
||||||
starts?.let {
|
starts?.let {
|
||||||
SimpleDateFormat.getDateTimeInstance(
|
SimpleDateFormat
|
||||||
DateFormat.SHORT,
|
.getDateTimeInstance(
|
||||||
DateFormat.SHORT,
|
DateFormat.SHORT,
|
||||||
).format(Date(starts * 1000))
|
DateFormat.SHORT,
|
||||||
|
).format(Date(starts * 1000))
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ open class Event(
|
|||||||
|
|
||||||
override fun forEachTaggedEvent(onEach: (eventId: HexKey) -> Unit) = forEachTagged("e", onEach)
|
override fun forEachTaggedEvent(onEach: (eventId: HexKey) -> Unit) = forEachTagged("e", onEach)
|
||||||
|
|
||||||
|
override fun forEachHashTag(onEach: (eventId: HexKey) -> Unit) = forEachTagged("t", onEach)
|
||||||
|
|
||||||
private fun forEachTagged(
|
private fun forEachTagged(
|
||||||
tagName: String,
|
tagName: String,
|
||||||
onEach: (eventId: HexKey) -> Unit,
|
onEach: (eventId: HexKey) -> Unit,
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ interface EventInterface {
|
|||||||
|
|
||||||
fun forEachTaggedEvent(onEach: (eventId: HexKey) -> Unit)
|
fun forEachTaggedEvent(onEach: (eventId: HexKey) -> Unit)
|
||||||
|
|
||||||
|
fun forEachHashTag(onEach: (eventId: HexKey) -> Unit)
|
||||||
|
|
||||||
fun <R> mapTaggedEvent(map: (eventId: HexKey) -> R): List<R>
|
fun <R> mapTaggedEvent(map: (eventId: HexKey) -> R): List<R>
|
||||||
|
|
||||||
fun <R> mapTaggedAddress(map: (address: String) -> R): List<R>
|
fun <R> mapTaggedAddress(map: (address: String) -> R): List<R>
|
||||||
|
|||||||
@@ -22,9 +22,7 @@ package com.vitorpamplona.quartz.utils
|
|||||||
|
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
fun String.bytesUsedInMemory(): Int {
|
fun String.bytesUsedInMemory(): Int = (8 * ((((this.length) * 2) + 45) / 8))
|
||||||
return (8 * ((((this.length) * 2) + 45) / 8))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.containsIgnoreCase(term: String): Boolean {
|
fun String.containsIgnoreCase(term: String): Boolean {
|
||||||
if (term.isEmpty()) return true // Empty string is contained
|
if (term.isEmpty()) return true // Empty string is contained
|
||||||
@@ -72,4 +70,7 @@ fun String.containsAny(terms: List<DualCase>): Boolean {
|
|||||||
return terms.any { containsIgnoreCase(it.lowercase, it.uppercase) }
|
return terms.any { containsIgnoreCase(it.lowercase, it.uppercase) }
|
||||||
}
|
}
|
||||||
|
|
||||||
class DualCase(val lowercase: String, val uppercase: String)
|
class DualCase(
|
||||||
|
val lowercase: String,
|
||||||
|
val uppercase: String,
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user