Introduce an atrocious bug when syncing.
This commit is contained in:
@@ -14,6 +14,7 @@ import ac.cord.auxiliary.compose.database.model.types.SynchronizationFilter
|
||||
import ac.cord.auxiliary.compose.nostr.Relays
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Transaction
|
||||
import androidx.room.useWriterConnection
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.events.taggedEvents
|
||||
@@ -289,6 +290,18 @@ abstract class NostrDao(
|
||||
nostrEvent.tags.taggedEvents().take(4).forEach { taggedEvent -> // We only look at the first 3 tagged events...
|
||||
val taggedNostrEvent = database.nostrEventDao().getNostrEventById(taggedEvent.eventId)
|
||||
if (taggedNostrEvent == null) {
|
||||
database.nostrEventDao().insert(
|
||||
NostrEvent(
|
||||
id = taggedEvent.eventId,
|
||||
content = "Pending Sync... ",
|
||||
createdAt = GENESIS_AT,
|
||||
pubKey = nostrEvent.pubKey,
|
||||
sig = "",
|
||||
kind = nostrEvent.kind,
|
||||
tags = emptyArray()
|
||||
)
|
||||
)
|
||||
|
||||
val recommendRelayUrl = taggedEvent.relay?.url
|
||||
|
||||
val synchronizeNostrEventRequests = if (recommendRelayUrl != null) {
|
||||
|
||||
@@ -16,28 +16,28 @@ import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface NostrEventDao {
|
||||
@Query("SELECT * FROM NostrEvent WHERE kind in (:kinds) ORDER BY createdAt DESC")
|
||||
@Query("SELECT * FROM NostrEvent WHERE kind in (:kinds) AND savedAt < strftime('%s', 'now') ORDER BY createdAt DESC")
|
||||
fun observeNostrEvents(kinds: Array<Kind>): Flow<List<LocalNostrEvent>>
|
||||
|
||||
@Query("SELECT * FROM NostrEvent WHERE content LIKE '%' || :search || '%' AND kind in (:kinds) ORDER BY createdAt DESC")
|
||||
@Query("SELECT * FROM NostrEvent WHERE content LIKE '%' || :search || '%' AND kind in (:kinds) AND savedAt < strftime('%s', 'now') ORDER BY createdAt DESC")
|
||||
fun observeFilteredNostrEvents(
|
||||
kinds: Array<Kind>,
|
||||
search: String
|
||||
): Flow<List<LocalNostrEvent>>
|
||||
|
||||
@Query("SELECT * FROM NostrEvent WHERE kind in (:kinds) AND id in (:ids) ORDER BY createdAt DESC")
|
||||
@Query("SELECT * FROM NostrEvent WHERE kind in (:kinds) AND id in (:ids) AND savedAt < strftime('%s', 'now') ORDER BY createdAt DESC")
|
||||
fun observeFilteredNostrEvents(
|
||||
kinds: Array<Kind>,
|
||||
ids: Array<HexKey>,
|
||||
): Flow<List<LocalNostrEvent>>
|
||||
|
||||
@Query("SELECT * FROM NostrEvent WHERE kind in (:kinds) AND pubKey in (:authors) ORDER BY createdAt DESC LIMIT 50")
|
||||
@Query("SELECT * FROM NostrEvent WHERE kind in (:kinds) AND pubKey in (:authors) AND savedAt < strftime('%s', 'now') ORDER BY createdAt DESC LIMIT 50")
|
||||
fun observeAuthoredNostrEvents(
|
||||
kinds: Array<Kind>,
|
||||
authors: Array<HexKey>,
|
||||
): Flow<List<LocalNostrEvent>>
|
||||
|
||||
@Query("SELECT * FROM NostrEvent WHERE tags LIKE '%' || :publicKey || '%' AND kind in (:kinds) ORDER BY createdAt DESC")
|
||||
@Query("SELECT * FROM NostrEvent WHERE tags LIKE '%' || :publicKey || '%' AND kind in (:kinds) AND savedAt < strftime('%s', 'now') ORDER BY createdAt DESC")
|
||||
fun observePublicKeyMentionedNostrEvents(
|
||||
kinds: Array<Kind>,
|
||||
publicKey: HexKey
|
||||
@@ -48,7 +48,7 @@ interface NostrEventDao {
|
||||
query: RoomRawQuery
|
||||
): Flow<List<LocalNostrEvent>>
|
||||
|
||||
@Query("SELECT * FROM NostrEvent WHERE kind in (:kinds) ORDER BY savedAt DESC")
|
||||
@Query("SELECT * FROM NostrEvent WHERE kind in (:kinds) AND savedAt < strftime('%s', 'now') ORDER BY savedAt DESC")
|
||||
fun getAllNostrEvents(kinds: Array<Kind>): List<NostrEvent>
|
||||
|
||||
@Query("SELECT * FROM NostrEvent WHERE id = :id")
|
||||
|
||||
@@ -6,6 +6,8 @@ import ac.cord.auxiliary.compose.database.model.traits.SoftDeletableEntity
|
||||
import ac.cord.auxiliary.compose.database.model.traits.TimestampedEntity
|
||||
import ac.cord.auxiliary.compose.database.model.traits.UnsignedNostrEventEntity
|
||||
import ac.cord.auxiliary.compose.database.model.types.SynchronizationFilter
|
||||
import ac.cord.auxiliary.compose.ui.composable.widgets.content.ContentParser
|
||||
import ac.cord.auxiliary.compose.ui.composable.widgets.content.ContentSegment
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.Index
|
||||
@@ -275,9 +277,22 @@ data class NostrEvent(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Get quoted event from content...
|
||||
|
||||
return null
|
||||
// TODO: Bring in quoted text
|
||||
// val quotedNotes = ContentParser.parse(content.trimEnd('\n', '\r'), emptyMap(), emptyMap(), trimBlankLines = true)
|
||||
// .filterIsInstance<ContentSegment.NostrNoteSegment>()
|
||||
// .firstOrNull()
|
||||
//
|
||||
// return quotedNotes?.let { quotedNote ->
|
||||
// QuotedRelation(
|
||||
// quotedNostrEventId = quotedNote.eventId,
|
||||
// quotedProfilePublicKey = null
|
||||
// ,
|
||||
//
|
||||
// quotingNostrEventId = id,
|
||||
// createdAt = createdAt
|
||||
// )
|
||||
// }
|
||||
} catch (e: Throwable) {
|
||||
logger.e("Failed to return Repost: ", e)
|
||||
return null
|
||||
|
||||
@@ -80,7 +80,7 @@ data class LocalNostrEvent(
|
||||
parentColumn = "id",
|
||||
entityColumn = "nostrEventId",
|
||||
)
|
||||
val mentionedProfiles: List<LocalMention> = emptyList(),
|
||||
val mentionedProfiles: List<LocalMention?> = emptyList(),
|
||||
) {
|
||||
@Composable
|
||||
fun RenderNotePreview() {
|
||||
|
||||
@@ -35,15 +35,11 @@ data class LocalQuotedNostrEvent(
|
||||
val profile: Profile?,
|
||||
|
||||
@Relation(
|
||||
entity = Mention::class,
|
||||
parentColumn = "id",
|
||||
entityColumn = "nostrEventId",
|
||||
associateBy = Junction(
|
||||
value = Mention::class,
|
||||
parentColumn = "publicKey",
|
||||
entityColumn = "publicKey"
|
||||
)
|
||||
)
|
||||
val mentionedProfiles: List<Profile> = emptyList()
|
||||
val mentionedProfiles: List<LocalMention?> = emptyList(),
|
||||
) {
|
||||
@Composable
|
||||
fun RenderNotePreview() {
|
||||
|
||||
@@ -23,14 +23,12 @@ import ac.cord.auxiliary.compose.nostr.Relays
|
||||
import ac.cord.auxiliary.compose.repository.NostrRepository
|
||||
import ac.cord.auxiliary.compose.repository.RelayRepository
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Kind
|
||||
import com.vitorpamplona.quartz.nip01Core.hints.EventHintBundle
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.hashtags.hashtags
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.PTag
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.people.taggedUsers
|
||||
import com.vitorpamplona.quartz.nip01Core.tags.references.references
|
||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||
import com.vitorpamplona.quartz.nip02FollowList.RelaySet
|
||||
@@ -39,14 +37,12 @@ import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip10Notes.content.findHashtags
|
||||
import com.vitorpamplona.quartz.nip10Notes.content.findNostrUris
|
||||
import com.vitorpamplona.quartz.nip10Notes.content.findURLs
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.markedETag
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.markedETags
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.notify
|
||||
import com.vitorpamplona.quartz.nip10Notes.tags.prepareETagsAsReplyTo
|
||||
import com.vitorpamplona.quartz.nip17Dm.settings.ChatMessageRelayListEvent
|
||||
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
||||
import com.vitorpamplona.quartz.nip18Reposts.quotes.QEventTag
|
||||
import com.vitorpamplona.quartz.nip18Reposts.quotes.QTag
|
||||
import com.vitorpamplona.quartz.nip18Reposts.quotes.quotes
|
||||
import com.vitorpamplona.quartz.nip21UriScheme.toNostrUri
|
||||
import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
|
||||
@@ -58,15 +54,20 @@ import com.vitorpamplona.quartz.nip51Lists.relayLists.RelayFeedsListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.RelayTag
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.collections.emptyMap
|
||||
import kotlin.collections.plus
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import kotlin.time.Instant
|
||||
|
||||
class DatabaseNostrRepository(
|
||||
private val database: AuxDatabase
|
||||
private val database: AuxDatabase,
|
||||
private val scope: CoroutineScope
|
||||
): NostrRepository, RelayRepository {
|
||||
companion object {
|
||||
const val TAG = "DatabaseNostrRepository"
|
||||
@@ -398,8 +399,17 @@ class DatabaseNostrRepository(
|
||||
synchronizeNostrEventRequest: SynchronizeNostrEventRequest,
|
||||
synchronizationRelayURLs: List<String>
|
||||
) {
|
||||
val triggerDelay = 5.seconds
|
||||
|
||||
val delayedFlowTriggerNostrEvent = nostrEvent.copy(
|
||||
savedAt = Instant.fromEpochSeconds(
|
||||
Clock.System.now().epochSeconds + triggerDelay.inWholeSeconds
|
||||
)
|
||||
)
|
||||
logger.d("savedAt: ${nostrEvent.savedAt}")
|
||||
logger.d("SavedAt: ${delayedFlowTriggerNostrEvent.savedAt}")
|
||||
database.nostrDao().storeNostrEvent(
|
||||
nostrEvent,
|
||||
delayedFlowTriggerNostrEvent,
|
||||
synchronizationRelayURLs = synchronizationRelayURLs,
|
||||
level = synchronizeNostrEventRequest.level
|
||||
)
|
||||
@@ -410,6 +420,19 @@ class DatabaseNostrRepository(
|
||||
status = "processed"
|
||||
)
|
||||
)
|
||||
|
||||
// Might not even need this delay
|
||||
// scope.launch {
|
||||
// delay(triggerDelay)
|
||||
// database.nostrEventDao().upsert(
|
||||
// nostrEvent
|
||||
// )
|
||||
// }
|
||||
// Trigger the nostrEvent to appear in the feed...
|
||||
delay(triggerDelay)
|
||||
database.nostrEventDao().upsert(
|
||||
nostrEvent
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun queueSynchronizeNostrEvent(
|
||||
|
||||
@@ -70,16 +70,6 @@ fun AuxNavHost(
|
||||
navController: NavHostController
|
||||
) {
|
||||
val logger = Logger.withTag("AuxNavHost")
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
|
||||
val databaseManager = DatabaseManager(auxGlobal)
|
||||
|
||||
val databaseNostrRepository = DatabaseNostrRepository(
|
||||
database = databaseManager.auxDatabase
|
||||
)
|
||||
val searchRepository = DatabaseSearchRepository(
|
||||
database = databaseManager.auxDatabase
|
||||
)
|
||||
|
||||
val exceptionHandler =
|
||||
CoroutineExceptionHandler { _, throwable ->
|
||||
@@ -89,6 +79,20 @@ fun AuxNavHost(
|
||||
val applicationIOScope = CoroutineScope(Dispatchers.IO + SupervisorJob() + exceptionHandler)
|
||||
val applicationMainScope = CoroutineScope(Dispatchers.Main)
|
||||
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
|
||||
val databaseManager = DatabaseManager(auxGlobal)
|
||||
|
||||
val databaseNostrRepository = DatabaseNostrRepository(
|
||||
database = databaseManager.auxDatabase,
|
||||
applicationIOScope
|
||||
)
|
||||
val searchRepository = DatabaseSearchRepository(
|
||||
database = databaseManager.auxDatabase
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
val navigationViewModel: NavigationViewModel = viewModel (
|
||||
factory = NavigationViewModel.factory(
|
||||
|
||||
@@ -101,14 +101,19 @@ fun RichContent(
|
||||
.filterIsInstance<ContentSegment.NostrProfileSegment>()
|
||||
.map { it.pubkey }
|
||||
|
||||
Logger.withTag("RichContent").d("profilePubKey: $profilePubkeys")
|
||||
val profileNames = remember(profilePubkeys) {
|
||||
val names = mutableMapOf<String, String>()
|
||||
for (pubkey in profilePubkeys) {
|
||||
|
||||
val mentionedProfile = localNostrEvent.mentionedProfiles.find { mentionedProfile -> mentionedProfile.profile?.publicKey == pubkey }
|
||||
names[pubkey] = mentionedProfile?.profile?.humanReadableNameOrPubkey()
|
||||
?: "${pubkey.take(8)}...${pubkey.takeLast(4)}"
|
||||
if (localNostrEvent.mentionedProfiles.isNotEmpty()) {
|
||||
Logger.withTag("RichContent").d("mentionedProfiles: ${localNostrEvent.mentionedProfiles}")
|
||||
for (pubkey in profilePubkeys) {
|
||||
val mentionedProfile = localNostrEvent.mentionedProfiles.find { mentionedProfile -> mentionedProfile?.profile?.publicKey == pubkey }
|
||||
names[pubkey] = mentionedProfile?.profile?.humanReadableNameOrPubkey()
|
||||
?: "${pubkey.take(8)}...${pubkey.takeLast(4)}"
|
||||
}
|
||||
}
|
||||
|
||||
names
|
||||
}
|
||||
// TODO Queue fetches for any missing profiles
|
||||
|
||||
@@ -202,22 +202,22 @@ private fun TextNoteFeedItem(
|
||||
)
|
||||
}
|
||||
|
||||
item {
|
||||
SuggestionChip(
|
||||
label = {
|
||||
Text(
|
||||
text = if (localNostrEvent.mentionedProfiles.isNotEmpty()) {
|
||||
localNostrEvent.mentionedProfiles.joinToString(",") { it.profile?.humanReadableNameOrPubkey() ?: "Find user information" }
|
||||
} else {
|
||||
":-("
|
||||
}
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
// item {
|
||||
// SuggestionChip(
|
||||
// label = {
|
||||
// Text(
|
||||
// text = if (localNostrEvent.mentionedProfiles.isNotEmpty()) {
|
||||
// localNostrEvent.mentionedProfiles.joinToString(",") { it?.profile?.humanReadableNameOrPubkey() ?: "Find user information" }
|
||||
// } else {
|
||||
// ":-("
|
||||
// }
|
||||
// )
|
||||
// },
|
||||
// onClick = {
|
||||
//
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
|
||||
items(
|
||||
items = nostrEvent.tags,
|
||||
|
||||
Reference in New Issue
Block a user