diff --git a/build.gradle.kts b/build.gradle.kts
index 5547acb75e876a45933fc5a3cb3eff6d9691ec0a..8bb51b50fe783d5a78fdcf64cdb615b32329f2a3 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 7799124423435b42e6bae8d0d170ec6b5c0b5442..fcefb0a02d8d386713e0a241e79b05d09a100baa 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 d1440e29517d04a98e805de8e9349c12472c6c53..04c9f7cb64757d09c5b6eadafb6449f41a3476e6 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 fd7c24d581c1bf39b79860ad45563552cec17867..748585e701664d3636c58a8c139f9b71e098f9f7 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 d59c006a8254b81ab786631a4f50ab91eddb14b8..1af1dba6238c98b295153ae7d44dff66580c2d23 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 c25c9b9e5955d89e4c1d0184a0e455dbcaae8845..5c6f22b2689c0734f11a846674e33e40eb561200 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 df879501d58922674163fffd4ea93b2c44033fe8..2cbc027279a6b33e4c0a2c670c962a80f88c36a5 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 1e831394bc0b5addb2df95cb662842f0cbd49661..313a9a03f8d21bced31834fda2b5737553cbd0b5 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 1e67c19a0c3280ded3cff2cb864d35f64cec82ca..60a6995ca4145f4e6de76ded77630215eb4a09e3 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 4f63345a50b048b23ed30808c61d3d77b58746b4..8ac643955cde77d7417a1ba56d59c1306afba695 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 306d8b0baeea64ac6c77baa9b887d1df859e2276..9c742e037c950919cd0ded8d662411fe3ad2e53b 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