From a48c0c0e7cb4d5ca2fa043bdd37278b3e5a1a6ce Mon Sep 17 00:00:00 2001 From: Ren Amamiya Date: Mon, 6 Jul 2026 09:26:45 +0700 Subject: [PATCH] update --- .../su/reya/coop/screens/NewIdentityScreen.kt | 6 ---- .../su/reya/coop/shared/ProfileEditor.kt | 20 +++++++---- .../su/reya/coop/viewmodel/AuthViewModel.kt | 35 ++++++------------- 3 files changed, 23 insertions(+), 38 deletions(-) diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/NewIdentityScreen.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/NewIdentityScreen.kt index 758d75d..80a3393 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/NewIdentityScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/NewIdentityScreen.kt @@ -1,9 +1,7 @@ package su.reya.coop.screens import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope -import androidx.lifecycle.compose.collectAsStateWithLifecycle import kotlinx.coroutines.launch import su.reya.coop.LocalAuthViewModel import su.reya.coop.LocalNavigator @@ -16,13 +14,9 @@ fun NewIdentityScreen() { val navigator = LocalNavigator.current val scope = rememberCoroutineScope() - val authState by authViewModel.state.collectAsStateWithLifecycle() - val isBusy = authState.isBusy - ProfileEditor( title = "Create a new identity", buttonLabel = "Continue", - isBusy = isBusy, onBack = { navigator.goBack() }, onConfirm = { name, bio, bytes, type -> scope.launch { diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/shared/ProfileEditor.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/shared/ProfileEditor.kt index 9aab16a..e975f85 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/shared/ProfileEditor.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/shared/ProfileEditor.kt @@ -68,7 +68,6 @@ fun ProfileEditor( initialName: String = "", initialBio: String = "", initialPicture: Any? = null, // Accepts Uri (picked) or String (current URL) - isBusy: Boolean = false, onBack: () -> Unit, onConfirm: (name: String, bio: String, pictureBytes: ByteArray?, contentType: String?) -> Unit ) { @@ -80,6 +79,7 @@ fun ProfileEditor( var name by remember(initialName) { mutableStateOf(initialName) } var bio by remember(initialBio) { mutableStateOf(initialBio) } var picture by remember(initialPicture) { mutableStateOf(initialPicture) } + var isBusy by remember { mutableStateOf(false) } val hasPicture = remember(picture) { when (picture) { @@ -267,14 +267,20 @@ fun ProfileEditor( .size(ButtonDefaults.MediumContainerHeight), onClick = { scope.launch { - val bytes = withContext(Dispatchers.IO) { - (picture as? Uri)?.let { - context.contentResolver.openInputStream(it)?.readBytes() + isBusy = true + try { + val bytes = withContext(Dispatchers.IO) { + (picture as? Uri)?.let { + context.contentResolver.openInputStream(it)?.readBytes() + } } + val type = + (picture as? Uri)?.let { context.contentResolver.getType(it) } + onConfirm(name, bio, bytes, type) + } catch (e: Exception) { + snackbarHostState.showSnackbar(e.message ?: "Error") } - val type = - (picture as? Uri)?.let { context.contentResolver.getType(it) } - onConfirm(name, bio, bytes, type) + isBusy = false } }, enabled = name.isNotBlank() && !isBusy diff --git a/shared/src/commonMain/kotlin/su/reya/coop/viewmodel/AuthViewModel.kt b/shared/src/commonMain/kotlin/su/reya/coop/viewmodel/AuthViewModel.kt index c92febd..56fbbf2 100644 --- a/shared/src/commonMain/kotlin/su/reya/coop/viewmodel/AuthViewModel.kt +++ b/shared/src/commonMain/kotlin/su/reya/coop/viewmodel/AuthViewModel.kt @@ -21,7 +21,6 @@ import su.reya.coop.storage.SecretStorage import kotlin.time.Duration.Companion.seconds data class AuthState( - val isBusy: Boolean = false, val signerRequired: Boolean? = null, val isNotificationBannerDismissed: Boolean = false, ) @@ -88,8 +87,6 @@ class AuthViewModel( fun logout(onLogout: () -> Unit = {}) { viewModelScope.launch { try { - _state.update { it.copy(isBusy = true) } - // Reset the nostr signer and prune the database nostr.signer.switch(Keys.generate()) nostr.prune() @@ -99,11 +96,10 @@ class AuthViewModel( // Clear credentials from persistent storage secretStore.clear(KEY_USER_SIGNER) secretStore.clear(KEY_BANNER_DISMISSED) - // Call cleanup callback (e.g. to reset other ViewModels) onLogout() - - _state.update { it.copy(isBusy = false, signerRequired = true) } + // Reset local states + _state.update { it.copy(signerRequired = true) } } } } @@ -207,27 +203,16 @@ class AuthViewModel( picture: ByteArray?, contentType: String? = null ) { - _state.update { it.copy(isBusy = true) } - val keys = Keys.generate() val secret = keys.secretKey().toBech32() - - try { - val avatarUrl = picture?.let { - mediaRepository.blossomUpload(nostr.signer.get(), it, contentType ?: "image/jpeg") - } - - // Create identity - nostr.profiles.createIdentity(keys = keys, name = name, bio = bio, picture = avatarUrl) - - // Persist the secret in the secret storage - secretStore.set(KEY_USER_SIGNER, secret) - - // Update local states - _state.update { it.copy(isBusy = false, signerRequired = false) } - } catch (e: Exception) { - showError("Error: ${e.message}") - _state.update { it.copy(isBusy = false) } + val avatarUrl = picture?.let { + mediaRepository.blossomUpload(nostr.signer.get(), it, contentType ?: "image/jpeg") } + // Create identity + nostr.profiles.createIdentity(keys = keys, name = name, bio = bio, picture = avatarUrl) + // Persist the secret in the secret storage + secretStore.set(KEY_USER_SIGNER, secret) + // Update local states + _state.update { it.copy(signerRequired = false) } } }