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() },
onConfirm = { name, bio, bytes, type ->
scope.launch {
//viewModel.updateProfile(name, bio, bytes, type)
viewModel.updateProfile(name, bio, bytes, type)
navigator.goBack()
}
}

View File

@@ -498,6 +498,45 @@ class Nostr {
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> {
try {
val filter = Filter().kind(Kind.fromStd(KindStandard.METADATA)).limit(100u)

View File

@@ -344,6 +344,53 @@ class NostrViewModel(
}
}
private suspend fun blossomUpload(file: ByteArray, contentType: String): String? {
try {
var avatarUrl: String? = null
// Upload picture to Blossom
val blossom = BlossomClient(
url = "https://blossom.band",
client = HttpClient {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
prettyPrint = true
isLenient = true
})
}
}
)
val descriptor = blossom.upload(
file = file,
contentType = contentType,
signer = nostr.signer
)
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?,
@@ -354,31 +401,7 @@ class NostrViewModel(
try {
val keys = Keys.generate()
val secret = keys.secretKey().toBech32()
var avatarUrl = ""
// Upload picture to Blossom
if (picture != null) {
val blossom = BlossomClient(
url = "https://blossom.band",
client = HttpClient {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
prettyPrint = true
isLenient = true
})
}
}
)
val descriptor = blossom.upload(
file = picture,
contentType = contentType,
signer = keys
)
avatarUrl = descriptor?.url ?: ""
}
val avatarUrl = picture?.let { blossomUpload(it, contentType ?: "image/jpeg") }
// Create identity
nostr.createIdentity(keys = keys, name = name, bio, picture = avatarUrl)