From 177417c3db4304fdb13068d1ce477fa359689ff2 Mon Sep 17 00:00:00 2001 From: "michael.thiele" <thiele.michael2@gmail.com> Date: Wed, 6 Sep 2023 14:45:01 +0200 Subject: [PATCH] merge with main --- build.gradle.kts | 1 + buildSrc/src/main/kotlin/Versions.kt | 3 +- trixnity-messenger/build.gradle.kts | 1 + .../initialsync/IosInitialSyncViewModel.kt | 4 +- .../messenger/viewmodel/RootRouter.kt | 20 ++++++ .../messenger/viewmodel/RootViewModel.kt | 11 +++ .../connecting/AddMatrixAccountViewModel.kt | 37 ++++++---- .../connecting/PasswordLoginViewModel.kt | 51 ++++++++------ .../connecting/RegisterNewAccountViewModel.kt | 70 ++++++++++--------- .../viewmodel/connecting/SSOLoginViewModel.kt | 45 +++++++----- .../viewmodel/settings/AppInfoViewModel.kt | 2 - 11 files changed, 156 insertions(+), 89 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 5547acb75..8bb51b50f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,6 +14,7 @@ buildscript { plugins { id("io.kotest.multiplatform") version Versions.kotest apply false id("com.google.devtools.ksp") version Versions.ksp apply false + id("org.jetbrains.dokka") version Versions.dokka } allprojects { diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 779912442..fcefb0a02 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -2,11 +2,12 @@ import org.gradle.api.JavaVersion import org.gradle.jvm.toolchain.JavaLanguageVersion object Versions { - const val trixnityMessenger = "1.0.4" + const val trixnityMessenger = "1.0.5" val kotlinJvmTarget = JavaVersion.VERSION_11 const val trixnity = "3.10.3" // https://gitlab.com/trixnity/trixnity/-/releases const val kotlin = "1.8.22" // https://kotlinlang.org/ + const val dokka = "1.8.20" // https://github.com/Kotlin/dokka/releases const val ksp = "1.8.22-1.0.11" // https://github.com/google/ksp/releases const val kotlinxCoroutines = "1.7.2" // https://github.com/Kotlin/kotlinx.coroutines/releases const val kotlinxSerialization = "1.5.1" // https://github.com/Kotlin/kotlinx.serialization/releases diff --git a/trixnity-messenger/build.gradle.kts b/trixnity-messenger/build.gradle.kts index d1440e295..04c9f7cb6 100644 --- a/trixnity-messenger/build.gradle.kts +++ b/trixnity-messenger/build.gradle.kts @@ -13,6 +13,7 @@ plugins { // kotlin("native.cocoapods") id("com.google.devtools.ksp") `maven-publish` + id("org.jetbrains.dokka") } @OptIn(ExperimentalKotlinGradlePluginApi::class) diff --git a/trixnity-messenger/src/appleMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/initialsync/IosInitialSyncViewModel.kt b/trixnity-messenger/src/appleMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/initialsync/IosInitialSyncViewModel.kt index fd7c24d58..748585e70 100644 --- a/trixnity-messenger/src/appleMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/initialsync/IosInitialSyncViewModel.kt +++ b/trixnity-messenger/src/appleMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/initialsync/IosInitialSyncViewModel.kt @@ -1,11 +1,11 @@ package de.connect2x.trixnity.messenger.viewmodel.initialsync +import de.connect2x.trixnity.messenger.util.StateFlowClass import de.connect2x.trixnity.messenger.viewmodel.ViewModelContext import de.connect2x.trixnity.messenger.viewmodel.matrixClients import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch private val log = KotlinLogging.logger { } @@ -40,7 +40,7 @@ class IosInitialSyncViewModel( job?.cancel() } - override val accountSyncStates: StateFlow<Map<String, AccountSync>> + override val accountSyncStates: StateFlowClass<Map<String, AccountSync>> get() = TODO("Not yet implemented") override fun cancel() { diff --git a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/RootRouter.kt b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/RootRouter.kt index d59c006a8..1af1dba62 100644 --- a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/RootRouter.kt +++ b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/RootRouter.kt @@ -8,6 +8,7 @@ import com.arkivanov.essenty.parcelable.Parcelize import com.benasher44.uuid.uuid4 import de.connect2x.trixnity.messenger.* import de.connect2x.trixnity.messenger.util.* +import de.connect2x.trixnity.messenger.viewmodel.RootRouter.RootWrapper import de.connect2x.trixnity.messenger.viewmodel.connecting.* import io.github.oshai.kotlinlogging.KotlinLogging import korlibs.io.async.launch @@ -16,6 +17,25 @@ import org.koin.dsl.module private val log = KotlinLogging.logger { } +/** + * root with these possible children: + * - [RootWrapper.MatrixClientInitialization] + * - [RootWrapper.MatrixClientLogout] + * - [RootWrapper.AddMatrixAccount] + * - [RootWrapper.PasswordLogin] + * - [RootWrapper.SSOLogin] + * - [RootWrapper.RegisterNewAccount] + * - [RootWrapper.StoreFailure] + * - [RootWrapper.Main] + * + * A typical flow for clients that have no login data locally is: + * show [RootWrapper.AddMatrixAccount] and choose a server. This determines the login methods. When + * [AddMatrixAccountViewModel.selectAddMatrixAccountMethod] is called with a + * [AddMatrixAccountViewModel.ServerDiscoveryState], the router switches to the corresponding child, e.g., + * [RootWrapper.PasswordLogin]. + * + * If the login is successful, the router switches to [RootWrapper.Main] and the messenger is shown. + */ class RootRouter( private val viewModelContext: ViewModelContext, private val matrixClientService: MatrixClientService, diff --git a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/RootViewModel.kt b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/RootViewModel.kt index c25c9b9e5..5c6f22b26 100644 --- a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/RootViewModel.kt +++ b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/RootViewModel.kt @@ -84,4 +84,15 @@ open class RootViewModelImpl( override fun dragFileExit() { router.dragFileExit() } + + // for iOS, since default parameters do not work there + companion object { + fun create( + componentContext: ComponentContext, + matrixClientService: MatrixClientService, + initialSyncOnceIsFinished: (Boolean) -> Unit, + koinApplication: KoinApplication + ): RootViewModel = + RootViewModelImpl(componentContext, matrixClientService, initialSyncOnceIsFinished, koinApplication) + } } \ No newline at end of file diff --git a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/AddMatrixAccountViewModel.kt b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/AddMatrixAccountViewModel.kt index df879501d..2cbc02727 100644 --- a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/AddMatrixAccountViewModel.kt +++ b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/AddMatrixAccountViewModel.kt @@ -1,12 +1,17 @@ package de.connect2x.trixnity.messenger.viewmodel.connecting import de.connect2x.trixnity.messenger.GetAccountNames +import de.connect2x.trixnity.messenger.util.MutableStateFlowClass +import de.connect2x.trixnity.messenger.util.StateFlowClass +import de.connect2x.trixnity.messenger.util.asFlowClass import de.connect2x.trixnity.messenger.viewmodel.ViewModelContext import de.connect2x.trixnity.messenger.viewmodel.connecting.AddMatrixAccountViewModel.ServerDiscoveryState import de.connect2x.trixnity.messenger.viewmodel.i18n import io.github.oshai.kotlinlogging.KotlinLogging import io.ktor.client.* import io.ktor.util.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.* @@ -34,10 +39,10 @@ interface AddMatrixAccountViewModelFactory { } interface AddMatrixAccountViewModel { - val isFirstMatrixClient: StateFlow<Boolean?> + val isFirstMatrixClient: StateFlowClass<Boolean?> - val serverUrl: MutableStateFlow<String> - val serverDiscoveryState: StateFlow<ServerDiscoveryState> + val serverUrl: MutableStateFlowClass<String> + val serverDiscoveryState: StateFlowClass<ServerDiscoveryState> sealed interface ServerDiscoveryState { object None : ServerDiscoveryState @@ -57,12 +62,13 @@ open class AddMatrixAccountViewModelImpl( private val onCancel: () -> Unit, private val httpClientFactory: (HttpClientConfig<*>.() -> Unit) -> HttpClient = { HttpClient(it) }, ) : ViewModelContext by viewModelContext, AddMatrixAccountViewModel { - override val isFirstMatrixClient: StateFlow<Boolean?> = + override val isFirstMatrixClient: StateFlowClass<Boolean?> = flow { emit(get<GetAccountNames>()()) } .map { it.isEmpty() } .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), null) + .asFlowClass(coroutineScope) - final override val serverUrl = MutableStateFlow("") + final override val serverUrl = MutableStateFlow("").asFlowClass(coroutineScope) final override val serverDiscoveryState = serverUrl.debounce(1.seconds).transformLatest { serverUrl -> @@ -127,11 +133,13 @@ open class AddMatrixAccountViewModelImpl( } } } - }.stateIn( - coroutineScope, - SharingStarted.WhileSubscribed(), - ServerDiscoveryState.None - ) + } + .stateIn( + coroutineScope, + SharingStarted.WhileSubscribed(), + ServerDiscoveryState.None + ) + .asFlowClass(coroutineScope) override fun selectAddMatrixAccountMethod(addMatrixAccountMethod: AddMatrixAccountMethod) { onAddMatrixAccountMethod(addMatrixAccountMethod) @@ -143,9 +151,12 @@ open class AddMatrixAccountViewModelImpl( } class PreviewAddMatrixAccountViewModel : AddMatrixAccountViewModel { - override val isFirstMatrixClient: StateFlow<Boolean?> = MutableStateFlow(true) - override val serverUrl: MutableStateFlow<String> = MutableStateFlow("") - override val serverDiscoveryState: StateFlow<ServerDiscoveryState> = MutableStateFlow(ServerDiscoveryState.None) + private val coroutineScope = CoroutineScope(Dispatchers.Default) + override val isFirstMatrixClient: MutableStateFlowClass<Boolean?> = + MutableStateFlow(true).asFlowClass(coroutineScope) + override val serverUrl: MutableStateFlowClass<String> = MutableStateFlow("").asFlowClass(coroutineScope) + override val serverDiscoveryState: MutableStateFlowClass<ServerDiscoveryState> = + MutableStateFlow(ServerDiscoveryState.None).asFlowClass(coroutineScope) override fun selectAddMatrixAccountMethod(addMatrixAccountMethod: AddMatrixAccountMethod) { } diff --git a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/PasswordLoginViewModel.kt b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/PasswordLoginViewModel.kt index 1e831394b..313a9a03f 100644 --- a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/PasswordLoginViewModel.kt +++ b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/PasswordLoginViewModel.kt @@ -2,10 +2,15 @@ package de.connect2x.trixnity.messenger.viewmodel.connecting import de.connect2x.trixnity.messenger.GetAccountNames import de.connect2x.trixnity.messenger.MatrixClientService +import de.connect2x.trixnity.messenger.util.MutableStateFlowClass +import de.connect2x.trixnity.messenger.util.StateFlowClass +import de.connect2x.trixnity.messenger.util.asFlowClass import de.connect2x.trixnity.messenger.viewmodel.ViewModelContext import de.connect2x.trixnity.messenger.viewmodel.i18n import io.github.oshai.kotlinlogging.KotlinLogging import korlibs.io.async.launch +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* import org.koin.core.component.get @@ -31,16 +36,16 @@ interface PasswordLoginViewModelFactory { } interface PasswordLoginViewModel { - val isFirstMatrixClient: StateFlow<Boolean?> + val isFirstMatrixClient: StateFlowClass<Boolean?> val serverUrl: String - val canLogin: StateFlow<Boolean> + val canLogin: StateFlowClass<Boolean> - val accountName: MutableStateFlow<String> - val username: MutableStateFlow<String> - val password: MutableStateFlow<String> + val accountName: MutableStateFlowClass<String> + val username: MutableStateFlowClass<String> + val password: MutableStateFlowClass<String> - val addMatrixAccountState: StateFlow<AddMatrixAccountState> + val addMatrixAccountState: StateFlowClass<AddMatrixAccountState> fun tryLogin() fun back() } @@ -55,17 +60,18 @@ open class PasswordLoginViewModelImpl( private val accountNames = channelFlow { send(get<GetAccountNames>()()) } .stateIn(coroutineScope, SharingStarted.Eagerly, null) - override val isFirstMatrixClient: StateFlow<Boolean?> = accountNames.map { it.isNullOrEmpty() } + override val isFirstMatrixClient: StateFlowClass<Boolean?> = accountNames.map { it.isNullOrEmpty() } .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), null) + .asFlowClass(coroutineScope) - override val accountName: MutableStateFlow<String> = MutableStateFlow(i18n.defaultAccountName()) - final override val username: MutableStateFlow<String> = MutableStateFlow("") - final override val password: MutableStateFlow<String> = MutableStateFlow("") + override val accountName: MutableStateFlowClass<String> = MutableStateFlow(i18n.defaultAccountName()).asFlowClass(coroutineScope) + final override val username: MutableStateFlowClass<String> = MutableStateFlow("").asFlowClass(coroutineScope) + final override val password: MutableStateFlowClass<String> = MutableStateFlow("").asFlowClass(coroutineScope) - override val addMatrixAccountState: MutableStateFlow<AddMatrixAccountState> = - MutableStateFlow(AddMatrixAccountState.None) + override val addMatrixAccountState: MutableStateFlowClass<AddMatrixAccountState> = + MutableStateFlow(AddMatrixAccountState.None).asFlowClass(coroutineScope) - override val canLogin: StateFlow<Boolean> = + override val canLogin: StateFlowClass<Boolean> = combine( accountName, username, @@ -77,7 +83,9 @@ open class PasswordLoginViewModelImpl( addMatrixAccountState.value = AddMatrixAccountState.Failure(i18n.accountAlreadyExistsLocally(accountName)) accountAlreadyExists.not() && accountName.isNotBlank() && username.isNotBlank() && password.isNotBlank() && serverUrl.isNotBlank() - }.stateIn(coroutineScope, SharingStarted.Eagerly, false) // eagerly because value is used below + } + .stateIn(coroutineScope, SharingStarted.Eagerly, false) // eagerly because value is used below + .asFlowClass(coroutineScope) override fun tryLogin() { coroutineScope.launch { @@ -104,14 +112,15 @@ open class PasswordLoginViewModelImpl( } class PreviewPasswordLoginViewModel : PasswordLoginViewModel { + private val coroutineScope = CoroutineScope(Dispatchers.Default) override val serverUrl: String = "https://timmy-messenger.de" - override val isFirstMatrixClient: StateFlow<Boolean?> = MutableStateFlow(false) - override val canLogin: StateFlow<Boolean> = MutableStateFlow(false) - override val accountName: MutableStateFlow<String> = MutableStateFlow("default") - override val username: MutableStateFlow<String> = MutableStateFlow("user") - override val password: MutableStateFlow<String> = MutableStateFlow("password") - override val addMatrixAccountState: StateFlow<AddMatrixAccountState> = - MutableStateFlow(AddMatrixAccountState.Failure("dino")) + override val isFirstMatrixClient: MutableStateFlowClass<Boolean?> = MutableStateFlow(false).asFlowClass(coroutineScope) + override val canLogin: MutableStateFlowClass<Boolean> = MutableStateFlow(false).asFlowClass(coroutineScope) + override val accountName: MutableStateFlowClass<String> = MutableStateFlow("default").asFlowClass(coroutineScope) + override val username: MutableStateFlowClass<String> = MutableStateFlow("user").asFlowClass(coroutineScope) + override val password: MutableStateFlowClass<String> = MutableStateFlow("password").asFlowClass(coroutineScope) + override val addMatrixAccountState: MutableStateFlowClass<AddMatrixAccountState> = + MutableStateFlow(AddMatrixAccountState.Failure("dino")).asFlowClass(coroutineScope) override fun tryLogin() { } diff --git a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/RegisterNewAccountViewModel.kt b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/RegisterNewAccountViewModel.kt index 1e67c19a0..60a6995ca 100644 --- a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/RegisterNewAccountViewModel.kt +++ b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/RegisterNewAccountViewModel.kt @@ -5,6 +5,7 @@ import de.connect2x.trixnity.messenger.MatrixClientService import de.connect2x.trixnity.messenger.deviceDisplayName import de.connect2x.trixnity.messenger.util.MutableStateFlowClass import de.connect2x.trixnity.messenger.util.StateFlowClass +import de.connect2x.trixnity.messenger.util.asFlowClass import de.connect2x.trixnity.messenger.viewmodel.ViewModelContext import de.connect2x.trixnity.messenger.viewmodel.connecting.RegisterNewAccountViewModel.RegistrationState import de.connect2x.trixnity.messenger.viewmodel.i18n @@ -13,6 +14,8 @@ import io.github.oshai.kotlinlogging.KotlinLogging import io.ktor.client.* import io.ktor.http.* import korlibs.io.async.launch +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* import net.folivo.trixnity.clientserverapi.client.MatrixClientServerApiClientImpl import net.folivo.trixnity.clientserverapi.client.UIA @@ -38,10 +41,10 @@ interface RegisterNewAccountViewModelFactory { } interface RegisterNewAccountViewModel { - val isFirstMatrixClient: StateFlow<Boolean?> + val isFirstMatrixClient: StateFlowClass<Boolean?> - val error: StateFlow<String?> - val registrationState: StateFlow<RegistrationState> + val error: StateFlowClass<String?> + val registrationState: StateFlowClass<RegistrationState> val registrationOptions: StateFlowClass<List<AuthenticationType>> val loadingRegistrationOptions: StateFlowClass<Boolean> @@ -49,15 +52,15 @@ interface RegisterNewAccountViewModel { val serverUrl: String - val accountName: MutableStateFlow<String> - val username: MutableStateFlow<String> - val password: MutableStateFlow<String> - val displayName: MutableStateFlow<String?> + val accountName: MutableStateFlowClass<String> + val username: MutableStateFlowClass<String> + val password: MutableStateFlowClass<String> + val displayName: MutableStateFlowClass<String?> val registrationToken: MutableStateFlowClass<String> - val canRegisterNewUser: StateFlow<Boolean> - val addMatrixAccountState: StateFlow<AddMatrixAccountState> + val canRegisterNewUser: StateFlowClass<Boolean> + val addMatrixAccountState: StateFlowClass<AddMatrixAccountState> fun tryRegistration() fun back() @@ -81,8 +84,9 @@ open class RegisterNewAccountViewModelImpl( private val accountNames = channelFlow { send(get<GetAccountNames>()()) } .stateIn(coroutineScope, SharingStarted.Eagerly, null) - override val isFirstMatrixClient: StateFlow<Boolean?> = accountNames.map { it.isNullOrEmpty() } + override val isFirstMatrixClient: StateFlowClass<Boolean?> = accountNames.map { it.isNullOrEmpty() } .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), null) + .asFlowClass(coroutineScope) override val error: MutableStateFlowClass<String?> = MutableStateFlow(null).asFlowClass(coroutineScope) override val registrationState: MutableStateFlowClass<RegistrationState> = @@ -94,16 +98,16 @@ open class RegisterNewAccountViewModelImpl( override val selectedRegistration: MutableStateFlowClass<AuthenticationType?> = MutableStateFlow(null).asFlowClass(coroutineScope) - override val accountName: MutableStateFlow<String> = MutableStateFlow(i18n.defaultAccountName()) - override val username: MutableStateFlow<String> = MutableStateFlow("") - override val displayName: MutableStateFlow<String?> = MutableStateFlow(null) - override val password: MutableStateFlow<String> = MutableStateFlow("") + override val accountName: MutableStateFlowClass<String> = MutableStateFlow(i18n.defaultAccountName()).asFlowClass(coroutineScope) + override val username: MutableStateFlowClass<String> = MutableStateFlow("").asFlowClass(coroutineScope) + override val displayName: MutableStateFlowClass<String?> = MutableStateFlow(null).asFlowClass(coroutineScope) + override val password: MutableStateFlowClass<String> = MutableStateFlow("").asFlowClass(coroutineScope) - override val registrationToken: MutableStateFlow<String> = MutableStateFlow("") - override val addMatrixAccountState: MutableStateFlow<AddMatrixAccountState> = - MutableStateFlow(AddMatrixAccountState.None) + override val registrationToken: MutableStateFlowClass<String> = MutableStateFlow("").asFlowClass(coroutineScope) + override val addMatrixAccountState: MutableStateFlowClass<AddMatrixAccountState> = + MutableStateFlow(AddMatrixAccountState.None).asFlowClass(coroutineScope) - override val canRegisterNewUser: StateFlow<Boolean> = combine( + override val canRegisterNewUser: StateFlowClass<Boolean> = combine( accountName, accountNames, username, password, selectedRegistration, registrationToken ) { accountName, existingAccountNames, username, password, selectedRegistration, registrationToken -> log.debug { "canRegisterNewUser: accountName=$accountName, existingAccountNames=$existingAccountNames, username=$username, selectedRegistration=$selectedRegistration, registrationToken=$registrationToken" } @@ -114,7 +118,9 @@ open class RegisterNewAccountViewModelImpl( selectedRegistration == AuthenticationType.RegistrationToken && registrationToken.isBlank() -> false else -> true } - }.stateIn(coroutineScope, SharingStarted.Eagerly, false) // is used down below + } + .stateIn(coroutineScope, SharingStarted.Eagerly, false) // is used down below + .asFlowClass(coroutineScope) init { coroutineScope.launch { @@ -315,20 +321,20 @@ class PreviewRegisterNewAccountViewModel : RegisterNewAccountViewModel { AuthenticationType.RegistrationToken, AuthenticationType.Password, ) - ) - override val loadingRegistrationOptions: MutableStateFlow<Boolean> = MutableStateFlow(false) - override val selectedRegistration: MutableStateFlow<AuthenticationType?> = - MutableStateFlow(AuthenticationType.RegistrationToken) - override val isFirstMatrixClient: StateFlow<Boolean?> = MutableStateFlow(false) - override val accountName: MutableStateFlow<String> = MutableStateFlow("Standard") + ).asFlowClass(coroutineScope) + override val loadingRegistrationOptions: MutableStateFlowClass<Boolean> = MutableStateFlow(false).asFlowClass(coroutineScope) + override val selectedRegistration: MutableStateFlowClass<AuthenticationType?> = + MutableStateFlow(AuthenticationType.RegistrationToken).asFlowClass(coroutineScope) + override val isFirstMatrixClient: MutableStateFlowClass<Boolean?> = MutableStateFlow(false).asFlowClass(coroutineScope) + override val accountName: MutableStateFlowClass<String> = MutableStateFlow("Standard").asFlowClass(coroutineScope) override val serverUrl: String = "http://localhost:8008" - override val username: MutableStateFlow<String> = MutableStateFlow("user1") - override val password: MutableStateFlow<String> = MutableStateFlow("user1-password") - override val displayName: MutableStateFlow<String?> = MutableStateFlow(null) - override val registrationToken: MutableStateFlow<String> = MutableStateFlow("myRegistrationToken") - override val addMatrixAccountState: MutableStateFlow<AddMatrixAccountState> = - MutableStateFlow(AddMatrixAccountState.None) - override val canRegisterNewUser: MutableStateFlow<Boolean> = MutableStateFlow(true) + override val username: MutableStateFlowClass<String> = MutableStateFlow("user1").asFlowClass(coroutineScope) + override val password: MutableStateFlowClass<String> = MutableStateFlow("user1-password").asFlowClass(coroutineScope) + override val displayName: MutableStateFlowClass<String?> = MutableStateFlow(null).asFlowClass(coroutineScope) + override val registrationToken: MutableStateFlowClass<String> = MutableStateFlow("myRegistrationToken").asFlowClass(coroutineScope) + override val addMatrixAccountState: MutableStateFlowClass<AddMatrixAccountState> = + MutableStateFlow(AddMatrixAccountState.None).asFlowClass(coroutineScope) + override val canRegisterNewUser: MutableStateFlowClass<Boolean> = MutableStateFlow(true).asFlowClass(coroutineScope) override fun tryRegistration() {} override fun back() {} diff --git a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/SSOLoginViewModel.kt b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/SSOLoginViewModel.kt index 4f63345a5..8ac643955 100644 --- a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/SSOLoginViewModel.kt +++ b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/connecting/SSOLoginViewModel.kt @@ -3,13 +3,18 @@ package de.connect2x.trixnity.messenger.viewmodel.connecting import com.benasher44.uuid.uuid4 import de.connect2x.trixnity.messenger.GetAccountNames import de.connect2x.trixnity.messenger.MatrixClientService +import de.connect2x.trixnity.messenger.util.MutableStateFlowClass +import de.connect2x.trixnity.messenger.util.StateFlowClass import de.connect2x.trixnity.messenger.util.UrlHandler +import de.connect2x.trixnity.messenger.util.asFlowClass import de.connect2x.trixnity.messenger.viewmodel.ViewModelContext import de.connect2x.trixnity.messenger.viewmodel.i18n import de.connect2x.trixnity.messenger.viewmodel.settings.MessengerSettings import io.github.oshai.kotlinlogging.KotlinLogging import io.ktor.http.* import korlibs.io.async.launch +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* import org.koin.core.component.get @@ -39,15 +44,15 @@ interface SSOLoginViewModelFactory { } interface SSOLoginViewModel { - val isFirstMatrixClient: StateFlow<Boolean?> + val isFirstMatrixClient: StateFlowClass<Boolean?> val serverUrl: String val providerName: String - val canLogin: StateFlow<Boolean> - val addMatrixAccountState: StateFlow<AddMatrixAccountState> + val canLogin: StateFlowClass<Boolean> + val addMatrixAccountState: StateFlowClass<AddMatrixAccountState> - val accountName: MutableStateFlow<String> - val loginToken: MutableStateFlow<String> + val accountName: MutableStateFlowClass<String> + val loginToken: MutableStateFlowClass<String> val loginUrl: String fun tryLogin() @@ -66,14 +71,15 @@ open class SSOLoginViewModelImpl( ) : ViewModelContext by viewModelContext, SSOLoginViewModel { private val accountNames = channelFlow { send(get<GetAccountNames>()()) } .stateIn(coroutineScope, SharingStarted.Eagerly, null) - override val isFirstMatrixClient: StateFlow<Boolean?> = accountNames.map { it.isNullOrEmpty() } + override val isFirstMatrixClient: StateFlowClass<Boolean?> = accountNames.map { it.isNullOrEmpty() } .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), null) + .asFlowClass(coroutineScope) - override val accountName: MutableStateFlow<String> = MutableStateFlow(i18n.defaultAccountName()) - override val loginToken: MutableStateFlow<String> = MutableStateFlow("") + override val accountName: MutableStateFlowClass<String> = MutableStateFlow(i18n.defaultAccountName()).asFlowClass(coroutineScope) + override val loginToken: MutableStateFlowClass<String> = MutableStateFlow("").asFlowClass(coroutineScope) - override val addMatrixAccountState: MutableStateFlow<AddMatrixAccountState> = - MutableStateFlow(AddMatrixAccountState.None) + override val addMatrixAccountState: MutableStateFlowClass<AddMatrixAccountState> = + MutableStateFlow(AddMatrixAccountState.None).asFlowClass(coroutineScope) private val urlHandler = get<UrlHandler>() private val messengerSettings = get<MessengerSettings>() @@ -100,7 +106,7 @@ open class SSOLoginViewModelImpl( override val loginUrl = Url("$serverUrl/_matrix/client/v3/login/sso/redirect/$providerId?redirectUrl=$redirectUrl").toString() - override val canLogin: StateFlow<Boolean> = + override val canLogin: StateFlowClass<Boolean> = combine( accountName, loginToken, @@ -111,7 +117,9 @@ open class SSOLoginViewModelImpl( addMatrixAccountState.value = AddMatrixAccountState.Failure(i18n.accountAlreadyExistsLocally(accountName)) accountAlreadyExists.not() && accountName.isNotBlank() && loginToken.isNotBlank() && serverUrl.isNotBlank() - }.stateIn(coroutineScope, SharingStarted.Eagerly, false) // eagerly because value is used below + } + .stateIn(coroutineScope, SharingStarted.Eagerly, false) // eagerly because value is used below + .asFlowClass(coroutineScope) override fun tryLogin() { coroutineScope.launch { @@ -137,14 +145,15 @@ open class SSOLoginViewModelImpl( } class PreviewSSOLoginViewModel : SSOLoginViewModel { + private val coroutineScope = CoroutineScope(Dispatchers.Default) override val serverUrl: String = "https://timmy-messenger.de" - override val isFirstMatrixClient: StateFlow<Boolean?> = MutableStateFlow(false) + override val isFirstMatrixClient: MutableStateFlowClass<Boolean?> = MutableStateFlow(false).asFlowClass(coroutineScope) override val providerName: String = "Timmy" - override val canLogin: StateFlow<Boolean> = MutableStateFlow(false) - override val accountName: MutableStateFlow<String> = MutableStateFlow("default") - override val loginToken: MutableStateFlow<String> = MutableStateFlow("") - override val addMatrixAccountState: StateFlow<AddMatrixAccountState> = - MutableStateFlow(AddMatrixAccountState.Failure("dino")) + override val canLogin: MutableStateFlowClass<Boolean> = MutableStateFlow(false).asFlowClass(coroutineScope) + override val accountName: MutableStateFlowClass<String> = MutableStateFlow("default").asFlowClass(coroutineScope) + override val loginToken: MutableStateFlowClass<String> = MutableStateFlow("").asFlowClass(coroutineScope) + override val addMatrixAccountState: MutableStateFlowClass<AddMatrixAccountState> = + MutableStateFlow(AddMatrixAccountState.Failure("dino")).asFlowClass(coroutineScope) override val loginUrl: String = Url("$serverUrl/_matrix/client/v3/login/sso/redirect?redirectUrl=trixnity://sso").toString() diff --git a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/settings/AppInfoViewModel.kt b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/settings/AppInfoViewModel.kt index 306d8b0ba..9c742e037 100644 --- a/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/settings/AppInfoViewModel.kt +++ b/trixnity-messenger/src/commonMain/kotlin/de/connect2x/trixnity/messenger/viewmodel/settings/AppInfoViewModel.kt @@ -1,8 +1,6 @@ package de.connect2x.trixnity.messenger.viewmodel.settings import com.arkivanov.essenty.backhandler.BackCallback -import de.connect2x.trixnity.messenger.getLicenses -import de.connect2x.trixnity.messenger.getVersion import de.connect2x.trixnity.messenger.util.MutableStateFlowClass import de.connect2x.trixnity.messenger.util.asFlowClass import de.connect2x.trixnity.messenger.viewmodel.ViewModelContext -- GitLab