mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-14 21:15:37 +00:00
desktop, android: user profiles move auth to change actions, show unread counts (#5171)
* auth only on change actions for profiles * show notification count in profiles view * auth to hidde profile * save authorized * refactor and icon fix * keep key
This commit is contained in:
+54
-35
@@ -268,22 +268,32 @@ fun UserPicker(
|
||||
painterResource(MR.images.ic_manage_accounts),
|
||||
stringResource(MR.strings.your_chat_profiles),
|
||||
{
|
||||
doWithAuth(
|
||||
generalGetString(MR.strings.auth_open_chat_profiles),
|
||||
generalGetString(MR.strings.auth_log_in_using_credential)
|
||||
) {
|
||||
ModalManager.start.showCustomModal(keyboardCoversBar = false) { close ->
|
||||
val search = rememberSaveable { mutableStateOf("") }
|
||||
val profileHidden = rememberSaveable { mutableStateOf(false) }
|
||||
ModalView(
|
||||
{ close() },
|
||||
showSearch = true,
|
||||
searchAlwaysVisible = true,
|
||||
onSearchValueChanged = {
|
||||
search.value = it
|
||||
},
|
||||
content = { UserProfilesView(chatModel, search, profileHidden) })
|
||||
}
|
||||
ModalManager.start.showCustomModal(keyboardCoversBar = false) { close ->
|
||||
val search = rememberSaveable { mutableStateOf("") }
|
||||
val profileHidden = rememberSaveable { mutableStateOf(false) }
|
||||
val authorized = remember { stateGetOrPut("authorized") { false } }
|
||||
ModalView(
|
||||
{ close() },
|
||||
showSearch = true,
|
||||
searchAlwaysVisible = true,
|
||||
onSearchValueChanged = {
|
||||
search.value = it
|
||||
},
|
||||
content = {
|
||||
UserProfilesView(chatModel, search, profileHidden) { block ->
|
||||
if (authorized.value) {
|
||||
block()
|
||||
} else {
|
||||
doWithAuth(
|
||||
generalGetString(MR.strings.auth_open_chat_profiles),
|
||||
generalGetString(MR.strings.auth_log_in_using_credential)
|
||||
) {
|
||||
authorized.value = true
|
||||
block()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
disabled = stopped
|
||||
@@ -412,26 +422,35 @@ fun UserProfilePickerItem(
|
||||
UserProfileRow(u, enabled)
|
||||
if (u.activeUser) {
|
||||
Icon(painterResource(MR.images.ic_done_filled), null, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground)
|
||||
} else if (u.hidden) {
|
||||
Icon(painterResource(MR.images.ic_lock), null, Modifier.size(20.dp), tint = MaterialTheme.colors.secondary)
|
||||
} else if (unreadCount > 0) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
unreadCountStr(unreadCount),
|
||||
color = Color.White,
|
||||
fontSize = 10.sp,
|
||||
modifier = Modifier
|
||||
.background(MaterialTheme.colors.primaryVariant, shape = CircleShape)
|
||||
.padding(2.dp)
|
||||
.badgeLayout()
|
||||
)
|
||||
}
|
||||
} else if (!u.showNtfs) {
|
||||
Icon(painterResource(MR.images.ic_notifications_off), null, Modifier.size(20.dp), tint = MaterialTheme.colors.secondary)
|
||||
} else {
|
||||
Box(Modifier.size(20.dp))
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
if (unreadCount > 0) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
unreadCountStr(unreadCount),
|
||||
color = Color.White,
|
||||
fontSize = 10.sp,
|
||||
modifier = Modifier
|
||||
.background(if (u.showNtfs) MaterialTheme.colors.primaryVariant else MaterialTheme.colors.secondary, shape = CircleShape)
|
||||
.padding(2.dp)
|
||||
.badgeLayout()
|
||||
)
|
||||
}
|
||||
|
||||
if (u.hidden) {
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Icon(painterResource(MR.images.ic_lock), null, Modifier.size(20.dp), tint = MaterialTheme.colors.secondary)
|
||||
}
|
||||
} else if (u.hidden) {
|
||||
Icon(painterResource(MR.images.ic_lock), null, Modifier.size(20.dp), tint = MaterialTheme.colors.secondary)
|
||||
} else if (!u.showNtfs) {
|
||||
Icon(painterResource(MR.images.ic_notifications_off), null, Modifier.size(20.dp), tint = MaterialTheme.colors.secondary)
|
||||
} else {
|
||||
Box(Modifier.size(20.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+66
-53
@@ -36,7 +36,7 @@ import dev.icerock.moko.resources.StringResource
|
||||
import kotlinx.coroutines.*
|
||||
|
||||
@Composable
|
||||
fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden: MutableState<Boolean>) {
|
||||
fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden: MutableState<Boolean>, withAuth: (block: () -> Unit) -> Unit) {
|
||||
val searchTextOrPassword = rememberSaveable { search }
|
||||
val users by remember { derivedStateOf { m.users.map { it.user } } }
|
||||
val filteredUsers by remember { derivedStateOf { filteredUsers(m, searchTextOrPassword.value) } }
|
||||
@@ -48,8 +48,10 @@ fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden:
|
||||
showHiddenProfilesNotice = m.controller.appPrefs.showHiddenProfilesNotice,
|
||||
visibleUsersCount = visibleUsersCount(m),
|
||||
addUser = {
|
||||
ModalManager.center.showModalCloseable { close ->
|
||||
CreateProfile(m, close)
|
||||
withAuth {
|
||||
ModalManager.center.showModalCloseable { close ->
|
||||
CreateProfile(m, close)
|
||||
}
|
||||
}
|
||||
},
|
||||
activateUser = { user ->
|
||||
@@ -64,68 +66,78 @@ fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden:
|
||||
}
|
||||
},
|
||||
removeUser = { user ->
|
||||
val text = buildAnnotatedString {
|
||||
append(generalGetString(MR.strings.users_delete_all_chats_deleted) + "\n\n" + generalGetString(MR.strings.users_delete_profile_for) + " ")
|
||||
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append(user.displayName)
|
||||
withAuth {
|
||||
val text = buildAnnotatedString {
|
||||
append(generalGetString(MR.strings.users_delete_all_chats_deleted) + "\n\n" + generalGetString(MR.strings.users_delete_profile_for) + " ")
|
||||
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append(user.displayName)
|
||||
}
|
||||
append(":")
|
||||
}
|
||||
append(":")
|
||||
}
|
||||
AlertManager.shared.showAlertDialogButtonsColumn(
|
||||
title = generalGetString(MR.strings.users_delete_question),
|
||||
text = text,
|
||||
buttons = {
|
||||
Column {
|
||||
SectionItemView({
|
||||
AlertManager.shared.hideAlert()
|
||||
removeUser(m, user, users, true, searchTextOrPassword.value.trim())
|
||||
}) {
|
||||
Text(stringResource(MR.strings.users_delete_with_connections), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red)
|
||||
}
|
||||
SectionItemView({
|
||||
AlertManager.shared.hideAlert()
|
||||
removeUser(m, user, users, false, searchTextOrPassword.value.trim())
|
||||
}
|
||||
) {
|
||||
Text(stringResource(MR.strings.users_delete_data_only), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red)
|
||||
AlertManager.shared.showAlertDialogButtonsColumn(
|
||||
title = generalGetString(MR.strings.users_delete_question),
|
||||
text = text,
|
||||
buttons = {
|
||||
Column {
|
||||
SectionItemView({
|
||||
AlertManager.shared.hideAlert()
|
||||
removeUser(m, user, users, true, searchTextOrPassword.value.trim())
|
||||
}) {
|
||||
Text(stringResource(MR.strings.users_delete_with_connections), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red)
|
||||
}
|
||||
SectionItemView({
|
||||
AlertManager.shared.hideAlert()
|
||||
removeUser(m, user, users, false, searchTextOrPassword.value.trim())
|
||||
}
|
||||
) {
|
||||
Text(stringResource(MR.strings.users_delete_data_only), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
unhideUser = { user ->
|
||||
if (passwordEntryRequired(user, searchTextOrPassword.value)) {
|
||||
ModalManager.start.showModalCloseable(true) { close ->
|
||||
ProfileActionView(UserProfileAction.UNHIDE, user) { pwd ->
|
||||
withBGApi {
|
||||
setUserPrivacy(m) { m.controller.apiUnhideUser(user, pwd) }
|
||||
close()
|
||||
withAuth {
|
||||
if (passwordEntryRequired(user, searchTextOrPassword.value)) {
|
||||
ModalManager.start.showModalCloseable(true) { close ->
|
||||
ProfileActionView(UserProfileAction.UNHIDE, user) { pwd ->
|
||||
withBGApi {
|
||||
setUserPrivacy(m) { m.controller.apiUnhideUser(user, pwd) }
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
withBGApi { setUserPrivacy(m) { m.controller.apiUnhideUser(user, searchTextOrPassword.value.trim()) } }
|
||||
}
|
||||
} else {
|
||||
withBGApi { setUserPrivacy(m) { m.controller.apiUnhideUser(user, searchTextOrPassword.value.trim()) } }
|
||||
}
|
||||
},
|
||||
muteUser = { user ->
|
||||
withBGApi {
|
||||
setUserPrivacy(m, onSuccess = {
|
||||
if (m.controller.appPrefs.showMuteProfileAlert.get()) showMuteProfileAlert(m.controller.appPrefs.showMuteProfileAlert)
|
||||
}) { m.controller.apiMuteUser(user) }
|
||||
withAuth {
|
||||
withBGApi {
|
||||
setUserPrivacy(m, onSuccess = {
|
||||
if (m.controller.appPrefs.showMuteProfileAlert.get()) showMuteProfileAlert(m.controller.appPrefs.showMuteProfileAlert)
|
||||
}) { m.controller.apiMuteUser(user) }
|
||||
}
|
||||
}
|
||||
},
|
||||
unmuteUser = { user ->
|
||||
withBGApi { setUserPrivacy(m) { m.controller.apiUnmuteUser(user) } }
|
||||
withAuth {
|
||||
withBGApi { setUserPrivacy(m) { m.controller.apiUnmuteUser(user) } }
|
||||
}
|
||||
},
|
||||
showHiddenProfile = { user ->
|
||||
ModalManager.start.showModalCloseable(true) { close ->
|
||||
HiddenProfileView(m, user) {
|
||||
profileHidden.value = true
|
||||
withBGApi {
|
||||
delay(10_000)
|
||||
profileHidden.value = false
|
||||
withAuth {
|
||||
ModalManager.start.showModalCloseable(true) { close ->
|
||||
HiddenProfileView(m, user) {
|
||||
profileHidden.value = true
|
||||
withBGApi {
|
||||
delay(10_000)
|
||||
profileHidden.value = false
|
||||
}
|
||||
close()
|
||||
}
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,7 +150,7 @@ fun UserProfilesView(m: ChatModel, search: MutableState<String>, profileHidden:
|
||||
@Composable
|
||||
private fun UserProfilesLayout(
|
||||
users: List<User>,
|
||||
filteredUsers: List<User>,
|
||||
filteredUsers: List<UserInfo>,
|
||||
searchTextOrPassword: MutableState<String>,
|
||||
profileHidden: MutableState<Boolean>,
|
||||
visibleUsersCount: Int,
|
||||
@@ -195,7 +207,7 @@ private fun UserProfilesLayout(
|
||||
|
||||
@Composable
|
||||
private fun UserView(
|
||||
user: User,
|
||||
userInfo: UserInfo,
|
||||
visibleUsersCount: Int,
|
||||
activateUser: (User) -> Unit,
|
||||
removeUser: (User) -> Unit,
|
||||
@@ -205,7 +217,8 @@ private fun UserView(
|
||||
showHiddenProfile: (User) -> Unit,
|
||||
) {
|
||||
val showMenu = remember { mutableStateOf(false) }
|
||||
UserProfilePickerItem(user, onLongClick = { showMenu.value = true }) {
|
||||
val user = userInfo.user
|
||||
UserProfilePickerItem(user, onLongClick = { showMenu.value = true }, unreadCount = userInfo.unreadCount) {
|
||||
activateUser(user)
|
||||
}
|
||||
Box(Modifier.padding(horizontal = DEFAULT_PADDING)) {
|
||||
@@ -290,7 +303,7 @@ private fun ProfileActionView(action: UserProfileAction, user: User, doAction: (
|
||||
}
|
||||
}
|
||||
|
||||
fun filteredUsers(m: ChatModel, searchTextOrPassword: String): List<User> {
|
||||
fun filteredUsers(m: ChatModel, searchTextOrPassword: String): List<UserInfo> {
|
||||
val s = searchTextOrPassword.trim()
|
||||
val lower = s.lowercase()
|
||||
return m.users.filter { u ->
|
||||
@@ -299,7 +312,7 @@ fun filteredUsers(m: ChatModel, searchTextOrPassword: String): List<User> {
|
||||
} else {
|
||||
correctPassword(u.user, s)
|
||||
}
|
||||
}.map { it.user }
|
||||
}
|
||||
}
|
||||
|
||||
private fun visibleUsersCount(m: ChatModel): Int = m.users.filter { u -> !u.user.hidden }.size
|
||||
|
||||
@@ -267,7 +267,7 @@
|
||||
<string name="auth_device_authentication_is_disabled_turning_off">Device authentication is disabled. Turning off SimpleX Lock.</string>
|
||||
<string name="auth_stop_chat">Stop chat</string>
|
||||
<string name="auth_open_chat_console">Open chat console</string>
|
||||
<string name="auth_open_chat_profiles">Open chat profiles</string>
|
||||
<string name="auth_open_chat_profiles">Change chat profiles</string>
|
||||
<string name="auth_open_migration_to_another_device">Open migration screen</string>
|
||||
<string name="lock_not_enabled">SimpleX Lock not enabled!</string>
|
||||
<string name="you_can_turn_on_lock">You can turn on SimpleX Lock via Settings.</string>
|
||||
|
||||
Reference in New Issue
Block a user