diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt
index dc1950011..060a5f523 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt
@@ -63,8 +63,11 @@ fun ChatInfoView(
setContactAlias(chat.chatInfo.apiId, it, chatModel)
},
openPreferences = {
- ModalManager.shared.showModal(true) {
- ContactPreferencesView(chatModel, chatModel.currentUser.value ?: return@showModal, contact.contactId)
+ ModalManager.shared.showCustomModal { close ->
+ val user = chatModel.currentUser.value
+ if (user != null) {
+ ContactPreferencesView(chatModel, user, contact.contactId, close)
+ }
}
},
deleteContact = { deleteContactDialog(chat.chatInfo, chatModel, close) },
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt
index 8fb3b41fe..4b28d1831 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ContactPreferences.kt
@@ -25,33 +25,45 @@ fun ContactPreferencesView(
m: ChatModel,
user: User,
contactId: Long,
+ close: () -> Unit,
) {
val contact = remember { derivedStateOf { (m.getContactChat(contactId)?.chatInfo as? ChatInfo.Direct)?.contact } }
val ct = contact.value ?: return
var featuresAllowed by remember(ct) { mutableStateOf(contactUserPrefsToFeaturesAllowed(ct.mergedPreferences)) }
var currentFeaturesAllowed by remember(ct) { mutableStateOf(featuresAllowed) }
- ContactPreferencesLayout(
- featuresAllowed,
- currentFeaturesAllowed,
- user,
- ct,
- applyPrefs = { prefs ->
- featuresAllowed = prefs
- },
- reset = {
- featuresAllowed = currentFeaturesAllowed
- },
- savePrefs = {
- withApi {
- val prefs = contactFeaturesAllowedToPrefs(featuresAllowed)
- val toContact = m.controller.apiSetContactPrefs(ct.contactId, prefs)
- if (toContact != null) {
- m.updateContact(toContact)
- currentFeaturesAllowed = featuresAllowed
- }
+
+ fun savePrefs(afterSave: () -> Unit = {}) {
+ withApi {
+ val prefs = contactFeaturesAllowedToPrefs(featuresAllowed)
+ val toContact = m.controller.apiSetContactPrefs(ct.contactId, prefs)
+ if (toContact != null) {
+ m.updateContact(toContact)
+ currentFeaturesAllowed = featuresAllowed
}
+ afterSave()
+ }
+ }
+ ModalView(
+ close = {
+ if (featuresAllowed == currentFeaturesAllowed) close()
+ else showUnsavedChangesAlert({ savePrefs(close) }, close)
},
- )
+ background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight
+ ) {
+ ContactPreferencesLayout(
+ featuresAllowed,
+ currentFeaturesAllowed,
+ user,
+ ct,
+ applyPrefs = { prefs ->
+ featuresAllowed = prefs
+ },
+ reset = {
+ featuresAllowed = currentFeaturesAllowed
+ },
+ savePrefs = ::savePrefs,
+ )
+ }
}
@Composable
@@ -139,3 +151,13 @@ private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Bool
}
}
}
+
+private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) {
+ AlertManager.shared.showAlertDialogStacked(
+ title = generalGetString(R.string.save_preferences_question),
+ confirmText = generalGetString(R.string.save_and_notify_contact),
+ dismissText = generalGetString(R.string.exit_without_saving),
+ onConfirm = save,
+ onDismiss = revert,
+ )
+}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt
index 2d216dd72..1ff21e665 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/AddGroupMembersView.kt
@@ -44,8 +44,8 @@ fun AddGroupMembersView(groupInfo: GroupInfo, creatingGroup: Boolean = false, ch
selectedRole = selectedRole,
allowModifyMembers = allowModifyMembers,
openPreferences = {
- ModalManager.shared.showModal(true) {
- GroupPreferencesView(chatModel, groupInfo.id)
+ ModalManager.shared.showCustomModal { close ->
+ GroupPreferencesView(chatModel, groupInfo.id, close)
}
},
inviteMembers = {
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt
index 144dafc27..d37941443 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt
@@ -65,10 +65,11 @@ fun GroupChatInfoView(chatModel: ChatModel, close: () -> Unit) {
ModalManager.shared.showCustomModal { close -> GroupProfileView(groupInfo, chatModel, close) }
},
openPreferences = {
- ModalManager.shared.showModal(true) {
+ ModalManager.shared.showCustomModal { close ->
GroupPreferencesView(
chatModel,
- chat.id
+ chat.id,
+ close
)
}
},
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt
index e015de1ba..98b5f2581 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupPreferences.kt
@@ -13,41 +13,50 @@ import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import chat.simplex.app.R
import chat.simplex.app.model.*
-import chat.simplex.app.ui.theme.HighOrLowlight
-import chat.simplex.app.ui.theme.SimplexGreen
+import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
@Composable
-fun GroupPreferencesView(m: ChatModel, chatId: String) {
+fun GroupPreferencesView(m: ChatModel, chatId: String, close: () -> Unit,) {
val groupInfo = remember { derivedStateOf { (m.getChat(chatId)?.chatInfo as? ChatInfo.Group)?.groupInfo } }
val gInfo = groupInfo.value ?: return
var preferences by remember(gInfo) { mutableStateOf(gInfo.fullGroupPreferences) }
var currentPreferences by remember(gInfo) { mutableStateOf(preferences) }
- GroupPreferencesLayout(
- preferences,
- currentPreferences,
- gInfo,
- applyPrefs = { prefs ->
- preferences = prefs
- },
- reset = {
- preferences = currentPreferences
- },
- savePrefs = {
- withApi {
- val gp = gInfo.groupProfile.copy(groupPreferences = preferences.toGroupPreferences())
- val gInfo = m.controller.apiUpdateGroup(gInfo.groupId, gp)
- if (gInfo != null) {
- m.updateGroup(gInfo)
- currentPreferences = preferences
- }
+
+ fun savePrefs(afterSave: () -> Unit = {}) {
+ withApi {
+ val gp = gInfo.groupProfile.copy(groupPreferences = preferences.toGroupPreferences())
+ val gInfo = m.controller.apiUpdateGroup(gInfo.groupId, gp)
+ if (gInfo != null) {
+ m.updateGroup(gInfo)
+ currentPreferences = preferences
}
+ afterSave()
+ }
+ }
+ ModalView(
+ close = {
+ if (preferences == currentPreferences) close()
+ else showUnsavedChangesAlert({ savePrefs(close) }, close)
},
- )
+ background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight
+ ) {
+ GroupPreferencesLayout(
+ preferences,
+ currentPreferences,
+ gInfo,
+ applyPrefs = { prefs ->
+ preferences = prefs
+ },
+ reset = {
+ preferences = currentPreferences
+ },
+ savePrefs = ::savePrefs,
+ )
+ }
}
@Composable
@@ -130,3 +139,13 @@ private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Bool
}
}
}
+
+private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) {
+ AlertManager.shared.showAlertDialogStacked(
+ title = generalGetString(R.string.save_preferences_question),
+ confirmText = generalGetString(R.string.save_and_notify_group_members),
+ dismissText = generalGetString(R.string.exit_without_saving),
+ onConfirm = save,
+ onDismiss = revert,
+ )
+}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt
index cc1f06274..4909d3eb6 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/AlertManager.kt
@@ -5,9 +5,10 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.unit.sp
+import androidx.compose.ui.unit.*
import androidx.compose.ui.window.Dialog
import chat.simplex.app.R
import chat.simplex.app.TAG
@@ -93,6 +94,41 @@ class AlertManager {
}
}
+ fun showAlertDialogStacked(
+ title: String,
+ text: String? = null,
+ confirmText: String = generalGetString(R.string.ok),
+ onConfirm: (() -> Unit)? = null,
+ dismissText: String = generalGetString(R.string.cancel_verb),
+ onDismiss: (() -> Unit)? = null,
+ onDismissRequest: (() -> Unit)? = null,
+ destructive: Boolean = false
+ ) {
+ val alertText: (@Composable () -> Unit)? = if (text == null) null else { -> Text(text) }
+ showAlert {
+ AlertDialog(
+ onDismissRequest = { onDismissRequest?.invoke(); hideAlert() },
+ title = { Text(title) },
+ text = alertText,
+ buttons = {
+ Column(
+ Modifier.fillMaxWidth().padding(horizontal = 8.dp).padding(top = 16.dp, bottom = 2.dp),
+ horizontalAlignment = Alignment.End
+ ) {
+ TextButton(onClick = {
+ onDismiss?.invoke()
+ hideAlert()
+ }) { Text(dismissText) }
+ TextButton(onClick = {
+ onConfirm?.invoke()
+ hideAlert()
+ }) { Text(confirmText, color = if (destructive) MaterialTheme.colors.error else Color.Unspecified) }
+ }
+ },
+ )
+ }
+ }
+
fun showAlertMsg(
title: String, text: String? = null,
confirmText: String = generalGetString(R.string.ok), onConfirm: (() -> Unit)? = null
@@ -128,4 +164,4 @@ class AlertManager {
companion object {
val shared = AlertManager()
}
-}
\ No newline at end of file
+}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt
index 33494d916..ac94c9aa9 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/Preferences.kt
@@ -19,33 +19,40 @@ import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
@Composable
-fun PreferencesView(m: ChatModel, user: User) {
+fun PreferencesView(m: ChatModel, user: User, close: () -> Unit,) {
var preferences by remember { mutableStateOf(user.fullPreferences) }
var currentPreferences by remember { mutableStateOf(preferences) }
- PreferencesLayout(
- preferences,
- currentPreferences,
- applyPrefs = { prefs ->
- preferences = prefs
- },
- reset = {
- preferences = currentPreferences
- },
- savePrefs = {
- withApi {
- val newProfile = user.profile.toProfile().copy(preferences = preferences.toPreferences())
- val updatedProfile = m.controller.apiUpdateProfile(newProfile)
- if (updatedProfile != null) {
- val updatedUser = user.copy(
- profile = updatedProfile.toLocalProfile(user.profile.profileId),
- fullPreferences = preferences
- )
- currentPreferences = preferences
- m.currentUser.value = updatedUser
- }
+
+ fun savePrefs(afterSave: () -> Unit = {}) {
+ withApi {
+ val newProfile = user.profile.toProfile().copy(preferences = preferences.toPreferences())
+ val updatedProfile = m.controller.apiUpdateProfile(newProfile)
+ if (updatedProfile != null) {
+ val updatedUser = user.copy(
+ profile = updatedProfile.toLocalProfile(user.profile.profileId),
+ fullPreferences = preferences
+ )
+ currentPreferences = preferences
+ m.currentUser.value = updatedUser
}
+ afterSave()
+ }
+ }
+ ModalView(
+ close = {
+ if (preferences == currentPreferences) close()
+ else showUnsavedChangesAlert({ savePrefs(close) }, close)
},
- )
+ background = if (isInDarkTheme()) MaterialTheme.colors.background else SettingsBackgroundLight
+ ) {
+ PreferencesLayout(
+ preferences,
+ currentPreferences,
+ applyPrefs = { preferences = it },
+ reset = { preferences = currentPreferences },
+ savePrefs = ::savePrefs,
+ )
+ }
}
@Composable
@@ -107,3 +114,13 @@ private fun ResetSaveButtons(reset: () -> Unit, save: () -> Unit, disabled: Bool
}
}
}
+
+private fun showUnsavedChangesAlert(save: () -> Unit, revert: () -> Unit) {
+ AlertManager.shared.showAlertDialogStacked(
+ title = generalGetString(R.string.save_preferences_question),
+ confirmText = generalGetString(R.string.save_and_notify_contacts),
+ dismissText = generalGetString(R.string.exit_without_saving),
+ onConfirm = save,
+ onDismiss = revert,
+ )
+}
diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt
index 048ce6845..5a1397657 100644
--- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt
+++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt
@@ -116,7 +116,7 @@ fun SettingsLayout(
SectionDivider()
SettingsActionItem(Icons.Outlined.QrCode, stringResource(R.string.your_simplex_contact_address), showModal { CreateLinkView(it, CreateLinkTab.LONG_TERM) }, disabled = stopped)
SectionDivider()
- ChatPreferencesItem(showSettingsModal)
+ ChatPreferencesItem(showCustomModal)
}
SectionSpacer()
@@ -239,14 +239,14 @@ fun MaintainIncognitoState(chatModel: ChatModel) {
}
}
-@Composable fun ChatPreferencesItem(showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit)) {
+@Composable fun ChatPreferencesItem(showCustomModal: ((@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit))) {
SettingsActionItem(
Icons.Outlined.ToggleOn,
stringResource(R.string.chat_preferences),
click = {
withApi {
- showSettingsModal {
- PreferencesView(it, it.currentUser.value ?: return@showSettingsModal)
+ showCustomModal { m, close ->
+ PreferencesView(m, m.currentUser.value ?: return@showCustomModal, close)
}()
}
}
diff --git a/apps/android/app/src/main/res/values-de/strings.xml b/apps/android/app/src/main/res/values-de/strings.xml
index a42701dc6..49f091060 100644
--- a/apps/android/app/src/main/res/values-de/strings.xml
+++ b/apps/android/app/src/main/res/values-de/strings.xml
@@ -475,9 +475,11 @@
Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt.\n\nSimpleX-Server können Ihr Profil nicht sehen.
Bild bearbeiten
Bild löschen
- Speichern (und Kontakt benachrichtigen)
- Speichern (und Kontakte benachrichtigen)
- Speichern (und Gruppenmitglieder benachrichtigen)
+ Präferenzen speichern?
+ Speichern und Kontakt benachrichtigen
+ Speichern und Kontakte benachrichtigen
+ Speichern und Gruppenmitglieder benachrichtigen
+ Beenden ohne Speichern
Sie haben volle Kontrolle über Ihren Chat!
diff --git a/apps/android/app/src/main/res/values-ru/strings.xml b/apps/android/app/src/main/res/values-ru/strings.xml
index 4602ee501..772d3a912 100644
--- a/apps/android/app/src/main/res/values-ru/strings.xml
+++ b/apps/android/app/src/main/res/values-ru/strings.xml
@@ -472,9 +472,11 @@
Ваш профиль хранится на вашем устройстве и отправляется только вашим контактам.\n\nSimpleX серверы не могут получить доступ к вашему профилю.
Поменять аватар
Удалить аватар
- Сохранить (и уведомить контакт)
- Сохранить (и послать обновление контактам)
- Сохранить (и уведомить членов группы)
+ Сохранить предпочтения?
+ Сохранить и уведомить контакт
+ Сохранить и уведомить контакты
+ Сохранить и уведомить членов группы
+ Выйти без сохранения
Вы котролируете ваш чат!
diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml
index b5b97611a..4863d5e27 100644
--- a/apps/android/app/src/main/res/values/strings.xml
+++ b/apps/android/app/src/main/res/values/strings.xml
@@ -475,9 +475,11 @@
Your profile is stored on your device and shared only with your contacts.\n\nSimpleX servers cannot see your profile.
Edit image
Delete image
- Save (and notify contact)
- Save (and notify contacts)
- Save (and notify group members)
+ Save preferences?
+ Save and notify contact
+ Save and notify contacts
+ Save and notify group members
+ Exit without saving
You control your chat!