1
Fork 0
mirror of https://github.com/Steffo99/twom.git synced 2024-11-21 23:54:26 +00:00

Get activity message passing working

This commit is contained in:
Steffo 2023-11-20 02:23:51 +01:00
parent c42027be24
commit 395ec102c8
Signed by: steffo
GPG key ID: 2A24051445686895
21 changed files with 458 additions and 329 deletions

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
@ -33,7 +32,8 @@
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true"> android:exported="true"
android:theme="@android:style/Theme.NoTitleBar">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
@ -42,8 +42,12 @@
</activity> </activity>
<activity <activity
android:name=".HomeserverActivity"> android:name=".ui.login.LoginActivity"
</activity> android:theme="@android:style/Theme.NoTitleBar" />
<activity
android:name=".ui.homeserver.SelectHomeserverActivity"
android:theme="@android:style/Theme.NoTitleBar" />
</application> </application>

View file

@ -1,21 +0,0 @@
package eu.steffo.twom
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import eu.steffo.twom.ui.fragment.HomeserverFragment
import eu.steffo.twom.ui.theme.TwoMTheme
class HomeserverActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
actionBar?.hide()
setContent {
TwoMTheme {
HomeserverFragment()
}
}
}
}

View file

@ -2,30 +2,65 @@ package eu.steffo.twom
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
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.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import eu.steffo.twom.global.TwoMMatrix import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import eu.steffo.twom.matrix.TwoMMatrix
import eu.steffo.twom.ui.login.LoginActivity
import eu.steffo.twom.ui.theme.TwoMTheme import eu.steffo.twom.ui.theme.TwoMTheme
@OptIn(ExperimentalMaterial3Api::class)
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
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.initMatrix(applicationContext)
TwoMMatrix.initSessionFromStorage() TwoMMatrix.tryInitSessionFromStorage()
// Do this in a better way loginLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if(TwoMMatrix.session == null) { Log.i("Garasauto", "Garaso")
val homeserverIntent = Intent(applicationContext, HomeserverActivity::class.java)
startActivity(homeserverIntent)
} }
}
override fun onStart() {
super.onStart()
setContent { setContent {
TwoMTheme { TwoMTheme {
Text("Garasauto") Scaffold(
topBar = {
CenterAlignedTopAppBar (
title = { Text(LocalContext.current.getString(R.string.app_name)) }
)
}
) {
Row(Modifier.padding(it)) {
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
loginLauncher.launch(Intent(applicationContext, LoginActivity::class.java))
}
) {
Text("")
}
}
}
} }
} }
} }

View file

@ -1,38 +0,0 @@
package eu.steffo.twom.global
import TwoMRoomDisplayNameFallbackProvider
import android.content.Context
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.session.Session
object TwoMMatrix {
lateinit var matrix: Matrix
private set
fun initMatrix(context: Context) {
matrix = Matrix(
context = context.applicationContext,
matrixConfiguration = MatrixConfiguration(
applicationFlavor = "TwoM",
roomDisplayNameFallbackProvider = TwoMRoomDisplayNameFallbackProvider(context.applicationContext)
)
)
}
var session: Session? = null
fun initSessionFromStorage() {
val lastSession = matrix.authenticationService().getLastAuthenticatedSession()
if(lastSession != null) {
session = lastSession
}
}
fun openSession() {
// FIXME: Possible race condition here?
session?.open()
session?.syncService()?.startSync(true)
}
}

View file

@ -0,0 +1,3 @@
package eu.steffo.twom.matrix
class MatrixAlreadyInitializedError : Exception()

View file

@ -0,0 +1,3 @@
package eu.steffo.twom.matrix
class SessionAlreadyInitializedError : Exception()

View file

@ -0,0 +1,3 @@
package eu.steffo.twom.matrix
class SessionNotInitializedError : Exception()

View file

@ -0,0 +1,56 @@
package eu.steffo.twom.matrix
import TwoMRoomDisplayNameFallbackProvider
import android.content.Context
import androidx.compose.runtime.currentComposer
import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.session.Session
object TwoMMatrix {
var matrix: Matrix? = null
private set
fun initMatrix(context: Context) {
if(matrix != null) {
throw MatrixAlreadyInitializedError()
}
matrix = Matrix(
context = context.applicationContext,
matrixConfiguration = MatrixConfiguration(
applicationFlavor = "TwoM",
roomDisplayNameFallbackProvider = TwoMRoomDisplayNameFallbackProvider(context.applicationContext)
)
)
}
var session: Session? = null
private set
fun tryInitSessionFromStorage() {
val lastSession = matrix?.authenticationService()?.getLastAuthenticatedSession()
if(lastSession != null) {
session = lastSession
}
}
// TODO: Does this throw an error if the session is already open?
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?
fun closeSession() {
val currentSession = session ?: throw SessionNotInitializedError()
currentSession.close()
currentSession.syncService().stopSync()
}
fun clearSession() {
closeSession()
session = null
}
}

