Add a module for the Matrix SDK with the aar of the Rust SDK
This commit is contained in:
parent
df315ecea6
commit
98eeb08772
14 changed files with 131 additions and 34 deletions
|
|
@ -57,6 +57,7 @@ android {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":libraries:ui:theme")
|
implementation project(":libraries:ui:theme")
|
||||||
implementation project(":libraries:ui:screens:login")
|
implementation project(":libraries:ui:screens:login")
|
||||||
|
implementation project(":libraries:sdk:matrix")
|
||||||
|
|
||||||
implementation 'androidx.core:core-ktx:1.9.0'
|
implementation 'androidx.core:core-ktx:1.9.0'
|
||||||
implementation "androidx.compose.ui:ui:$compose_version"
|
implementation "androidx.compose.ui:ui:$compose_version"
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".ElementXApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package io.element.android.x
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import io.element.android.x.sdk.matrix.MatrixInstance
|
||||||
|
|
||||||
|
class ElementXApplication : Application() {
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
MatrixInstance.init(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest />
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
|
</manifest>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
package io.element.android.x.sdk.matrix
|
||||||
|
|
||||||
|
internal const val LOG_TAG = "Matrix"
|
||||||
|
|
@ -1,40 +1,18 @@
|
||||||
package io.element.android.x.sdk.matrix
|
package io.element.android.x.sdk.matrix
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import uniffi.matrix_sdk_ffi.AuthenticationService
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
private const val LOG_TAG = "Matrix"
|
|
||||||
|
|
||||||
class Matrix(
|
class Matrix(
|
||||||
private val context: Context,
|
context: Context,
|
||||||
) {
|
) {
|
||||||
fun login(username: String, password: String) {
|
private val authFolder = File(context.filesDir, "auth")
|
||||||
val authFolder = File(context.filesDir, "auth")
|
|
||||||
|
fun login(homeserver: String, username: String, password: String): MatrixClient {
|
||||||
val authService = AuthenticationService(authFolder.absolutePath)
|
val authService = AuthenticationService(authFolder.absolutePath)
|
||||||
authService.configureHomeserver("matrix.org")
|
authService.configureHomeserver(homeserver)
|
||||||
val client = authService.login(username, password, "MatrixRustSDKSample", null)
|
val client = authService.login(username, password, "MatrixRustSDKSample", null)
|
||||||
val clientDelegate = object : ClientDelegate {
|
return MatrixClient(client)
|
||||||
override fun didReceiveAuthError(isSoftLogout: Boolean) {
|
|
||||||
Log.v(LOG_TAG, "didReceiveAuthError()")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun didReceiveSyncUpdate() {
|
|
||||||
Log.v(LOG_TAG, "didReceiveSyncUpdate()")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun didUpdateRestoreToken() {
|
|
||||||
Log.v(LOG_TAG, "didUpdateRestoreToken()")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.setDelegate(clientDelegate)
|
|
||||||
Log.v(LOG_TAG, "DisplayName = ${client.displayName()}")
|
|
||||||
try {
|
|
||||||
client.fullSlidingSync()
|
|
||||||
} catch (failure: Throwable) {
|
|
||||||
Log.e(LOG_TAG, "fullSlidingSync() fail", failure)
|
|
||||||
}
|
|
||||||
client.logout()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package io.element.android.x.sdk.matrix
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import uniffi.matrix_sdk_ffi.Client
|
||||||
|
import uniffi.matrix_sdk_ffi.ClientDelegate
|
||||||
|
|
||||||
|
class MatrixClient internal constructor(
|
||||||
|
private val client: Client
|
||||||
|
) {
|
||||||
|
fun startSync() {
|
||||||
|
val clientDelegate = object : ClientDelegate {
|
||||||
|
override fun didReceiveAuthError(isSoftLogout: Boolean) {
|
||||||
|
Log.v(LOG_TAG, "didReceiveAuthError()")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun didReceiveSyncUpdate() {
|
||||||
|
Log.v(LOG_TAG, "didReceiveSyncUpdate()")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun didUpdateRestoreToken() {
|
||||||
|
Log.v(LOG_TAG, "didUpdateRestoreToken()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client.setDelegate(clientDelegate)
|
||||||
|
Log.v(LOG_TAG, "DisplayName = ${client.displayName()}")
|
||||||
|
try {
|
||||||
|
client.fullSlidingSync()
|
||||||
|
} catch (failure: Throwable) {
|
||||||
|
Log.e(LOG_TAG, "fullSlidingSync() fail", failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logout() {
|
||||||
|
client.logout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
package io.element.android.x.sdk.matrix
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Context
|
||||||
|
|
||||||
|
|
||||||
|
object MatrixInstance {
|
||||||
|
@SuppressLint("StaticFieldLeak")
|
||||||
|
private lateinit var instance: Matrix
|
||||||
|
|
||||||
|
fun init(context: Context) {
|
||||||
|
instance = Matrix(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getInstance(): Matrix {
|
||||||
|
return instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -37,6 +37,7 @@ android {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":libraries:ui:theme")
|
implementation project(":libraries:ui:theme")
|
||||||
|
implementation project(":libraries:sdk:matrix")
|
||||||
|
|
||||||
implementation 'androidx.core:core-ktx:1.9.0'
|
implementation 'androidx.core:core-ktx:1.9.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.5.1'
|
implementation 'androidx.appcompat:appcompat:1.5.1'
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package io.element.android.x.ui.screen.login
|
package io.element.android.x.ui.screen.login
|
||||||
|
|
||||||
sealed interface LoginActions {
|
sealed interface LoginActions {
|
||||||
|
data class SetHomeserver(val homeserver: String) : LoginActions
|
||||||
data class SetLogin(val login: String) : LoginActions
|
data class SetLogin(val login: String) : LoginActions
|
||||||
data class SetPassword(val password: String) : LoginActions
|
data class SetPassword(val password: String) : LoginActions
|
||||||
object Submit : LoginActions
|
object Submit : LoginActions
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,11 @@ class LoginActivity : ComponentActivity() {
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
val state = viewModel.state.collectAsState().value
|
val state = viewModel.state.collectAsState().value
|
||||||
|
VectorTextField(
|
||||||
|
value = state.homeserver,
|
||||||
|
onValueChange = {
|
||||||
|
viewModel.handle(LoginActions.SetHomeserver(it))
|
||||||
|
})
|
||||||
VectorTextField(
|
VectorTextField(
|
||||||
value = state.login,
|
value = state.login,
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,72 @@
|
||||||
package io.element.android.x.ui.screen.login
|
package io.element.android.x.ui.screen.login
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import io.element.android.x.sdk.matrix.MatrixInstance
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class LoginViewModel : ViewModel() {
|
class LoginViewModel : ViewModel() {
|
||||||
|
|
||||||
|
private val matrix = MatrixInstance.getInstance()
|
||||||
|
|
||||||
private val _state = MutableStateFlow(LoginViewState())
|
private val _state = MutableStateFlow(LoginViewState())
|
||||||
val state = _state.asStateFlow()
|
val state = _state.asStateFlow()
|
||||||
|
|
||||||
|
init {
|
||||||
|
observeState()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun observeState() {
|
||||||
|
// TODO Update submitEnabled when other state members are updated.
|
||||||
|
}
|
||||||
|
|
||||||
fun handle(action: LoginActions) {
|
fun handle(action: LoginActions) {
|
||||||
when (action) {
|
when (action) {
|
||||||
|
is LoginActions.SetHomeserver -> handleSetHomeserver(action)
|
||||||
is LoginActions.SetLogin -> handleSetName(action)
|
is LoginActions.SetLogin -> handleSetName(action)
|
||||||
is LoginActions.SetPassword -> handleSetPassword(action)
|
is LoginActions.SetPassword -> handleSetPassword(action)
|
||||||
LoginActions.Submit -> handleSubmit()
|
LoginActions.Submit -> handleSubmit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleSetHomeserver(action: LoginActions.SetHomeserver) {
|
||||||
|
_state.value = _state.value.copy(
|
||||||
|
homeserver = action.homeserver,
|
||||||
|
submitEnabled = _state.value.login.isNotEmpty() &&
|
||||||
|
_state.value.password.isNotEmpty() &&
|
||||||
|
action.homeserver.isNotEmpty()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleSubmit() {
|
private fun handleSubmit() {
|
||||||
// TODO
|
viewModelScope.launch {
|
||||||
|
val currentState = state.value
|
||||||
|
try {
|
||||||
|
matrix.login(currentState.homeserver, currentState.login, currentState.password)
|
||||||
|
} catch (throwable: Throwable) {
|
||||||
|
Log.e("Error", "Cannot login", throwable)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSetPassword(action: LoginActions.SetPassword) {
|
private fun handleSetPassword(action: LoginActions.SetPassword) {
|
||||||
_state.value = _state.value.copy(
|
_state.value = _state.value.copy(
|
||||||
password = action.password,
|
password = action.password,
|
||||||
submitEnabled = _state.value.login.isNotEmpty() && action.password.isNotEmpty()
|
submitEnabled = _state.value.login.isNotEmpty() &&
|
||||||
|
_state.value.homeserver.isNotEmpty() &&
|
||||||
|
action.password.isNotEmpty()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSetName(action: LoginActions.SetLogin) {
|
private fun handleSetName(action: LoginActions.SetLogin) {
|
||||||
_state.value = _state.value.copy(
|
_state.value = _state.value.copy(
|
||||||
login = action.login,
|
login = action.login,
|
||||||
submitEnabled = action.login.isNotEmpty() && _state.value.password.isNotEmpty()
|
submitEnabled = action.login.isNotEmpty() &&
|
||||||
|
_state.value.homeserver.isNotEmpty() &&
|
||||||
|
_state.value.password.isNotEmpty()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package io.element.android.x.ui.screen.login
|
package io.element.android.x.ui.screen.login
|
||||||
|
|
||||||
data class LoginViewState(
|
data class LoginViewState(
|
||||||
|
val homeserver: String = "matrix.org",
|
||||||
val login: String = "",
|
val login: String = "",
|
||||||
val password: String = "",
|
val password: String = "",
|
||||||
val submitEnabled: Boolean = false,
|
val submitEnabled: Boolean = false,
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ dependencyResolutionManagement {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
flatDir {
|
flatDir {
|
||||||
dirs 'libs'
|
dirs 'libraries/sdk/matrix/libs'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue