- Restructures the old static datasource model into dynamic filter assemblers.

- Moves filter assemblers, viewModels and DAL classes to their own packages.
- Creates Composable observers for Users and Notes
- Deletes most of the secondary LiveData objects in the move to Flow
- Manipulates nostr filters depending on the account of the current screen, not a global account.
- Unifies all FilterAssembly lifecycle watchers to a few classes.
- Prepares to separate The Nostr Client as an Engine of Amethyst.
- Moves the pre-caching processor of new events from the datasource to the accountViewModel
- Reorganizes search to be per-screen basis
- Moves authentication to a fixed Coordinator class for all accounts in all relays.
- Moves NOTIFY command to its own coordinator class for all accounts
- Moves the connection between filters and cache to its own class.
- Significantly reduces the dependency on a single ServiceManager class.
This commit is contained in:
Vitor Pamplona
2025-04-23 16:24:41 -04:00
parent faf0f6dc1a
commit a84371a0b3
272 changed files with 7055 additions and 5068 deletions
@@ -420,6 +420,9 @@ class SimpleClientRelay(
}
interface Listener {
/**
* New Event arrives from the relay.
*/
fun onEvent(
relay: SimpleClientRelay,
subscriptionId: String,
@@ -427,49 +430,76 @@ class SimpleClientRelay(
afterEOSE: Boolean,
)
/**
* New EOSE command arrives for a subscription
*/
fun onEOSE(
relay: SimpleClientRelay,
subscriptionId: String,
)
/**
* New error
*/
fun onError(
relay: SimpleClientRelay,
subscriptionId: String,
error: Error,
)
/**
* Relay is requesting authentication with the given challenge.
*/
fun onAuth(
relay: SimpleClientRelay,
challenge: String,
)
/**
* RelayState changes
*/
fun onRelayStateChange(
relay: SimpleClientRelay,
type: RelayState,
)
/**
* NOTIFY command has arrived.
*/
fun onNotify(
relay: SimpleClientRelay,
description: String,
)
/**
* Relay closed the subscription
*/
fun onClosed(
relay: SimpleClientRelay,
subscriptionId: String,
message: String,
)
/**
* Triggers this before sending the event.
*/
fun onBeforeSend(
relay: SimpleClientRelay,
event: Event,
)
/**
* Triggers after the event has been sent.
*/
fun onSend(
relay: SimpleClientRelay,
msg: String,
success: Boolean,
)
/**
* Relay accepted or rejected the event
*/
fun onSendResponse(
relay: SimpleClientRelay,
eventId: String,
@@ -44,4 +44,7 @@ sealed class VerificationState {
val errorMessage: String,
val time: Long = TimeUtils.now(),
) : VerificationState()
@Immutable
object Verifying : VerificationState()
}
@@ -27,21 +27,32 @@ import com.vitorpamplona.quartz.utils.TimeUtils
class VerificationStateCache {
private val cache = LruCache<HexKey, VerificationState>(200)
fun verify(
event: OtsEvent,
resolverBuilder: () -> OtsResolver,
): VerificationState {
cache.put(event.id, VerificationState.Verifying)
return event.verifyState(resolverBuilder()).also { cache.put(event.id, it) }
}
fun cacheVerify(
event: OtsEvent,
resolverBuilder: () -> OtsResolver,
): VerificationState =
when (val verif = cache[event.id]) {
is VerificationState.Verifying -> verif
is VerificationState.Verified -> verif
is VerificationState.NetworkError -> {
// try again in 5 mins
if (verif.time < TimeUtils.fiveMinutesAgo()) {
event.verifyState(resolverBuilder()).also { cache.put(event.id, it) }
} else {
verif
verify(event, resolverBuilder)
}
}
is VerificationState.Error -> verif
else -> event.verifyState(resolverBuilder()).also { cache.put(event.id, it) }
else -> {
verify(event, resolverBuilder)
}
}
}
@@ -28,6 +28,8 @@ fun findHashtags(
content: String,
output: MutableSet<String> = mutableSetOf(),
): List<String> {
if (content.isBlank()) return emptyList()
val matcher = hashtagSearch.matcher(content)
while (matcher.find()) {
try {
@@ -26,8 +26,6 @@ import com.vitorpamplona.quartz.nip01Core.signers.eventTemplate
import com.vitorpamplona.quartz.nip01Core.tags.dTags.dTag
import com.vitorpamplona.quartz.nip01Core.tags.kinds.kind
import com.vitorpamplona.quartz.nip31Alts.alt
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent.Companion.ALT_DESCRIPTION
import com.vitorpamplona.quartz.nip37Drafts.DraftEvent.Companion.KIND
import com.vitorpamplona.quartz.utils.TimeUtils
class DraftBuilder {
@@ -41,8 +39,8 @@ class DraftBuilder {
) {
signer.nip44Encrypt(draft.toJson(), signer.pubKey) { encryptedContent ->
val template =
eventTemplate<DraftEvent>(KIND, encryptedContent, createdAt) {
alt(ALT_DESCRIPTION)
eventTemplate<DraftEvent>(DraftEvent.KIND, encryptedContent, createdAt) {
alt(DraftEvent.ALT_DESCRIPTION)
dTag(dTag)
kind(draft.kind)