View file

@ -1,119 +0,0 @@
package eu.steffo.twom.ui.fragment
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.global.TwoMMatrix
import eu.steffo.twom.ui.input.SelectHomeserverField
import eu.steffo.twom.ui.input.SelectHomeserverFieldState
import eu.steffo.twom.ui.scaffold.TwoMTopAppBar
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
@Composable
@Preview
fun HomeserverFragment() {
val scope = rememberCoroutineScope()
val matrix = TwoMMatrix.matrix
var homeserver by rememberSaveable { mutableStateOf("") }
var state by rememberSaveable { mutableStateOf(SelectHomeserverFieldState.Empty) }
var urlValid by rememberSaveable { mutableStateOf<Boolean?>(null) }
var flowValid by rememberSaveable { mutableStateOf<Boolean?>(null) }
TwoMTopAppBar {
Column(
modifier = Modifier.padding(it)
) {
Row(
modifier = Modifier.padding(start = 20.dp, end = 20.dp, bottom = 10.dp)
) {
Text(LocalContext.current.getString(R.string.login_welcome_text))
}
Row(
modifier = Modifier.padding(start = 20.dp, end = 20.dp, bottom = 10.dp)
) {
SelectHomeserverField(
modifier = Modifier.fillMaxWidth(),
value = homeserver,
onValueChange = OnValueChange@{
homeserver = it
urlValid = null
flowValid = null
state = SelectHomeserverFieldState.Empty
if(homeserver == "") {
return@OnValueChange
}
if(!(URLUtil.isHttpUrl(homeserver) || URLUtil.isHttpsUrl(homeserver))) {
state = SelectHomeserverFieldState.Error
urlValid = false
return@OnValueChange
}
urlValid = true
val uri = Uri.parse(homeserver)
scope.launch ValidateFlows@{
state = SelectHomeserverFieldState.Waiting
delay(500L)
if(homeserver != it) return@ValidateFlows
val authenticationService = matrix.authenticationService()
state = SelectHomeserverFieldState.Validating
try {
authenticationService.getLoginFlow(HomeServerConnectionConfig(
homeServerUri = uri,
))
}
catch(e: Throwable) {
state = SelectHomeserverFieldState.Error
flowValid = false
return@ValidateFlows
}
state = SelectHomeserverFieldState.Done
flowValid = true
}
},
state = state,
error =
if(urlValid == false) LocalContext.current.getString(R.string.homeserver_error_malformedurl)
else if(flowValid == false) LocalContext.current.getString(R.string.homeserver_error_notmatrix)
else null
,
)
}
Row(
modifier = Modifier.padding(start = 20.dp, end = 20.dp, top = 10.dp, bottom = 10.dp)
) {
Button(
onClick = {},
enabled = urlValid == true && flowValid == true,
modifier = Modifier.fillMaxWidth(),
) {
Text(LocalContext.current.getString(R.string.login_button_continue_text))
}
}
}
}
}

View file

@ -0,0 +1,30 @@
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()
}
)
}
}
}

View file

@ -0,0 +1,102 @@
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 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) }
val padding = Modifier.padding(all = 10.dp)
Column(modifier) {
Row(padding) {
Text(LocalContext.current.getString(R.string.selecthomeserver_text))
}
Row(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(padding) {
Button(
onClick = {
onComplete(homeserver)
},
enabled = (state == SelectHomeserverFieldState.Valid),
modifier = Modifier.fillMaxWidth(),
) {
Text(LocalContext.current.getString(R.string.selecthomeserver_complete_text))
}
}
}
}

View file

@ -0,0 +1,70 @@
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
}
)
}

View file

@ -0,0 +1,10 @@
package eu.steffo.twom.ui.homeserver
enum class SelectHomeserverFieldState {
Empty,
Waiting,
Validating,
URLInvalid,
FlowInvalid,
Valid,
}

View file

@ -0,0 +1,51 @@
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
)
}
}
}

View file

@ -1,67 +0,0 @@
package eu.steffo.twom.ui.input
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Build
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
enum class SelectHomeserverFieldState {
Empty,
Waiting,
Validating,
Error,
Done,
}
@Composable
@Preview
fun SelectHomeserverField(
modifier: Modifier = Modifier,
value: String = "",
onValueChange: (String) -> Unit = {},
enabled: Boolean = true,
state: SelectHomeserverFieldState = SelectHomeserverFieldState.Empty,
error: String? = null,
) {
TextField(
modifier = modifier,
value = value,
onValueChange = onValueChange,
enabled = enabled,
singleLine = true,
label = {
Text(LocalContext.current.getString(R.string.homeserver_label))
},
placeholder = {
Text(LocalContext.current.getString(R.string.homeserver_placeholder))
},
trailingIcon = {
Icon(
when(state) {
SelectHomeserverFieldState.Empty -> Icons.Default.Build
SelectHomeserverFieldState.Waiting -> Icons.Default.Create
SelectHomeserverFieldState.Validating -> Icons.Default.Send
SelectHomeserverFieldState.Error -> Icons.Default.Close
SelectHomeserverFieldState.Done -> Icons.Default.Check
},
LocalContext.current.getString(R.string.homeserver_trailingicon_validating_description)
)
},
supportingText = {
Text(error ?: LocalContext.current.getString(R.string.homeserver_supporting))
},
isError = (error != null)
)
}

