Create a profile

This commit is contained in:
Kgothatso Ngako committed 2026-03-26 03:46:44 +02:00
1 parent 3d045fbf8d
commit f73a46ae5c
12 files changed
+343 -136

No files matched your search

@@ -1,11 +1,11 @@
package ac.aux.compose.database.repository package ac.aux.compose.database.repository
import ac.aux.compose.database.AuxDatabase import ac.aux.compose.database.AuxDatabase
import ac.aux.compose.database.model.NostrEvent
import ac.aux.compose.database.model.Profile import ac.aux.compose.database.model.Profile
import ac.aux.compose.database.model.UnsignedNostrEvent import ac.aux.compose.database.model.UnsignedNostrEvent
import ac.aux.compose.database.model.intermdiate.LocalProfile import ac.aux.compose.database.model.intermdiate.LocalProfile
import ac.aux.compose.repository.NostrRepository import ac.aux.compose.repository.NostrRepository
import co.touchlab.kermit.Logger
import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.HexKey
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@@ -15,6 +15,12 @@ import kotlin.time.Instant
class DatabaseNostrRepository( class DatabaseNostrRepository(
private val database: AuxDatabase private val database: AuxDatabase
): NostrRepository { ): NostrRepository {
companion object {
const val TAG = "DatabaseNostrRepository"
}
val logger = Logger.withTag(TAG)
override suspend fun observeProfile(publicKey: HexKey): Flow<LocalProfile?> { override suspend fun observeProfile(publicKey: HexKey): Flow<LocalProfile?> {
return database.profileDao().observeProfile(publicKey) return database.profileDao().observeProfile(publicKey)
} }
@@ -24,8 +30,6 @@ class DatabaseNostrRepository(
name: String, name: String,
biography: String, biography: String,
onError: () -> Unit, onError: () -> Unit,
onUnsignProfile: (UnsignedNostrEvent) -> Unit,
onUnbroadcastedProfile: (NostrEvent) -> Unit,
onProfileReady: (Profile) -> Unit onProfileReady: (Profile) -> Unit
) { ) {
val profileEventTemplate = MetadataEvent.createNew( val profileEventTemplate = MetadataEvent.createNew(
@@ -43,34 +47,7 @@ class DatabaseNostrRepository(
) )
) )
if (unsignedNostrEvent != null) { if (unsignedNostrEvent == null) {
onUnsignProfile.invoke(unsignedNostrEvent)
delay(7_500) // Seeming busy is very important...
// TODO: Call and collect kind 0 nostrEvent with pubKey
onUnbroadcastedProfile.invoke(
NostrEvent(
id = "",
pubKey = "",
kind = 0,
content = "Something here",
tags = emptyArray(),
sig = ""
)
)
delay(4_500) // Seeming busy is very important...
onProfileReady.invoke(
Profile(
publicKey = "",
nostrEventId = "",
displayName = name,
about = biography,
)
)
} else {
onError.invoke() onError.invoke()
} }
} }
@@ -81,6 +58,7 @@ class DatabaseNostrRepository(
id = database.unsignedNostrEventDao().upsert(unsignedNostrEvent) id = database.unsignedNostrEventDao().upsert(unsignedNostrEvent)
) )
} catch (e: Throwable) { } catch (e: Throwable) {
logger.e("Failed to saveUnsignedNostrEvent", e)
null null
} }
@@ -1,6 +1,5 @@
package ac.aux.compose.repository package ac.aux.compose.repository
import ac.aux.compose.database.model.NostrEvent
import ac.aux.compose.database.model.Profile import ac.aux.compose.database.model.Profile
import ac.aux.compose.database.model.UnsignedNostrEvent import ac.aux.compose.database.model.UnsignedNostrEvent
import ac.aux.compose.database.model.intermdiate.LocalProfile import ac.aux.compose.database.model.intermdiate.LocalProfile
@@ -15,8 +14,8 @@ interface NostrRepository {
name: String, name: String,
biography: String, biography: String,
onError: () -> Unit, onError: () -> Unit,
onUnsignProfile: (UnsignedNostrEvent) -> Unit, // onUnsignProfile: (UnsignedNostrEvent) -> Unit,
onUnbroadcastedProfile: (NostrEvent) -> Unit, // onUnbroadcastedProfile: (NostrEvent) -> Unit,
onProfileReady: (Profile) -> Unit onProfileReady: (Profile) -> Unit
) )
@@ -35,8 +34,6 @@ interface NostrRepository {
name: String, name: String,
biography: String, biography: String,
onError: () -> Unit, onError: () -> Unit,
onUnsignProfile: (UnsignedNostrEvent) -> Unit,
onUnbroadcastedProfile: (NostrEvent) -> Unit,
onProfileReady: (Profile) -> Unit onProfileReady: (Profile) -> Unit
) { ) {
} }
@@ -1,10 +1,9 @@
package ac.aux.compose.ui.composable package ac.aux.compose.ui.composable
import ac.aux.compose.database.model.NostrEvent
import ac.aux.compose.database.model.Profile import ac.aux.compose.database.model.Profile
import ac.aux.compose.database.model.UnsignedNostrEvent
import ac.aux.compose.repository.NostrRepository import ac.aux.compose.repository.NostrRepository
import ac.aux.compose.ui.composable.widgets.LoadingDataIndicator import ac.aux.compose.ui.composable.navigation.routes.UnannouncedProfileRoute
import ac.aux.compose.ui.composable.navigation.routes.UnsignedProfileRoute
import ac.aux.compose.ui.theme.AuxTheme import ac.aux.compose.ui.theme.AuxTheme
import ac.aux.compose.ui.theme.BluePill import ac.aux.compose.ui.theme.BluePill
import ac.aux.compose.ui.theme.RedPill import ac.aux.compose.ui.theme.RedPill
@@ -297,54 +296,6 @@ fun CreateProfileScreen(
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)
) )
} }
is CreateProfileUIState.UnsignedProfile -> {
Spacer(
modifier = Modifier.weight(1f)
)
Text(
text = "Your profile is almost ready... just getting it's first cryptographic signature together.",
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center
)
Text(
text = "As long as you control your keys there can be no dispute about who ${createAccountUIState.name} actually is.",
style = MaterialTheme.typography.bodySmall,
textAlign = TextAlign.Center
)
LoadingDataIndicator(
fillScreen = false
)
Spacer(
modifier = Modifier.weight(2f)
)
}
is CreateProfileUIState.UnbroadcastedProfile -> {
Spacer(
modifier = Modifier.weight(1f)
)
Text(
text = "Everything is cryptographical sound. Just announcing your profile to the world.",
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center
)
Text(
text = "Aux will be broadcast to what you publish to relays so that it's distributed and decentralized.",
style = MaterialTheme.typography.bodySmall,
textAlign = TextAlign.Center
)
LoadingDataIndicator(
fillScreen = false
)
Spacer(
modifier = Modifier.weight(2f)
)
}
is CreateProfileUIState.ProfileReady -> { is CreateProfileUIState.ProfileReady -> {
Spacer( Spacer(
@@ -400,8 +351,6 @@ fun CreateProfileScreen(
) )
} }
} }
} }
} }
} }
@@ -0,0 +1,114 @@
package ac.aux.compose.ui.composable
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.repository.NostrRepository
import ac.aux.compose.ui.composable.widgets.LoadingDataIndicator
import ac.aux.compose.ui.theme.AuxTheme
import ac.aux.compose.ui.theme.BluePill
import ac.aux.compose.ui.theme.RedPill
import ac.aux.compose.ui.view.model.CreateProfileViewModel
import ac.aux.compose.ui.view.state.CreateProfileUIState
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.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Badge
import androidx.compose.material.icons.filled.Description
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.LoadingIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.KeyboardType
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 UnannouncedProfileScreen(
nostrEvent: NostrEvent,
) {
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 = "Everything is cryptographical sound. Just announcing your profile to the world.",
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center
)
Text(
text = "Aux will be broadcast to what you publish to relays so that it's distributed and decentralized.",
style = MaterialTheme.typography.bodySmall,
textAlign = TextAlign.Center
)
Spacer(
modifier = Modifier.weight(1f)
)
LoadingDataIndicator(
fillScreen = false
)
Spacer(
modifier = Modifier.weight(8f)
)
// TODO: Give user ability to start over...
}
}
}
}
@Preview
@Composable
private fun UnannouncedProfileScreenPreview() {
AuxTheme {
Surface(
modifier = Modifier.fillMaxSize()
) {
UnannouncedProfileScreen(
nostrEvent = NostrEvent(
id = "",
pubKey = "",
kind = 0,
content = "Something here",
tags = emptyArray(),
sig = ""
),
)
}
}
}
@@ -0,0 +1,117 @@
package ac.aux.compose.ui.composable
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.repository.NostrRepository
import ac.aux.compose.ui.composable.navigation.routes.UnannouncedProfileRoute
import ac.aux.compose.ui.composable.widgets.LoadingDataIndicator
import ac.aux.compose.ui.theme.AuxTheme
import ac.aux.compose.ui.theme.BluePill
import ac.aux.compose.ui.theme.RedPill
import ac.aux.compose.ui.view.model.CreateProfileViewModel
import ac.aux.compose.ui.view.state.CreateProfileUIState
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.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Badge
import androidx.compose.material.icons.filled.Description
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.LoadingIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.KeyboardType
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
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun UnsignedProfileScreen(
unsignedNostrEvent: UnsignedNostrEvent
) {
val metadataEvent = MetadataEvent(
id = unsignedNostrEvent.id.toString(),
pubKey = unsignedNostrEvent.pubKey,
createdAt = unsignedNostrEvent.createdAt.toEpochMilliseconds(),
tags = unsignedNostrEvent.tags,
content = unsignedNostrEvent.content,
sig = ""
)
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 = "Your profile is almost ready... just getting it's first cryptographic signature together.",
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center
)
Text(
text = "As long as you control your keys there can be no dispute about who ${metadataEvent.contactMetaData()?.displayName ?: "YOU"} actually is.",
style = MaterialTheme.typography.bodySmall,
textAlign = TextAlign.Center
)
LoadingDataIndicator(
fillScreen = false
)
Spacer(
modifier = Modifier.weight(2f)
)
}
}
}
}
@Preview
@Composable
private fun UnsignedProfileScreenPreview() {
AuxTheme {
Surface(
modifier = Modifier.fillMaxSize()
) {
UnsignedProfileScreen(
unsignedNostrEvent = UnsignedNostrEvent(
pubKey = "",
kind = 0,
content = "Something here",
tags = emptyArray(),
)
)
}
}
}
@@ -1,7 +1,6 @@
package ac.aux.compose.ui.composable.navigation package ac.aux.compose.ui.composable.navigation
import ac.aux.compose.AuxGlobal import ac.aux.compose.AuxGlobal
import ac.aux.compose.database.model.NostrEvent
import ac.aux.compose.database.repository.DatabaseNostrRepository import ac.aux.compose.database.repository.DatabaseNostrRepository
import ac.aux.compose.managers.DatabaseManager import ac.aux.compose.managers.DatabaseManager
import ac.aux.compose.ui.composable.CreateProfileScreen import ac.aux.compose.ui.composable.CreateProfileScreen
@@ -10,6 +9,8 @@ import ac.aux.compose.ui.composable.ImplementationPendingScreen
import ac.aux.compose.ui.composable.LandingScreen import ac.aux.compose.ui.composable.LandingScreen
import ac.aux.compose.ui.composable.LoadingScreen import ac.aux.compose.ui.composable.LoadingScreen
import ac.aux.compose.ui.composable.SocialPreconditionScreen import ac.aux.compose.ui.composable.SocialPreconditionScreen
import ac.aux.compose.ui.composable.UnannouncedProfileScreen
import ac.aux.compose.ui.composable.UnsignedProfileScreen
import ac.aux.compose.ui.composable.navigation.routes.BlankRoute import ac.aux.compose.ui.composable.navigation.routes.BlankRoute
import ac.aux.compose.ui.composable.navigation.routes.CreateProfileRoute import ac.aux.compose.ui.composable.navigation.routes.CreateProfileRoute
import ac.aux.compose.ui.composable.navigation.routes.FeedRoute import ac.aux.compose.ui.composable.navigation.routes.FeedRoute
@@ -21,11 +22,11 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.toRoute import androidx.navigation.toRoute
import ac.aux.compose.ui.composable.navigation.routes.Route
import ac.aux.compose.ui.composable.navigation.routes.SocialPreconditionRoute 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.UnsignedProfileRoute
import ac.aux.compose.ui.composable.widgets.feed.DUMMY_EVENTS import ac.aux.compose.ui.composable.widgets.feed.DUMMY_EVENTS
import ac.aux.compose.ui.view.model.NavigationViewModel import ac.aux.compose.ui.view.model.NavigationViewModel
import ac.aux.compose.ui.view.state.CreateProfileUIState
import ac.aux.compose.ui.view.state.FeedListUIState import ac.aux.compose.ui.view.state.FeedListUIState
import ac.aux.compose.ui.view.state.NavigationUIState import ac.aux.compose.ui.view.state.NavigationUIState
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@@ -82,10 +83,17 @@ fun AuxNavHost(
popUpTo(0) popUpTo(0)
} }
} }
is NavigationUIState.UnbroadcastedProfile -> { is NavigationUIState.UnsignedProfile -> {
navController.navigate( navController.navigate(
route = CreateProfileRoute( route = UnsignedProfileRoute
nostrEventId = state.nostrEvent.id ) {
popUpTo(0)
}
}
is NavigationUIState.UnannouncedProfile -> {
navController.navigate(
route = UnannouncedProfileRoute(
state.nostrEvent.id
) )
) { ) {
popUpTo(0) popUpTo(0)
@@ -93,7 +101,7 @@ fun AuxNavHost(
} }
is NavigationUIState.ProfileLoaded -> { is NavigationUIState.ProfileLoaded -> {
navController.navigate( navController.navigate(
route = FeedRoute route = SocialPreconditionRoute
) { ) {
popUpTo(0) popUpTo(0)
} }
@@ -139,11 +147,6 @@ fun AuxNavHost(
val route = backStackEntry.toRoute<CreateProfileRoute>() val route = backStackEntry.toRoute<CreateProfileRoute>()
CreateProfileScreen( CreateProfileScreen(
initialCreateProfileUIState = route.toPlaceholderNostrEvent()?.let { placeholderNostrEvent ->
CreateProfileUIState.UnbroadcastedProfile(
placeholderNostrEvent
)
} ?: CreateProfileUIState.Declaration,
onNavigateToSocialPreconditionRoute = { onNavigateToSocialPreconditionRoute = {
navController.navigate( navController.navigate(
route = SocialPreconditionRoute route = SocialPreconditionRoute
@@ -159,6 +162,20 @@ fun AuxNavHost(
nostrRepository = nostrRepository nostrRepository = nostrRepository
) )
} }
composable<UnsignedProfileRoute> { backStackEntry ->
val route = backStackEntry.toRoute<UnsignedProfileRoute>()
UnsignedProfileScreen(
unsignedNostrEvent = route.toPlaceholderUnsignedNostrEvent()
)
}
composable<UnannouncedProfileRoute> { backStackEntry ->
val route = backStackEntry.toRoute<UnannouncedProfileRoute>()
UnannouncedProfileScreen(
nostrEvent = route.toPlaceholderNostrEvent()
)
}
composable<SocialPreconditionRoute> { composable<SocialPreconditionRoute> {
SocialPreconditionScreen( SocialPreconditionScreen(
onNavigateToSkipForNow = { onNavigateToSkipForNow = {
@@ -0,0 +1,22 @@
package ac.aux.compose.ui.composable.navigation.routes
import ac.aux.compose.database.model.NostrEvent
import ac.aux.compose.database.model.Profile
import kotlinx.serialization.Serializable
import kotlin.time.Clock
@Serializable
data class UnannouncedProfileRoute(
val nostrEventId: String,
): Route() {
fun toPlaceholderNostrEvent(): NostrEvent = NostrEvent(
id = nostrEventId,
pubKey = "",
createdAt = Clock.System.now(),
tags = emptyArray(),
kind = 0,
sig = "",
content = ""
)
}
@@ -0,0 +1,20 @@
package ac.aux.compose.ui.composable.navigation.routes
import ac.aux.compose.database.model.UnsignedNostrEvent
import kotlinx.serialization.Serializable
import kotlin.time.Clock
@Serializable
data class UnsignedProfileRoute(
val unsignedNostrEventId: Long,
): Route() {
fun toPlaceholderUnsignedNostrEvent(): UnsignedNostrEvent = UnsignedNostrEvent(
id = unsignedNostrEventId,
pubKey = "",
createdAt = Clock.System.now(),
tags = emptyArray(),
kind = 0,
content = ""
)
}
@@ -64,7 +64,10 @@ class CreateProfileViewModel(
return true return true
} }
public fun createAccount() { public fun createAccount(
// onNavigateToUnsignedProfile: (UnsignedProfileRoute) -> Unit,
// onNavigateToUnannouncedProfile: (UnannouncedProfileRoute) -> Unit
) {
logger.d { "createAccount" } logger.d { "createAccount" }
isActionPending.value = true isActionPending.value = true
@@ -77,18 +80,20 @@ class CreateProfileViewModel(
onError = { onError = {
createProfileUIState.value = CreateProfileUIState.Error createProfileUIState.value = CreateProfileUIState.Error
}, },
onUnsignProfile = { unsignedNostrEvent -> // onUnsignProfile = { unsignedNostrEvent ->
createProfileUIState.value = CreateProfileUIState.UnsignedProfile( // onNavigateToUnsignedProfile.invoke(
unsignedNostrEvent = unsignedNostrEvent, // UnsignedProfileRoute(
name = createProfileFormState.nameField.text.value, // unsignedNostrEvent.id
bio = createProfileFormState.biographyField.text.value // )
) // )
}, // },
onUnbroadcastedProfile = { unbroadcastedNostrEvent -> // onUnbroadcastedProfile = { unannouncedNostrEvent ->
createProfileUIState.value = CreateProfileUIState.UnbroadcastedProfile( // onNavigateToUnannouncedProfile.invoke(
nostrEvent = unbroadcastedNostrEvent, // UnannouncedProfileRoute(
) // nostrEventId = unannouncedNostrEvent.id
} // )
// )
// }
) { profile -> ) { profile ->
createProfileUIState.value = CreateProfileUIState.ProfileReady( createProfileUIState.value = CreateProfileUIState.ProfileReady(
profile = profile profile = profile
@@ -10,7 +10,6 @@ import androidx.lifecycle.viewmodel.viewModelFactory
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import co.touchlab.kermit.Logger import co.touchlab.kermit.Logger
import com.vitorpamplona.quartz.nip01Core.core.toHexKey import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
@@ -20,7 +19,6 @@ import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.random.Random
class NavigationViewModel( class NavigationViewModel(
initialNavigationUIState: NavigationUIState, initialNavigationUIState: NavigationUIState,
@@ -72,20 +70,20 @@ class NavigationViewModel(
profile = localProfile.profile profile = localProfile.profile
) )
} else if (localProfile.nostrEvent != null) { } else if (localProfile.nostrEvent != null) {
NavigationUIState.UnbroadcastedProfile( NavigationUIState.UnannouncedProfile(
nostrEvent = localProfile.nostrEvent nostrEvent = localProfile.nostrEvent
) )
// TODO: Support unsignedNostrEvent with pubKey so we can have multi account support...
// } else if (localProfile.nostrEvent != null) {
// NavigationUIState.UnbroadcastedProfile(
// nostrEvent = localProfile.nostrEvent
// )
} else { } else {
NavigationUIState.Error NavigationUIState.UnsignedProfile(
unsignedNostrEvent = localProfile.unsignedNostrEvent
)
} }
} }
}.catch { }.catch { e ->
NavigationUIState.Error logger.e("Error observing profile:", e)
_navigationUIState.getAndUpdate {
NavigationUIState.Error
}
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), NavigationUIState.Landing) }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), NavigationUIState.Landing)
} }
} }
@@ -16,16 +16,6 @@ abstract class CreateProfileUIState {
val bio: String val bio: String
) : CreateProfileUIState() ) : CreateProfileUIState()
data class UnsignedProfile(
val unsignedNostrEvent: UnsignedNostrEvent,
val name: String,
val bio: String,
) : CreateProfileUIState()
data class UnbroadcastedProfile(
val nostrEvent: NostrEvent,
) : CreateProfileUIState()
data class ProfileReady( data class ProfileReady(
val profile: Profile val profile: Profile
) : CreateProfileUIState() ) : CreateProfileUIState()
@@ -15,7 +15,7 @@ abstract class NavigationUIState {
val unsignedNostrEvent: UnsignedNostrEvent, val unsignedNostrEvent: UnsignedNostrEvent,
) : NavigationUIState() ) : NavigationUIState()
data class UnbroadcastedProfile( data class UnannouncedProfile(
val nostrEvent: NostrEvent, val nostrEvent: NostrEvent,
) : NavigationUIState() ) : NavigationUIState()