Create a profile
This commit is contained in:
1 parent
3d045fbf8d
commit
f73a46ae5c
12 files changed
+343
-136
No files matched your search
+9
-31
@@ -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
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-53
@@ -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(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+114
@@ -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 = ""
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+117
@@ -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(),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
-12
@@ -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 = {
|
||||||
|
|||||||
+22
@@ -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 = ""
|
||||||
|
)
|
||||||
|
}
|
||||||
+20
@@ -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 = ""
|
||||||
|
)
|
||||||
|
}
|
||||||
+18
-13
@@ -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
|
||||||
|
|||||||
+9
-11
@@ -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()
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user