View file

@ -0,0 +1,63 @@
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 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.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import eu.steffo.twom.R
import eu.steffo.twom.ui.homeserver.SelectHomeserverActivity
import eu.steffo.twom.ui.theme.TwoMTheme
@OptIn(ExperimentalMaterial3Api::class)
class LoginActivity : ComponentActivity() {
private lateinit var homeserverLauncher: ActivityResultLauncher<Intent>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
homeserverLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
Log.i("Garasauto", it.data?.getStringExtra(SelectHomeserverActivity.HOMESERVER_EXTRA_KEY) ?: "Undefined")
}
}
override fun onStart() {
super.onStart()
setContent {
TwoMTheme {
Scaffold(
topBar = {
TopAppBar (
title = { Text(LocalContext.current.getString(R.string.login_title)) }
)
}
) {
Row(Modifier.padding(it)) {
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
homeserverLauncher.launch(Intent(applicationContext, SelectHomeserverActivity::class.java))
}
) {
Text("")
}
}
}
}
}
}
}

View file

@ -1,36 +0,0 @@
package eu.steffo.twom.ui.scaffold
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun TwoMNavigationDrawer(
modifier: Modifier = Modifier,
content: @Composable () -> Unit = {},
) {
ModalNavigationDrawer(
drawerContent = {
Drawer()
}
) {
Surface(
modifier = modifier,
color = MaterialTheme.colorScheme.background
) {
content()
}
}
}
@Composable
fun Drawer() {
ModalDrawerSheet {
Text("garasauto")
}
}

View file

@ -1,26 +0,0 @@
package eu.steffo.twom.ui.scaffold
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import eu.steffo.twom.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TwoMTopAppBar(
content: @Composable (innerPadding: PaddingValues) -> Unit = {},
) {
Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = { Text(LocalContext.current.getString(R.string.app_name)) }
)
}
) {
content(it)
}
}

View file

@ -1,9 +1,9 @@
<resources> <resources>
<string name="app_name">TwoM</string> <string name="app_name">TwoM</string>
<string name="homeserver_placeholder">https://candy.steffo.eu</string> <string name="selecthomeserver_input_placeholder">https://candy.steffo.eu</string>
<string name="homeserver_label">Homeserver</string> <string name="selecthomeserver_input_label">Homeserver</string>
<string name="homeserver_supporting">The URL of the homeserver providing you with Matrix access.</string> <string name="selecthomeserver_input_supporting_empty">The URL of the homeserver providing you with Matrix access.</string>
<string name="homeserver_error_malformedurl">The homeserver URL you provided is not a valid URL.</string> <string name="selecthomeserver_input_supporting_urlinvalid">The homeserver URL you provided is not a valid URL.</string>
<string name="room_name_fallback_members_0">Is this even a party?</string> <string name="room_name_fallback_members_0">Is this even a party?</string>
<string name="room_name_fallback_members_1">%1$s\'s party</string> <string name="room_name_fallback_members_1">%1$s\'s party</string>
<string name="room_name_fallback_members_2">%1$s and %2$s\'s party</string> <string name="room_name_fallback_members_2">%1$s and %2$s\'s party</string>
@ -11,10 +11,13 @@
<string name="room_name_fallback_members_4">%1$s, %2$s, %3$s, %4$s\'s party</string> <string name="room_name_fallback_members_4">%1$s, %2$s, %3$s, %4$s\'s 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_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="login_button_continue_text">Continue</string> <string name="selecthomeserver_complete_text">Continue</string>
<string name="login_welcome_text">Welcome to TwoM! To start using the app, you\'ll need to select the Matrix homeserver you want to use.</string> <string name="selecthomeserver_text">Please select the homeserver you would like to log into.</string>
<string name="homeserver_error_notmatrix">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="homeserver_trailingicon_validating_description">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="homeserver_trailingicon_waiting_description">Waiting for you to stop writing…</string> <string name="selecthomeserver_input_supporting_waiting">Waiting for you to stop writing…</string>
<string name="homeserver_trailingicon_waiting_done">All checks complete.</string> <string name="selecthomeserver_input_supporting_valid">All checks complete!</string>
<string name="homeserver_title">Select homeserver</string>
<string name="login_title">Log into Matrix</string>
<string name="back">Go back</string>
</resources> </resources>

View file

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>