diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000000..bd2a5052f8
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000000..d2ce72d10e
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 2a4d5b521d..54d5acd7d7 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,7 @@
-
+
+
diff --git a/app/build.gradle b/app/build.gradle
index 71c9701f6b..42f612ab00 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,6 +1,7 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
+ id 'com.google.devtools.ksp' version '1.7.20-1.0.7'
}
android {
@@ -36,7 +37,7 @@ android {
compose true
}
composeOptions {
- kotlinCompilerExtensionVersion compose_version
+ kotlinCompilerExtensionVersion "1.3.2"
}
packagingOptions {
resources {
@@ -44,6 +45,14 @@ android {
}
}
+ applicationVariants.all { variant ->
+ kotlin.sourceSets {
+ getByName(variant.name) {
+ kotlin.srcDir("build/generated/ksp/${variant.name}/kotlin")
+ }
+ }
+ }
+
signingConfigs {
debug {
keyAlias 'androiddebugkey'
@@ -55,19 +64,26 @@ android {
}
dependencies {
- implementation project(":libraries:ui:theme")
- implementation project(":libraries:ui:screens:login")
- implementation project(":libraries:ui:screens:roomlist")
- implementation project(":libraries:sdk:matrix")
+ implementation project(":libraries:designsystem")
+ implementation project(":libraries:matrix")
+ implementation project(":features:login")
+ implementation project(":features:roomlist")
+
+ implementation 'io.github.raamcosta.compose-destinations:core:1.7.23-beta'
+ ksp 'io.github.raamcosta.compose-destinations:ksp:1.7.23-beta'
+
+ def composeBom = platform('androidx.compose:compose-bom:2022.10.00')
+ implementation composeBom
+ androidTestImplementation composeBom
implementation 'androidx.core:core-ktx:1.9.0'
- implementation "androidx.compose.ui:ui:$compose_version"
- implementation 'androidx.compose.material3:material3:1.0.0-rc01'
- implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
+ implementation "androidx.compose.ui:ui"
+ implementation 'androidx.compose.material3:material3'
+ implementation "androidx.compose.ui:ui-tooling-preview"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
- implementation 'androidx.activity:activity-compose:1.6.0'
- debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
- debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
-
- implementation 'com.airbnb.android:mavericks-compose:2.7.0'
+ implementation 'androidx.activity:activity-compose:1.6.1'
+ implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1'
+ debugImplementation "androidx.compose.ui:ui-tooling"
+ debugImplementation "androidx.compose.ui:ui-test-manifest"
+ implementation 'com.airbnb.android:mavericks-compose:3.0.1'
}
\ No newline at end of file
diff --git a/app/src/main/java/io/element/android/x/ElementXApplication.kt b/app/src/main/java/io/element/android/x/ElementXApplication.kt
index 88136d002b..7cf10d0e7e 100644
--- a/app/src/main/java/io/element/android/x/ElementXApplication.kt
+++ b/app/src/main/java/io/element/android/x/ElementXApplication.kt
@@ -2,7 +2,7 @@ package io.element.android.x
import android.app.Application
import com.airbnb.mvrx.Mavericks
-import io.element.android.x.sdk.matrix.MatrixInstance
+import io.element.android.x.matrix.MatrixInstance
class ElementXApplication : Application() {
diff --git a/app/src/main/java/io/element/android/x/MainActivity.kt b/app/src/main/java/io/element/android/x/MainActivity.kt
index 6f3b51cded..460fd533f3 100644
--- a/app/src/main/java/io/element/android/x/MainActivity.kt
+++ b/app/src/main/java/io/element/android/x/MainActivity.kt
@@ -1,41 +1,41 @@
package io.element.android.x
-import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
-import androidx.activity.result.contract.ActivityResultContracts
+import androidx.activity.compose.setContent
import androidx.activity.viewModels
-import androidx.lifecycle.lifecycleScope
-import io.element.android.x.ui.screen.login.LoginActivity
-import io.element.android.x.ui.screen.roomlist.RoomListActivity
-import kotlinx.coroutines.launch
+import androidx.compose.runtime.Composable
+import com.ramcosta.composedestinations.DestinationsNavHost
+import com.ramcosta.composedestinations.rememberNavHostEngine
+import io.element.android.x.designsystem.ElementXTheme
+import io.element.android.x.destinations.LoginScreenNavigationDestination
+import kotlinx.coroutines.runBlocking
class MainActivity : ComponentActivity() {
- private val launcher =
- registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
- if (it.resultCode == RESULT_OK) {
- // Launch the room Activity and finish
- startRoomActivityAndFinish()
- } else {
- finish()
- }
- }
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- lifecycleScope.launch {
- if (viewModel.hasSession()) {
- startRoomActivityAndFinish()
- } else {
- launcher.launch(Intent(this@MainActivity, LoginActivity::class.java))
+ setContent {
+ ElementXTheme {
+ MainScreen(viewModel = viewModel)
}
}
}
-
- private fun startRoomActivityAndFinish() {
- startActivity(Intent(this, RoomListActivity::class.java))
- finish()
- }
+}
+
+@Composable
+private fun MainScreen(viewModel: MainViewModel) {
+ val engine = rememberNavHostEngine()
+ val navController = engine.rememberNavController()
+ val startRoute = runBlocking {
+ if (!viewModel.hasSession()) LoginScreenNavigationDestination else NavGraphs.root.startRoute
+ }
+ DestinationsNavHost(
+ engine = engine,
+ navController = navController,
+ navGraph = NavGraphs.root,
+ startRoute = startRoute
+ )
}
diff --git a/app/src/main/java/io/element/android/x/MainViewModel.kt b/app/src/main/java/io/element/android/x/MainViewModel.kt
index 7474901daa..7790a9f133 100644
--- a/app/src/main/java/io/element/android/x/MainViewModel.kt
+++ b/app/src/main/java/io/element/android/x/MainViewModel.kt
@@ -1,7 +1,7 @@
package io.element.android.x
import androidx.lifecycle.ViewModel
-import io.element.android.x.sdk.matrix.MatrixInstance
+import io.element.android.x.matrix.MatrixInstance
class MainViewModel : ViewModel() {
private val matrix = MatrixInstance.getInstance()
diff --git a/app/src/main/java/io/element/android/x/Navigation.kt b/app/src/main/java/io/element/android/x/Navigation.kt
new file mode 100644
index 0000000000..b53d0e9e8e
--- /dev/null
+++ b/app/src/main/java/io/element/android/x/Navigation.kt
@@ -0,0 +1,28 @@
+package io.element.android.x
+
+import androidx.compose.runtime.Composable
+import com.ramcosta.composedestinations.annotation.Destination
+import com.ramcosta.composedestinations.annotation.RootNavGraph
+import com.ramcosta.composedestinations.navigation.DestinationsNavigator
+import io.element.android.x.destinations.RoomListScreenNavigationDestination
+import io.element.android.x.features.login.LoginScreen
+import io.element.android.x.features.roomlist.RoomListScreen
+
+@Destination
+@Composable
+fun LoginScreenNavigation(navigator: DestinationsNavigator) {
+ LoginScreen(
+ onLoginWithSuccess = {
+ navigator.clearBackStack(RoomListScreenNavigationDestination)
+ }
+ )
+}
+
+@RootNavGraph(start = true)
+@Destination
+@Composable
+fun RoomListScreenNavigation() {
+ RoomListScreen()
+}
+
+
diff --git a/libraries/ui/theme/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
similarity index 100%
rename from libraries/ui/theme/src/main/res/drawable-v24/ic_launcher_foreground.xml
rename to app/src/main/res/drawable-v24/ic_launcher_foreground.xml
diff --git a/libraries/ui/theme/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
similarity index 100%
rename from libraries/ui/theme/src/main/res/drawable/ic_launcher_background.xml
rename to app/src/main/res/drawable/ic_launcher_background.xml
diff --git a/libraries/ui/theme/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
rename to app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
diff --git a/libraries/ui/theme/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
rename to app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
diff --git a/libraries/ui/theme/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-hdpi/ic_launcher.webp
rename to app/src/main/res/mipmap-hdpi/ic_launcher.webp
diff --git a/libraries/ui/theme/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-hdpi/ic_launcher_round.webp
rename to app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
diff --git a/libraries/ui/theme/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-mdpi/ic_launcher.webp
rename to app/src/main/res/mipmap-mdpi/ic_launcher.webp
diff --git a/libraries/ui/theme/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-mdpi/ic_launcher_round.webp
rename to app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
diff --git a/libraries/ui/theme/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-xhdpi/ic_launcher.webp
rename to app/src/main/res/mipmap-xhdpi/ic_launcher.webp
diff --git a/libraries/ui/theme/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
rename to app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
diff --git a/libraries/ui/theme/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-xxhdpi/ic_launcher.webp
rename to app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
diff --git a/libraries/ui/theme/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
rename to app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
diff --git a/libraries/ui/theme/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
rename to app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
diff --git a/libraries/ui/theme/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
similarity index 100%
rename from libraries/ui/theme/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
rename to app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
diff --git a/libraries/ui/theme/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
similarity index 100%
rename from libraries/ui/theme/src/main/res/values/colors.xml
rename to app/src/main/res/values/colors.xml
diff --git a/libraries/ui/theme/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
similarity index 100%
rename from libraries/ui/theme/src/main/res/values/strings.xml
rename to app/src/main/res/values/strings.xml
diff --git a/libraries/ui/theme/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
similarity index 100%
rename from libraries/ui/theme/src/main/res/values/themes.xml
rename to app/src/main/res/values/themes.xml
diff --git a/libraries/ui/theme/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml
similarity index 100%
rename from libraries/ui/theme/src/main/res/xml/backup_rules.xml
rename to app/src/main/res/xml/backup_rules.xml
diff --git a/libraries/ui/theme/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
similarity index 100%
rename from libraries/ui/theme/src/main/res/xml/data_extraction_rules.xml
rename to app/src/main/res/xml/data_extraction_rules.xml
diff --git a/build.gradle b/build.gradle
index 8de5e8911d..ce9450edaf 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,12 +1,8 @@
-buildscript {
- ext {
- compose_version = '1.3.0-rc01'
- }
-}// Top-level build file where you can add configuration options common to all sub-projects/modules.
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.3.0' apply false
id 'com.android.library' version '7.3.0' apply false
- id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
+ id 'org.jetbrains.kotlin.android' version '1.7.20' apply false
}
task clean(type: Delete) {
diff --git a/features/login/.gitignore b/features/login/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/features/login/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/features/login/build.gradle.kts b/features/login/build.gradle.kts
new file mode 100644
index 0000000000..8524e67615
--- /dev/null
+++ b/features/login/build.gradle.kts
@@ -0,0 +1,18 @@
+plugins {
+ id("io.element.android-compose")
+}
+
+android {
+ namespace = "io.element.android.x.features.login"
+}
+
+dependencies {
+ implementation(project(":libraries:core"))
+ implementation(project(":libraries:matrix"))
+ implementation(project(":libraries:designsystem"))
+ implementation("com.airbnb.android:mavericks-compose:3.0.1")
+
+ testImplementation("junit:junit:4.13.2")
+ androidTestImplementation("androidx.test.ext:junit:1.1.3")
+ androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
+}
\ No newline at end of file
diff --git a/features/login/consumer-rules.pro b/features/login/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/features/login/proguard-rules.pro b/features/login/proguard-rules.pro
new file mode 100644
index 0000000000..ff59496d81
--- /dev/null
+++ b/features/login/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.kts.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/features/login/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt b/features/login/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000000..ba9eb96b15
--- /dev/null
+++ b/features/login/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package io.element.android.x.features.login
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("io.element.android.x.features.login.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/libraries/ui/theme/src/main/AndroidManifest.xml b/features/login/src/main/AndroidManifest.xml
similarity index 100%
rename from libraries/ui/theme/src/main/AndroidManifest.xml
rename to features/login/src/main/AndroidManifest.xml
diff --git a/libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginActions.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginActions.kt
similarity index 85%
rename from libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginActions.kt
rename to features/login/src/main/java/io/element/android/x/features/login/LoginActions.kt
index b52e5fde8a..f9d8cbbb62 100644
--- a/libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginActions.kt
+++ b/features/login/src/main/java/io/element/android/x/features/login/LoginActions.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.ui.screen.login
+package io.element.android.x.features.login
sealed interface LoginActions {
data class SetHomeserver(val homeserver: String) : LoginActions
diff --git a/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt
new file mode 100644
index 0000000000..2bc570d369
--- /dev/null
+++ b/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt
@@ -0,0 +1,133 @@
+@file:OptIn(ExperimentalMaterial3Api::class)
+
+package io.element.android.x.features.login
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.text.KeyboardOptions
+import androidx.compose.material3.*
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.input.ImeAction
+import androidx.compose.ui.text.input.KeyboardType
+import androidx.compose.ui.unit.dp
+import com.airbnb.mvrx.Fail
+import com.airbnb.mvrx.Loading
+import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.compose.collectAsState
+import com.airbnb.mvrx.compose.mavericksViewModel
+import io.element.android.x.designsystem.components.VectorButton
+
+@Composable
+fun LoginScreen(
+ viewModel: LoginViewModel = mavericksViewModel(),
+ onLoginWithSuccess: () -> Unit = { }
+) {
+ val state: LoginViewState by viewModel.collectAsState()
+ LoginContent(
+ state = state,
+ onHomeserverChanged = { viewModel.handle(LoginActions.SetHomeserver(it)) },
+ onLoginChanged = { viewModel.handle(LoginActions.SetLogin(it)) },
+ onPasswordChanged = { viewModel.handle(LoginActions.SetPassword(it)) },
+ onSubmitClicked = { viewModel.handle(LoginActions.Submit) },
+ onLoginWithSuccess = onLoginWithSuccess
+ )
+}
+
+
+@Composable
+fun LoginContent(
+ state: LoginViewState,
+ onHomeserverChanged: (String) -> Unit,
+ onLoginChanged: (String) -> Unit,
+ onPasswordChanged: (String) -> Unit,
+ onSubmitClicked: () -> Unit,
+ onLoginWithSuccess: () -> Unit
+) {
+ Surface(color = MaterialTheme.colorScheme.background) {
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(16.dp)
+ ) {
+ Column(
+ modifier = Modifier.fillMaxSize(),
+ ) {
+ val isError = state.isLoggedIn is Fail
+ Image(
+ painterResource(id = R.drawable.element_logo_green),
+ contentDescription = null,
+ modifier = Modifier
+ .align(Alignment.CenterHorizontally)
+ .padding(40.dp)
+ )
+ OutlinedTextField(
+ value = state.homeserver,
+ modifier = Modifier.fillMaxWidth(),
+ onValueChange = {
+ onHomeserverChanged(it)
+ },
+ keyboardOptions = KeyboardOptions(
+ keyboardType = KeyboardType.Uri,
+ ),
+ )
+ OutlinedTextField(
+ value = state.login,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 8.dp),
+ onValueChange = {
+ onLoginChanged(it)
+ },
+ keyboardOptions = KeyboardOptions(
+ keyboardType = KeyboardType.Text,
+ ),
+ )
+ OutlinedTextField(
+ value = state.password,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 8.dp),
+ onValueChange = {
+ onPasswordChanged(it)
+ },
+ isError = isError,
+ keyboardOptions = KeyboardOptions(
+ keyboardType = KeyboardType.Password,
+ imeAction = ImeAction.Send,
+ ),
+ )
+ if (isError) {
+ Text(
+ text = (state.isLoggedIn as? Fail)?.toString().orEmpty(),
+ color = MaterialTheme.colorScheme.error,
+ style = MaterialTheme.typography.bodySmall,
+ modifier = Modifier.padding(start = 16.dp)
+ )
+ }
+ VectorButton(
+ text = "Submit",
+ onClick = {
+ onSubmitClicked()
+ },
+ enabled = state.submitEnabled,
+ modifier = Modifier
+ .align(Alignment.End)
+ .padding(top = 16.dp)
+ )
+ if (state.isLoggedIn is Loading) {
+ // FIXME This does not work, we never enter this if block
+ CircularProgressIndicator(
+ modifier = Modifier.align(Alignment.CenterHorizontally)
+ )
+ }
+ if (state.isLoggedIn is Success) {
+ onLoginWithSuccess()
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginViewModel.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt
similarity index 58%
rename from libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginViewModel.kt
rename to features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt
index efb486ca5e..ce1d093925 100644
--- a/libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginViewModel.kt
+++ b/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt
@@ -1,11 +1,11 @@
-package io.element.android.x.ui.screen.login
+package io.element.android.x.features.login
import android.util.Log
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksViewModel
import com.airbnb.mvrx.Success
-import io.element.android.x.sdk.matrix.MatrixInstance
+import io.element.android.x.matrix.MatrixInstance
import kotlinx.coroutines.launch
class LoginViewModel(initialState: LoginViewState) :
@@ -13,28 +13,6 @@ class LoginViewModel(initialState: LoginViewState) :
private val matrix = MatrixInstance.getInstance()
- init {
- observeState()
- }
-
- private fun observeState() {
- onEach(
- LoginViewState::homeserver,
- LoginViewState::login,
- LoginViewState::password,
- LoginViewState::isLoggedIn,
- ) { homeserver, login, password, isLoggedIn ->
- setState {
- copy(
- submitEnabled = homeserver.isNotEmpty() &&
- login.isNotEmpty() &&
- password.isNotEmpty() &&
- isLoggedIn !is Loading
- )
- }
- }
- }
-
fun handle(action: LoginActions) {
when (action) {
is LoginActions.SetHomeserver -> handleSetHomeserver(action)
@@ -44,14 +22,6 @@ class LoginViewModel(initialState: LoginViewState) :
}
}
- private fun handleSetHomeserver(action: LoginActions.SetHomeserver) {
- setState {
- copy(
- homeserver = action.homeserver
- )
- }
- }
-
private fun handleSubmit() = withState { state ->
viewModelScope.launch {
setState { copy(isLoggedIn = Loading()) }
@@ -65,20 +35,15 @@ class LoginViewModel(initialState: LoginViewState) :
}
}
+ private fun handleSetHomeserver(action: LoginActions.SetHomeserver) {
+ setState { copy(homeserver = action.homeserver) }
+ }
+
private fun handleSetPassword(action: LoginActions.SetPassword) {
- setState {
- copy(
- password = action.password
- )
- }
+ setState { copy(password = action.password) }
}
private fun handleSetName(action: LoginActions.SetLogin) {
- setState {
- copy(
-
- login = action.login
- )
- }
+ setState { copy(login = action.login) }
}
}
\ No newline at end of file
diff --git a/libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginViewState.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt
similarity index 63%
rename from libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginViewState.kt
rename to features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt
index 83c9ec295a..018c9d08f2 100644
--- a/libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginViewState.kt
+++ b/features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.ui.screen.login
+package io.element.android.x.features.login
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MavericksState
@@ -8,6 +8,10 @@ data class LoginViewState(
val homeserver: String = "matrix.org",
val login: String = "",
val password: String = "",
- val submitEnabled: Boolean = false,
val isLoggedIn: Async = Uninitialized,
-) : MavericksState
+) : MavericksState {
+
+ val submitEnabled = homeserver.isNotEmpty() && login.isNotEmpty() && password.isNotEmpty()
+
+
+}
diff --git a/features/login/src/main/res/drawable/element_logo_green.xml b/features/login/src/main/res/drawable/element_logo_green.xml
new file mode 100644
index 0000000000..6e948c3536
--- /dev/null
+++ b/features/login/src/main/res/drawable/element_logo_green.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
diff --git a/features/login/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt b/features/login/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt
new file mode 100644
index 0000000000..bcc403cdbf
--- /dev/null
+++ b/features/login/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package io.element.android.x.features.login
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/features/messages/.gitignore b/features/messages/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/features/messages/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/features/messages/build.gradle b/features/messages/build.gradle
new file mode 100644
index 0000000000..b67bfc7680
--- /dev/null
+++ b/features/messages/build.gradle
@@ -0,0 +1,41 @@
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ namespace 'io.element.android.x.features.messages'
+ compileSdk 32
+
+ defaultConfig {
+ minSdk 24
+ targetSdk 32
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.core:core-ktx:1.7.0'
+ implementation 'androidx.appcompat:appcompat:1.4.1'
+ implementation 'com.google.android.material:material:1.5.0'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+}
\ No newline at end of file
diff --git a/features/messages/consumer-rules.pro b/features/messages/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/features/messages/proguard-rules.pro b/features/messages/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/features/messages/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/features/messages/src/androidTest/java/io/element/android/x/features/messages/ExampleInstrumentedTest.kt b/features/messages/src/androidTest/java/io/element/android/x/features/messages/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000000..5594e59678
--- /dev/null
+++ b/features/messages/src/androidTest/java/io/element/android/x/features/messages/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package io.element.android.x.features.messages
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("io.element.android.x.features.messages.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/libraries/ui/screens/login/src/main/AndroidManifest.xml b/features/messages/src/main/AndroidManifest.xml
similarity index 57%
rename from libraries/ui/screens/login/src/main/AndroidManifest.xml
rename to features/messages/src/main/AndroidManifest.xml
index eb40e709cb..a5918e68ab 100644
--- a/libraries/ui/screens/login/src/main/AndroidManifest.xml
+++ b/features/messages/src/main/AndroidManifest.xml
@@ -1,8 +1,4 @@
-
-
-
-
\ No newline at end of file
diff --git a/features/messages/src/test/java/io/element/android/x/features/messages/ExampleUnitTest.kt b/features/messages/src/test/java/io/element/android/x/features/messages/ExampleUnitTest.kt
new file mode 100644
index 0000000000..d1fddda9b7
--- /dev/null
+++ b/features/messages/src/test/java/io/element/android/x/features/messages/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package io.element.android.x.features.messages
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/features/roomlist/.gitignore b/features/roomlist/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/features/roomlist/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/features/roomlist/build.gradle.kts b/features/roomlist/build.gradle.kts
new file mode 100644
index 0000000000..9fc5858ba0
--- /dev/null
+++ b/features/roomlist/build.gradle.kts
@@ -0,0 +1,18 @@
+plugins {
+ id("io.element.android-compose")
+}
+
+android {
+ namespace = "io.element.android.x.features.roomlist"
+}
+
+dependencies {
+ implementation(project(":libraries:core"))
+ implementation(project(":libraries:matrix"))
+ implementation(project(":libraries:designsystem"))
+ implementation("com.airbnb.android:mavericks-compose:3.0.1")
+
+ testImplementation("junit:junit:4.13.2")
+ androidTestImplementation("androidx.test.ext:junit:1.1.3")
+ androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
+}
\ No newline at end of file
diff --git a/features/roomlist/consumer-rules.pro b/features/roomlist/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/features/roomlist/proguard-rules.pro b/features/roomlist/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/features/roomlist/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/features/roomlist/src/androidTest/java/io/element/android/x/features/roomlist/ExampleInstrumentedTest.kt b/features/roomlist/src/androidTest/java/io/element/android/x/features/roomlist/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000000..8b9c88c9c3
--- /dev/null
+++ b/features/roomlist/src/androidTest/java/io/element/android/x/features/roomlist/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package io.element.android.x.features.roomlist
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("io.element.android.x.features.roomlist.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/libraries/ui/screens/roomlist/src/main/AndroidManifest.xml b/features/roomlist/src/main/AndroidManifest.xml
similarity index 57%
rename from libraries/ui/screens/roomlist/src/main/AndroidManifest.xml
rename to features/roomlist/src/main/AndroidManifest.xml
index f292776d9a..a5918e68ab 100644
--- a/libraries/ui/screens/roomlist/src/main/AndroidManifest.xml
+++ b/features/roomlist/src/main/AndroidManifest.xml
@@ -1,8 +1,4 @@
-
-
-
-
\ No newline at end of file
diff --git a/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/MatrixUser.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/MatrixUser.kt
similarity index 73%
rename from libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/MatrixUser.kt
rename to features/roomlist/src/main/java/io/element/android/x/features/roomlist/MatrixUser.kt
index f62d0733f5..a9f5672ffd 100644
--- a/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/MatrixUser.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/MatrixUser.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.ui.screen.roomlist
+package io.element.android.x.features.roomlist
data class MatrixUser(
val username: String? = null,
diff --git a/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListActions.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListActions.kt
similarity index 57%
rename from libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListActions.kt
rename to features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListActions.kt
index d8f08220f6..8dbb84733d 100644
--- a/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListActions.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListActions.kt
@@ -1,7 +1,6 @@
-package io.element.android.x.ui.screen.roomlist
+package io.element.android.x.features.roomlist
sealed interface RoomListActions {
- object Init : RoomListActions
object LoadMore : RoomListActions
object Logout : RoomListActions
}
diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt
new file mode 100644
index 0000000000..a5257184c5
--- /dev/null
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt
@@ -0,0 +1,70 @@
+package io.element.android.x.features.roomlist
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import com.airbnb.mvrx.Success
+import com.airbnb.mvrx.compose.collectAsState
+import com.airbnb.mvrx.compose.mavericksViewModel
+import org.matrix.rustcomponents.sdk.Room
+
+@Composable
+fun RoomListScreen(
+ viewModel: RoomListViewModel = mavericksViewModel(),
+ onRoomClicked: (String) -> Unit = { }
+) {
+ val state by viewModel.collectAsState()
+ RoomListContent(state, onRoomClicked)
+}
+
+@Composable
+fun RoomListContent(
+ state: RoomListViewState,
+ onRoomClicked: (String) -> Unit
+) {
+ Surface(color = MaterialTheme.colorScheme.background) {
+ Column(
+ modifier = Modifier.fillMaxSize()
+ ) {
+ val rooms = state.rooms
+ if (rooms is Success) {
+ LazyColumn {
+ items(rooms()) { room ->
+ RoomItem(room = room) {
+ onRoomClicked(it)
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+private fun RoomItem(
+ modifier: Modifier = Modifier,
+ room: Room,
+ onClick: (String) -> Unit
+) {
+ Row(verticalAlignment = Alignment.CenterVertically,
+ modifier = modifier
+ .clickable {
+ onClick(room.id())
+ }
+ .fillMaxWidth()
+ ) {
+ Column(modifier = modifier.padding(8.dp)) {
+ Text(text = "Room: ${room.name() ?: room.id()}")
+ Text(text = if (room.isDirect()) "Direct" else "Room")
+ }
+ }
+}
\ No newline at end of file
diff --git a/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListViewModel.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt
similarity index 92%
rename from libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListViewModel.kt
rename to features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt
index 95cd777e75..9e195b2da4 100644
--- a/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListViewModel.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt
@@ -1,12 +1,12 @@
-package io.element.android.x.ui.screen.roomlist
+package io.element.android.x.features.roomlist
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MavericksViewModel
import com.airbnb.mvrx.Success
import io.element.android.x.core.data.tryOrNull
-import io.element.android.x.sdk.matrix.MatrixClient
-import io.element.android.x.sdk.matrix.MatrixInstance
+import io.element.android.x.matrix.MatrixClient
+import io.element.android.x.matrix.MatrixInstance
import kotlinx.coroutines.launch
import org.matrix.rustcomponents.sdk.Room
import org.matrix.rustcomponents.sdk.StoppableSpawn
@@ -19,9 +19,12 @@ class RoomListViewModel(initialState: RoomListViewState) :
private var sync: StoppableSpawn? = null
private val matrix = MatrixInstance.getInstance()
+ init {
+ handleInit()
+ }
+
fun handle(action: RoomListActions) {
when (action) {
- RoomListActions.Init -> handleInit()
RoomListActions.LoadMore -> TODO()
RoomListActions.Logout -> handleLogout()
}
diff --git a/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListViewState.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewState.kt
similarity index 90%
rename from libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListViewState.kt
rename to features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewState.kt
index d66a31e41f..337f7eac77 100644
--- a/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListViewState.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewState.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.ui.screen.roomlist
+package io.element.android.x.features.roomlist
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MavericksState
diff --git a/features/roomlist/src/test/java/io/element/android/x/features/roomlist/ExampleUnitTest.kt b/features/roomlist/src/test/java/io/element/android/x/features/roomlist/ExampleUnitTest.kt
new file mode 100644
index 0000000000..39034b2cb2
--- /dev/null
+++ b/features/roomlist/src/test/java/io/element/android/x/features/roomlist/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package io.element.android.x.features.roomlist
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 0000000000..ca640e4cdb
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,67 @@
+[versions]
+# Project
+android_gradle_plugin = "7.3.1"
+kotlin = "1.7.20"
+
+# AndroidX
+material = "1.6.1"
+corektx = "1.9.0"
+datastore = "1.0.0"
+
+# Compose
+compose_compiler = "1.3.2"
+compose_bom = "2022.10.00"
+
+# Coroutines
+coroutines = "1.6.4"
+
+# Accompanist
+accompanist = "0.27.0"
+
+# Test
+test_junit = "4.13.2"
+test_runner = "1.4.0"
+test_core = "1.4.0"
+test_mockk = "1.13.2"
+test_uiautomator = "2.2.0"
+test_junitext = "1.1.3"
+test_barista = "4.2.0"
+test_hamcrest = "2.2"
+test_orchestrator = "1.4.1"
+
+[libraries]
+# Project
+android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref = "android_gradle_plugin" }
+kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
+
+# AndroidX
+androidx_material = { module = "com.google.android.material:material", version.ref = "material" }
+androidx_corektx = { module = "androidx.core:core-ktx", version.ref = "corektx" }
+androidx_datastore = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore" }
+
+androidx_compose_bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose_bom" }
+androidx_compose_foundation = { group = "androidx.compose.foundation", name = "foundation" }
+
+# Coroutines
+coroutines_core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }
+coroutines_test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
+
+# Accompanist
+accompanist_animation = { module = "com.google.accompanist:accompanist-navigation-animation", version.ref = "accompanist" }
+accompanist_permission = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" }
+accompanist_material = { module = "com.google.accompanist:accompanist-navigation-material", version.ref = "accompanist" }
+
+# Test
+test_junit = { module = "junit:junit", version.ref = "test_junit" }
+test_runner = { module = "androidx.test:runner", version.ref = "test_runner" }
+test_core = { module = "androidx.test:core", version.ref = "test_core" }
+test_corektx = { module = "androidx.test:core-ktx", version.ref = "test_core" }
+test_uiautomator = { module = "androidx.test.uiautomator:uiautomator", version.ref = "test_uiautomator" }
+test_junitext = { module = "androidx.test.ext:junit", version.ref = "test_junitext" }
+test_mockk = { module = "io.mockk:mockk", version.ref = "test_mockk" }
+test_barista = { module = "com.adevinta.android:barista", version.ref = "test_barista" }
+test_hamcrest = { module = "org.hamcrest:hamcrest", version.ref = "test_hamcrest" }
+test_orchestrator = { module = "androidx.test:orchestrator", version.ref = "test_orchestrator" }
+
+[bundles]
+
diff --git a/libraries/core/build.gradle b/libraries/core/build.gradle
index b1ec9bdb80..2363a4bdc7 100644
--- a/libraries/core/build.gradle
+++ b/libraries/core/build.gradle
@@ -28,7 +28,7 @@ android {
compose true
}
composeOptions {
- kotlinCompilerExtensionVersion compose_version
+ kotlinCompilerExtensionVersion "1.3.2"
}
kotlinOptions {
jvmTarget = '1.8'
@@ -39,13 +39,13 @@ dependencies {
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
- implementation 'com.google.android.material:material:1.6.1'
+ implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
- implementation 'androidx.activity:activity-compose:1.6.0'
+ implementation 'androidx.activity:activity-compose:1.6.1'
implementation 'androidx.fragment:fragment-ktx:1.5.3'
- implementation 'com.airbnb.android:mavericks-compose:2.7.0'
+ implementation 'com.airbnb.android:mavericks-compose:3.0.1'
}
\ No newline at end of file
diff --git a/libraries/designsystem/.gitignore b/libraries/designsystem/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/libraries/designsystem/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/libraries/designsystem/build.gradle.kts b/libraries/designsystem/build.gradle.kts
new file mode 100644
index 0000000000..ad560836e4
--- /dev/null
+++ b/libraries/designsystem/build.gradle.kts
@@ -0,0 +1,12 @@
+plugins {
+ id("io.element.android-compose")
+}
+
+android {
+ namespace = "io.element.android.x.libraries.designsystem"
+
+ dependencies {
+ // Should not be there, but this is a POC
+ implementation("io.coil-kt:coil-compose:2.2.1")
+ }
+}
\ No newline at end of file
diff --git a/libraries/designsystem/consumer-rules.pro b/libraries/designsystem/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/libraries/designsystem/proguard-rules.pro b/libraries/designsystem/proguard-rules.pro
new file mode 100644
index 0000000000..ff59496d81
--- /dev/null
+++ b/libraries/designsystem/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.kts.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/libraries/designsystem/src/main/AndroidManifest.xml b/libraries/designsystem/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..a5918e68ab
--- /dev/null
+++ b/libraries/designsystem/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/Color.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Color.kt
similarity index 85%
rename from libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/Color.kt
rename to libraries/designsystem/src/main/java/io/element/android/x/designsystem/Color.kt
index e3c4f84570..087195d9e4 100644
--- a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/Color.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Color.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.ui.theme
+package io.element.android.x.designsystem
import androidx.compose.ui.graphics.Color
diff --git a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/Theme.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt
similarity index 97%
rename from libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/Theme.kt
rename to libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt
index 84acfe49c5..88cac26359 100644
--- a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/Theme.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.ui.theme
+package io.element.android.x.designsystem
import android.app.Activity
import android.os.Build
diff --git a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/Type.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt
similarity index 95%
rename from libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/Type.kt
rename to libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt
index 70b0b2a77f..61abc8f135 100644
--- a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/Type.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.ui.theme
+package io.element.android.x.designsystem
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
diff --git a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/components/Avatar.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/Avatar.kt
similarity index 100%
rename from libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/components/Avatar.kt
rename to libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/Avatar.kt
diff --git a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/components/VectorButton.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorButton.kt
similarity index 88%
rename from libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/components/VectorButton.kt
rename to libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorButton.kt
index 03413a9b72..ee7c188f8c 100644
--- a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/components/VectorButton.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorButton.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.ui.theme.components
+package io.element.android.x.designsystem.components
import androidx.compose.material3.Button
import androidx.compose.material3.Text
diff --git a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/components/VectorTextField.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorTextField.kt
similarity index 91%
rename from libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/components/VectorTextField.kt
rename to libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorTextField.kt
index 7d2b61e734..53ffa2739a 100644
--- a/libraries/ui/theme/src/main/java/io/element/android/x/ui/theme/components/VectorTextField.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorTextField.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.ui.theme.components
+package io.element.android.x.designsystem.components
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.ExperimentalMaterial3Api
diff --git a/libraries/sdk/matrix/build.gradle b/libraries/matrix/build.gradle
similarity index 100%
rename from libraries/sdk/matrix/build.gradle
rename to libraries/matrix/build.gradle
diff --git a/libraries/sdk/matrix/src/main/AndroidManifest.xml b/libraries/matrix/src/main/AndroidManifest.xml
similarity index 100%
rename from libraries/sdk/matrix/src/main/AndroidManifest.xml
rename to libraries/matrix/src/main/AndroidManifest.xml
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/LogTag.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/LogTag.kt
new file mode 100644
index 0000000000..cb480d172f
--- /dev/null
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/LogTag.kt
@@ -0,0 +1,3 @@
+package io.element.android.x.matrix
+
+internal const val LOG_TAG = "Matrix"
diff --git a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/Matrix.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/Matrix.kt
similarity index 90%
rename from libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/Matrix.kt
rename to libraries/matrix/src/main/java/io/element/android/x/matrix/Matrix.kt
index dff931f53e..f230a36185 100644
--- a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/Matrix.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/Matrix.kt
@@ -1,8 +1,8 @@
-package io.element.android.x.sdk.matrix
+package io.element.android.x.matrix
import android.content.Context
-import io.element.android.x.sdk.matrix.store.SessionStore
-import io.element.android.x.sdk.matrix.util.logError
+import io.element.android.x.matrix.store.SessionStore
+import io.element.android.x.matrix.util.logError
import org.matrix.rustcomponents.sdk.AuthenticationService
import org.matrix.rustcomponents.sdk.ClientBuilder
import java.io.File
diff --git a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/MatrixClient.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt
similarity index 96%
rename from libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/MatrixClient.kt
rename to libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt
index 7cf37ebc5b..7225da6dda 100644
--- a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/MatrixClient.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt
@@ -1,7 +1,7 @@
-package io.element.android.x.sdk.matrix
+package io.element.android.x.matrix
import android.util.Log
-import io.element.android.x.sdk.matrix.store.SessionStore
+import io.element.android.x.matrix.store.SessionStore
import org.matrix.rustcomponents.sdk.*
class MatrixClient internal constructor(
diff --git a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/MatrixInstance.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixInstance.kt
similarity index 88%
rename from libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/MatrixInstance.kt
rename to libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixInstance.kt
index 231ae54eb6..f7217b1695 100644
--- a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/MatrixInstance.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixInstance.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.sdk.matrix
+package io.element.android.x.matrix
import android.annotation.SuppressLint
import android.content.Context
diff --git a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/RoomWrapper.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/RoomWrapper.kt
similarity index 89%
rename from libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/RoomWrapper.kt
rename to libraries/matrix/src/main/java/io/element/android/x/matrix/RoomWrapper.kt
index bf20258a4c..90aaaa6251 100644
--- a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/RoomWrapper.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/RoomWrapper.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.sdk.matrix
+package io.element.android.x.matrix
import android.util.Log
import org.matrix.rustcomponents.sdk.Client
diff --git a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/store/SessionStore.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/store/SessionStore.kt
similarity index 79%
rename from libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/store/SessionStore.kt
rename to libraries/matrix/src/main/java/io/element/android/x/matrix/store/SessionStore.kt
index 62e802a164..f483256c08 100644
--- a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/store/SessionStore.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/store/SessionStore.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.sdk.matrix.store
+package io.element.android.x.matrix.store
import android.content.Context
import androidx.datastore.core.DataStore
@@ -10,6 +10,10 @@ import kotlinx.coroutines.flow.firstOrNull
private val Context.dataStore: DataStore 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")
internal class SessionStore(
context: Context
@@ -21,10 +25,6 @@ internal class SessionStore(
private val store = context.dataStore
- 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")
suspend fun storeData(sessionData: SessionData) {
store.edit { prefs ->
diff --git a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/util/Error.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/util/Error.kt
similarity index 78%
rename from libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/util/Error.kt
rename to libraries/matrix/src/main/java/io/element/android/x/matrix/util/Error.kt
index e9a7e7c4d8..7fda7869c9 100644
--- a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/util/Error.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/util/Error.kt
@@ -1,7 +1,7 @@
-package io.element.android.x.sdk.matrix.util
+package io.element.android.x.matrix.util
import android.util.Log
-import io.element.android.x.sdk.matrix.LOG_TAG
+import io.element.android.x.matrix.LOG_TAG
import org.matrix.rustcomponents.sdk.ClientException
fun logError(throwable: Throwable) {
diff --git a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/LogTag.kt b/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/LogTag.kt
deleted file mode 100644
index 29092e5fa5..0000000000
--- a/libraries/sdk/matrix/src/main/java/io/element/android/x/sdk/matrix/LogTag.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package io.element.android.x.sdk.matrix
-
-internal const val LOG_TAG = "Matrix"
diff --git a/libraries/ui/screens/login/build.gradle b/libraries/ui/screens/login/build.gradle
deleted file mode 100644
index 14552fbb08..0000000000
--- a/libraries/ui/screens/login/build.gradle
+++ /dev/null
@@ -1,61 +0,0 @@
-plugins {
- id 'com.android.library'
- id 'org.jetbrains.kotlin.android'
-}
-
-android {
- namespace 'io.element.android.x.ui.screen.login'
- compileSdk 33
-
- defaultConfig {
- minSdk 29
- targetSdk 33
-
- consumerProguardFiles "consumer-rules.pro"
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- buildFeatures {
- compose true
- }
- composeOptions {
- kotlinCompilerExtensionVersion compose_version
- }
- kotlinOptions {
- jvmTarget = '1.8'
- }
-}
-
-dependencies {
- implementation project(":libraries:core")
- implementation project(":libraries:ui:theme")
- implementation project(":libraries:sdk:matrix")
-
- implementation 'androidx.core:core-ktx:1.9.0'
- implementation 'androidx.appcompat:appcompat:1.5.1'
-
- implementation 'com.google.android.material:material:1.6.1'
-
- implementation "androidx.compose.ui:ui:$compose_version"
- implementation 'androidx.compose.material3:material3:1.0.0-rc01'
- implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
- debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
- debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
-
- implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
- implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
- implementation 'androidx.activity:activity-compose:1.6.0'
-
- implementation 'androidx.fragment:fragment-ktx:1.5.3'
-
- implementation 'com.airbnb.android:mavericks-compose:2.7.0'
-}
\ No newline at end of file
diff --git a/libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginActivity.kt b/libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginActivity.kt
deleted file mode 100644
index 2b196d0b1d..0000000000
--- a/libraries/ui/screens/login/src/main/java/io/element/android/x/ui/screen/login/LoginActivity.kt
+++ /dev/null
@@ -1,129 +0,0 @@
-package io.element.android.x.ui.screen.login
-
-import android.app.Activity
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.*
-import androidx.compose.foundation.text.KeyboardOptions
-import androidx.compose.material3.*
-import androidx.compose.runtime.getValue
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.text.input.ImeAction
-import androidx.compose.ui.text.input.KeyboardType
-import androidx.compose.ui.unit.dp
-import com.airbnb.mvrx.Fail
-import com.airbnb.mvrx.Loading
-import com.airbnb.mvrx.Success
-import com.airbnb.mvrx.compose.collectAsState
-import com.airbnb.mvrx.compose.mavericksViewModel
-import io.element.android.x.ui.theme.ElementXTheme
-import io.element.android.x.ui.theme.components.VectorButton
-
-class LoginActivity : ComponentActivity() {
-
- @OptIn(ExperimentalMaterial3Api::class)
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- setContent {
- ElementXTheme {
- // A surface container using the 'background' color from the theme
- Surface(
- modifier = Modifier
- .fillMaxSize()
- .padding(16.dp),
- color = MaterialTheme.colorScheme.background
- ) {
- Box(modifier = Modifier.fillMaxSize()) {
- Column(
- modifier = Modifier.fillMaxSize(),
- ) {
- val viewModel: LoginViewModel = mavericksViewModel()
- val state by viewModel.collectAsState()
- val isError = state.isLoggedIn is Fail
- Image(
- painterResource(id = R.drawable.element_logo_green),
- contentDescription = null,
- modifier = Modifier
- .align(Alignment.CenterHorizontally)
- .padding(40.dp)
- )
- OutlinedTextField(
- value = state.homeserver,
- modifier = Modifier.fillMaxWidth(),
- onValueChange = {
- viewModel.handle(LoginActions.SetHomeserver(it))
- },
- keyboardOptions = KeyboardOptions(
- keyboardType = KeyboardType.Uri,
- ),
- )
- OutlinedTextField(
- value = state.login,
- modifier = Modifier
- .fillMaxWidth()
- .padding(top = 8.dp),
- onValueChange = {
- viewModel.handle(LoginActions.SetLogin(it))
- },
- keyboardOptions = KeyboardOptions(
- keyboardType = KeyboardType.Text,
- ),
- )
- OutlinedTextField(
- value = state.password,
- modifier = Modifier
- .fillMaxWidth()
- .padding(top = 8.dp),
- onValueChange = {
- viewModel.handle(LoginActions.SetPassword(it))
- },
- isError = isError,
- keyboardOptions = KeyboardOptions(
- keyboardType = KeyboardType.Password,
- imeAction = ImeAction.Send,
- ),
- )
- if (isError) {
- Text(
- text = (state.isLoggedIn as? Fail)?.toString().orEmpty(),
- color = MaterialTheme.colorScheme.error,
- style = MaterialTheme.typography.bodySmall,
- modifier = Modifier.padding(start = 16.dp)
- )
- }
- VectorButton(
- text = "Submit",
- onClick = {
- viewModel.handle(LoginActions.Submit)
- },
- enabled = state.submitEnabled,
- modifier = Modifier
- .align(Alignment.End)
- .padding(top = 16.dp)
- )
- if (state.isLoggedIn is Loading) {
- // FIXME This does not work, we never enter this if block
- CircularProgressIndicator(
- modifier = Modifier.align(Alignment.CenterHorizontally)
- )
- }
- if (state.isLoggedIn is Success) {
- openRoomList()
- }
- }
- }
- }
- }
- }
- }
-
- private fun openRoomList() {
- setResult(Activity.RESULT_OK)
- finish()
- }
-}
diff --git a/libraries/ui/screens/login/src/main/res/drawable/element_logo_green.xml b/libraries/ui/screens/login/src/main/res/drawable/element_logo_green.xml
deleted file mode 100644
index e9b119c969..0000000000
--- a/libraries/ui/screens/login/src/main/res/drawable/element_logo_green.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
diff --git a/libraries/ui/screens/roomlist/build.gradle b/libraries/ui/screens/roomlist/build.gradle
deleted file mode 100644
index 98641a9681..0000000000
--- a/libraries/ui/screens/roomlist/build.gradle
+++ /dev/null
@@ -1,62 +0,0 @@
-plugins {
- id 'com.android.library'
- id 'org.jetbrains.kotlin.android'
-}
-
-android {
- namespace 'io.element.android.x.ui.screen.roomlist'
- compileSdk 33
-
- defaultConfig {
- minSdk 29
- targetSdk 33
-
- consumerProguardFiles "consumer-rules.pro"
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- buildFeatures {
- compose true
- }
- composeOptions {
- kotlinCompilerExtensionVersion compose_version
- }
- kotlinOptions {
- jvmTarget = '1.8'
- }
-}
-
-dependencies {
- implementation project(":libraries:core")
- implementation project(":libraries:ui:theme")
- implementation project(":libraries:sdk:matrix")
-
- implementation 'androidx.core:core-ktx:1.9.0'
- implementation 'androidx.appcompat:appcompat:1.5.1'
-
- implementation 'com.google.android.material:material:1.6.1'
-
- implementation "androidx.compose.ui:ui:$compose_version"
- implementation 'androidx.compose.material3:material3:1.0.0-rc01'
- implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
- debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
- debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
-
- implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
- implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
- implementation 'androidx.activity:activity-compose:1.6.0'
-
- implementation 'androidx.fragment:fragment-ktx:1.5.3'
-
- implementation 'com.airbnb.android:mavericks-compose:2.7.0'
- implementation 'io.coil-kt:coil-compose:2.2.1'
-}
\ No newline at end of file
diff --git a/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListActivity.kt b/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListActivity.kt
deleted file mode 100644
index cfa77df37f..0000000000
--- a/libraries/ui/screens/roomlist/src/main/java/io/element/android/x/ui/screen/roomlist/RoomListActivity.kt
+++ /dev/null
@@ -1,126 +0,0 @@
-package io.element.android.x.ui.screen.roomlist
-
-import android.os.Bundle
-import android.util.Log
-import android.widget.Toast
-import androidx.activity.ComponentActivity
-import androidx.activity.compose.setContent
-import androidx.compose.foundation.Image
-import androidx.compose.foundation.border
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.*
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.items
-import androidx.compose.foundation.shape.CircleShape
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.ExitToApp
-import androidx.compose.material3.*
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.clip
-import androidx.compose.ui.unit.dp
-import coil.compose.rememberAsyncImagePainter
-import com.airbnb.mvrx.Success
-import com.airbnb.mvrx.compose.collectAsState
-import com.airbnb.mvrx.compose.mavericksViewModel
-import io.element.android.x.ui.theme.ElementXTheme
-import io.element.android.x.ui.theme.components.Avatar
-import org.matrix.rustcomponents.sdk.Room
-
-class RoomListActivity : ComponentActivity() {
-
- private var initDone = false
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- setContent {
- ElementXTheme {
- val viewModel: RoomListViewModel = mavericksViewModel()
- if (!initDone) {
- initDone = true
- viewModel.handle(RoomListActions.Init)
- }
- val state = viewModel.collectAsState()
- // A surface container using the 'background' color from the theme
- Surface(
- modifier = Modifier
- .fillMaxSize()
- .padding(16.dp),
- color = MaterialTheme.colorScheme.background
- ) {
- Column(
- modifier = Modifier.fillMaxSize()
- ) {
- OptionMenu(state.value.user, viewModel)
- val rooms = state.value.rooms
- if (rooms is Success) {
- LazyColumn {
- items(rooms()) { room ->
- RoomCompose(room) {
- Toast.makeText(
- this@RoomListActivity,
- "Room $it clicked!",
- Toast.LENGTH_SHORT
- ).show()
- }
- }
- }
- }
- }
- }
- if (state.value.logoutAction is Success) {
- finish()
- }
- }
- }
- }
-
- @Composable
- private fun RoomCompose(room: Room, onClick: (String) -> Unit) {
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .clickable { onClick.invoke(room.id()) },
- ) {
- Image(
- painter = rememberAsyncImagePainter(model = room.avatarUrl()),
- contentDescription = null,
- modifier = Modifier.size(32.dp),
- )
- Spacer(modifier = Modifier.width(8.dp))
- Column(
- modifier = Modifier
- .fillMaxWidth()
- .height(32.dp),
- ) {
- Text(text = "Room: ${room.name() ?: room.id()}")
- Text(text = if (room.isDirect()) "Direct" else "Room")
- }
-
- }
- }
-
- @OptIn(ExperimentalMaterial3Api::class)
- @Composable
- private fun OptionMenu(matrixUser: MatrixUser, viewModel: RoomListViewModel) {
- TopAppBar(
- title = {
- Row(
- modifier = Modifier.fillMaxWidth()
- ) {
- Avatar(data = matrixUser.avatarData)
- Spacer(modifier = Modifier.width(8.dp))
- Text("${matrixUser.username}")
- }
- },
- actions = {
- IconButton(
- onClick = { viewModel.handle(RoomListActions.Logout) }
- ) {
- Icon(Icons.Default.ExitToApp, contentDescription = "logout")
- }
- }
- )
- }
-}
diff --git a/libraries/ui/theme/build.gradle b/libraries/ui/theme/build.gradle
deleted file mode 100644
index 796034f2cf..0000000000
--- a/libraries/ui/theme/build.gradle
+++ /dev/null
@@ -1,52 +0,0 @@
-plugins {
- id 'com.android.library'
- id 'org.jetbrains.kotlin.android'
-}
-
-android {
- namespace 'io.element.android.x.theme'
- compileSdk 33
-
- defaultConfig {
- minSdk 29
- targetSdk 33
-
- consumerProguardFiles "consumer-rules.pro"
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- buildFeatures {
- compose true
- }
- composeOptions {
- kotlinCompilerExtensionVersion compose_version
- }
- kotlinOptions {
- jvmTarget = '1.8'
- }
-}
-
-dependencies {
- implementation 'androidx.core:core-ktx:1.9.0'
- implementation 'androidx.appcompat:appcompat:1.5.1'
- implementation 'com.google.android.material:material:1.6.1'
-
- implementation "androidx.compose.ui:ui:$compose_version"
- implementation 'androidx.compose.material3:material3:1.0.0-rc01'
- implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
- debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
- debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
-
- implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
-
- implementation 'io.coil-kt:coil-compose:2.2.1'
-}
\ No newline at end of file
diff --git a/plugins/build.gradle.kts b/plugins/build.gradle.kts
new file mode 100644
index 0000000000..dcb444f0fd
--- /dev/null
+++ b/plugins/build.gradle.kts
@@ -0,0 +1,14 @@
+plugins {
+ `kotlin-dsl`
+ `kotlin-dsl-precompiled-script-plugins`
+}
+
+repositories {
+ mavenCentral()
+ google()
+}
+
+dependencies {
+ implementation(libs.android.gradle.plugin)
+ implementation(libs.kotlin.gradle.plugin)
+}
diff --git a/plugins/settings.gradle.kts b/plugins/settings.gradle.kts
new file mode 100644
index 0000000000..c3b0279a15
--- /dev/null
+++ b/plugins/settings.gradle.kts
@@ -0,0 +1,10 @@
+dependencyResolutionManagement {
+ repositories {
+ mavenCentral()
+ }
+ versionCatalogs {
+ create("libs") {
+ from(files("../gradle/libs.versions.toml"))
+ }
+ }
+}
diff --git a/plugins/src/main/java/Versions.kt b/plugins/src/main/java/Versions.kt
new file mode 100644
index 0000000000..14e5953e38
--- /dev/null
+++ b/plugins/src/main/java/Versions.kt
@@ -0,0 +1,17 @@
+import org.gradle.api.JavaVersion
+import org.gradle.api.artifacts.VersionCatalog
+import org.gradle.jvm.toolchain.JavaLanguageVersion
+
+val VersionCatalog.composeVersion: String
+ get() = findVersion("compose_compiler").get().requiredVersion
+
+object Versions {
+ const val versionCode = 100100
+ const val versionName = "0.1.0"
+
+ const val compileSdk = 33
+ const val targetSdk = 33
+ const val minSdk = 24
+ val javaCompileVersion = JavaVersion.VERSION_11
+ val javaLanguageVersion: JavaLanguageVersion = JavaLanguageVersion.of(11)
+}
diff --git a/plugins/src/main/java/extension/CommonExtension.kt b/plugins/src/main/java/extension/CommonExtension.kt
new file mode 100644
index 0000000000..da97ef62c5
--- /dev/null
+++ b/plugins/src/main/java/extension/CommonExtension.kt
@@ -0,0 +1,50 @@
+package extension
+
+import Versions
+import com.android.build.api.dsl.CommonExtension
+import com.android.build.api.dsl.LibraryExtension
+import composeVersion
+import org.gradle.api.artifacts.VersionCatalog
+
+fun CommonExtension<*, *, *, *>.androidConfig() {
+
+
+
+ defaultConfig {
+ compileSdk = Versions.compileSdk
+ minSdk = Versions.minSdk
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ testOptions {
+ unitTests.isReturnDefaultValues = true
+ }
+}
+
+fun CommonExtension<*, *, *, *>.composeConfig() {
+ buildFeatures {
+ compose = true
+ }
+
+ composeOptions {
+ kotlinCompilerExtensionVersion = "1.3.2"
+ }
+
+ packagingOptions {
+ resources.excludes.apply {
+ add("META-INF/AL2.0")
+ add("META-INF/LGPL2.1")
+ }
+ }
+}
+
+fun LibraryExtension.proguardConfig() {
+ buildTypes {
+ getByName("release") {
+ isMinifyEnabled = true
+ proguardFiles("proguard-android.txt", "proguard-rules.pro")
+ consumerProguardFiles("proguard-rules.pro")
+ }
+ }
+}
+
diff --git a/plugins/src/main/java/io.element.android-compose.gradle.kts b/plugins/src/main/java/io.element.android-compose.gradle.kts
new file mode 100644
index 0000000000..1f1ca3861f
--- /dev/null
+++ b/plugins/src/main/java/io.element.android-compose.gradle.kts
@@ -0,0 +1,29 @@
+import extension.androidConfig
+import extension.composeConfig
+import extension.proguardConfig
+
+plugins {
+ id("com.android.library")
+ id("kotlin-android")
+}
+
+android {
+ androidConfig()
+ proguardConfig()
+ composeConfig()
+}
+
+dependencies {
+ implementation(platform("androidx.compose:compose-bom:2022.10.00"))
+
+ implementation("androidx.compose.ui:ui")
+ implementation("androidx.compose.material3:material3")
+ implementation("androidx.compose.ui:ui-tooling-preview")
+ implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.5.1")
+ implementation("androidx.activity:activity-compose:1.6.1")
+ implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1")
+ implementation("com.airbnb.android:mavericks-compose:3.0.1")
+ debugImplementation("androidx.compose.ui:ui-tooling")
+ debugImplementation("androidx.compose.ui:ui-test-manifest")
+
+}
diff --git a/plugins/src/main/java/io.element.android-library.gradle.kts b/plugins/src/main/java/io.element.android-library.gradle.kts
new file mode 100644
index 0000000000..c80c9ae399
--- /dev/null
+++ b/plugins/src/main/java/io.element.android-library.gradle.kts
@@ -0,0 +1,12 @@
+import extension.androidConfig
+import extension.proguardConfig
+
+plugins {
+ id("com.android.library")
+ id("kotlin-android")
+}
+
+android {
+ androidConfig()
+ proguardConfig()
+}
diff --git a/settings.gradle b/settings.gradle.kts
similarity index 55%
rename from settings.gradle
rename to settings.gradle.kts
index aa27129117..e64417e0aa 100644
--- a/settings.gradle
+++ b/settings.gradle.kts
@@ -1,5 +1,6 @@
pluginManagement {
repositories {
+ includeBuild("plugins")
gradlePluginPortal()
google()
mavenCentral()
@@ -11,14 +12,15 @@ dependencyResolutionManagement {
google()
mavenCentral()
flatDir {
- dirs 'libraries/sdk/matrix/libs'
+ dirs("libraries/matrix/libs")
}
}
}
rootProject.name = "ElementX"
-include ':app'
-include ':libraries:core'
-include ':libraries:ui:theme'
-include ':libraries:ui:screens:login'
-include ':libraries:ui:screens:roomlist'
-include ':libraries:sdk:matrix'
+include(":app")
+include(":libraries:core")
+include(":libraries:matrix")
+include(":features:login")
+include(":features:roomlist")
+include(":features:messages")
+include(":libraries:designsystem")