Fix bunch of issues around login/logout and introduces messages feature

This commit is contained in:
ganfra 2022-11-04 14:50:30 +01:00
parent b5e4ef9637
commit d04d847521
19 changed files with 314 additions and 89 deletions

View file

@ -4,15 +4,20 @@ import android.content.Context
import io.element.android.x.core.data.CoroutineDispatchers
import io.element.android.x.matrix.session.SessionStore
import io.element.android.x.matrix.util.logError
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.AuthenticationService
import org.matrix.rustcomponents.sdk.Client
import org.matrix.rustcomponents.sdk.ClientBuilder
import java.io.File
import java.util.Optional
class Matrix(
coroutineScope: CoroutineScope,
context: Context,
) {
private val coroutineDispatchers = CoroutineDispatchers(
io = Dispatchers.IO,
computation = Dispatchers.Default,
@ -20,9 +25,31 @@ class Matrix(
)
private val baseFolder = File(context.filesDir, "matrix")
private val sessionStore = SessionStore(context)
private val matrixClient = MutableStateFlow<Optional<MatrixClient>>(Optional.empty())
private val isLoggedIn = MutableStateFlow(false)
suspend fun restoreSession(): MatrixClient? {
return sessionStore.getStoredData()
init {
sessionStore.isLoggedIn()
.distinctUntilChanged()
.onEach { isLoggedIn ->
this.isLoggedIn.value = isLoggedIn
if (!isLoggedIn) {
matrixClient.value = Optional.empty()
}
}
.launchIn(coroutineScope)
}
fun isLoggedIn(): Flow<Boolean> {
return isLoggedIn
}
fun matrixClient(): Flow<Optional<MatrixClient>> {
return matrixClient
}
suspend fun restoreSession() = withContext(coroutineDispatchers.io) {
sessionStore.getStoredData()
?.let { sessionData ->
try {
ClientBuilder()
@ -36,15 +63,26 @@ class Matrix(
null
}
}?.let {
MatrixClient(it, sessionStore, coroutineDispatchers)
createMatrixClient(it)
}
}
suspend fun login(homeserver: String, username: String, password: String): MatrixClient {
val authService = AuthenticationService(baseFolder.absolutePath)
authService.configureHomeserver(homeserver)
val client = authService.login(username, password, "MatrixRustSDKSample", null)
sessionStore.storeData(SessionStore.SessionData(client.userId(), client.restoreToken()))
return MatrixClient(client, sessionStore, coroutineDispatchers)
suspend fun login(homeserver: String, username: String, password: String): MatrixClient =
withContext(coroutineDispatchers.io) {
val authService = AuthenticationService(baseFolder.absolutePath)
authService.configureHomeserver(homeserver)
val client = authService.login(username, password, "MatrixRustSDKSample", null)
sessionStore.storeData(SessionStore.SessionData(client.userId(), client.restoreToken()))
createMatrixClient(client)
}
private fun createMatrixClient(client: Client): MatrixClient {
return MatrixClient(
client = client,
sessionStore = sessionStore,
dispatchers = coroutineDispatchers
).also {
matrixClient.value = Optional.of(it)
}
}
}

View file

@ -61,7 +61,6 @@ class MatrixClient internal constructor(
init {
client.setDelegate(clientDelegate)
}
fun startSync() {
slidingSync.setObserver(slidingSyncObserver)
slidingSyncObserverToken = slidingSync.sync()

View file

@ -2,6 +2,7 @@ package io.element.android.x.matrix
import android.annotation.SuppressLint
import android.content.Context
import kotlinx.coroutines.GlobalScope
object MatrixInstance {
@ -9,7 +10,7 @@ object MatrixInstance {
private lateinit var instance: Matrix
fun init(context: Context) {
instance = Matrix(context)
instance = Matrix(GlobalScope, context)
}
fun getInstance(): Matrix {

View file

@ -6,10 +6,13 @@ import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "elementx_sessions")
private val userIdPreference = stringPreferencesKey("userId")
// TODO It contains the access token, so it has to be stored in a more secured storage.
// I would expect the Rust SDK to provide a more obscure token.
private val restoreTokenPreference = stringPreferencesKey("restoreToken")
@ -25,6 +28,11 @@ internal class SessionStore(
private val store = context.dataStore
fun isLoggedIn(): Flow<Boolean> {
return store.data.map { prefs ->
prefs[userIdPreference] != null && prefs[restoreTokenPreference] != null
}
}
suspend fun storeData(sessionData: SessionData) {
store.edit { prefs ->