mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2024-09-30 00:40:49 +00:00
Fixes the rendering of highlights when no user is present and includes options to render by e
tags
This commit is contained in:
parent
95694ac355
commit
5e417dd890
@ -138,7 +138,7 @@ private fun LoadAndDisplayEvent(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun DisplayEvent(
|
fun DisplayEvent(
|
||||||
hex: HexKey,
|
hex: HexKey,
|
||||||
kind: Int?,
|
kind: Int?,
|
||||||
additionalChars: String?,
|
additionalChars: String?,
|
||||||
@ -293,7 +293,7 @@ public fun DisplayUser(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun RenderUserAsClickableText(
|
public fun RenderUserAsClickableText(
|
||||||
baseUser: User,
|
baseUser: User,
|
||||||
additionalChars: String?,
|
additionalChars: String?,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
|
@ -40,19 +40,27 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
|
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.ui.components.ClickableUrl
|
import com.vitorpamplona.amethyst.ui.components.ClickableUrl
|
||||||
import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji
|
import com.vitorpamplona.amethyst.ui.components.CreateClickableTextWithEmoji
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.DisplayEvent
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.RenderUserAsClickableText
|
||||||
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
||||||
import com.vitorpamplona.amethyst.ui.components.measureSpaceWidth
|
import com.vitorpamplona.amethyst.ui.components.measureSpaceWidth
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.routeFor
|
import com.vitorpamplona.amethyst.ui.navigation.routeFor
|
||||||
import com.vitorpamplona.amethyst.ui.note.LoadAddressableNote
|
import com.vitorpamplona.amethyst.ui.note.LoadAddressableNote
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.quartz.encoders.ATag
|
import com.vitorpamplona.quartz.encoders.ATag
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
|
import com.vitorpamplona.quartz.events.BaseTextNoteEvent
|
||||||
import com.vitorpamplona.quartz.events.EmptyTagList
|
import com.vitorpamplona.quartz.events.EmptyTagList
|
||||||
import com.vitorpamplona.quartz.events.HighlightEvent
|
import com.vitorpamplona.quartz.events.HighlightEvent
|
||||||
import com.vitorpamplona.quartz.events.LongTextNoteEvent
|
import com.vitorpamplona.quartz.events.LongTextNoteEvent
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -72,6 +80,7 @@ fun RenderHighlight(
|
|||||||
authorHex = noteEvent.author(),
|
authorHex = noteEvent.author(),
|
||||||
url = noteEvent.inUrl(),
|
url = noteEvent.inUrl(),
|
||||||
postAddress = noteEvent.inPost(),
|
postAddress = noteEvent.inPost(),
|
||||||
|
postVersion = noteEvent.inPostVersion(),
|
||||||
makeItShort = makeItShort,
|
makeItShort = makeItShort,
|
||||||
canPreview = canPreview,
|
canPreview = canPreview,
|
||||||
quotesLeft = quotesLeft,
|
quotesLeft = quotesLeft,
|
||||||
@ -81,12 +90,14 @@ fun RenderHighlight(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun DisplayHighlight(
|
fun DisplayHighlight(
|
||||||
highlight: String,
|
highlight: String,
|
||||||
authorHex: String?,
|
authorHex: String?,
|
||||||
url: String?,
|
url: String?,
|
||||||
postAddress: ATag?,
|
postAddress: ATag?,
|
||||||
|
postVersion: HexKey?,
|
||||||
makeItShort: Boolean,
|
makeItShort: Boolean,
|
||||||
canPreview: Boolean,
|
canPreview: Boolean,
|
||||||
quotesLeft: Int,
|
quotesLeft: Int,
|
||||||
@ -112,54 +123,151 @@ fun DisplayHighlight(
|
|||||||
nav = nav,
|
nav = nav,
|
||||||
)
|
)
|
||||||
|
|
||||||
DisplayQuoteAuthor(authorHex ?: "", url, postAddress, accountViewModel, nav)
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
|
||||||
@Composable
|
|
||||||
private fun DisplayQuoteAuthor(
|
|
||||||
authorHex: String,
|
|
||||||
url: String?,
|
|
||||||
postAddress: ATag?,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: (String) -> Unit,
|
|
||||||
) {
|
|
||||||
var userBase by remember { mutableStateOf<User?>(accountViewModel.getUserIfExists(authorHex)) }
|
|
||||||
|
|
||||||
if (userBase == null) {
|
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
accountViewModel.checkGetOrCreateUser(authorHex) { newUserBase ->
|
|
||||||
userBase = newUserBase
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val spaceWidth = measureSpaceWidth(textStyle = LocalTextStyle.current)
|
val spaceWidth = measureSpaceWidth(textStyle = LocalTextStyle.current)
|
||||||
|
|
||||||
FlowRow(
|
FlowRow(
|
||||||
horizontalArrangement = Arrangement.spacedBy(spaceWidth),
|
horizontalArrangement = Arrangement.spacedBy(spaceWidth),
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
) {
|
) {
|
||||||
userBase?.let { userBase ->
|
DisplayQuoteAuthor(
|
||||||
val userMetadata by userBase.live().userMetadataInfo.observeAsState()
|
authorHex = authorHex,
|
||||||
|
url = url,
|
||||||
CreateClickableTextWithEmoji(
|
postAddress = postAddress,
|
||||||
clickablePart = userMetadata?.bestName() ?: userBase.pubkeyDisplayHex(),
|
postVersion = postVersion,
|
||||||
maxLines = 1,
|
accountViewModel = accountViewModel,
|
||||||
route = "User/${userBase.pubkeyHex}",
|
nav = nav,
|
||||||
nav = nav,
|
)
|
||||||
tags = userMetadata?.tags,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
url?.let { url -> LoadAndDisplayUrl(url) }
|
|
||||||
|
|
||||||
postAddress?.let { address -> LoadAndDisplayPost(address, accountViewModel, nav) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LoadAndDisplayUrl(url: String) {
|
private fun DisplayQuoteAuthor(
|
||||||
|
authorHex: String?,
|
||||||
|
url: String?,
|
||||||
|
postAddress: ATag?,
|
||||||
|
postVersion: HexKey?,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit,
|
||||||
|
) {
|
||||||
|
var userBase by remember { mutableStateOf<User?>(authorHex?.let { accountViewModel.getUserIfExists(it) }) }
|
||||||
|
|
||||||
|
if (userBase == null && authorHex != null) {
|
||||||
|
LaunchedEffect(authorHex) {
|
||||||
|
accountViewModel.checkGetOrCreateUser(authorHex) { newUserBase ->
|
||||||
|
userBase = newUserBase
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var addressable by remember {
|
||||||
|
mutableStateOf<AddressableNote?>(postAddress?.let { accountViewModel.getAddressableNoteIfExists(it.toTag()) })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addressable == null && postAddress != null) {
|
||||||
|
LaunchedEffect(key1 = postAddress) {
|
||||||
|
val newNote =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
accountViewModel.getOrCreateAddressableNote(postAddress)
|
||||||
|
}
|
||||||
|
if (addressable != newNote) {
|
||||||
|
addressable = newNote
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var version by remember {
|
||||||
|
mutableStateOf<Note?>(postVersion?.let { accountViewModel.getNoteIfExists(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version == null && postVersion != null) {
|
||||||
|
LaunchedEffect(key1 = postVersion) {
|
||||||
|
val newNote =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
accountViewModel.getOrCreateNote(postVersion)
|
||||||
|
}
|
||||||
|
if (version != newNote) {
|
||||||
|
version = newNote
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addressable != null) {
|
||||||
|
addressable?.let {
|
||||||
|
DisplayEntryForNote(it, userBase, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
} else if (version != null) {
|
||||||
|
version?.let {
|
||||||
|
DisplayEntryForNote(it, userBase, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
} else if (url != null) {
|
||||||
|
DisplayEntryForAUrl(url, userBase, accountViewModel, nav)
|
||||||
|
} else if (userBase != null) {
|
||||||
|
userBase?.let {
|
||||||
|
DisplayEntryForUser(it, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DisplayEntryForUser(
|
||||||
|
userBase: User,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit,
|
||||||
|
) {
|
||||||
|
val userMetadata by userBase.live().userMetadataInfo.observeAsState()
|
||||||
|
|
||||||
|
CreateClickableTextWithEmoji(
|
||||||
|
clickablePart = userMetadata?.bestName() ?: userBase.pubkeyDisplayHex(),
|
||||||
|
maxLines = 1,
|
||||||
|
route = "User/${userBase.pubkeyHex}",
|
||||||
|
nav = nav,
|
||||||
|
tags = userMetadata?.tags,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DisplayEntryForNote(
|
||||||
|
note: Note,
|
||||||
|
userBase: User?,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit,
|
||||||
|
) {
|
||||||
|
val noteState by note.live().metadata.observeAsState()
|
||||||
|
|
||||||
|
val author = userBase ?: noteState?.note?.author
|
||||||
|
|
||||||
|
if (author != null) {
|
||||||
|
RenderUserAsClickableText(author, null, nav)
|
||||||
|
}
|
||||||
|
|
||||||
|
val noteEvent = noteState?.note?.event as? BaseTextNoteEvent ?: return
|
||||||
|
|
||||||
|
val description = noteEvent.firstTagFor("title", "subject", "alt")
|
||||||
|
|
||||||
|
Text("-", maxLines = 1)
|
||||||
|
|
||||||
|
if (description != null) {
|
||||||
|
ClickableText(
|
||||||
|
text = AnnotatedString(description),
|
||||||
|
onClick = { routeFor(note, accountViewModel.userProfile())?.let { nav(it) } },
|
||||||
|
style = LocalTextStyle.current.copy(color = MaterialTheme.colorScheme.primary),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
DisplayEvent(noteEvent.id, noteEvent.kind, "", accountViewModel, nav)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DisplayEntryForAUrl(
|
||||||
|
url: String,
|
||||||
|
userBase: User?,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit,
|
||||||
|
) {
|
||||||
|
if (userBase != null) {
|
||||||
|
DisplayEntryForUser(userBase, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
|
||||||
val validatedUrl =
|
val validatedUrl =
|
||||||
remember {
|
remember {
|
||||||
try {
|
try {
|
||||||
@ -171,7 +279,9 @@ fun LoadAndDisplayUrl(url: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
validatedUrl?.host?.let { host ->
|
validatedUrl?.host?.let { host ->
|
||||||
Text("-", maxLines = 1)
|
if (userBase != null) {
|
||||||
|
Text("-", maxLines = 1)
|
||||||
|
}
|
||||||
ClickableUrl(urlText = host, url = url)
|
ClickableUrl(urlText = host, url = url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,3 +308,21 @@ private fun LoadAndDisplayPost(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun LoadAndDisplayPostVersion(
|
||||||
|
postEvent: HexKey,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit,
|
||||||
|
) {
|
||||||
|
LoadNote(baseNoteHex = postEvent, accountViewModel) { baseNote ->
|
||||||
|
baseNote?.let { note ->
|
||||||
|
val noteState by note.live().metadata.observeAsState()
|
||||||
|
val noteEvent = noteState?.note?.event as? BaseTextNoteEvent ?: return@LoadNote
|
||||||
|
|
||||||
|
Text("-", maxLines = 1)
|
||||||
|
|
||||||
|
DisplayEvent(noteEvent.id, noteEvent.kind, "", accountViewModel, nav)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -121,6 +121,8 @@ open class Event(
|
|||||||
|
|
||||||
override fun taggedUrls() = tags.filter { it.size > 1 && it[0] == "r" }.map { it[1] }
|
override fun taggedUrls() = tags.filter { it.size > 1 && it[0] == "r" }.map { it[1] }
|
||||||
|
|
||||||
|
override fun firstTagFor(vararg key: String) = tags.firstOrNull { it.size > 1 && it[0] in key }?.let { it[1] }
|
||||||
|
|
||||||
override fun firstTaggedUser() = tags.firstOrNull { it.size > 1 && it[0] == "p" }?.let { it[1] }
|
override fun firstTaggedUser() = tags.firstOrNull { it.size > 1 && it[0] == "p" }?.let { it[1] }
|
||||||
|
|
||||||
override fun firstTaggedEvent() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.let { it[1] }
|
override fun firstTaggedEvent() = tags.firstOrNull { it.size > 1 && it[0] == "e" }?.let { it[1] }
|
||||||
|
@ -133,6 +133,8 @@ interface EventInterface {
|
|||||||
|
|
||||||
fun taggedUrls(): List<String>
|
fun taggedUrls(): List<String>
|
||||||
|
|
||||||
|
fun firstTagFor(vararg key: String): String?
|
||||||
|
|
||||||
fun firstTaggedAddress(): ATag?
|
fun firstTaggedAddress(): ATag?
|
||||||
|
|
||||||
fun firstTaggedUser(): HexKey?
|
fun firstTaggedUser(): HexKey?
|
||||||
|
@ -42,6 +42,8 @@ class HighlightEvent(
|
|||||||
|
|
||||||
fun inPost() = firstTaggedAddress()
|
fun inPost() = firstTaggedAddress()
|
||||||
|
|
||||||
|
fun inPostVersion() = firstTaggedEvent()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val KIND = 9802
|
const val KIND = 9802
|
||||||
const val ALT = "Highlight/quote event"
|
const val ALT = "Highlight/quote event"
|
||||||
|
Loading…
Reference in New Issue
Block a user