Introduce taggedEvent + taggedAuthor...

This commit is contained in:
Kgothatso Ngako
2026-03-31 19:48:09 +02:00
parent ba12077912
commit c3c92d96ad
5 changed files with 90 additions and 17 deletions

View File

@@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "6c8c4b9a4b44bed3c7fde29fcf54d7df",
"identityHash": "a9975543a4ca1505dcf4ee74321b3e69",
"entities": [
{
"tableName": "BroadcastNostrEventReceipt",
@@ -181,7 +181,7 @@
},
{
"tableName": "NostrEvent",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `pubKey` TEXT NOT NULL, `kind` INTEGER NOT NULL, `tags` TEXT NOT NULL, `content` TEXT NOT NULL, `sig` TEXT NOT NULL, `unsignedNostrEventId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`))",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `pubKey` TEXT NOT NULL, `kind` INTEGER NOT NULL, `tags` TEXT NOT NULL, `content` TEXT NOT NULL, `sig` TEXT NOT NULL, `taggedNostrEventId` TEXT, `taggedNostrEventRelayUrl` TEXT, `taggedPublicKey` TEXT, `taggedPublicKeyRelayUrl` TEXT, `unsignedNostrEventId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `deletedAt` INTEGER, `broadcastedAt` INTEGER, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
@@ -219,6 +219,26 @@
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "taggedNostrEventId",
"columnName": "taggedNostrEventId",
"affinity": "TEXT"
},
{
"fieldPath": "taggedNostrEventRelayUrl",
"columnName": "taggedNostrEventRelayUrl",
"affinity": "TEXT"
},
{
"fieldPath": "taggedPublicKey",
"columnName": "taggedPublicKey",
"affinity": "TEXT"
},
{
"fieldPath": "taggedPublicKeyRelayUrl",
"columnName": "taggedPublicKeyRelayUrl",
"affinity": "TEXT"
},
{
"fieldPath": "unsignedNostrEventId",
"columnName": "unsignedNostrEventId",
@@ -1342,7 +1362,7 @@
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6c8c4b9a4b44bed3c7fde29fcf54d7df')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a9975543a4ca1505dcf4ee74321b3e69')"
]
}
}

View File

@@ -38,6 +38,12 @@ data class NostrEvent(
val content: String,
val sig: HexKey,
val taggedNostrEventId: HexKey? = null,
val taggedNostrEventRelayUrl: String? = null,
val taggedPublicKey: HexKey? = null,
val taggedPublicKeyRelayUrl: String? = null,
override val unsignedNostrEventId: Long? = null,
override val createdAt: Instant = Clock.System.now(),

View File

@@ -21,4 +21,16 @@ data class LocalNostrEvent(
entityColumn = "nostrEventId"
)
val repost: Repost? = null,
@Relation(
parentColumn = "taggedNostrEventId",
entityColumn = "id"
)
val taggedNostrEvent: NostrEvent? = null,
@Relation(
parentColumn = "taggedPublicKey",
entityColumn = "publicKey"
)
val taggedAuthor: Profile? = null,
)

View File

