Merge pull request #4259 from nextcloud/password_improvement

Password improvement
This commit is contained in:
Marcel Hibbe 2024-09-26 13:16:36 +02:00 committed by GitHub
commit 0354501b41
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 156 additions and 22 deletions

View File

@ -20,25 +20,31 @@ import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
@ -48,6 +54,7 @@ import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
@ -55,7 +62,7 @@ import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -67,9 +74,11 @@ import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.core.view.WindowCompat
import androidx.lifecycle.ViewModelProvider
import autodagger.AutoInjector
@ -436,6 +445,8 @@ fun RoomCreationOptions(conversationCreationViewModel: ConversationCreationViewM
.isConversationAvailableForRegisteredUsers.value
val isOpenForGuestAppUsers = conversationCreationViewModel.openForGuestAppUsers.value
val isPasswordSet = conversationCreationViewModel.isPasswordEnabled.value
Text(
text = stringResource(id = R.string.nc_new_conversation_visibility).uppercase(),
fontSize = 14.sp,
@ -452,15 +463,21 @@ fun RoomCreationOptions(conversationCreationViewModel: ConversationCreationViewM
}
)
},
showDialog = false,
conversationCreationViewModel = conversationCreationViewModel
)
if (isGuestsAllowed) {
if (isGuestsAllowed && !isPasswordSet) {
ConversationOptions(
icon = R.drawable.baseline_lock_open_24,
text = R.string.nc_set_password,
conversationCreationViewModel = conversationCreationViewModel
)
}
if (isGuestsAllowed && isPasswordSet) {
ConversationOptions(
icon = R.drawable.ic_lock_grey600_24px,
text = R.string.nc_set_password,
showDialog = true,
text = R.string.nc_change_password,
conversationCreationViewModel = conversationCreationViewModel
)
}
@ -476,7 +493,6 @@ fun RoomCreationOptions(conversationCreationViewModel: ConversationCreationViewM
}
)
},
showDialog = false,
conversationCreationViewModel = conversationCreationViewModel
)
@ -491,7 +507,6 @@ fun RoomCreationOptions(conversationCreationViewModel: ConversationCreationViewM
}
)
},
showDialog = false,
conversationCreationViewModel = conversationCreationViewModel
)
}
@ -502,19 +517,23 @@ fun ConversationOptions(
icon: Int? = null,
text: Int,
switch: @Composable (() -> Unit)? = null,
showDialog: Boolean,
conversationCreationViewModel: ConversationCreationViewModel
) {
var showPasswordDialog by remember { mutableStateOf(false) }
var showPasswordDialog by rememberSaveable { mutableStateOf(false) }
var showPasswordChangeDialog by rememberSaveable { mutableStateOf(false) }
Row(
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 16.dp, bottom = 8.dp)
.then(
if (showDialog) {
if (!conversationCreationViewModel.isPasswordEnabled.value) {
Modifier.clickable {
showPasswordDialog = true
}
} else if (conversationCreationViewModel.isPasswordEnabled.value) {
Modifier.clickable {
showPasswordChangeDialog = true
}
} else {
Modifier
}
@ -545,24 +564,99 @@ fun ConversationOptions(
conversationCreationViewModel = conversationCreationViewModel
)
}
if (showPasswordChangeDialog) {
ShowChangePassword(
onDismiss = {
showPasswordChangeDialog = false
},
conversationCreationViewModel = conversationCreationViewModel
)
}
}
}
@Composable
fun ShowChangePassword(onDismiss: () -> Unit, conversationCreationViewModel: ConversationCreationViewModel) {
var changedPassword by rememberSaveable { mutableStateOf("") }
Dialog(onDismissRequest = {
onDismiss()
}) {
Card(
modifier = Modifier
.fillMaxWidth()
.height(375.dp)
.padding(32.dp)
.clip(RoundedCornerShape(16.dp))
.background(color = colorResource(id = R.color.appbar))
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(vertical = 16.dp, horizontal = 16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(text = stringResource(id = R.string.nc_set_new_password), fontWeight = FontWeight.SemiBold)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = changedPassword,
onValueChange = {
changedPassword = it
},
label = { Text(text = stringResource(id = R.string.nc_password)) },
singleLine = true
)
Spacer(modifier = Modifier.height(16.dp))
Column(
modifier = Modifier.fillMaxWidth()
.padding(vertical = 8.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
TextButton(
onClick = {
conversationCreationViewModel.updatePassword(changedPassword)
conversationCreationViewModel.isPasswordEnabled.value = true
onDismiss()
},
enabled = changedPassword.isNotEmpty() && changedPassword.isNotBlank(),
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)
) {
Text(text = stringResource(id = R.string.nc_change_password))
}
Spacer(modifier = Modifier.height(4.dp))
TextButton(
onClick = {
conversationCreationViewModel.isPasswordEnabled.value = false
onDismiss()
},
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)
) {
Text(
text = stringResource(id = R.string.nc_remove_password),
color = colorResource(id = R.color.nc_darkRed)
)
}
Spacer(modifier = Modifier.height(4.dp))
TextButton(
onClick = { onDismiss() },
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)
) {
Text(text = stringResource(id = R.string.nc_cancel))
}
}
}
}
}
}
@Composable
fun ShowPasswordDialog(onDismiss: () -> Unit, conversationCreationViewModel: ConversationCreationViewModel) {
var password by remember { mutableStateOf("") }
var password by rememberSaveable { mutableStateOf("") }
AlertDialog(
containerColor = colorResource(id = R.color.dialog_background),
onDismissRequest = onDismiss,
confirmButton = {
Button(onClick = {
conversationCreationViewModel.updatePassword(password)
onDismiss()
}) {
Text(text = stringResource(id = R.string.save))
}
},
title = { Text(text = stringResource(id = R.string.nc_set_password)) },
text = {
TextField(
@ -573,8 +667,20 @@ fun ShowPasswordDialog(onDismiss: () -> Unit, conversationCreationViewModel: Con
label = { Text(text = stringResource(id = R.string.nc_guest_access_password_dialog_hint)) }
)
},
confirmButton = {
TextButton(
onClick = {
if (password.isNotEmpty() && password.isNotBlank()) {
conversationCreationViewModel.updatePassword(password)
conversationCreationViewModel.isPasswordEnabled(true)
}
}
) {
Text(text = stringResource(id = R.string.save))
}
},
dismissButton = {
Button(onClick = { onDismiss() }) {
TextButton(onClick = { onDismiss() }) {
Text(text = stringResource(id = R.string.nc_cancel))
}
}

View File

@ -38,14 +38,20 @@ class ConversationCreationViewModel @Inject constructor(
private val _currentUser = userManager.currentUser.blockingGet()
val currentUser: User = _currentUser
private val _isPasswordEnabled = mutableStateOf(false)
val isPasswordEnabled = _isPasswordEnabled
fun updateSelectedParticipants(participants: List<AutocompleteUser>) {
_selectedParticipants.value = participants
}
fun isPasswordEnabled(value: Boolean) {
_isPasswordEnabled.value = value
}
fun updateSelectedImageUri(uri: Uri?) {
_selectedImageUri.value = uri
}
private val _roomName = MutableStateFlow("")
val roomName: StateFlow<String> = _roomName
private val _password = MutableStateFlow("")

View File

@ -0,0 +1,18 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2024 Google LLC
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<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,17c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6h1.9c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM18,20L6,20L6,10h12v10z"/>
</vector>

View File

@ -434,6 +434,10 @@ How to translate with transifex:
<string name="nc_guest_access_allow_summary">Allow guests to share a public link to join this conversation.</string>
<string name="nc_guest_access_allow_failed">Cannot enable/disable guest access.</string>
<string name="nc_set_password">Set Password</string>
<string name="nc_password">Password</string>
<string name="nc_change_password">Change Password</string>
<string name="nc_remove_password">Remove Password</string>
<string name="nc_set_new_password">Set new password</string>
<string name="nc_guest_access_password_title">Password protection</string>
<string name="nc_guest_access_password_summary">Set a password to restrict who can use the public link.</string>
<string name="nc_guest_access_password_dialog_title">Guest access password</string>