feat: add update profile screen #14

Merged
reya merged 3 commits from feat/update-profile-screen into master 2026-06-06 05:50:33 +00:00
3 changed files with 88 additions and 26 deletions
Showing only changes of commit 6c923a1b68 - Show all commits

View File

@@ -32,7 +32,7 @@ fun UpdateProfileScreen() {
onBack = { navigator.goBack() }, onBack = { navigator.goBack() },
onConfirm = { name, bio, bytes, type -> onConfirm = { name, bio, bytes, type ->
scope.launch { scope.launch {
//viewModel.updateProfile(name, bio, bytes, type) viewModel.updateProfile(name, bio, bytes, type)
navigator.goBack() navigator.goBack()
} }
} }

View File

@@ -498,6 +498,45 @@ class Nostr {
setSigner(keys) setSigner(keys)
} }
suspend fun updateProfile(
name: String? = null,
bio: String? = null,
picture: String? = null
) {
val currentUser = signer.currentUser ?: throw IllegalStateException("User not signed in")
try {
val record = getLatestMetadata(currentUser)?.asRecord() ?: MetadataRecord()
val newRecord = record.copy(
displayName = name ?: record.displayName,
about = bio ?: record.about,
picture = picture ?: record.picture
)
val event = EventBuilder.metadata(Metadata.fromRecord(newRecord)).signAsync(signer)
client?.sendEvent(
event = event,
target = SendEventTarget.broadcast(),
ackPolicy = AckPolicy.none()
)
} catch (e: Exception) {
throw IllegalStateException("Failed to update identity: ${e.message}", e)
}
}
private suspend fun getLatestMetadata(pubkey: PublicKey): Metadata? {
return try {
val kind = Kind.fromStd(KindStandard.METADATA);
val filter = Filter().kind(kind).author(pubkey).limit(1u)
val event = client?.database()?.query(filter)?.first() ?: return null
Metadata.fromJson(event.content())
} catch (e: Exception) {
println("Failed to get latest metadata: ${e.message}")
null
}
}
suspend fun getAllCacheMetadata(): Map<PublicKey, Metadata> { suspend fun getAllCacheMetadata(): Map<PublicKey, Metadata> {
try { try {
val filter = Filter().kind(Kind.fromStd(KindStandard.METADATA)).limit(100u) val filter = Filter().kind(Kind.fromStd(KindStandard.METADATA)).limit(100u)

View File

@@ -344,20 +344,11 @@ class NostrViewModel(
} }
} }
suspend fun createIdentity( private suspend fun blossomUpload(file: ByteArray, contentType: String): String? {
name: String,
bio: String?,
picture: ByteArray?,
contentType: String? = null
) {
_isLoggedIn.value = true
try { try {
val keys = Keys.generate() var avatarUrl: String? = null
val secret = keys.secretKey().toBech32()
var avatarUrl = ""
// Upload picture to Blossom // Upload picture to Blossom
if (picture != null) {
val blossom = BlossomClient( val blossom = BlossomClient(
url = "https://blossom.band", url = "https://blossom.band",
client = HttpClient { client = HttpClient {
@@ -372,13 +363,45 @@ class NostrViewModel(
) )
val descriptor = blossom.upload( val descriptor = blossom.upload(
file = picture, file = file,
contentType = contentType, contentType = contentType,
signer = keys signer = nostr.signer
) )
avatarUrl = descriptor?.url ?: "" avatarUrl = descriptor?.url
return avatarUrl
} catch (e: Exception) {
showError("Error: ${e.message}")
return null
} }
}
suspend fun updateProfile(
name: String? = null,
bio: String? = null,
picture: ByteArray? = null,
contentType: String? = null
) {
try {
val avatarUrl = picture?.let { blossomUpload(it, contentType ?: "image/jpeg") }
nostr.updateProfile(name, bio, avatarUrl)
} catch (e: Exception) {
showError("Error: ${e.message}")
}
}
suspend fun createIdentity(
name: String,
bio: String?,
picture: ByteArray?,
contentType: String? = null
) {
_isLoggedIn.value = true
try {
val keys = Keys.generate()
val secret = keys.secretKey().toBech32()
val avatarUrl = picture?.let { blossomUpload(it, contentType ?: "image/jpeg") }
// Create identity // Create identity
nostr.createIdentity(keys = keys, name = name, bio, picture = avatarUrl) nostr.createIdentity(keys = keys, name = name, bio, picture = avatarUrl)