Sync taggedEvent + taggedAuthor...
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 1,
|
||||
"identityHash": "a9975543a4ca1505dcf4ee74321b3e69",
|
||||
"identityHash": "31032766d6bdd6ae4664e854a928dd32",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "BroadcastNostrEventReceipt",
|
||||
@@ -929,7 +929,7 @@
|
||||
},
|
||||
{
|
||||
"tableName": "SynchronizeNostrEventRequest",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `status` TEXT NOT NULL, `relayURL` TEXT NOT NULL, `synchronizationFilters` TEXT NOT NULL, `nostrEventId` TEXT, `unsignedNostrEventId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`unsignedNostrEventId`) REFERENCES `UnsignedNostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `status` TEXT NOT NULL, `relayURL` TEXT NOT NULL, `isRecommendedRelay` INTEGER NOT NULL, `synchronizationFilters` TEXT NOT NULL, `nostrEventId` TEXT, `unsignedNostrEventId` INTEGER, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`nostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`unsignedNostrEventId`) REFERENCES `UnsignedNostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
@@ -949,6 +949,12 @@
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "isRecommendedRelay",
|
||||
"columnName": "isRecommendedRelay",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "synchronizationFilters",
|
||||
"columnName": "synchronizationFilters",
|
||||
@@ -1362,7 +1368,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, 'a9975543a4ca1505dcf4ee74321b3e69')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '31032766d6bdd6ae4664e854a928dd32')"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ import androidx.room.Dao
|
||||
import androidx.room.Transaction
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEvents
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
||||
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
|
||||
import kotlin.time.Clock
|
||||
|
||||
@@ -122,6 +124,77 @@ abstract class NostrDao(
|
||||
}
|
||||
}
|
||||
|
||||
// Sync tagged events and authors...
|
||||
nostrEvent.tags.taggedEvents().forEach { taggedEvent ->
|
||||
val taggedNostrEvent = database.nostrEventDao().getNostrEventById(taggedEvent.eventId)
|
||||
if (taggedNostrEvent == null) {
|
||||
val recommendRelayUrl = taggedEvent.relay?.url
|
||||
|
||||
val synchronizeNostrEventRequests = if (recommendRelayUrl != null) {
|
||||
listOf(
|
||||
SynchronizeNostrEventRequest(
|
||||
synchronizationFilters = arrayOf(
|
||||
SynchronizationFilter(
|
||||
ids = arrayOf(taggedEvent.eventId)
|
||||
)
|
||||
),
|
||||
relayURL = recommendRelayUrl,
|
||||
isRecommendedRelay = true,
|
||||
)
|
||||
)
|
||||
} else {
|
||||
synchronizationRelayURLs.map { synchronizationRelayURL ->
|
||||
SynchronizeNostrEventRequest(
|
||||
synchronizationFilters = arrayOf(
|
||||
SynchronizationFilter(
|
||||
ids = arrayOf(taggedEvent.eventId)
|
||||
)
|
||||
),
|
||||
relayURL = synchronizationRelayURL
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
database.synchronizeNostrEventRequestDao().insert(
|
||||
synchronizeNostrEventRequests
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
nostrEvent.tags.taggedUsers().forEach { taggedUser ->
|
||||
val recommendedRelay = taggedUser.relayHint?.url
|
||||
|
||||
val synchronizeNostrEventRequests = if (recommendedRelay != null) {
|
||||
listOf(
|
||||
SynchronizeNostrEventRequest(
|
||||
synchronizationFilters = arrayOf(
|
||||
SynchronizationFilter(
|
||||
authors = arrayOf(taggedUser.pubKey),
|
||||
kinds = arrayOf(MetadataEvent.KIND)
|
||||
)
|
||||
),
|
||||
relayURL = recommendedRelay,
|
||||
isRecommendedRelay = true,
|
||||
)
|
||||
)
|
||||
} else {
|
||||
synchronizationRelayURLs.map { synchronizationRelayURL ->
|
||||
SynchronizeNostrEventRequest(
|
||||
synchronizationFilters = arrayOf(
|
||||
SynchronizationFilter(
|
||||
authors = arrayOf(taggedUser.pubKey),
|
||||
kinds = arrayOf(MetadataEvent.KIND)
|
||||
)
|
||||
),
|
||||
relayURL = synchronizationRelayURL
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
database.synchronizeNostrEventRequestDao().insert(
|
||||
synchronizeNostrEventRequests
|
||||
)
|
||||
}
|
||||
nostrEvent.toPost()?.let { post ->
|
||||
if (post.replyToId != null) {
|
||||
// Find or create placeHolder note that is replyTo
|
||||
@@ -132,82 +205,14 @@ abstract class NostrDao(
|
||||
database.postDao().insert(
|
||||
Post(
|
||||
id = post.replyToId,
|
||||
nostrEventId = nostrEvent.id, // Will get overwriting by sync,
|
||||
nostrEventId = nostrEvent.id, // Will get overwriting by sync handled by tagged events...
|
||||
content = post.replyToId,
|
||||
profilePublicKey = nostrEvent.pubKey // Will get overwriting by sync,
|
||||
profilePublicKey = nostrEvent.pubKey // Will get overwriting by sync handled by tagged events...
|
||||
)
|
||||
)
|
||||
|
||||
// Request a sync for the post being replied to
|
||||
database.synchronizeNostrEventRequestDao().insert(
|
||||
synchronizationRelayURLs.map { synchronizationRelayURL ->
|
||||
SynchronizeNostrEventRequest(
|
||||
synchronizationFilters = arrayOf(
|
||||
SynchronizationFilter(
|
||||
ids = arrayOf(post.replyToId)
|
||||
)
|
||||
),
|
||||
relayURL = synchronizationRelayURL
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// if (post.repostId != null) {
|
||||
// val repostPost = database.postDao().getPostById(post.repostId)
|
||||
//
|
||||
// if (repostPost == null) {
|
||||
// // Placeholder Post...
|
||||
// database.postDao().insert(
|
||||
// Post(
|
||||
// id = post.repostId,
|
||||
// nostrEventId = nostrEvent.id, // Will get overwriting by sync,
|
||||
// content = post.repostId,
|
||||
// profilePublicKey = nostrEvent.pubKey // Will get overwriting by sync,
|
||||
// )
|
||||
// )
|
||||
// // Request a sync for the post being reposted
|
||||
// database.synchronizeNostrEventRequestDao().insert(
|
||||
// synchronizationRelayURLs.map { synchronizationRelayURL ->
|
||||
// SynchronizeNostrEventRequest(
|
||||
// synchronizationFilters = arrayOf(
|
||||
// SynchronizationFilter(
|
||||
// ids = arrayOf(post.repostId)
|
||||
// )
|
||||
// ),
|
||||
// relayURL = synchronizationRelayURL
|
||||
// )
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// // repostProfile??
|
||||
// val profile = database.profileDao().getProfileByPublicKey(post.profilePublicKey)
|
||||
//
|
||||
// if (profile == null) {
|
||||
// val placeHolderProfile = Profile(
|
||||
// publicKey = nostrEvent.pubKey,
|
||||
// nostrEventId = nostrEvent.id, // Will get overwriting by sync,
|
||||
// )
|
||||
// database.profileDao().insertPlaceholderProfile(placeHolderProfile)
|
||||
//
|
||||
// database.synchronizeNostrEventRequestDao().insert(
|
||||
// synchronizationRelayURLs.map { synchronizationRelayURL ->
|
||||
// SynchronizeNostrEventRequest(
|
||||
// synchronizationFilters = arrayOf(
|
||||
// SynchronizationFilter(
|
||||
// authors = arrayOf(nostrEvent.pubKey),
|
||||
// kinds = arrayOf(MetadataEvent.KIND)
|
||||
// )
|
||||
// ),
|
||||
// relayURL = synchronizationRelayURL
|
||||
// )
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
|
||||
database.postDao().upsert(post)
|
||||
}
|
||||
|
||||
@@ -228,25 +233,11 @@ abstract class NostrDao(
|
||||
database.postDao().insert(
|
||||
Post(
|
||||
id = repost.repostedPostId,
|
||||
nostrEventId = nostrEvent.id, // Will get overwriting by sync,
|
||||
nostrEventId = nostrEvent.id, // Will get overwriting by sync handled by tagged events...
|
||||
content = repost.repostedPostId,
|
||||
profilePublicKey = nostrEvent.pubKey // Will get overwriting by sync,
|
||||
profilePublicKey = nostrEvent.pubKey // Will get overwriting by sync handled by tagged events...
|
||||
)
|
||||
)
|
||||
|
||||
// Request a sync for the post being replied to
|
||||
database.synchronizeNostrEventRequestDao().insert(
|
||||
synchronizationRelayURLs.map { synchronizationRelayURL ->
|
||||
SynchronizeNostrEventRequest(
|
||||
synchronizationFilters = arrayOf(
|
||||
SynchronizationFilter(
|
||||
ids = arrayOf(repost.repostedPostId)
|
||||
)
|
||||
),
|
||||
relayURL = synchronizationRelayURL
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
val repostedPostProfile = database.profileDao().getProfileByPublicKey(repost.repostedPostAuthorPublicKey)
|
||||
@@ -256,7 +247,7 @@ abstract class NostrDao(
|
||||
database.profileDao().insertPlaceholderProfile(
|
||||
Profile(
|
||||
publicKey = nostrEvent.pubKey,
|
||||
nostrEventId = nostrEvent.id, // Will get overwriting by sync,
|
||||
nostrEventId = nostrEvent.id, // Will get overwriting by sync handled by tagged events...
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -19,7 +19,10 @@ interface NostrEventDao {
|
||||
fun getAllNostrEvents(kinds: Array<Kind>): List<NostrEvent>
|
||||
|
||||
@Query("SELECT * FROM NostrEvent WHERE id = :id")
|
||||
fun getNostrEventById(id: String): Flow<NostrEvent?>
|
||||
fun observeNostrEventById(id: String): Flow<NostrEvent?>
|
||||
|
||||
@Query("SELECT * FROM NostrEvent WHERE id = :id")
|
||||
fun getNostrEventById(id: String): NostrEvent?
|
||||
|
||||
@Upsert
|
||||
suspend fun upsert(nostrEvent: NostrEvent)
|
||||
|
||||
@@ -40,6 +40,7 @@ data class SynchronizeNostrEventRequest(
|
||||
val id: String = Uuid.generateV4().toHexDashString(),
|
||||
val status: String = "pending",
|
||||
val relayURL: String,
|
||||
val isRecommendedRelay: Boolean = false,
|
||||
|
||||
val synchronizationFilters: SynchronizationFilterArray,
|
||||
|
||||
|
||||
@@ -41,12 +41,13 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun FeedScreen(
|
||||
initialFeedListUIState: FeedListUIState,
|
||||
onNavigateToEvent: (NostrEvent) -> Unit,
|
||||
onNavigateToEvent: (HexKey) -> Unit,
|
||||
onNavigateToWriteNewNote: () -> Unit,
|
||||
nostrRepository: NostrRepository,
|
||||
) {
|
||||
|
||||
@@ -295,10 +295,10 @@ fun AuxNavHost(
|
||||
composable<FeedRoute> {
|
||||
FeedScreen(
|
||||
initialFeedListUIState = FeedListUIState.Loading,
|
||||
onNavigateToEvent = { event ->
|
||||
onNavigateToEvent = { nostrEventId ->
|
||||
navController.navigate(
|
||||
route = ImplementationPendingRoute(
|
||||
event.content
|
||||
nostrEventId
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ import ac.aux.compose.database.model.Repost
|
||||
import ac.aux.compose.database.model.intermdiate.LocalNostrEvent
|
||||
import ac.aux.compose.extensions.toFormattedTimeAndDateString
|
||||
import ac.aux.compose.ui.theme.AuxTheme
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -29,24 +30,28 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
||||
import kotlin.time.Instant
|
||||
|
||||
@Composable
|
||||
fun LocalNostrEvent.ListView(
|
||||
onNavigateToEvent: (NostrEvent) -> Unit
|
||||
onNavigateToEvent: (HexKey) -> Unit
|
||||
) {
|
||||
when (nostrEvent.kind) {
|
||||
RepostEvent.KIND -> {
|
||||
// TODO: Make use of the indexed Repost field to render...
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth().padding(10.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier.fillMaxWidth().clickable(
|
||||
enabled = true,
|
||||
onClick = {
|
||||
onNavigateToEvent.invoke(profile.nostrEventId)
|
||||
}
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
@@ -105,14 +110,32 @@ fun LocalNostrEvent.ListView(
|
||||
private fun TextNoteFeedItem(
|
||||
nostrEvent: NostrEvent,
|
||||
profile: Profile?,
|
||||
onNavigateToEvent: (NostrEvent) -> Unit
|
||||
taggedNostrEvent: NostrEvent? = null,
|
||||
taggedAuthor: Profile? = null,
|
||||
onNavigateToEvent: (HexKey) -> Unit
|
||||
) {
|
||||
if (nostrEvent.kind == 1 && taggedNostrEvent != null) {
|
||||
Row {
|
||||
Text(
|
||||
"In reply to"
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.clickable(
|
||||
onClick = {
|
||||
onNavigateToEvent.invoke(taggedNostrEvent.id)
|
||||
}
|
||||
),
|
||||
text = taggedAuthor?.displayName ?: taggedAuthor?.userName ?: "loading information..."
|
||||
)
|
||||
}
|
||||
}
|
||||
ElevatedCard(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = 10.dp
|
||||
),
|
||||
onClick = {
|
||||
onNavigateToEvent.invoke(nostrEvent)
|
||||
onNavigateToEvent.invoke(nostrEvent.id)
|
||||
}
|
||||
) {
|
||||
Column(
|
||||
@@ -120,21 +143,32 @@ private fun TextNoteFeedItem(
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.Start),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Person,
|
||||
contentDescription = "Profile picture",
|
||||
)
|
||||
if (profile != null) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().clickable(
|
||||
onClick = {
|
||||
onNavigateToEvent.invoke(profile?.nostrEventId ?: nostrEvent.id)
|
||||
}
|
||||
),
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.Start),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Person,
|
||||
contentDescription = "Profile picture",
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = profile?.displayName ?: profile?.userName ?: nostrEvent.pubKey,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = profile?.displayName ?: profile?.userName ?: nostrEvent.pubKey,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
text = "Loading author information"
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = nostrEvent.content,
|
||||
)
|
||||
@@ -182,87 +216,6 @@ private fun TextNoteFeedItem(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RepostFeedItem(
|
||||
repost: Repost,
|
||||
localNostrEvent: LocalNostrEvent,
|
||||
onNavigateToEvent: (NostrEvent) -> Unit
|
||||
) {
|
||||
ElevatedCard(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = 10.dp
|
||||
),
|
||||
onClick = {
|
||||
onNavigateToEvent.invoke(localNostrEvent.nostrEvent)
|
||||
}
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(10.dp).fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp, Alignment.Start),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Person,
|
||||
contentDescription = "Profile picture",
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
text = repost.repostedPostAuthorPublicKey,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = repost.content,
|
||||
)
|
||||
|
||||
LazyRow(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(
|
||||
10.dp,
|
||||
alignment = Alignment.Start
|
||||
)
|
||||
) {
|
||||
item {
|
||||
AssistChip(
|
||||
label = {
|
||||
Text(
|
||||
text = localNostrEvent.nostrEvent.kind.toString() // TODO: Kind by name...
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
items(
|
||||
items = localNostrEvent.nostrEvent.tags,
|
||||
) { tag ->
|
||||
SuggestionChip(
|
||||
label = {
|
||||
Text(
|
||||
text = tag.joinToString(":")
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
text = localNostrEvent.nostrEvent.createdAt.toFormattedTimeAndDateString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun EventListViewPreview() {
|
||||
|
||||
@@ -7,11 +7,12 @@ import androidx.compose.material3.ElevatedCard
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
|
||||
@Composable
|
||||
fun FeedListItem(
|
||||
localNostrEvent: LocalNostrEvent,
|
||||
onNavigateToEvent: (NostrEvent) -> Unit
|
||||
onNavigateToEvent: (HexKey) -> Unit
|
||||
) {
|
||||
localNostrEvent.ListView(
|
||||
onNavigateToEvent = onNavigateToEvent
|
||||
|
||||
Reference in New Issue
Block a user