diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt index 8487d023..b1560f9e 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfilePresenter.kt @@ -1,84 +1,83 @@ package network.bisq.mobile.presentation.ui.uicases.startup import androidx.navigation.NavController +import co.touchlab.kermit.Logger import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.IO -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import kotlinx.coroutines.flow.collectLatest import network.bisq.mobile.domain.data.BackgroundDispatcher import network.bisq.mobile.domain.data.repository.UserProfileRepository -import network.bisq.mobile.domain.data.model.UserProfile import network.bisq.mobile.presentation.BasePresenter -import network.bisq.mobile.presentation.ui.navigation.Routes import network.bisq.mobile.presentation.MainPresenter +import network.bisq.mobile.presentation.ui.navigation.Routes open class CreateProfilePresenter( mainPresenter: MainPresenter, private val navController: NavController, private val userProfileRepository: UserProfileRepository -) : BasePresenter(mainPresenter), ICreateProfilePresenter { +) : BasePresenter(mainPresenter) { - private val _profileName = MutableStateFlow("") - override val profileName: StateFlow = _profileName - override val nym: StateFlow = MutableStateFlow("") - override val id: StateFlow = MutableStateFlow("") + private val log = Logger.withTag("CreateProfilePresenter") + private val userProfileModel = userProfileRepository.model - // TODO: Not working - init { - CoroutineScope(BackgroundDispatcher).launch { - userProfileRepository.data.collectLatest { userProfile -> - userProfile?.let { - _profileName.value = it.name - } - } - } - } + val nickName: StateFlow = userProfileModel.nickName + val nym: StateFlow = userProfileModel.nym + val id: StateFlow = userProfileModel.id - override fun onProfileNameChanged(newName: String) { - _profileName.value = newName - } - override fun navigateToNextScreen() { - if (_profileName.value.isNotEmpty()) { - saveUserProfile() - navController.navigate(Routes.TrustedNodeSetup.name) { - popUpTo(Routes.CreateProfile.name) { inclusive = true } - } - } - } - - override fun onGenerateKeyPair() { + override fun onViewAttached() { + onGenerateKeyPair() + // Currently we just always show the create profile page. + // We need to make the UI behaving to the intended use case. + // 1. After loading screen -> check if there is an existing user profile by + // calling `userProfileRepository.service.hasUserProfile()` + // 1a. If there is an existing user profile, do not show create user profile screen, + // but show user profile is some not yet defined way (right top corner in Desktop shows user profile). + // `userProfileRepository.service.applySelectedUserProfile()` fills the user profile data to + // userProfileRepository.model to be used in the UI. + // 1b. If there is no existing user profile, show create profile screen and call + // `onGenerateKeyPair()` when view is ready. } - override fun onCreateAndPublishNewUserProfile() { - this.navigateToNextScreen() + fun onNickNameChanged(value: String) { + userProfileRepository.model.setNickName(value) } - fun saveUserProfile() { + fun onGenerateKeyPair() { + // takes 200 -1000 ms + // todo start busy animation in UI CoroutineScope(BackgroundDispatcher).launch { - val updatedProfile = UserProfile().apply { - name = _profileName.value + userProfileRepository.model.generateKeyPairInProgress.collect { inProgress -> + if (!inProgress) { + // todo stop busy animation in UI + } } - userProfileRepository.update(updatedProfile) } - } - /* - fun onNicknameChanged(newNickname: String) { - _nickname.value = newNickname + CoroutineScope(BackgroundDispatcher).launch { + userProfileRepository.service.generateKeyPair() + } } - fun navigateToNextScreen() { - if (_nickname.value.isNotEmpty()) { - navController.navigate(Routes.TrustedNodeSetup.name) { - popUpTo(Routes.CreateProfile.name) { inclusive = true } + fun onCreateAndPublishNewUserProfile() { + // todo start busy animation in UI + // We cannot use BackgroundDispatcher here as we get error: + // `Method setCurrentState must be called on the main thread` + CoroutineScope(Dispatchers.Main).launch { + userProfileRepository.model.createAndPublishInProgress.collect { inProgress -> + if (!inProgress) { + // todo stop busy animation in UI + navController.navigate(Routes.TrustedNodeSetup.name) { + popUpTo(Routes.CreateProfile.name) { inclusive = true } + } + } } } - } - */ + CoroutineScope(BackgroundDispatcher).launch { + userProfileRepository.service.createAndPublishNewUserProfile() + } + } } diff --git a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt index 3557aae4..15d7c168 100644 --- a/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt +++ b/bisqapps/shared/presentation/src/commonMain/kotlin/network/bisq/mobile/presentation/ui/uicases/startup/CreateProfileScreen.kt @@ -16,9 +16,7 @@ import androidx.navigation.NavHostController import bisqapps.shared.presentation.generated.resources.Res import bisqapps.shared.presentation.generated.resources.img_bot_image import cafe.adriel.lyricist.LocalStrings -import kotlinx.coroutines.flow.StateFlow import network.bisq.mobile.components.MaterialTextField -import network.bisq.mobile.presentation.ViewPresenter import network.bisq.mobile.presentation.ui.components.atoms.BisqButton import network.bisq.mobile.presentation.ui.components.atoms.BisqText import network.bisq.mobile.presentation.ui.components.atoms.icons.BisqLogo @@ -29,26 +27,15 @@ import org.koin.compose.koinInject import org.koin.core.parameter.parametersOf import org.koin.core.qualifier.named -interface ICreateProfilePresenter: ViewPresenter { - val profileName: StateFlow - val nym: StateFlow - val id: StateFlow - - fun onProfileNameChanged(newName: String) - fun navigateToNextScreen() - fun onGenerateKeyPair() - fun onCreateAndPublishNewUserProfile() -} - @Composable fun CreateProfileScreen( ) { val strings = LocalStrings.current val navController: NavHostController = koinInject(named("RootNavController")) - val presenter: ICreateProfilePresenter = koinInject { parametersOf(navController) } + val presenter: CreateProfilePresenter = koinInject { parametersOf(navController) } - val profileName = presenter.profileName.collectAsState().value + val profileName = presenter.nickName.collectAsState().value LaunchedEffect(Unit) { presenter.onViewAttached() @@ -76,12 +63,12 @@ fun CreateProfileScreen( color = BisqTheme.colors.light2, ) MaterialTextField( - text = presenter.profileName.collectAsState().value, + text = presenter.nickName.collectAsState().value, placeholder = strings.onboarding_createProfile_nickName_prompt, - onValueChanged = { presenter.onProfileNameChanged(it) }) + onValueChanged = { presenter.onNickNameChanged(it) }) } Spacer(modifier = Modifier.height(36.dp)) - Image(painterResource(Res.drawable.img_bot_image), "Crypto geHostnerated image (PoW)") // TODO: Translation + Image(painterResource(Res.drawable.img_bot_image), "User profile icon generated from the hash of the public key") // TODO: Translation Spacer(modifier = Modifier.height(32.dp)) BisqText.baseRegular( text = presenter.nym.collectAsState().value,