Browse Source

Add a module for the Matrix SDK with the aar of the Rust SDK

feature/bma/flipper
Benoit Marty 2 years ago
parent
commit
1238047b08
  1. 1
      app/build.gradle
  2. 1
      app/src/main/AndroidManifest.xml
  3. 12
      app/src/main/java/io/element/android/x/ElementXApplication.kt
  4. 6
      libraries/sdk/matrix/src/main/AndroidManifest.xml
  5. 3
      libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/LogTag.kt
  6. 36
      libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/Matrix.kt
  7. 37
      libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/MatrixClient.kt
  8. 18
      libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/MatrixInstance.kt
  9. 1
      libraries/ui/screens/login/build.gradle
  10. 1
      libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginActions.kt
  11. 5
      libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginActivity.kt
  12. 41
      libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginViewModel.kt
  13. 1
      libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginViewState.kt
  14. 2
      settings.gradle

1
app/build.gradle

@ -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"

1
app/src/main/AndroidManifest.xml

@ -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"

12
app/src/main/java/io/element/android/x/ElementXApplication.kt

@ -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)
}
}

6
libraries/sdk/matrix/src/main/AndroidManifest.xml

@ -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>

3
libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/LogTag.kt

@ -0,0 +1,3 @@
package io.element.android.x.sdk.matrix
internal const val LOG_TAG = "Matrix"

36
libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/Matrix.kt

@ -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()
} }
} }

37
libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/MatrixClient.kt

@ -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()
}
}

18
libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/MatrixInstance.kt

@ -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
}
}

1
libraries/ui/screens/login/build.gradle

@ -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
libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginActions.kt

@ -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

5
libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginActivity.kt

@ -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 = {

41
libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginViewModel.kt

@ -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
libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginViewState.kt

@ -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,

2
settings.gradle

@ -11,7 +11,7 @@ dependencyResolutionManagement {
google() google()
mavenCentral() mavenCentral()
flatDir { flatDir {
dirs 'libs' dirs 'libraries/sdk/matrix/libs'
} }
} }
} }

Loading…
Cancel
Save