Add pubKey to UnsignedNostrEvent.kt to support multi account.

This commit is contained in:
Kgothatso Ngako
2026-03-26 03:03:42 +02:00
parent d116e85247
commit 3d045fbf8d
9 changed files with 51 additions and 23 deletions

View File

@@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "80c7032502d17a1893ea8dc67debd365",
"identityHash": "3d48904218bb18d9efb6dba14449f27c",
"entities": [
{
"tableName": "BroadcastNostrEventReceipt",
@@ -836,7 +836,7 @@
},
{
"tableName": "UnsignedNostrEvent",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `kind` INTEGER NOT NULL, `tags` TEXT NOT NULL, `content` TEXT NOT NULL, `signedNostrEventId` TEXT, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `deletedAt` INTEGER, `broadcastedAt` INTEGER, FOREIGN KEY(`signedNostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `pubKey` TEXT NOT NULL, `kind` INTEGER NOT NULL, `tags` TEXT NOT NULL, `content` TEXT NOT NULL, `signedNostrEventId` TEXT, `createdAt` INTEGER NOT NULL, `updatedAt` INTEGER NOT NULL, `savedAt` INTEGER NOT NULL, `deletedAt` INTEGER, `broadcastedAt` INTEGER, FOREIGN KEY(`signedNostrEventId`) REFERENCES `NostrEvent`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "id",
@@ -844,6 +844,12 @@
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "pubKey",
"columnName": "pubKey",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "kind",
"columnName": "kind",
@@ -1095,7 +1101,7 @@
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '80c7032502d17a1893ea8dc67debd365')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3d48904218bb18d9efb6dba14449f27c')"
]
}
}

View File

@@ -30,7 +30,7 @@ interface ProfileDao {
@Upsert
suspend fun upsert(profile: Profile)
@Query("SELECT * FROM NostrEvent WHERE kind = 0 AND pubKey = :publicKey")
@Query("SELECT * FROM UnsignedNostrEvent WHERE kind = 0 AND pubKey = :publicKey")
fun observeProfile(publicKey: String): Flow<LocalProfile?>
}

View File

@@ -39,6 +39,7 @@ data class UnsignedNostrEvent(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
val pubKey: HexKey,
val kind: Kind,
val tags: TagArray,
val content: String,

View File

@@ -2,11 +2,18 @@ package ac.aux.compose.database.model.intermdiate
import ac.aux.compose.database.model.NostrEvent
import ac.aux.compose.database.model.Profile
import ac.aux.compose.database.model.UnsignedNostrEvent
import androidx.room.Embedded
import androidx.room.Relation
data class LocalProfile(
@Embedded val nostrEvent: NostrEvent,
@Embedded val unsignedNostrEvent: UnsignedNostrEvent,
@Relation(
parentColumn = "signedNostrEventId",
entityColumn = "id"
)
val nostrEvent: NostrEvent?,
@Relation(
parentColumn = "pubKey",

View File

@@ -20,6 +20,7 @@ class DatabaseNostrRepository(
}
override suspend fun createNewProfile(
publicKey: HexKey,
name: String,
biography: String,
onError: () -> Unit,
@@ -34,6 +35,7 @@ class DatabaseNostrRepository(
val unsignedNostrEvent = saveUnsignedNostrEvent(
UnsignedNostrEvent(
pubKey = publicKey,
kind = profileEventTemplate.kind,
createdAt = Instant.fromEpochMilliseconds(profileEventTemplate.createdAt),
tags = profileEventTemplate.tags,

View File

@@ -0,0 +1,16 @@
package ac.aux.compose.managers
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
import kotlin.random.Random
object SeedManager {
private val tempDevelopmentKeyPair = KeyPair(
privKey = Random(21_012_256L).nextBytes(32)
)
fun activePublicKey(): ByteArray {
// TODO: Actually set and get a pair...
return tempDevelopmentKeyPair.pubKey
}
}

View File

@@ -1,11 +1,9 @@
package ac.aux.compose.repository
import ac.aux.compose.database.dao.ProfileDao
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
import ac.aux.compose.ui.view.state.CreateProfileUIState
import com.vitorpamplona.quartz.nip01Core.core.HexKey
import kotlinx.coroutines.flow.Flow
@@ -13,6 +11,7 @@ interface NostrRepository {
suspend fun observeProfile(publicKey: HexKey): Flow<LocalProfile?>
suspend fun createNewProfile(
publicKey: HexKey,
name: String,
biography: String,
onError: () -> Unit,
@@ -32,6 +31,7 @@ interface NostrRepository {
}
override suspend fun createNewProfile(
publicKey: HexKey,
name: String,
biography: String,
onError: () -> Unit,

View File

@@ -1,8 +1,6 @@
package ac.aux.compose.ui.view.model
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.managers.SeedManager
import ac.aux.compose.repository.NostrRepository
import ac.aux.compose.ui.view.state.CreateProfileUIState
import androidx.compose.runtime.MutableState
@@ -14,12 +12,10 @@ import androidx.lifecycle.viewmodel.viewModelFactory
import ac.aux.compose.ui.view.state.form.CreateProfileFormState
import androidx.lifecycle.viewModelScope
import co.touchlab.kermit.Logger
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.time.Instant
class CreateProfileViewModel(
val initialCreateProfileUIState: CreateProfileUIState,
@@ -75,6 +71,7 @@ class CreateProfileViewModel(
viewModelScope.launch(Dispatchers.IO) {
nostrRepository.createNewProfile(
SeedManager.activePublicKey().toHexKey(),
name = createProfileFormState.nameField.text.value,
biography = createProfileFormState.biographyField.text.value,
onError = {
@@ -91,13 +88,12 @@ class CreateProfileViewModel(
createProfileUIState.value = CreateProfileUIState.UnbroadcastedProfile(
nostrEvent = unbroadcastedNostrEvent,
)
},
onProfileReady = { profile ->
createProfileUIState.value = CreateProfileUIState.ProfileReady(
profile = profile
)
}
)
) { profile ->
createProfileUIState.value = CreateProfileUIState.ProfileReady(
profile = profile
)
}
}
}

View File

@@ -1,5 +1,6 @@
package ac.aux.compose.ui.view.model
import ac.aux.compose.managers.SeedManager
import ac.aux.compose.repository.NostrRepository
import ac.aux.compose.ui.view.state.NavigationUIState
import androidx.lifecycle.ViewModel
@@ -41,9 +42,6 @@ class NavigationViewModel(
}
}
val tempDevelopmentKeyPair = KeyPair(
privKey = Random(21_000_000L).nextBytes(32)
)
private val _navigationUIState = MutableStateFlow(
initialNavigationUIState
)
@@ -63,7 +61,9 @@ class NavigationViewModel(
_navigationUIState.getAndUpdate {
NavigationUIState.Landing
}
nostrRepository.observeProfile(tempDevelopmentKeyPair.pubKey.toHexKey()).map { localProfile ->
nostrRepository.observeProfile(
publicKey = SeedManager.activePublicKey().toHexKey()
).map { localProfile ->
_navigationUIState.getAndUpdate {
if (localProfile == null) {
NavigationUIState.Landing