mirror of
https://codeberg.org/NextPush/nextpush-android.git
synced 2024-12-26 09:42:39 +01:00
Migrate start activity to jetpack
This commit is contained in:
parent
9ac56626cb
commit
c53f304c03
@ -64,6 +64,7 @@ if (project.hasProperty("sign")) {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.accompanist.permissions)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(libs.androidx.constraintlayout)
|
||||
implementation(libs.androidx.coordinatorlayout)
|
||||
|
@ -28,15 +28,15 @@ object AccountFactory {
|
||||
account = null
|
||||
}
|
||||
|
||||
fun Context.setTypeSSO() {
|
||||
fun setTypeSSO(context: Context) {
|
||||
account = null
|
||||
AccountStore(this).accountType = AccountType.SSO
|
||||
DirectAccountStore(this).wipe() // Just in case
|
||||
AccountStore(context).accountType = AccountType.SSO
|
||||
DirectAccountStore(context).wipe() // Just in case
|
||||
}
|
||||
|
||||
fun Context.setTypeDirect(url: String, username: String, password: String) {
|
||||
fun setTypeDirect(context: Context, url: String, username: String, password: String) {
|
||||
account = null
|
||||
AccountStore(this).accountType = AccountType.Direct
|
||||
DirectAccount.setCredentials(this, url, username, password)
|
||||
AccountStore(context).accountType = AccountType.Direct
|
||||
DirectAccount.setCredentials(context, url, username, password)
|
||||
}
|
||||
}
|
||||
|
@ -32,10 +32,14 @@ class AppAction(private val type: Type, private val argv: Map<String, Any>? = nu
|
||||
DisableBatteryOptimisation,
|
||||
CopyEndpoint,
|
||||
DeleteRegistration,
|
||||
LoginSSO,
|
||||
LoginDirect
|
||||
}
|
||||
|
||||
fun handle(context: Context) {
|
||||
when (type) {
|
||||
Type.LoginSSO -> loginSSO(context)
|
||||
Type.LoginDirect -> loginDirect(context, argv)
|
||||
Type.RestartService -> restartService(context)
|
||||
Type.Logout -> logout(context)
|
||||
Type.AddChannel -> addChannel(context, argv)
|
||||
@ -45,6 +49,19 @@ class AppAction(private val type: Type, private val argv: Map<String, Any>? = nu
|
||||
}
|
||||
}
|
||||
|
||||
private fun loginSSO(context: Context) {
|
||||
AccountFactory.setTypeSSO(context)
|
||||
UiAction.publish(UiAction.Type.Login)
|
||||
}
|
||||
|
||||
private fun loginDirect(context: Context, argv: Map<String, Any>?) {
|
||||
val username = argv?.get(ARG_USERNAME) as String? ?: return
|
||||
val password = argv?.get(ARG_PASSWORD) as String? ?: return
|
||||
val url = argv?.get(ARG_URL) as String? ?: return
|
||||
AccountFactory.setTypeDirect(context, url, username, password)
|
||||
UiAction.publish(UiAction.Type.Login)
|
||||
}
|
||||
|
||||
private fun restartService(context: Context) {
|
||||
Log.d(TAG, "Restarting the Listener")
|
||||
FailureHandler.clearFails()
|
||||
@ -112,6 +129,9 @@ class AppAction(private val type: Type, private val argv: Map<String, Any>? = nu
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ARG_USERNAME = "username"
|
||||
const val ARG_PASSWORD = "password"
|
||||
const val ARG_URL = "url"
|
||||
const val ARG_NEW_CHANNEL_TITLE = "title"
|
||||
const val ARG_TOKEN = "token"
|
||||
const val ARG_REGISTRATIONS = "registrations"
|
||||
|
@ -55,6 +55,7 @@ class MainActivity : ComponentActivity() {
|
||||
StartActivity.goToStartActivity(this@MainActivity)
|
||||
finish()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,68 +0,0 @@
|
||||
package org.unifiedpush.distributor.nextpush.activities
|
||||
|
||||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import org.unifiedpush.distributor.nextpush.R
|
||||
import org.unifiedpush.distributor.nextpush.activities.PermissionsRequest.requestAppPermissions
|
||||
import org.unifiedpush.distributor.nextpush.utils.TAG
|
||||
|
||||
object PermissionsRequest {
|
||||
|
||||
fun AppCompatActivity.requestAppPermissions() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS)
|
||||
!= PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
Log.d(TAG, "Requesting POST_NOTIFICATIONS permission")
|
||||
this.registerForActivityResult(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
) { granted ->
|
||||
Log.d(TAG, "POST_NOTIFICATIONS permission granted: $granted")
|
||||
if (!granted) {
|
||||
if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
|
||||
Log.d(TAG, "Show POST_NOTIFICATIONS permission rationale")
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.no_notification_dialog_title))
|
||||
.setMessage(R.string.no_notification_dialog_message)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}.launch(
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
)
|
||||
}
|
||||
} else if (Build.VERSION.SDK_INT < 26) {
|
||||
this.requestAccountPermission()
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("For SDK<26 only")
|
||||
fun AppCompatActivity.requestAccountPermission() {
|
||||
if (checkSelfPermission(Manifest.permission.GET_ACCOUNTS)
|
||||
!= PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
Log.d(TAG, "Requesting GET_ACCOUNT permission")
|
||||
this.registerForActivityResult(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
) { granted ->
|
||||
Log.d(TAG, "GET_ACCOUNT permission granted: $granted")
|
||||
if (!granted) {
|
||||
if (shouldShowRequestPermissionRationale(Manifest.permission.GET_ACCOUNTS)) {
|
||||
Log.d(TAG, "Show GET_ACCOUNTS permission rationale")
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.no_notification_dialog_title))
|
||||
.setMessage(R.string.no_notification_dialog_message)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}.launch(
|
||||
Manifest.permission.GET_ACCOUNTS
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,61 +1,82 @@
|
||||
package org.unifiedpush.distributor.nextpush.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isGone
|
||||
import org.unifiedpush.distributor.nextpush.R
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import org.unifiedpush.distributor.nextpush.EventBus
|
||||
import org.unifiedpush.distributor.nextpush.account.AccountFactory
|
||||
import org.unifiedpush.distributor.nextpush.account.AccountFactory.setTypeDirect
|
||||
import org.unifiedpush.distributor.nextpush.account.AccountFactory.setTypeSSO
|
||||
import org.unifiedpush.distributor.nextpush.activities.MainActivity.Companion.goToMainActivity
|
||||
import org.unifiedpush.distributor.nextpush.activities.PermissionsRequest.requestAppPermissions
|
||||
import org.unifiedpush.distributor.nextpush.activities.ui.StartUi
|
||||
import org.unifiedpush.distributor.nextpush.activities.ui.theme.AppTheme
|
||||
import org.unifiedpush.distributor.nextpush.utils.TAG
|
||||
|
||||
class StartActivity : AppCompatActivity() {
|
||||
private var onResult: ((activity: Activity, requestCode: Int, resultCode: Int, data: Intent?, block: (success: Boolean) -> Unit) -> Unit)? = null
|
||||
class StartActivity : ComponentActivity() {
|
||||
private var jobs: MutableList<Job> = emptyList<Job>().toMutableList()
|
||||
|
||||
private var onResult: (
|
||||
(
|
||||
activity: Activity,
|
||||
requestCode: Int,
|
||||
resultCode: Int,
|
||||
data: Intent?,
|
||||
block: (success: Boolean) -> Unit
|
||||
) -> Unit
|
||||
)? = null
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_start)
|
||||
this.requestAppPermissions()
|
||||
|
||||
if (AccountFactory.getAccount(this)?.connected == true) {
|
||||
goToMainActivity(this)
|
||||
finish()
|
||||
}
|
||||
findViewById<Button>(R.id.btn_sso_login).setOnClickListener {
|
||||
setTypeSSO()
|
||||
login()
|
||||
|
||||
setContent {
|
||||
val viewModel =
|
||||
viewModel {
|
||||
StartViewModel()
|
||||
}
|
||||
AppTheme {
|
||||
StartUi(viewModel)
|
||||
}
|
||||
subscribeActions()
|
||||
}
|
||||
findViewById<EditText>(R.id.edt_url).setText("https://")
|
||||
findViewById<Button>(R.id.btn_manual_login).setOnClickListener {
|
||||
val url = findViewById<EditText>(R.id.edt_url).text.toString().let {
|
||||
if (it.last() != '/') {
|
||||
"$it/"
|
||||
} else {
|
||||
it
|
||||
}
|
||||
|
||||
private fun subscribeActions() {
|
||||
Log.d(TAG, "Subscribing to actions")
|
||||
jobs += CoroutineScope(Dispatchers.IO).launch {
|
||||
EventBus.subscribe<AppAction> { it.handle(this@StartActivity) }
|
||||
}
|
||||
jobs += CoroutineScope(Dispatchers.IO).launch {
|
||||
EventBus.subscribe<UiAction> {
|
||||
it.handle { type ->
|
||||
when (type) {
|
||||
UiAction.Type.Login -> login()
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
val username = findViewById<EditText>(R.id.edt_username).text.toString()
|
||||
val password = findViewById<EditText>(R.id.edt_password).text.toString()
|
||||
setTypeDirect(url, username, password)
|
||||
login()
|
||||
}
|
||||
findViewById<TextView>(R.id.manual_login).setOnClickListener {
|
||||
findViewById<LinearLayout>(R.id.manual_login_wrapper).apply {
|
||||
isGone = !isGone
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
Log.d(TAG, "Destroy")
|
||||
jobs.removeAll {
|
||||
it.cancel()
|
||||
true
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
@ -67,7 +88,11 @@ class StartActivity : AppCompatActivity() {
|
||||
goToMainActivity(this)
|
||||
finish()
|
||||
} else {
|
||||
Toast.makeText(applicationContext, "Could not connect to UnifiedPush provider", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(
|
||||
applicationContext,
|
||||
"Could not connect to UnifiedPush provider",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,7 +100,10 @@ class StartActivity : AppCompatActivity() {
|
||||
|
||||
private fun login() {
|
||||
AccountFactory.getAccount(this, connected = false)?.let {
|
||||
onResult = { activity: Activity, i: Int, i1: Int, intent: Intent?, block: (success: Boolean) -> Unit ->
|
||||
onResult = { activity: Activity, i: Int, i1: Int, intent: Intent?,
|
||||
block: (
|
||||
success: Boolean
|
||||
) -> Unit ->
|
||||
it.onActivityResult(activity, i, i1, intent, block)
|
||||
}
|
||||
it.connect(this)
|
||||
@ -84,10 +112,11 @@ class StartActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
fun goToStartActivity(context: Context) {
|
||||
val intent = Intent(
|
||||
context,
|
||||
StartActivity::class.java
|
||||
)
|
||||
val intent =
|
||||
Intent(
|
||||
context,
|
||||
StartActivity::class.java
|
||||
)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
package org.unifiedpush.distributor.nextpush.activities
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class StartViewModel : ViewModel()
|
@ -9,6 +9,7 @@ class UiAction(val type: Type) {
|
||||
enum class Type {
|
||||
UpdateRegistrations,
|
||||
Logout,
|
||||
Login
|
||||
}
|
||||
|
||||
fun handle(action: (Type) -> Unit) {
|
||||
|
@ -0,0 +1,46 @@
|
||||
package org.unifiedpush.distributor.nextpush.activities.ui
|
||||
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import org.unifiedpush.distributor.nextpush.R
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Preview
|
||||
@Composable
|
||||
fun PermissionsUi(onDone: () -> Unit = {}) {
|
||||
val notificationsPermissionState =
|
||||
rememberPermissionState(
|
||||
android.Manifest.permission.POST_NOTIFICATIONS
|
||||
)
|
||||
if (!notificationsPermissionState.status.isGranted) {
|
||||
AlertDialog(
|
||||
title = {
|
||||
Text(stringResource(R.string.dialog_permissions_title))
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.dialog_permissions_content))
|
||||
},
|
||||
onDismissRequest = {
|
||||
onDone()
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
notificationsPermissionState.launchPermissionRequest()
|
||||
onDone
|
||||
}
|
||||
) {
|
||||
Text(stringResource(android.R.string.ok))
|
||||
}
|
||||
},
|
||||
dismissButton = {}
|
||||
)
|
||||
}
|
||||
}
|
@ -0,0 +1,191 @@
|
||||
package org.unifiedpush.distributor.nextpush.activities.ui
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldColors
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.unifiedpush.distributor.nextpush.R
|
||||
import org.unifiedpush.distributor.nextpush.activities.AppAction
|
||||
import org.unifiedpush.distributor.nextpush.activities.StartViewModel
|
||||
import org.unifiedpush.distributor.nextpush.activities.publishAction
|
||||
import org.unifiedpush.distributor.nextpush.activities.ui.theme.nextcloud
|
||||
|
||||
@Composable
|
||||
fun StartUi(viewModel: StartViewModel, showManualLogin: Boolean = false) {
|
||||
var showManualLogin by remember { mutableStateOf(showManualLogin) }
|
||||
var showPassword by remember { mutableStateOf(false) }
|
||||
var usernameValue by remember { mutableStateOf("") }
|
||||
var passwordValue by remember { mutableStateOf("www") }
|
||||
var urlValue by remember { mutableStateOf("https://") }
|
||||
var showPermissionDialog by remember { mutableStateOf(true) }
|
||||
|
||||
if (showPermissionDialog) {
|
||||
PermissionsUi {
|
||||
showPermissionDialog = false
|
||||
}
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.background(nextcloud)
|
||||
.fillMaxSize()
|
||||
.imePadding(),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.ic_logo),
|
||||
contentDescription = "NextPush Logo"
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.app_name),
|
||||
style = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.Bold),
|
||||
color = Color.White
|
||||
)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Button(
|
||||
colors = ButtonDefaults.buttonColors(containerColor = Color.White),
|
||||
onClick = {
|
||||
viewModel.publishAction(AppAction(AppAction.Type.LoginSSO))
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
color = nextcloud,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = stringResource(R.string.button_start_sso_connection)
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Text(
|
||||
color = Color.White,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = stringResource(R.string.button_start_manual_login),
|
||||
modifier = Modifier.clickable {
|
||||
showManualLogin = !showManualLogin
|
||||
}
|
||||
)
|
||||
if (showManualLogin) {
|
||||
Spacer(Modifier.height(16.dp))
|
||||
TextField(
|
||||
colors = textFieldColor(),
|
||||
value = usernameValue,
|
||||
onValueChange = { usernameValue = it },
|
||||
label = { Text(stringResource(R.string.login_hint_username)) },
|
||||
maxLines = 1
|
||||
)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
TextField(
|
||||
colors = textFieldColor(),
|
||||
value = passwordValue,
|
||||
onValueChange = { passwordValue = it },
|
||||
label = { Text(stringResource(R.string.login_hint_password)) },
|
||||
maxLines = 1,
|
||||
visualTransformation = if (showPassword) {
|
||||
VisualTransformation.None
|
||||
} else {
|
||||
PasswordVisualTransformation()
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
|
||||
trailingIcon = {
|
||||
IconButton(
|
||||
onClick = { showPassword = !showPassword }
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(
|
||||
if (showPassword) {
|
||||
R.drawable.ic_visibility_24
|
||||
} else {
|
||||
R.drawable.ic_visibility_off_24
|
||||
}
|
||||
),
|
||||
tint = Color.White,
|
||||
contentDescription = if (showPassword) {
|
||||
"Hide password"
|
||||
} else {
|
||||
"Show password"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
TextField(
|
||||
colors = textFieldColor(),
|
||||
value = urlValue,
|
||||
onValueChange = { urlValue = it },
|
||||
label = { Text(stringResource(R.string.login_hint_nextcloud_root_url)) },
|
||||
maxLines = 1
|
||||
)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Button(
|
||||
colors = ButtonDefaults.buttonColors(containerColor = Color.White),
|
||||
onClick = {
|
||||
viewModel.publishAction(
|
||||
AppAction(
|
||||
AppAction.Type.LoginDirect,
|
||||
mapOf(
|
||||
AppAction.ARG_USERNAME to usernameValue,
|
||||
AppAction.ARG_PASSWORD to passwordValue,
|
||||
AppAction.ARG_URL to urlValue
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
color = nextcloud,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = stringResource(R.string.login_button_sign_in)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun textFieldColor(): TextFieldColors {
|
||||
return TextFieldDefaults.colors(
|
||||
focusedContainerColor = nextcloud,
|
||||
unfocusedContainerColor = nextcloud,
|
||||
focusedTextColor = Color.White,
|
||||
unfocusedTextColor = Color.White,
|
||||
focusedLabelColor = Color.White,
|
||||
unfocusedLabelColor = Color.White
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreviewStartUi() {
|
||||
StartUi(StartViewModel(), true)
|
||||
}
|
5
app/src/main/res/drawable/ic_visibility_24.xml
Normal file
5
app/src/main/res/drawable/ic_visibility_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
|
||||
|
||||
</vector>
|
5
app/src/main/res/drawable/ic_visibility_off_24.xml
Normal file
5
app/src/main/res/drawable/ic_visibility_off_24.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 6,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z"/>
|
||||
|
||||
</vector>
|
@ -1,134 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/nextcloud">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:animateLayoutChanges="true"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/material_grey_100"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
app:drawableTopCompat="@drawable/ic_logo" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_sso_login"
|
||||
style="@style/NextcloudButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@string/sso_connection_button"
|
||||
app:cornerRadius="24dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manual_login"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/manual_login"
|
||||
android:textColor="@color/material_grey_100" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/manual_login_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/username_container"
|
||||
style="@style/TextInputLayoutStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/TextInputLayoutAppearance">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edt_username"
|
||||
style="@style/TextInputEditTextLogin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/login_hint_username"
|
||||
android:inputType="textEmailAddress" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/password_container"
|
||||
style="@style/TextInputLayoutStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/TextInputLayoutAppearance"
|
||||
app:endIconMode="password_toggle"
|
||||
app:endIconTint="@color/white">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edt_password"
|
||||
style="@style/TextInputEditTextLogin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/login_hint_password"
|
||||
android:inputType="textPassword"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/url_container"
|
||||
style="@style/TextInputLayoutStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/TextInputLayoutAppearance">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edt_url"
|
||||
style="@style/TextInputEditTextLogin"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/login_hint_nextcloud_root_url"
|
||||
android:inputType="textUri"
|
||||
android:maxLines="1"
|
||||
android:selectAllOnFocus="false"
|
||||
android:singleLine="true"
|
||||
android:theme="@style/TextInputEditTextLogin" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_manual_login"
|
||||
style="@style/NextcloudButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:text="@string/login_button_sign_in"
|
||||
app:cornerRadius="24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
@ -3,7 +3,7 @@
|
||||
<string name="foreground_notif_description">Notification to run in the foreground</string>
|
||||
<string name="foreground_notif_content_no_reg">Waiting for registration to connect</string>
|
||||
<string name="foreground_notif_content_with_reg">Connected for %s registration(s)</string>
|
||||
<string name="sso_connection_button">Login with the Nextcloud File application</string>
|
||||
<string name="button_start_sso_connection">Login with the Nextcloud File application</string>
|
||||
<string name="logout_alert_title">Logout</string>
|
||||
<string name="logout_alert_content">Confirm to logout</string>
|
||||
<string name="main_account_desc">You are connected as %s</string>
|
||||
@ -27,7 +27,7 @@
|
||||
<string name="nextcloud_files_not_found_title">Nextcloud Files not found</string>
|
||||
<string name="no_notification_dialog_title">Notifications refused</string>
|
||||
<string name="no_notification_dialog_message">You won\'t be notified when the application is disconnected.\nYou can enable notifications later in the settings.</string>
|
||||
<string name="manual_login">Manual login</string>
|
||||
<string name="button_start_manual_login">Manual login</string>
|
||||
<string name="login_hint_username">Username</string>
|
||||
<string name="login_hint_password">Application password</string>
|
||||
<string name="login_hint_nextcloud_root_url">Nextcloud root url</string>
|
||||
@ -49,4 +49,6 @@
|
||||
<string name="bar_unregister_title">%d selected</string>
|
||||
<string name="bar_unregister_back_description">Unselect all</string>
|
||||
<string name="bar_unregister_delete_description">Unregister selection</string>
|
||||
<string name="dialog_permissions_title">Permissions</string>
|
||||
<string name="dialog_permissions_content">This application requires notifications permission to work.</string>
|
||||
</resources>
|
||||
|
@ -1,4 +1,5 @@
|
||||
[versions]
|
||||
accompanistPermissions = "0.36.0"
|
||||
android-gradle-plugin = "8.7.2"
|
||||
androidx-activityCompose = "1.9.3"
|
||||
androidx-constraintlayout = "2.2.0"
|
||||
@ -20,6 +21,7 @@ material3Android = "1.3.1"
|
||||
uiTooling = "1.7.5"
|
||||
|
||||
[libraries]
|
||||
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissions" }
|
||||
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activityCompose" }
|
||||
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx-constraintlayout" }
|
||||
androidx-coordinatorlayout = { module = "androidx.coordinatorlayout:coordinatorlayout", version.ref = "androidx-coordinatorlayout" }
|
||||
|
Loading…
Reference in New Issue
Block a user