diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/WriteNewNoteScreen.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/WriteNewNoteScreen.kt index f7930417..4f08ab33 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/WriteNewNoteScreen.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/WriteNewNoteScreen.kt @@ -1,6 +1,11 @@ package ac.cord.auxiliary.compose.ui.composable +import ac.cord.auxiliary.compose.database.model.NostrEvent +import ac.cord.auxiliary.compose.database.model.Profile +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalProfileWithFollowing import ac.cord.auxiliary.compose.repository.NostrRepository +import ac.cord.auxiliary.compose.ui.composable.widgets.LoadingDataIndicator +import ac.cord.auxiliary.compose.ui.composable.widgets.profile.ProfileAvatar import ac.cord.auxiliary.compose.ui.theme.AuxTheme import ac.cord.auxiliary.compose.ui.view.model.WriteNewNoteViewModel import ac.cord.auxiliary.compose.ui.view.state.WriteNewNoteUIState @@ -24,6 +29,7 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextField import androidx.compose.runtime.Composable +import androidx.compose.runtime.key import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.input.KeyboardType @@ -31,11 +37,12 @@ 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.nip10Notes.TextNoteEvent @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun WriteNewNoteScreen( - initialWriteNewNoteUIState: WriteNewNoteUIState = WriteNewNoteUIState.InputPrompt, + initialWriteNewNoteUIState: WriteNewNoteUIState = WriteNewNoteUIState.Loading, onNostrEventPublished: () -> Unit, nostrRepository: NostrRepository ) { @@ -58,7 +65,10 @@ fun WriteNewNoteScreen( verticalArrangement = Arrangement.spacedBy(20.dp) ) { - when (val writeNewNoteUIState = writeNewNoteViewModel.writeNewNoteUIState.value) { + when (val writeNewNoteUIState = writeNewNoteViewModel.writeNewNoteUIState) { + is WriteNewNoteUIState.Loading -> { + LoadingDataIndicator() + } is WriteNewNoteUIState.InputPrompt -> { Text( "Write new note", @@ -98,24 +108,18 @@ fun WriteNewNoteScreen( ) }, leadingIcon = { - Icon( - Icons.Default.Create, - contentDescription = "Write note" + ProfileAvatar( + profile = writeNewNoteUIState.localProfile.profile, + size = 35.dp ) } ) Button( onClick = { - - writeNewNoteViewModel.validateInput().let { isInputValid -> - if (isInputValid) { - writeNewNoteViewModel.writeNewNoteUIState.value = - WriteNewNoteUIState.ConfirmNote( - text = writeNewNoteViewModel.writeNewNoteFormState.textField.text.value, - ) - } - } + writeNewNoteViewModel.confirmNote( + localProfile = writeNewNoteUIState.localProfile + ) }, ) { Text( @@ -190,6 +194,10 @@ fun WriteNewNoteScreen( } } } + + key(true) { + writeNewNoteViewModel.initiate() + } } @Preview @@ -201,33 +209,28 @@ private fun WriteNewNoteScreenPreview() { ) { WriteNewNoteScreen( initialWriteNewNoteUIState = - WriteNewNoteUIState.InputPrompt, -// CreateProfileUIState.Error, -// CreateProfileUIState.ConfirmInput( -// name = "Alan Turing", -// bio = "Polyglot: Math... is my middle name, computer scientist. cryptographer, and gold hider." -// ), -// CreateProfileUIState.UnsignedProfile( -// unsignedNostrEvent = UnsignedNostrEvent( -// kind = 0, -// content = "Something here", -// tags = emptyArray(), -// ), -// name = "Alan Turing", -// bio = "Polyglot: Math... is my middle name, computer scientist. cryptographer, and gold hider." -// ), -// CreateProfileUIState.UnbroadcastedProfile( -// nostrEvent = NostrEvent( -// id = "", -// pubKey = "", -// kind = 0, -// content = "Something here", -// tags = emptyArray(), -// sig = "" -// ), -// name = "Alan Turing", -// bio = "Polyglot: Math... is my middle name, computer scientist. cryptographer, and gold hider." -// ), + WriteNewNoteUIState.InputPrompt( + localProfile = LocalProfileWithFollowing( + nostrEvent = NostrEvent( + id = "eventId", + pubKey = "publicKey", + content = """Lorem Ipsum is simply dummy text of the printing and typesetting industry. + +Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. + +It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.""".trimIndent(), + tags = emptyArray(), + sig = "", + kind = TextNoteEvent.KIND + ), + profile = Profile( + publicKey = "pubKey", + displayName = "John Doe", + nostrEventId = "nostrEventId" + ), + following = emptyList() + ) + ), onNostrEventPublished = {}, nostrRepository = NostrRepository.NO_OP_NOSTR_REPOSITORY) } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/profile/ProfileAvatar.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/profile/ProfileAvatar.kt index aafb6816..1c643843 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/profile/ProfileAvatar.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/profile/ProfileAvatar.kt @@ -26,6 +26,20 @@ import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage import kotlin.math.abs +@Composable +fun ProfileAvatar( + size: Dp = 55.dp, + shape: Shape = CircleShape, + profile: Profile +) { + ProfileAvatar( + size = size, + shape = shape, + profile = profile, + publicKey = profile.publicKey + ) +} + @Composable fun ProfileAvatar( size: Dp = 55.dp, diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/WriteNewNoteViewModel.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/WriteNewNoteViewModel.kt index d832ad18..2f073030 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/WriteNewNoteViewModel.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/WriteNewNoteViewModel.kt @@ -1,7 +1,10 @@ package ac.cord.auxiliary.compose.ui.view.model +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalProfile +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalProfileWithFollowing import ac.cord.auxiliary.compose.managers.SeedManager import ac.cord.auxiliary.compose.repository.NostrRepository +import ac.cord.auxiliary.compose.ui.view.state.HomeScreenUIState import ac.cord.auxiliary.compose.ui.view.state.WriteNewNoteUIState import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf @@ -10,6 +13,8 @@ import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.initializer import androidx.lifecycle.viewmodel.viewModelFactory import ac.cord.auxiliary.compose.ui.view.state.form.WriteNewNoteFormState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue import androidx.lifecycle.viewModelScope import co.touchlab.kermit.Logger import com.vitorpamplona.quartz.nip01Core.core.toHexKey @@ -42,9 +47,47 @@ class WriteNewNoteViewModel( val isActionPending: MutableState = mutableStateOf(false) - var writeNewNoteUIState: MutableState = mutableStateOf( - initialWriteNewNoteUIState - ) + var writeNewNoteUIState: WriteNewNoteUIState by mutableStateOf(initialWriteNewNoteUIState) + private set + + fun initiate() { + observeActiveUserProfileWithFollowing() + } + + fun observeActiveUserProfileWithFollowing() { + logger.d("observeActiveUserProfileWithFollowing") + viewModelScope.launch(Dispatchers.IO) { + val activePublicKey = SeedManager.activePublicKey().toHexKey() + + // TODO: Get note being replied too... + // TODO: Get note being quoted... + // TODO: Get users being mentioned... + nostrRepository.observeProfileWithFollowing( + activePublicKey + ).collect { profileWithFollowing -> + writeNewNoteUIState = if (profileWithFollowing != null) { + WriteNewNoteUIState.InputPrompt( + localProfile = profileWithFollowing + ) + } else { + WriteNewNoteUIState.Error + } + } + } + } + + fun confirmNote(localProfile: LocalProfileWithFollowing) { + validateInput().let { isInputValid -> + if (isInputValid) { + writeNewNoteUIState = + WriteNewNoteUIState.ConfirmNote( + localProfile = localProfile, + text = writeNewNoteFormState.textField.text.value, + ) + } + } + + } fun validateInput(): Boolean { if (writeNewNoteFormState.textField.text.value.isBlank()) { @@ -63,14 +106,12 @@ class WriteNewNoteViewModel( isActionPending.value = true viewModelScope.launch(Dispatchers.IO) { - - nostrRepository.createNewTextNote( publicKey = SeedManager.activePublicKey().toHexKey(), text = writeNewNoteFormState.textField.text.value, onSuccess = onNostrEventPublished, onError = { - writeNewNoteUIState.value = WriteNewNoteUIState.Error + writeNewNoteUIState = WriteNewNoteUIState.Error } ) } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/state/WriteNewNoteUIState.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/state/WriteNewNoteUIState.kt index 4d92deee..e7f50405 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/state/WriteNewNoteUIState.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/state/WriteNewNoteUIState.kt @@ -1,11 +1,19 @@ package ac.cord.auxiliary.compose.ui.view.state +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalProfile +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalProfileWithFollowing + abstract class WriteNewNoteUIState { + data object Loading: WriteNewNoteUIState() + data object Error: WriteNewNoteUIState() - data object InputPrompt: WriteNewNoteUIState() + data class InputPrompt( + val localProfile: LocalProfileWithFollowing + ): WriteNewNoteUIState() data class ConfirmNote( + val localProfile: LocalProfileWithFollowing, val text: String, ) : WriteNewNoteUIState()