mirror of
https://github.com/Steffo99/twom.git
synced 2024-11-25 09:34:25 +00:00
Progress. Probably.
This commit is contained in:
parent
1204669c88
commit
cdad623e96
21 changed files with 128 additions and 441 deletions
|
@ -31,7 +31,7 @@
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".matrix.MatrixActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:theme="@android:style/Theme.NoTitleBar">
|
android:theme="@android:style/Theme.NoTitleBar">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@ -42,11 +42,11 @@
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.login.LoginActivity"
|
android:name=".login.LoginActivity"
|
||||||
android:theme="@android:style/Theme.NoTitleBar" />
|
android:theme="@android:style/Theme.NoTitleBar" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.homeserver.SelectHomeserverActivity"
|
android:name=".homeserver.SelectHomeserverActivity"
|
||||||
android:theme="@android:style/Theme.NoTitleBar" />
|
android:theme="@android:style/Theme.NoTitleBar" />
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
15
app/src/main/java/eu/steffo/twom/login/LoginActivity.kt
Normal file
15
app/src/main/java/eu/steffo/twom/login/LoginActivity.kt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package eu.steffo.twom.login
|
||||||
|
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.activity.compose.setContent
|
||||||
|
|
||||||
|
|
||||||
|
class LoginActivity : ComponentActivity() {
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
|
||||||
|
setContent {
|
||||||
|
LoginActivityScaffold()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
package eu.steffo.twom.ui.login
|
package eu.steffo.twom.login
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
@ -17,7 +19,7 @@ import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import eu.steffo.twom.R
|
import eu.steffo.twom.R
|
||||||
import eu.steffo.twom.matrix.TwoMMatrix
|
import eu.steffo.twom.matrix.TwoMMatrix
|
||||||
import eu.steffo.twom.ui.BASE_PADDING
|
import eu.steffo.twom.theme.TwoMPadding
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
|
||||||
|
@ -26,8 +28,6 @@ import org.matrix.android.sdk.api.session.Session
|
||||||
@Preview(showBackground = true)
|
@Preview(showBackground = true)
|
||||||
fun LoginActivityControl(
|
fun LoginActivityControl(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
selectedHomeserver: String? = null,
|
|
||||||
onSelectHomeserver: () -> Unit = {},
|
|
||||||
onLogin: (session: Session) -> Unit = {},
|
onLogin: (session: Session) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
@ -38,19 +38,20 @@ fun LoginActivityControl(
|
||||||
var loggingIn by rememberSaveable { mutableStateOf(false) }
|
var loggingIn by rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
Column(modifier) {
|
Column(modifier) {
|
||||||
Row(BASE_PADDING) {
|
if (loggingIn) {
|
||||||
|
LinearProgressIndicator(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
LinearProgressIndicator(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
progress = 0.0f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row(TwoMPadding.base) {
|
||||||
Text(LocalContext.current.getString(R.string.login_text))
|
Text(LocalContext.current.getString(R.string.login_text))
|
||||||
}
|
}
|
||||||
Row(BASE_PADDING) {
|
Row(TwoMPadding.base) {
|
||||||
Button(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
onClick = onSelectHomeserver,
|
|
||||||
enabled = true,
|
|
||||||
) {
|
|
||||||
Text(LocalContext.current.getString(R.string.login_selecthomeserver_text))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Row(BASE_PADDING) {
|
|
||||||
TextField(
|
TextField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = username,
|
value = username,
|
||||||
|
@ -64,18 +65,9 @@ fun LoginActivityControl(
|
||||||
supportingText = {
|
supportingText = {
|
||||||
Text(LocalContext.current.getString(R.string.login_username_supporting))
|
Text(LocalContext.current.getString(R.string.login_username_supporting))
|
||||||
},
|
},
|
||||||
prefix = {
|
|
||||||
Text("@")
|
|
||||||
},
|
|
||||||
suffix = {
|
|
||||||
// TODO: Properly perform the login process
|
|
||||||
val localpart = selectedHomeserver?.replace(Regex("^https?://"), "")
|
|
||||||
Text(":$localpart")
|
|
||||||
},
|
|
||||||
enabled = (selectedHomeserver != null),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Row(BASE_PADDING) {
|
Row(TwoMPadding.base) {
|
||||||
PasswordField(
|
PasswordField(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
value = password,
|
value = password,
|
||||||
|
@ -89,26 +81,48 @@ fun LoginActivityControl(
|
||||||
supportingText = {
|
supportingText = {
|
||||||
Text(LocalContext.current.getString(R.string.login_password_supporting))
|
Text(LocalContext.current.getString(R.string.login_password_supporting))
|
||||||
},
|
},
|
||||||
enabled = (selectedHomeserver != null),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Row(BASE_PADDING) {
|
Row(TwoMPadding.base) {
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
onClick = {
|
onClick = {
|
||||||
val wizard = TwoMMatrix.matrix!!.authenticationService().getLoginWizard()
|
scope.launch Login@{
|
||||||
|
Log.d(this::class.qualifiedName, "Launching login wizard...")
|
||||||
|
val wizard = TwoMMatrix.matrix.authenticationService().getLoginWizard()
|
||||||
|
|
||||||
scope.launch {
|
// TODO: Which exceptions can this spawn?
|
||||||
val session = wizard.login(
|
Log.d(this::class.qualifiedName, "Trying to login as: $username")
|
||||||
login = "@$username:$selectedHomeserver",
|
loggingIn = true
|
||||||
|
|
||||||
|
lateinit var session: Session
|
||||||
|
// TODO: Why does this not catch the exception?
|
||||||
|
try {
|
||||||
|
session = wizard.login(
|
||||||
|
login = username,
|
||||||
password = password,
|
password = password,
|
||||||
initialDeviceName = "Garasauto", // TODO
|
initialDeviceName = "Garasauto", // TODO
|
||||||
deviceId = "Garasauto", // TODO
|
deviceId = "Garasauto", // TODO
|
||||||
)
|
)
|
||||||
TwoMMatrix.session = session
|
} catch (e: RuntimeException) {
|
||||||
|
Log.e(
|
||||||
|
this::class.qualifiedName,
|
||||||
|
"Something went wrong while logging in as: $username",
|
||||||
|
e
|
||||||
|
)
|
||||||
|
return@Login
|
||||||
|
} finally {
|
||||||
|
loggingIn = false
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(
|
||||||
|
this::class.qualifiedName,
|
||||||
|
"Logged in with session id: ${session.sessionId}"
|
||||||
|
)
|
||||||
|
onLogin(session)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
enabled = (username != "" && TwoMMatrix.matrix != null),
|
enabled = (username != ""),
|
||||||
) {
|
) {
|
||||||
Text(LocalContext.current.getString(R.string.login_complete_text))
|
Text(LocalContext.current.getString(R.string.login_complete_text))
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.steffo.twom.ui.login
|
package eu.steffo.twom.login
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
@ -14,7 +14,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import eu.steffo.twom.R
|
import eu.steffo.twom.R
|
||||||
import eu.steffo.twom.ui.theme.TwoMTheme
|
import eu.steffo.twom.theme.TwoMTheme
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,11 +43,7 @@ fun LoginActivityScaffold(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
LoginActivityControl(
|
LoginActivityControl(Modifier.padding(it))
|
||||||
modifier = Modifier.padding(it),
|
|
||||||
selectedHomeserver = selectedHomeserver,
|
|
||||||
onSelectHomeserver = onSelectHomeserver,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package eu.steffo.twom.ui.login
|
package eu.steffo.twom.login
|
||||||
|
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
@ -10,7 +9,6 @@ import androidx.compose.material.icons.filled.FavoriteBorder
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.LocalTextStyle
|
import androidx.compose.material3.LocalTextStyle
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.material3.TextFieldColors
|
import androidx.compose.material3.TextFieldColors
|
||||||
import androidx.compose.material3.TextFieldDefaults
|
import androidx.compose.material3.TextFieldDefaults
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.steffo.twom
|
package eu.steffo.twom.matrix
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -17,24 +17,24 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import eu.steffo.twom.matrix.TwoMMatrix
|
import eu.steffo.twom.R
|
||||||
import eu.steffo.twom.ui.login.LoginActivity
|
import eu.steffo.twom.login.LoginActivity
|
||||||
import eu.steffo.twom.ui.theme.TwoMTheme
|
import eu.steffo.twom.theme.TwoMTheme
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
class MainActivity : ComponentActivity() {
|
class MatrixActivity : ComponentActivity() {
|
||||||
private lateinit var loginLauncher: ActivityResultLauncher<Intent>
|
private lateinit var loginLauncher: ActivityResultLauncher<Intent>
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
actionBar?.hide()
|
actionBar?.hide()
|
||||||
|
|
||||||
TwoMMatrix.initMatrix(applicationContext)
|
TwoMMatrix.ensureMatrix(applicationContext)
|
||||||
TwoMMatrix.tryInitSessionFromStorage()
|
|
||||||
|
|
||||||
loginLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
loginLauncher =
|
||||||
Log.i("Garasauto", "Garaso")
|
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||||
|
Log.d(this::class.qualifiedName, "LoginActivity has returned a result.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,8 +45,10 @@ class MainActivity : ComponentActivity() {
|
||||||
TwoMTheme {
|
TwoMTheme {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
CenterAlignedTopAppBar (
|
CenterAlignedTopAppBar(
|
||||||
title = { Text(LocalContext.current.getString(R.string.app_name)) }
|
title = {
|
||||||
|
Text(LocalContext.current.getString(R.string.app_name))
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) {
|
) {
|
|
@ -1,3 +0,0 @@
|
||||||
package eu.steffo.twom.matrix
|
|
||||||
|
|
||||||
class MatrixAlreadyInitializedError : Exception()
|
|
|
@ -1,3 +0,0 @@
|
||||||
package eu.steffo.twom.matrix
|
|
||||||
|
|
||||||
class SessionAlreadyInitializedError : Exception()
|
|
|
@ -1,3 +0,0 @@
|
||||||
package eu.steffo.twom.matrix
|
|
||||||
|
|
||||||
class SessionNotInitializedError : Exception()
|
|
|
@ -1,20 +1,32 @@
|
||||||
package eu.steffo.twom.matrix
|
package eu.steffo.twom.matrix
|
||||||
|
|
||||||
import TwoMRoomDisplayNameFallbackProvider
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import org.matrix.android.sdk.api.Matrix
|
import org.matrix.android.sdk.api.Matrix
|
||||||
import org.matrix.android.sdk.api.MatrixConfiguration
|
import org.matrix.android.sdk.api.MatrixConfiguration
|
||||||
import org.matrix.android.sdk.api.session.Session
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object containing the global state of the application.
|
||||||
|
*/
|
||||||
object TwoMMatrix {
|
object TwoMMatrix {
|
||||||
var matrix: Matrix? = null
|
/**
|
||||||
private set
|
* The global [Matrix] object of the application.
|
||||||
|
*
|
||||||
|
* Most activities will expect this to be available.
|
||||||
|
*/
|
||||||
|
lateinit var matrix: Matrix
|
||||||
|
|
||||||
fun initMatrix(context: Context) {
|
private fun isMatrixInitialized(): Boolean {
|
||||||
if(matrix != null) {
|
return this::matrix.isInitialized
|
||||||
throw MatrixAlreadyInitializedError()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure the [matrix] object is available, constructing it if it isn't initialized.
|
||||||
|
*
|
||||||
|
* Uses the passed [Context] to access the [application context][Context.getApplicationContext], which is required by the SDK provided by the Matrix Foundation.
|
||||||
|
*/
|
||||||
|
fun ensureMatrix(context: Context): Matrix? {
|
||||||
|
if (!isMatrixInitialized()) {
|
||||||
matrix = Matrix(
|
matrix = Matrix(
|
||||||
context = context.applicationContext,
|
context = context.applicationContext,
|
||||||
matrixConfiguration = MatrixConfiguration(
|
matrixConfiguration = MatrixConfiguration(
|
||||||
|
@ -22,37 +34,8 @@ object TwoMMatrix {
|
||||||
roomDisplayNameFallbackProvider = TwoMRoomDisplayNameFallbackProvider(context.applicationContext)
|
roomDisplayNameFallbackProvider = TwoMRoomDisplayNameFallbackProvider(context.applicationContext)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
return matrix
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
var session: Session? = null
|
|
||||||
set(value) {
|
|
||||||
if (field != null) {
|
|
||||||
closeSession()
|
|
||||||
}
|
|
||||||
field = value
|
|
||||||
if (field != null) {
|
|
||||||
openSession()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun tryInitSessionFromStorage() {
|
|
||||||
val lastSession = matrix?.authenticationService()?.getLastAuthenticatedSession()
|
|
||||||
if(lastSession != null) {
|
|
||||||
session = lastSession
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Does this throw an error if the session is already open?
|
|
||||||
private fun openSession() {
|
|
||||||
val currentSession = session ?: throw SessionNotInitializedError()
|
|
||||||
currentSession.open()
|
|
||||||
currentSession.syncService().startSync(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Does this throw an error if the session is already closed?
|
|
||||||
private fun closeSession() {
|
|
||||||
val currentSession = session ?: throw SessionNotInitializedError()
|
|
||||||
currentSession.close()
|
|
||||||
currentSession.syncService().stopSync()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
package eu.steffo.twom.matrix
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import eu.steffo.twom.R
|
import eu.steffo.twom.R
|
||||||
import org.matrix.android.sdk.api.provider.RoomDisplayNameFallbackProvider
|
import org.matrix.android.sdk.api.provider.RoomDisplayNameFallbackProvider
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package eu.steffo.twom.ui
|
package eu.steffo.twom.theme
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
|
||||||
val BASE_PADDING = Modifier.padding(all = 10.dp)
|
object TwoMPadding {
|
||||||
|
val base = Modifier.padding(all = 10.dp)
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
package eu.steffo.twom.ui.theme
|
package eu.steffo.twom.theme
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Typography
|
||||||
import androidx.compose.material3.dynamicDarkColorScheme
|
import androidx.compose.material3.dynamicDarkColorScheme
|
||||||
import androidx.compose.material3.dynamicLightColorScheme
|
import androidx.compose.material3.dynamicLightColorScheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
@ -34,9 +35,11 @@ fun TwoMTheme(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val typography = Typography()
|
||||||
|
|
||||||
MaterialTheme(
|
MaterialTheme(
|
||||||
colorScheme = colorScheme,
|
colorScheme = colorScheme,
|
||||||
typography = Typography,
|
typography = typography,
|
||||||
content = content
|
content = content
|
||||||
)
|
)
|
||||||
}
|
}
|
|
@ -1,30 +0,0 @@
|
||||||
package eu.steffo.twom.ui.homeserver
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.compose.setContent
|
|
||||||
|
|
||||||
|
|
||||||
class SelectHomeserverActivity : ComponentActivity() {
|
|
||||||
companion object {
|
|
||||||
const val HOMESERVER_EXTRA_KEY = "homeserver"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
setContent {
|
|
||||||
SelectHomeserverScaffold(
|
|
||||||
onBack = {
|
|
||||||
setResult(RESULT_CANCELED)
|
|
||||||
finish()
|
|
||||||
},
|
|
||||||
onComplete = {
|
|
||||||
val result = Intent()
|
|
||||||
result.putExtra(HOMESERVER_EXTRA_KEY, it)
|
|
||||||
setResult(RESULT_OK, result)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
package eu.steffo.twom.ui.homeserver
|
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import android.webkit.URLUtil
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import eu.steffo.twom.R
|
|
||||||
import eu.steffo.twom.matrix.TwoMMatrix
|
|
||||||
import eu.steffo.twom.ui.BASE_PADDING
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
fun SelectHomeserverControl(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
onComplete: (homeserver: String) -> Unit = {},
|
|
||||||
) {
|
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
var homeserver by rememberSaveable { mutableStateOf("") }
|
|
||||||
var state by rememberSaveable { mutableStateOf(SelectHomeserverFieldState.Empty) }
|
|
||||||
|
|
||||||
Column(modifier) {
|
|
||||||
Row(BASE_PADDING) {
|
|
||||||
Text(LocalContext.current.getString(R.string.selecthomeserver_text))
|
|
||||||
}
|
|
||||||
Row(BASE_PADDING) {
|
|
||||||
SelectHomeserverField(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
value = homeserver,
|
|
||||||
onValueChange = OnValueChange@{
|
|
||||||
homeserver = it
|
|
||||||
state = SelectHomeserverFieldState.Empty
|
|
||||||
|
|
||||||
if (homeserver == "") {
|
|
||||||
return@OnValueChange
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(URLUtil.isHttpUrl(homeserver) || URLUtil.isHttpsUrl(homeserver))) {
|
|
||||||
state = SelectHomeserverFieldState.URLInvalid
|
|
||||||
return@OnValueChange
|
|
||||||
}
|
|
||||||
|
|
||||||
val uri = Uri.parse(homeserver)
|
|
||||||
|
|
||||||
scope.launch ValidateFlows@{
|
|
||||||
state = SelectHomeserverFieldState.Waiting
|
|
||||||
delay(500L)
|
|
||||||
if (homeserver != it) return@ValidateFlows
|
|
||||||
|
|
||||||
val authenticationService = TwoMMatrix.matrix!!.authenticationService()
|
|
||||||
|
|
||||||
state = SelectHomeserverFieldState.Validating
|
|
||||||
try {
|
|
||||||
authenticationService.getLoginFlow(
|
|
||||||
HomeServerConnectionConfig(
|
|
||||||
homeServerUri = uri,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
state = SelectHomeserverFieldState.FlowInvalid
|
|
||||||
return@ValidateFlows
|
|
||||||
}
|
|
||||||
|
|
||||||
state = SelectHomeserverFieldState.Valid
|
|
||||||
}
|
|
||||||
},
|
|
||||||
enabled = (TwoMMatrix.matrix != null),
|
|
||||||
state = state,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Row(BASE_PADDING) {
|
|
||||||
Button(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
onClick = {
|
|
||||||
onComplete(homeserver)
|
|
||||||
},
|
|
||||||
enabled = (state == SelectHomeserverFieldState.Valid),
|
|
||||||
) {
|
|
||||||
Text(LocalContext.current.getString(R.string.selecthomeserver_complete_text))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
package eu.steffo.twom.ui.homeserver
|
|
||||||
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.Check
|
|
||||||
import androidx.compose.material.icons.filled.Close
|
|
||||||
import androidx.compose.material.icons.filled.Create
|
|
||||||
import androidx.compose.material.icons.filled.Send
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextField
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import eu.steffo.twom.R
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
@Preview
|
|
||||||
fun SelectHomeserverField(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
value: String = "",
|
|
||||||
onValueChange: (String) -> Unit = {},
|
|
||||||
enabled: Boolean = true,
|
|
||||||
state: SelectHomeserverFieldState = SelectHomeserverFieldState.Empty,
|
|
||||||
) {
|
|
||||||
TextField(
|
|
||||||
modifier = modifier,
|
|
||||||
value = value,
|
|
||||||
onValueChange = onValueChange,
|
|
||||||
enabled = enabled,
|
|
||||||
singleLine = true,
|
|
||||||
label = {
|
|
||||||
Text(LocalContext.current.getString(R.string.selecthomeserver_input_label))
|
|
||||||
},
|
|
||||||
placeholder = {
|
|
||||||
Text(LocalContext.current.getString(R.string.selecthomeserver_input_placeholder))
|
|
||||||
},
|
|
||||||
trailingIcon = {
|
|
||||||
Icon(
|
|
||||||
when(state) {
|
|
||||||
SelectHomeserverFieldState.Empty -> Icons.Default.Create
|
|
||||||
SelectHomeserverFieldState.Waiting -> Icons.Default.Create
|
|
||||||
SelectHomeserverFieldState.Validating -> Icons.Default.Send
|
|
||||||
SelectHomeserverFieldState.URLInvalid -> Icons.Default.Close
|
|
||||||
SelectHomeserverFieldState.FlowInvalid -> Icons.Default.Close
|
|
||||||
SelectHomeserverFieldState.Valid -> Icons.Default.Check
|
|
||||||
},
|
|
||||||
null
|
|
||||||
)
|
|
||||||
},
|
|
||||||
supportingText = {
|
|
||||||
Text(
|
|
||||||
when(state) {
|
|
||||||
SelectHomeserverFieldState.Empty -> LocalContext.current.getString(R.string.selecthomeserver_input_supporting_empty)
|
|
||||||
SelectHomeserverFieldState.Waiting -> LocalContext.current.getString(R.string.selecthomeserver_input_supporting_waiting)
|
|
||||||
SelectHomeserverFieldState.Validating -> LocalContext.current.getString(R.string.selecthomeserver_input_supporting_validating)
|
|
||||||
SelectHomeserverFieldState.URLInvalid -> LocalContext.current.getString(R.string.selecthomeserver_input_supporting_urlinvalid)
|
|
||||||
SelectHomeserverFieldState.FlowInvalid -> LocalContext.current.getString(R.string.selecthomeserver_input_supporting_flowinvalid)
|
|
||||||
SelectHomeserverFieldState.Valid -> LocalContext.current.getString(R.string.selecthomeserver_input_supporting_valid)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
isError = when(state) {
|
|
||||||
SelectHomeserverFieldState.URLInvalid -> true
|
|
||||||
SelectHomeserverFieldState.FlowInvalid -> true
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package eu.steffo.twom.ui.homeserver
|
|
||||||
|
|
||||||
enum class SelectHomeserverFieldState {
|
|
||||||
Empty,
|
|
||||||
Waiting,
|
|
||||||
Validating,
|
|
||||||
URLInvalid,
|
|
||||||
FlowInvalid,
|
|
||||||
Valid,
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package eu.steffo.twom.ui.homeserver
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import eu.steffo.twom.R
|
|
||||||
import eu.steffo.twom.ui.theme.TwoMTheme
|
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
@Preview
|
|
||||||
fun SelectHomeserverScaffold(
|
|
||||||
onBack: () -> Unit = {},
|
|
||||||
onComplete: (homeserver: String) -> Unit = {},
|
|
||||||
) {
|
|
||||||
TwoMTheme {
|
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
|
||||||
TopAppBar (
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = onBack) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Filled.ArrowBack,
|
|
||||||
contentDescription = LocalContext.current.getString(R.string.back)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = {
|
|
||||||
Text(LocalContext.current.getString(R.string.homeserver_title))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
SelectHomeserverControl(
|
|
||||||
modifier = Modifier.padding(it),
|
|
||||||
onComplete = onComplete
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
package eu.steffo.twom.ui.login
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.compose.setContent
|
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import eu.steffo.twom.ui.homeserver.SelectHomeserverActivity
|
|
||||||
|
|
||||||
|
|
||||||
class LoginActivity : ComponentActivity() {
|
|
||||||
private lateinit var homeserverLauncher: ActivityResultLauncher<Intent>
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
homeserverLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
|
||||||
val selectedHomeserver =
|
|
||||||
it.data?.getStringExtra(SelectHomeserverActivity.HOMESERVER_EXTRA_KEY)
|
|
||||||
Log.d("LoginActivity", "Selected homeserver: $selectedHomeserver")
|
|
||||||
setContent {
|
|
||||||
LoginActivityScaffold(
|
|
||||||
selectedHomeserver = selectedHomeserver,
|
|
||||||
onSelectHomeserver = {
|
|
||||||
homeserverLauncher.launch(
|
|
||||||
Intent(
|
|
||||||
applicationContext,
|
|
||||||
SelectHomeserverActivity::class.java
|
|
||||||
)
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
|
|
||||||
setContent {
|
|
||||||
LoginActivityScaffold(
|
|
||||||
onSelectHomeserver = {
|
|
||||||
homeserverLauncher.launch(Intent(applicationContext, SelectHomeserverActivity::class.java))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
package eu.steffo.twom.ui.theme
|
|
||||||
|
|
||||||
import androidx.compose.material3.Typography
|
|
||||||
|
|
||||||
// Set of Material typography styles to start with
|
|
||||||
val Typography = Typography()
|
|
|
@ -12,7 +12,6 @@
|
||||||
<string name="room_name_fallback_members_more">%1$s, %2$s, %3$s and %4$d others\' party</string>
|
<string name="room_name_fallback_members_more">%1$s, %2$s, %3$s and %4$d others\' party</string>
|
||||||
<string name="room_name_fallback_invite">Party invite</string>
|
<string name="room_name_fallback_invite">Party invite</string>
|
||||||
<string name="selecthomeserver_complete_text">Continue</string>
|
<string name="selecthomeserver_complete_text">Continue</string>
|
||||||
<string name="selecthomeserver_text">Please select the homeserver you would like to log into.</string>
|
|
||||||
<string name="selecthomeserver_input_supporting_flowinvalid">The homeserver URL you provided does not point to a Matrix homeserver.</string>
|
<string name="selecthomeserver_input_supporting_flowinvalid">The homeserver URL you provided does not point to a Matrix homeserver.</string>
|
||||||
<string name="selecthomeserver_input_supporting_validating">Checking if the URL points to a Matrix homeserver…</string>
|
<string name="selecthomeserver_input_supporting_validating">Checking if the URL points to a Matrix homeserver…</string>
|
||||||
<string name="selecthomeserver_input_supporting_waiting">Waiting for you to stop writing…</string>
|
<string name="selecthomeserver_input_supporting_waiting">Waiting for you to stop writing…</string>
|
||||||
|
@ -22,13 +21,13 @@
|
||||||
<string name="back">Go back</string>
|
<string name="back">Go back</string>
|
||||||
<string name="login_text">To use TwoM, you need to log into a Matrix homeserver. Currently, TwoM supports only username and password authentication.</string>
|
<string name="login_text">To use TwoM, you need to log into a Matrix homeserver. Currently, TwoM supports only username and password authentication.</string>
|
||||||
<string name="login_complete_text">Log in</string>
|
<string name="login_complete_text">Log in</string>
|
||||||
<string name="login_selecthomeserver_text">Select homeserver</string>
|
<string name="login_username_placeholder">\@steffo:candy.steffo.eu</string>
|
||||||
<string name="login_username_placeholder">steffo</string>
|
<string name="login_username_supporting">The Matrix ID to login as, including the leading \"@\" and the trailing \":localpart\".</string>
|
||||||
<string name="login_username_supporting">The Matrix ID to login as.</string>
|
|
||||||
<string name="login_password_placeholder">p4ssw0rd!</string>
|
<string name="login_password_placeholder">p4ssw0rd!</string>
|
||||||
<string name="login_password_supporting">The password of the Matrix account.</string>
|
<string name="login_password_supporting">The password of the Matrix account.</string>
|
||||||
<string name="login_username_label">Username</string>
|
<string name="login_username_label">Username</string>
|
||||||
<string name="login_password_label">Password</string>
|
<string name="login_password_label">Password</string>
|
||||||
<string name="password_show">Show password</string>
|
<string name="password_show">Show password</string>
|
||||||
<string name="password_hide">Hide password</string>
|
<string name="password_hide">Hide password</string>
|
||||||
|
<string name="selecthomeserver_text">Please enter the localpart of your Matrix homeserver.</string>
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue