From 3f889fa02b3927f99ba95cb45c7255c612f3563e Mon Sep 17 00:00:00 2001 From: Kgothatso Ngako Date: Sun, 29 Mar 2026 23:17:12 +0200 Subject: [PATCH] Queue synchronization of local profile --- .../ac/aux/compose/database/dao/NostrDao.kt | 9 -- .../dao/SynchronizeNostrEventRequestDao.kt | 3 + .../model/intermdiate/LocalProfile.kt | 12 ++- .../repository/DatabaseNostrRepository.kt | 28 +++++- .../aux/compose/repository/NostrRepository.kt | 10 +- .../UnqueuedProfileSynchronizationScreen.kt | 97 +++++++++++++++++++ .../ui/composable/navigation/AuxNavHost.kt | 18 +++- .../UnqueuedProfileSynchronizationRoute.kt | 9 ++ .../ui/view/model/CreateProfileViewModel.kt | 27 ++---- .../ui/view/model/NavigationViewModel.kt | 27 ++++-- .../ui/view/model/SignInToProfileViewModel.kt | 9 +- ...UnqueuedProfileSynchronizationViewModel.kt | 65 +++++++++++++ .../ui/view/state/NavigationUIState.kt | 5 +- 13 files changed, 269 insertions(+), 50 deletions(-) create mode 100644 composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/UnqueuedProfileSynchronizationScreen.kt create mode 100755 composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/navigation/routes/UnqueuedProfileSynchronizationRoute.kt create mode 100644 composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/UnqueuedProfileSynchronizationViewModel.kt diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/database/dao/NostrDao.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/database/dao/NostrDao.kt index c9210521..a1257545 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/database/dao/NostrDao.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/database/dao/NostrDao.kt @@ -80,7 +80,6 @@ abstract class NostrDao( @Transaction open suspend fun storeNostrEvent( nostrEvent: NostrEvent, - synchronizeNostrEventRequest: SynchronizeNostrEventRequest, synchronizationRelayURLs: List ) { logger.i("Store Nostr Event: $nostrEvent") @@ -121,14 +120,6 @@ abstract class NostrDao( nostrEvent = nostrEvent, synchronizationRelayURLs = synchronizationRelayURLs ) - - // Save synchronizationResult - database.synchronizeNostrEventResultDao().upsert( - SynchronizeNostrEventResult( - nostrEventId = nostrEvent.id, - relayURL = synchronizeNostrEventRequest.relayURL - ) - ) } private suspend fun indexNostrEvent( diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/database/dao/SynchronizeNostrEventRequestDao.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/database/dao/SynchronizeNostrEventRequestDao.kt index c10d2049..f8f5ca83 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/database/dao/SynchronizeNostrEventRequestDao.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/database/dao/SynchronizeNostrEventRequestDao.kt @@ -13,4 +13,7 @@ interface SynchronizeNostrEventRequestDao { @Upsert fun upsert(synchronizeNostrEventRequest: SynchronizeNostrEventRequest) + + @Upsert + fun insert(synchronizeNostrEventRequests: List) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/database/model/intermdiate/LocalProfile.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/database/model/intermdiate/LocalProfile.kt index a316a987..e8384317 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/database/model/intermdiate/LocalProfile.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/database/model/intermdiate/LocalProfile.kt @@ -4,6 +4,7 @@ import ac.aux.compose.database.model.BroadcastNostrEventReceipt import ac.aux.compose.database.model.BroadcastNostrEventRequest import ac.aux.compose.database.model.NostrEvent import ac.aux.compose.database.model.Profile +import ac.aux.compose.database.model.SynchronizeNostrEventRequest import ac.aux.compose.database.model.UnsignedNostrEvent import androidx.room.Embedded import androidx.room.Relation @@ -33,5 +34,12 @@ data class LocalProfile( parentColumn = "id", entityColumn = "unsignedNostrEventId" ) - val broadcastNostrEventReceipt: BroadcastNostrEventReceipt? -) + val broadcastNostrEventReceipt: BroadcastNostrEventReceipt?, + + @Relation( + parentColumn = "id", + entityColumn = "unsignedNostrEventId" + ) + val synchronizeNostrEventRequests: List, + + ) diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/database/repository/DatabaseNostrRepository.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/database/repository/DatabaseNostrRepository.kt index 1beb1d3c..0416ee75 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/database/repository/DatabaseNostrRepository.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/database/repository/DatabaseNostrRepository.kt @@ -49,7 +49,8 @@ class DatabaseNostrRepository( name: String?, biography: String?, onError: () -> Unit, - onProfileReady: (Profile) -> Unit + onProfileReady: (Profile) -> Unit, + synchronizationRelayURLs: List ) { val profileEventTemplate = MetadataEvent.createNew( name = name, @@ -82,6 +83,15 @@ class DatabaseNostrRepository( if (unsignedNostrEvent.signedAt != null) { // Submit a SyncNostrEventRequest + synchronizationRelayURLs.forEach { relayUrl -> + database.synchronizeNostrEventRequestDao().upsert( + SynchronizeNostrEventRequest( + authorPublicKeys = unsignedNostrEvent.pubKey, + status = "pending", + relayURL = relayUrl + ) + ) + } } } } @@ -171,11 +181,27 @@ class DatabaseNostrRepository( synchronizeNostrEventRequest: SynchronizeNostrEventRequest, synchronizationRelayURLs: List ) { + database.nostrDao().storeNostrEvent( nostrEvent, synchronizeNostrEventRequest, synchronizationRelayURLs = synchronizationRelayURLs ) + + database.synchronizeNostrEventRequestDao().upsert( + synchronizeNostrEventRequest.copy( + nostrEventId = nostrEvent.id + ) + ) + } + + override suspend fun queueSynchronizeNostrEvent( + synchronizeNostrEventRequests: List, + ) { + // Save synchronizationResult + database.synchronizeNostrEventRequestDao().insert( + synchronizeNostrEventRequests + ) } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/repository/NostrRepository.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/repository/NostrRepository.kt index 71f5a51d..3bcf3ea2 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/repository/NostrRepository.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/repository/NostrRepository.kt @@ -27,7 +27,8 @@ interface NostrRepository { onError: () -> Unit, // onUnsignProfile: (UnsignedNostrEvent) -> Unit, // onUnbroadcastedProfile: (NostrEvent) -> Unit, - onProfileReady: (Profile) -> Unit + onProfileReady: (Profile) -> Unit, + synchronizationRelayURLs: List ) suspend fun createNewTextNote( @@ -59,6 +60,10 @@ interface NostrRepository { synchronizationRelayURLs: List ) + suspend fun queueSynchronizeNostrEvent( + synchronizeNostrEventRequests: List, + ) + companion object { val NO_OP_NOSTR_REPOSITORY = object : NostrRepository { override suspend fun observeProfile(publicKey: HexKey): Flow { @@ -82,7 +87,8 @@ interface NostrRepository { name: String?, biography: String?, onError: () -> Unit, - onProfileReady: (Profile) -> Unit + onProfileReady: (Profile) -> Unit, + synchronizationRelayURLs: List ) { } diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/UnqueuedProfileSynchronizationScreen.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/UnqueuedProfileSynchronizationScreen.kt new file mode 100644 index 00000000..7085c1d3 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/UnqueuedProfileSynchronizationScreen.kt @@ -0,0 +1,97 @@ +package ac.aux.compose.ui.composable + +import ac.aux.compose.repository.NostrRepository +import ac.aux.compose.ui.composable.widgets.LoadingDataIndicator +import ac.aux.compose.ui.theme.AuxTheme +import ac.aux.compose.ui.view.model.UnqueuedProfileSynchronizationViewModel +import ac.aux.compose.ui.view.model.WriteNewNoteViewModel +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel + +@OptIn(ExperimentalMaterial3ExpressiveApi::class) +@Composable +fun UnqueuedProfileSynchronizationScreen( + profilePublicKey: String, + nostrRepository: NostrRepository +) { + val unqueuedProfileSynchronizationViewModel: UnqueuedProfileSynchronizationViewModel = viewModel( + factory = UnqueuedProfileSynchronizationViewModel.factory( + profilePublicKey = profilePublicKey, + nostrRepository = nostrRepository + ) + ) + + Scaffold { innerPadding -> + Column( + modifier = Modifier.padding(innerPadding) + ) { + + Column( + modifier = Modifier.fillMaxWidth().padding( + 10.dp + ), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(20.dp) + ) { + + Spacer( + modifier = Modifier.weight(1f) + ) + Text( + text = "We are searching the internet to find your profile and complete sign in.", + style = MaterialTheme.typography.bodyLarge, + textAlign = TextAlign.Center + ) + + Text( + text = "We are looking for your profile on as many relays as possible. Nostr aims to be decentralized by distributing data to multiple nodse.", + style = MaterialTheme.typography.bodySmall, + textAlign = TextAlign.Center + ) + + LoadingDataIndicator( + fillScreen = false + ) + + Spacer( + modifier = Modifier.weight(2f) + ) + } + } + } + + LaunchedEffect(true) { + unqueuedProfileSynchronizationViewModel.queueSynchronization() + } +} + +@Preview +@Composable +private fun UnqueuedProfileSynchronizationScreenPreview() { + AuxTheme { + Surface( + modifier = Modifier.fillMaxSize() + ) { + UnqueuedProfileSynchronizationScreen( + profilePublicKey = "npub is for living." + ) + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/navigation/AuxNavHost.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/navigation/AuxNavHost.kt index 772cb813..844d25c0 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/navigation/AuxNavHost.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/navigation/AuxNavHost.kt @@ -32,6 +32,7 @@ import ac.aux.compose.ui.composable.navigation.routes.SocialPreconditionRoute import ac.aux.compose.ui.composable.navigation.routes.UnannouncedProfileRoute import ac.aux.compose.ui.composable.navigation.routes.UnindexedProfileRoute import ac.aux.compose.ui.composable.navigation.routes.UnqueuedProfileRoute +import ac.aux.compose.ui.composable.navigation.routes.UnqueuedProfileSynchronizationRoute import ac.aux.compose.ui.composable.navigation.routes.UnsignedProfileRoute import ac.aux.compose.ui.composable.navigation.routes.UnsyncedProfileRoute import ac.aux.compose.ui.composable.navigation.routes.WriteNewNoteRoute @@ -42,7 +43,6 @@ import ac.aux.compose.ui.view.state.NavigationUIState import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Surface import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.lifecycle.compose.LocalLifecycleOwner @@ -53,7 +53,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.IO import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch @Composable @@ -129,6 +128,15 @@ fun AuxNavHost( popUpTo(0) } } + is NavigationUIState.UnqueuedProfileSynchronization -> { + navController.navigate( + route = UnqueuedProfileSynchronizationRoute( + state.unsignedNostrEvent.pubKey + ) + ) { + popUpTo(0) + } + } is NavigationUIState.UnindexedProfile -> { navController.navigate( route = UnindexedProfileRoute( @@ -243,6 +251,12 @@ fun AuxNavHost( unsyncedProfilePublicKey = route.publicKey ) } + composable { backStackEntry -> + val route = backStackEntry.toRoute() + UnqueuedProfileSynchronizationRoute( + publicKey = route.publicKey + ) + } composable { UnindexedProfileScreen() } diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/navigation/routes/UnqueuedProfileSynchronizationRoute.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/navigation/routes/UnqueuedProfileSynchronizationRoute.kt new file mode 100755 index 00000000..fa10946f --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/navigation/routes/UnqueuedProfileSynchronizationRoute.kt @@ -0,0 +1,9 @@ +package ac.aux.compose.ui.composable.navigation.routes + +import kotlinx.serialization.Serializable + +@Serializable +data class UnqueuedProfileSynchronizationRoute( + val publicKey: String, +): Route() { +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/CreateProfileViewModel.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/CreateProfileViewModel.kt index 29bf1785..ee2e5234 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/CreateProfileViewModel.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/CreateProfileViewModel.kt @@ -1,6 +1,7 @@ package ac.aux.compose.ui.view.model import ac.aux.compose.managers.SeedManager +import ac.aux.compose.nostr.Relays import ac.aux.compose.repository.NostrRepository import ac.aux.compose.ui.view.state.CreateProfileUIState import androidx.compose.runtime.MutableState @@ -80,25 +81,13 @@ class CreateProfileViewModel( onError = { createProfileUIState.value = CreateProfileUIState.Error }, -// onUnsignProfile = { unsignedNostrEvent -> -// onNavigateToUnsignedProfile.invoke( -// UnsignedProfileRoute( -// unsignedNostrEvent.id -// ) -// ) -// }, -// onUnbroadcastedProfile = { unannouncedNostrEvent -> -// onNavigateToUnannouncedProfile.invoke( -// UnannouncedProfileRoute( -// nostrEventId = unannouncedNostrEvent.id -// ) -// ) -// } - ) { profile -> - createProfileUIState.value = CreateProfileUIState.ProfileReady( - profile = profile - ) - } + { profile -> + createProfileUIState.value = CreateProfileUIState.ProfileReady( + profile = profile + ) + }, + synchronizationRelayURLs = Relays.eventPublishRelaySet.map { normalizedRelayUrl -> normalizedRelayUrl.url } + ) } } diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/NavigationViewModel.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/NavigationViewModel.kt index 73418b31..7a08aa19 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/NavigationViewModel.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/NavigationViewModel.kt @@ -193,16 +193,18 @@ class NavigationViewModel( jsonText ) + val nostrEvent = NostrEvent( + id = event.id, + pubKey = event.pubKey, + kind = event.kind, + content = event.content, + tags = event.tags, + createdAt = Instant.fromEpochMilliseconds(event.createdAt), + sig = event.sig + ) + nostrRepository.saveNostrEvent( - nostrEvent = NostrEvent( - id = event.id, - pubKey = event.pubKey, - kind = event.kind, - content = event.content, - tags = event.tags, - createdAt = Instant.fromEpochMilliseconds(event.createdAt), - sig = event.sig - ), + nostrEvent = nostrEvent, synchronizeNostrEventRequest, synchronizationRelayURLs = Relays.eventPublishRelaySet.map { normalizedRelayUrl -> normalizedRelayUrl.url } ) @@ -315,7 +317,12 @@ class NavigationViewModel( NavigationUIState.UnindexedProfile( nostrEvent = localProfile.nostrEvent ) - } else if (localProfile.unsignedNostrEvent != null && localProfile.unsignedNostrEvent.signedAt != null) { + } else if (localProfile.unsignedNostrEvent.signedAt != null && localProfile.synchronizeNostrEventRequests.isEmpty()) { + logger.i("We should request to sync profile: ${localProfile.unsignedNostrEvent}") + NavigationUIState.UnqueuedProfileSynchronization( + unsignedNostrEvent = localProfile.unsignedNostrEvent + ) + } else if (localProfile.unsignedNostrEvent.signedAt != null) { logger.i("We should be syncing the profile: ${localProfile.unsignedNostrEvent}") NavigationUIState.UnsyncedProfile( unsignedNostrEvent = localProfile.unsignedNostrEvent diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/SignInToProfileViewModel.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/SignInToProfileViewModel.kt index d967984f..659877d4 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/SignInToProfileViewModel.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/SignInToProfileViewModel.kt @@ -1,6 +1,6 @@ package ac.aux.compose.ui.view.model -import ac.aux.compose.managers.SeedManager +import ac.aux.compose.nostr.Relays import ac.aux.compose.repository.NostrRepository import ac.aux.compose.ui.view.state.SignInToProfileUIState import ac.aux.compose.ui.view.state.form.SignInToProfileFormState @@ -12,7 +12,6 @@ import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory import androidx.lifecycle.viewModelScope import co.touchlab.kermit.Logger -import com.vitorpamplona.quartz.nip01Core.core.toHexKey import com.vitorpamplona.quartz.nip19Bech32.Nip19Parser import com.vitorpamplona.quartz.nip19Bech32.entities.Entity import com.vitorpamplona.quartz.nip19Bech32.entities.NPub @@ -78,7 +77,8 @@ class SignInToProfileViewModel( name = null, biography = null, onError = onError, - onProfileReady = {} + onProfileReady = {}, + synchronizationRelayURLs = Relays.eventPublishRelaySet.map { normalizedRelayUrl -> normalizedRelayUrl.url } ) } is NSec -> { @@ -87,7 +87,8 @@ class SignInToProfileViewModel( name = null, biography = null, onError = onError, - onProfileReady = {} + onProfileReady = {}, + synchronizationRelayURLs = Relays.eventPublishRelaySet.map { normalizedRelayUrl -> normalizedRelayUrl.url } ) } else -> { diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/UnqueuedProfileSynchronizationViewModel.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/UnqueuedProfileSynchronizationViewModel.kt new file mode 100644 index 00000000..69bd6ddd --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/model/UnqueuedProfileSynchronizationViewModel.kt @@ -0,0 +1,65 @@ +package ac.aux.compose.ui.view.model + +import ac.aux.compose.database.model.SynchronizeNostrEventRequest +import ac.aux.compose.nostr.Relays +import ac.aux.compose.repository.NostrRepository +import ac.aux.compose.ui.view.state.SignInToProfileUIState +import ac.aux.compose.ui.view.state.form.SignInToProfileFormState +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewmodel.initializer +import androidx.lifecycle.viewmodel.viewModelFactory +import androidx.lifecycle.viewModelScope +import co.touchlab.kermit.Logger +import com.vitorpamplona.quartz.nip19Bech32.Nip19Parser +import com.vitorpamplona.quartz.nip19Bech32.entities.Entity +import com.vitorpamplona.quartz.nip19Bech32.entities.NPub +import com.vitorpamplona.quartz.nip19Bech32.entities.NSec +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO +import kotlinx.coroutines.launch + +class UnqueuedProfileSynchronizationViewModel( + val profilePublicKey: String, + val nostrRepository: NostrRepository +): ViewModel() { + companion object { + private const val TAG = "UnqueuedProfileSynchronizationViewModel" + + fun factory( + profilePublicKey: String, + nostrRepository: NostrRepository + ): ViewModelProvider.Factory = viewModelFactory { + initializer { + UnqueuedProfileSynchronizationViewModel( + profilePublicKey = profilePublicKey, + nostrRepository = nostrRepository + ) + } + } + } + + private val logger = Logger.withTag(TAG) + + val isActionPending: MutableState = mutableStateOf(false) + + fun queueSynchronization() { + logger.d { "queueSynchronization" } + viewModelScope.launch(Dispatchers.IO) { + + nostrRepository.queueSynchronizeNostrEvent( + Relays.eventPublishRelaySet.map { normalizedRelayUrl -> + SynchronizeNostrEventRequest( + authorPublicKeys = profilePublicKey, + kinds = "0", + relayURL = normalizedRelayUrl.url + ) + } + + ) + } + + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/state/NavigationUIState.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/state/NavigationUIState.kt index e333c35a..7076ea1c 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/state/NavigationUIState.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/view/state/NavigationUIState.kt @@ -5,7 +5,6 @@ import ac.aux.compose.database.model.BroadcastNostrEventRequest import ac.aux.compose.database.model.NostrEvent import ac.aux.compose.database.model.Profile import ac.aux.compose.database.model.UnsignedNostrEvent -import ac.aux.compose.database.model.intermdiate.LocalProfile abstract class NavigationUIState { data object Error: NavigationUIState() @@ -22,6 +21,10 @@ abstract class NavigationUIState { val unsignedNostrEvent: UnsignedNostrEvent, ) : NavigationUIState() + data class UnqueuedProfileSynchronization( + val unsignedNostrEvent: UnsignedNostrEvent, + ) : NavigationUIState() + data class UnindexedProfile( val nostrEvent: NostrEvent, ) : NavigationUIState()