@@ -30,6 +30,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.vitorpamplona.quartz.nip01Core.core.Event
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
import kotlin.time.Instant
@Composable
fun LocalNostrEvent.ListView(
@@ -57,21 +58,43 @@ fun LocalNostrEvent.ListView(
style = MaterialTheme.typography.labelSmall)
}
if (repost != null) {
RepostFeedItem(
repost,
this@ListView,
if (taggedNostrEvent != null) {
TextNoteFeedItem(
nostrEvent = taggedNostrEvent,
profile = taggedAuthor,
onNavigateToEvent = onNavigateToEvent
)
} else {
Text("Missing note")
val containedPost = RepostEvent(
id = nostrEvent.id,
pubKey = nostrEvent.pubKey,
createdAt = nostrEvent.createdAt.epochSeconds,
content = nostrEvent.content,
sig = nostrEvent.sig,
tags = nostrEvent.tags
).containedPost()
if (containedPost != null) {
Text("Loading author information...")
Text(
containedPost.content
)
Text(
text = Instant.fromEpochSeconds(containedPost.createdAt).toFormattedTimeAndDateString()
)
} else {
Text("Malformed Note")
}
}
}
}
// TODO: Support other kinds...
else -> {
TextNoteFeedItem(
this,
nostrEvent = nostrEvent,
profile = profile,
onNavigateToEvent = onNavigateToEvent
)
}
@@ -80,7 +103,8 @@ fun LocalNostrEvent.ListView(
@Composable
private fun TextNoteFeedItem(
localNostrEvent: LocalNostrEvent,
nostrEvent: NostrEvent,
profile: Profile?,
onNavigateToEvent: (NostrEvent) -> Unit
) {
ElevatedCard(
@@ -88,7 +112,7 @@ private fun TextNoteFeedItem(
horizontal = 10.dp
),
onClick = {
onNavigateToEvent.invoke(localNostrEvent.nostrEvent)
onNavigateToEvent.invoke(nostrEvent)
}
) {
Column(
@@ -107,12 +131,12 @@ private fun TextNoteFeedItem(
)
Text(
modifier = Modifier.weight(1f),
text = localNostrEvent.profile.displayName ?: localNostrEvent.profile.userName ?: localNostrEvent.profile.publicKey,
text = profile?.displayName ?: profile?.userName ?: nostrEvent.pubKey,
style = MaterialTheme.typography.bodyMedium
)
}
Text(
text = localNostrEvent.nostrEvent.content,
text = nostrEvent.content,
)
LazyRow(
@@ -126,7 +150,7 @@ private fun TextNoteFeedItem(
AssistChip(
label = {
Text(
text = localNostrEvent.nostrEvent.kind.toString() // TODO: Kind by name...
text = nostrEvent.kind.toString() // TODO: Kind by name...
)
},
onClick = {
@@ -136,7 +160,7 @@ private fun TextNoteFeedItem(
}
items(
items = localNostrEvent.nostrEvent.tags,
items = nostrEvent.tags,
) { tag ->
SuggestionChip(
label = {
@@ -152,7 +176,7 @@ private fun TextNoteFeedItem(
}
Text(
text = localNostrEvent.nostrEvent.createdAt.toFormattedTimeAndDateString()
text = nostrEvent.createdAt.toFormattedTimeAndDateString()
)
}
}

View File

@@ -17,6 +17,8 @@ import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.ReqCmd
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerSync
import com.vitorpamplona.quartz.nip01Core.tags.events.firstTaggedEvent
import com.vitorpamplona.quartz.nip01Core.tags.people.firstTaggedUser
import com.vitorpamplona.quartz.nip51Lists.encryption.PrivateTagsInContent
import com.vitorpamplona.quartz.utils.text
import io.ktor.client.HttpClient
@@ -197,6 +199,9 @@ class NavigationViewModel(
// TODO: Do profile specific cache (to avoid wiping an updated profile)
syncEventCache.getOrPut(event.id, {
val taggedEvent = event.firstTaggedEvent()
val taggedUser = event.firstTaggedUser()
val nostrEvent = NostrEvent(
id = event.id,
pubKey = event.pubKey,
@@ -205,7 +210,13 @@ class NavigationViewModel(
tags = event.tags,
createdAt = Instant.fromEpochSeconds(event.createdAt),
unsignedNostrEventId = synchronizeNostrEventRequest.unsignedNostrEventId,
sig = event.sig
sig = event.sig,
taggedNostrEventId = taggedEvent?.eventId,
taggedNostrEventRelayUrl = taggedEvent?.relay?.url,
taggedPublicKey = taggedUser?.pubKey,
taggedPublicKeyRelayUrl = taggedUser?.relayHint?.url
)
nostrRepository.saveNostrEvent(