mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-06-08 15:13:34 +00:00
android, desktop: settings navigation reorganization
Restructure the root Settings screen into two top-level sections and fold previously-scattered items into three new sub-screens. Root: - Appearance, Your privacy, Chat data - Help & support, Migrate to another device, Advanced settings Your privacy (renamed from Privacy & security): keeps Device, link previews / remove tracking, auto-accept images, blur media, contact requests from groups. Adds a "More privacy" sub-screen. More privacy (new): show last messages, message draft, encrypt local files, protect IP address (with original dynamic footer preserved), notification preview mode (moved from Notifications), and delivery receipts. Help & support (new): merges Help and Support SimpleX Chat sections into Help / About (with App version) / Contact / Support the project. Advanced settings (new): Network & servers, Notifications (Android), Audio & video calls; then Developer tools, Restart and Shutdown (Android), App update channel (desktop). Notifications is hidden on desktop because the screen is empty after Show preview moves to More privacy. Chat data is the new top-level menu label for the existing Database passphrase & export screen.
This commit is contained in:
+3
-6
@@ -11,20 +11,17 @@ import dev.icerock.moko.resources.compose.painterResource
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
|
||||
@Composable
|
||||
actual fun SettingsSectionApp(
|
||||
actual fun AdvancedSettingsAppSection(
|
||||
showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
|
||||
showVersion: () -> Unit,
|
||||
withAuth: (title: String, desc: String, block: () -> Unit) -> Unit
|
||||
withAuth: (title: String, desc: String, block: () -> Unit) -> Unit,
|
||||
) {
|
||||
SectionView(stringResource(MR.strings.settings_section_title_app)) {
|
||||
SectionView {
|
||||
SettingsActionItem(painterResource(MR.images.ic_restart_alt), stringResource(MR.strings.settings_restart_app), ::restartApp)
|
||||
SettingsActionItem(painterResource(MR.images.ic_power_settings_new), stringResource(MR.strings.settings_shutdown), { shutdownAppAlert(::shutdownApp) })
|
||||
SettingsActionItem(painterResource(MR.images.ic_code), stringResource(MR.strings.settings_developer_tools), showSettingsModal { DeveloperView(withAuth) })
|
||||
AppVersionItem(showVersion)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun restartApp() {
|
||||
ProcessPhoenix.triggerRebirth(androidAppContext)
|
||||
shutdownApp()
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package chat.simplex.common.views.usersettings
|
||||
|
||||
import SectionBottomSpacer
|
||||
import SectionDividerSpaced
|
||||
import SectionView
|
||||
import androidx.compose.runtime.*
|
||||
import chat.simplex.common.model.ChatModel
|
||||
import chat.simplex.common.model.NotificationsMode
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.common.views.usersettings.networkAndServers.NetworkAndServersView
|
||||
import chat.simplex.res.MR
|
||||
import dev.icerock.moko.resources.compose.painterResource
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
|
||||
@Composable
|
||||
fun AdvancedSettingsView(
|
||||
chatModel: ChatModel,
|
||||
showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
|
||||
showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
|
||||
showCustomModal: (@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit),
|
||||
withAuth: (title: String, desc: String, block: () -> Unit) -> Unit,
|
||||
) {
|
||||
val stopped = chatModel.chatRunning.value == false
|
||||
val notificationsMode = remember { chatModel.controller.appPrefs.notificationsMode.state }
|
||||
ColumnWithScrollBar {
|
||||
AppBarTitle(stringResource(MR.strings.advanced_settings))
|
||||
|
||||
SectionView {
|
||||
SettingsActionItem(painterResource(MR.images.ic_wifi_tethering), stringResource(MR.strings.network_and_servers), showCustomModal { _, close -> NetworkAndServersView(close) }, disabled = stopped)
|
||||
if (appPlatform == AppPlatform.ANDROID) {
|
||||
SettingsActionItem(painterResource(if (notificationsMode.value == NotificationsMode.OFF) MR.images.ic_bolt_off else MR.images.ic_bolt), stringResource(MR.strings.notifications), showSettingsModal { NotificationsSettingsView(it) }, disabled = stopped)
|
||||
}
|
||||
SettingsActionItem(painterResource(MR.images.ic_videocam), stringResource(MR.strings.settings_audio_video_calls), showSettingsModal { CallSettingsView(it, showModal) }, disabled = stopped)
|
||||
}
|
||||
SectionDividerSpaced()
|
||||
|
||||
AdvancedSettingsAppSection(showSettingsModal, withAuth)
|
||||
SectionBottomSpacer()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
expect fun AdvancedSettingsAppSection(
|
||||
showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
|
||||
withAuth: (title: String, desc: String, block: () -> Unit) -> Unit,
|
||||
)
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package chat.simplex.common.views.usersettings
|
||||
|
||||
import SectionBottomSpacer
|
||||
import SectionDividerSpaced
|
||||
import SectionItemView
|
||||
import SectionView
|
||||
import TextIconSpaced
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.platform.UriHandler
|
||||
import chat.simplex.common.BuildConfigCommon
|
||||
import chat.simplex.common.model.ChatModel
|
||||
import chat.simplex.common.platform.ColumnWithScrollBar
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.common.views.onboarding.SimpleXInfo
|
||||
import chat.simplex.common.views.onboarding.WhatsNewView
|
||||
import chat.simplex.res.MR
|
||||
import dev.icerock.moko.resources.compose.painterResource
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
|
||||
@Composable
|
||||
fun HelpAndSupportView(
|
||||
chatModel: ChatModel,
|
||||
userDisplayName: String?,
|
||||
showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
|
||||
showCustomModal: (@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit),
|
||||
showVersion: () -> Unit,
|
||||
) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val stopped = chatModel.chatRunning.value == false
|
||||
ColumnWithScrollBar {
|
||||
AppBarTitle(stringResource(MR.strings.help_and_support))
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_help)) {
|
||||
SettingsActionItem(painterResource(MR.images.ic_help), stringResource(MR.strings.how_to_use_simplex_chat), showModal { HelpView(userDisplayName ?: "") }, disabled = stopped)
|
||||
SettingsActionItem(painterResource(MR.images.ic_add), stringResource(MR.strings.whats_new), showCustomModal { _, close -> WhatsNewView(viaSettings = true, close = close) }, disabled = stopped)
|
||||
}
|
||||
SectionDividerSpaced()
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_about)) {
|
||||
SettingsActionItem(painterResource(MR.images.ic_info), stringResource(MR.strings.about_simplex_chat), showModal { SimpleXInfo(it, onboarding = false) })
|
||||
AppVersionItem(showVersion)
|
||||
}
|
||||
SectionDividerSpaced()
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_contact)) {
|
||||
if (!chatModel.desktopNoUserNoRemote) {
|
||||
SettingsActionItem(painterResource(MR.images.ic_tag), stringResource(MR.strings.chat_with_the_founder), { uriHandler.openVerifiedSimplexUri(simplexTeamUri) }, textColor = MaterialTheme.colors.primary, disabled = stopped)
|
||||
}
|
||||
SettingsActionItem(painterResource(MR.images.ic_mail), stringResource(MR.strings.send_us_an_email), { uriHandler.openUriCatching("mailto:chat@simplex.chat") }, textColor = MaterialTheme.colors.primary)
|
||||
}
|
||||
SectionDividerSpaced()
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_support_project)) {
|
||||
if (!BuildConfigCommon.ANDROID_BUNDLE) {
|
||||
ContributeItem(uriHandler)
|
||||
}
|
||||
RateAppItem(uriHandler)
|
||||
StarOnGithubItem(uriHandler)
|
||||
}
|
||||
SectionBottomSpacer()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable private fun ContributeItem(uriHandler: UriHandler) {
|
||||
SectionItemView({ uriHandler.openExternalLink("https://github.com/simplex-chat/simplex-chat#contribute") }) {
|
||||
Icon(
|
||||
painterResource(MR.images.ic_keyboard),
|
||||
contentDescription = "GitHub",
|
||||
tint = MaterialTheme.colors.secondary,
|
||||
)
|
||||
TextIconSpaced()
|
||||
Text(generalGetString(MR.strings.contribute), color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable private fun RateAppItem(uriHandler: UriHandler) {
|
||||
SectionItemView({
|
||||
runCatching { uriHandler.openUriCatching("market://details?id=chat.simplex.app") }
|
||||
.onFailure { uriHandler.openUriCatching("https://play.google.com/store/apps/details?id=chat.simplex.app") }
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painterResource(MR.images.ic_star),
|
||||
contentDescription = "Google Play",
|
||||
tint = MaterialTheme.colors.secondary,
|
||||
)
|
||||
TextIconSpaced()
|
||||
Text(generalGetString(MR.strings.rate_the_app), color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable private fun StarOnGithubItem(uriHandler: UriHandler) {
|
||||
SectionItemView({ uriHandler.openExternalLink("https://github.com/simplex-chat/simplex-chat") }) {
|
||||
Icon(
|
||||
painter = painterResource(MR.images.ic_github),
|
||||
contentDescription = "GitHub",
|
||||
tint = MaterialTheme.colors.secondary,
|
||||
)
|
||||
TextIconSpaced()
|
||||
Text(generalGetString(MR.strings.star_on_github), color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
+1
-18
@@ -24,19 +24,12 @@ import kotlin.collections.ArrayList
|
||||
fun NotificationsSettingsView(
|
||||
chatModel: ChatModel,
|
||||
) {
|
||||
val onNotificationPreviewModeSelected = { mode: NotificationPreviewMode ->
|
||||
chatModel.controller.appPrefs.notificationPreviewMode.set(mode.name)
|
||||
chatModel.notificationPreviewMode.value = mode
|
||||
}
|
||||
|
||||
NotificationsSettingsLayout(
|
||||
notificationsMode = remember { chatModel.controller.appPrefs.notificationsMode.state },
|
||||
notificationPreviewMode = chatModel.notificationPreviewMode,
|
||||
showPage = { page ->
|
||||
ModalManager.start.showModalCloseable(true) {
|
||||
when (page) {
|
||||
CurrentPage.NOTIFICATIONS_MODE -> NotificationsModeView(chatModel.controller.appPrefs.notificationsMode.state) { changeNotificationsMode(it, chatModel) }
|
||||
CurrentPage.NOTIFICATION_PREVIEW_MODE -> NotificationPreviewView(chatModel.notificationPreviewMode, onNotificationPreviewModeSelected)
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -44,17 +37,15 @@ fun NotificationsSettingsView(
|
||||
}
|
||||
|
||||
enum class CurrentPage {
|
||||
NOTIFICATIONS_MODE, NOTIFICATION_PREVIEW_MODE
|
||||
NOTIFICATIONS_MODE
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NotificationsSettingsLayout(
|
||||
notificationsMode: State<NotificationsMode>,
|
||||
notificationPreviewMode: State<NotificationPreviewMode>,
|
||||
showPage: (CurrentPage) -> Unit,
|
||||
) {
|
||||
val modes = remember { notificationModes() }
|
||||
val previewModes = remember { notificationPreviewModes() }
|
||||
|
||||
ColumnWithScrollBar {
|
||||
AppBarTitle(stringResource(MR.strings.notifications))
|
||||
@@ -69,14 +60,6 @@ fun NotificationsSettingsLayout(
|
||||
)
|
||||
}
|
||||
}
|
||||
SettingsActionItemWithContent(null, stringResource(MR.strings.settings_notification_preview_mode_title), { showPage(CurrentPage.NOTIFICATION_PREVIEW_MODE) }) {
|
||||
Text(
|
||||
previewModes.firstOrNull { it.value == notificationPreviewMode.value }?.title ?: "",
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.colors.secondary
|
||||
)
|
||||
}
|
||||
}
|
||||
if (platform.androidIsXiaomiDevice() && (notificationsMode.value == NotificationsMode.PERIODIC || notificationsMode.value == NotificationsMode.SERVICE)) {
|
||||
SectionTextFooter(annotatedStringResource(MR.strings.xiaomi_ignore_battery_optimization))
|
||||
|
||||
+102
-55
@@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.*
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import dev.icerock.moko.resources.compose.painterResource
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -73,6 +74,48 @@ fun PrivacySettingsView(
|
||||
stringResource(MR.strings.sanitize_links_toggle),
|
||||
chatModel.controller.appPrefs.privacySanitizeLinks
|
||||
)
|
||||
}
|
||||
SectionDividerSpaced()
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_files)) {
|
||||
SettingsPreferenceItem(painterResource(MR.images.ic_image), stringResource(MR.strings.auto_accept_images), chatModel.controller.appPrefs.privacyAcceptImages)
|
||||
BlurRadiusOptions(remember { appPrefs.privacyMediaBlurRadius.state }) {
|
||||
appPrefs.privacyMediaBlurRadius.set(it)
|
||||
}
|
||||
}
|
||||
|
||||
val currentUser = chatModel.currentUser.value
|
||||
if (currentUser != null && !chatModel.desktopNoUserNoRemote) {
|
||||
SectionDividerSpaced()
|
||||
ContacRequestsFromGroupsSection(
|
||||
currentUser = currentUser,
|
||||
setAutoAcceptGrpDirectInvs = { enable ->
|
||||
withApi {
|
||||
chatModel.controller.apiSetUserAutoAcceptMemberContacts(currentUser, enable)
|
||||
chatModel.currentUser.value = currentUser.copy(autoAcceptMemberContacts = enable)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
SectionDividerSpaced()
|
||||
SectionView {
|
||||
SettingsActionItem(
|
||||
painterResource(MR.images.ic_more_horiz),
|
||||
stringResource(MR.strings.more_privacy),
|
||||
showSettingsModal { MorePrivacyView(it) }
|
||||
)
|
||||
}
|
||||
SectionBottomSpacer()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MorePrivacyView(chatModel: ChatModel) {
|
||||
ColumnWithScrollBar {
|
||||
AppBarTitle(stringResource(MR.strings.more_privacy))
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_chats)) {
|
||||
SettingsPreferenceItem(
|
||||
painterResource(MR.images.ic_chat_bubble),
|
||||
stringResource(MR.strings.privacy_show_last_messages),
|
||||
@@ -98,10 +141,6 @@ fun PrivacySettingsView(
|
||||
SettingsPreferenceItem(painterResource(MR.images.ic_lock), stringResource(MR.strings.encrypt_local_files), chatModel.controller.appPrefs.privacyEncryptLocalFiles, onChange = { enable ->
|
||||
withBGApi { chatModel.controller.apiSetEncryptLocalFiles(enable) }
|
||||
})
|
||||
SettingsPreferenceItem(painterResource(MR.images.ic_image), stringResource(MR.strings.auto_accept_images), chatModel.controller.appPrefs.privacyAcceptImages)
|
||||
BlurRadiusOptions(remember { appPrefs.privacyMediaBlurRadius.state }) {
|
||||
appPrefs.privacyMediaBlurRadius.set(it)
|
||||
}
|
||||
SettingsPreferenceItem(painterResource(MR.images.ic_security), stringResource(MR.strings.protect_ip_address), chatModel.controller.appPrefs.privacyAskToApproveRelays)
|
||||
}
|
||||
SectionTextFooter(
|
||||
@@ -111,9 +150,34 @@ fun PrivacySettingsView(
|
||||
stringResource(MR.strings.without_tor_or_vpn_ip_address_will_be_visible_to_file_servers)
|
||||
}
|
||||
)
|
||||
SectionDividerSpaced()
|
||||
|
||||
SectionView(stringResource(MR.strings.notifications)) {
|
||||
val previewModes = remember { notificationPreviewModes() }
|
||||
val notificationPreviewMode = remember { chatModel.notificationPreviewMode }
|
||||
SettingsActionItemWithContent(
|
||||
painterResource(MR.images.ic_visibility_off),
|
||||
stringResource(MR.strings.settings_notification_preview_mode_title),
|
||||
click = {
|
||||
ModalManager.start.showModalCloseable(true) {
|
||||
NotificationPreviewView(notificationPreviewMode) { mode ->
|
||||
chatModel.controller.appPrefs.notificationPreviewMode.set(mode.name)
|
||||
chatModel.notificationPreviewMode.value = mode
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
previewModes.firstOrNull { it.value == notificationPreviewMode.value }?.title ?: "",
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.colors.secondary
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val currentUser = chatModel.currentUser.value
|
||||
if (currentUser != null) {
|
||||
if (currentUser != null && !chatModel.desktopNoUserNoRemote) {
|
||||
fun setSendReceiptsContacts(enable: Boolean, clearOverrides: Boolean) {
|
||||
withLongRunningApi(slow = 60_000) {
|
||||
val mrs = UserMsgReceiptSettings(enable, clearOverrides)
|
||||
@@ -164,57 +228,40 @@ fun PrivacySettingsView(
|
||||
}
|
||||
}
|
||||
|
||||
fun setAutoAcceptGrpDirectInvs(enable: Boolean) {
|
||||
withApi {
|
||||
chatModel.controller.apiSetUserAutoAcceptMemberContacts(currentUser, enable)
|
||||
chatModel.currentUser.value = currentUser.copy(autoAcceptMemberContacts = enable)
|
||||
SectionDividerSpaced()
|
||||
DeliveryReceiptsSection(
|
||||
currentUser = currentUser,
|
||||
setOrAskSendReceiptsContacts = { enable ->
|
||||
val contactReceiptsOverrides = chatModel.chats.value.fold(0) { count, chat ->
|
||||
if (chat.chatInfo is ChatInfo.Direct) {
|
||||
val sendRcpts = chat.chatInfo.contact.chatSettings.sendRcpts
|
||||
count + (if (sendRcpts == null || sendRcpts == enable) 0 else 1)
|
||||
} else {
|
||||
count
|
||||
}
|
||||
}
|
||||
if (contactReceiptsOverrides == 0) {
|
||||
setSendReceiptsContacts(enable, clearOverrides = false)
|
||||
} else {
|
||||
showUserContactsReceiptsAlert(enable, contactReceiptsOverrides, ::setSendReceiptsContacts)
|
||||
}
|
||||
},
|
||||
setOrAskSendReceiptsGroups = { enable ->
|
||||
val groupReceiptsOverrides = chatModel.chats.value.fold(0) { count, chat ->
|
||||
if (chat.chatInfo is ChatInfo.Group) {
|
||||
val sendRcpts = chat.chatInfo.groupInfo.chatSettings.sendRcpts
|
||||
count + (if (sendRcpts == null || sendRcpts == enable) 0 else 1)
|
||||
} else {
|
||||
count
|
||||
}
|
||||
}
|
||||
if (groupReceiptsOverrides == 0) {
|
||||
setSendReceiptsGroups(enable, clearOverrides = false)
|
||||
} else {
|
||||
showUserGroupsReceiptsAlert(enable, groupReceiptsOverrides, ::setSendReceiptsGroups)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!chatModel.desktopNoUserNoRemote) {
|
||||
SectionDividerSpaced()
|
||||
ContacRequestsFromGroupsSection(
|
||||
currentUser = currentUser,
|
||||
setAutoAcceptGrpDirectInvs = { enable ->
|
||||
setAutoAcceptGrpDirectInvs(enable)
|
||||
}
|
||||
)
|
||||
|
||||
SectionDividerSpaced()
|
||||
DeliveryReceiptsSection(
|
||||
currentUser = currentUser,
|
||||
setOrAskSendReceiptsContacts = { enable ->
|
||||
val contactReceiptsOverrides = chatModel.chats.value.fold(0) { count, chat ->
|
||||
if (chat.chatInfo is ChatInfo.Direct) {
|
||||
val sendRcpts = chat.chatInfo.contact.chatSettings.sendRcpts
|
||||
count + (if (sendRcpts == null || sendRcpts == enable) 0 else 1)
|
||||
} else {
|
||||
count
|
||||
}
|
||||
}
|
||||
if (contactReceiptsOverrides == 0) {
|
||||
setSendReceiptsContacts(enable, clearOverrides = false)
|
||||
} else {
|
||||
showUserContactsReceiptsAlert(enable, contactReceiptsOverrides, ::setSendReceiptsContacts)
|
||||
}
|
||||
},
|
||||
setOrAskSendReceiptsGroups = { enable ->
|
||||
val groupReceiptsOverrides = chatModel.chats.value.fold(0) { count, chat ->
|
||||
if (chat.chatInfo is ChatInfo.Group) {
|
||||
val sendRcpts = chat.chatInfo.groupInfo.chatSettings.sendRcpts
|
||||
count + (if (sendRcpts == null || sendRcpts == enable) 0 else 1)
|
||||
} else {
|
||||
count
|
||||
}
|
||||
}
|
||||
if (groupReceiptsOverrides == 0) {
|
||||
setSendReceiptsGroups(enable, clearOverrides = false)
|
||||
} else {
|
||||
showUserGroupsReceiptsAlert(enable, groupReceiptsOverrides, ::setSendReceiptsGroups)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
SectionBottomSpacer()
|
||||
}
|
||||
|
||||
+10
-90
@@ -22,7 +22,6 @@ import dev.icerock.moko.resources.compose.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.*
|
||||
import chat.simplex.common.BuildConfigCommon
|
||||
import chat.simplex.common.model.*
|
||||
import chat.simplex.common.model.ChatController.appPrefs
|
||||
import chat.simplex.common.platform.*
|
||||
@@ -30,9 +29,6 @@ import chat.simplex.common.ui.theme.*
|
||||
import chat.simplex.common.views.database.DatabaseView
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.common.views.migration.MigrateFromDeviceView
|
||||
import chat.simplex.common.views.onboarding.SimpleXInfo
|
||||
import chat.simplex.common.views.onboarding.WhatsNewView
|
||||
import chat.simplex.common.views.usersettings.networkAndServers.NetworkAndServersView
|
||||
import chat.simplex.res.MR
|
||||
|
||||
@Composable
|
||||
@@ -43,7 +39,6 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit, close: (
|
||||
stopped,
|
||||
chatModel.chatDbEncrypted.value == true,
|
||||
remember { chatModel.controller.appPrefs.storeDBPassphrase.state }.value,
|
||||
remember { chatModel.controller.appPrefs.notificationsMode.state },
|
||||
user?.displayName,
|
||||
setPerformLA = setPerformLA,
|
||||
showModal = { modalView -> { ModalManager.start.showModal { modalView(chatModel) } } },
|
||||
@@ -84,7 +79,6 @@ fun SettingsLayout(
|
||||
stopped: Boolean,
|
||||
encrypted: Boolean,
|
||||
passphraseSaved: Boolean,
|
||||
notificationsMode: State<NotificationsMode>,
|
||||
userDisplayName: String?,
|
||||
setPerformLA: (Boolean) -> Unit,
|
||||
showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
|
||||
@@ -98,58 +92,25 @@ fun SettingsLayout(
|
||||
LaunchedEffect(Unit) {
|
||||
hideKeyboard(view)
|
||||
}
|
||||
val uriHandler = LocalUriHandler.current
|
||||
ColumnWithScrollBar {
|
||||
AppBarTitle(stringResource(MR.strings.your_settings))
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_settings)) {
|
||||
SettingsActionItem(painterResource(if (notificationsMode.value == NotificationsMode.OFF) MR.images.ic_bolt_off else MR.images.ic_bolt), stringResource(MR.strings.notifications), showSettingsModal { NotificationsSettingsView(it) }, disabled = stopped)
|
||||
SettingsActionItem(painterResource(MR.images.ic_wifi_tethering), stringResource(MR.strings.network_and_servers), showCustomModal { _, close -> NetworkAndServersView(close) }, disabled = stopped)
|
||||
SettingsActionItem(painterResource(MR.images.ic_videocam), stringResource(MR.strings.settings_audio_video_calls), showSettingsModal { CallSettingsView(it, showModal) }, disabled = stopped)
|
||||
SettingsActionItem(painterResource(MR.images.ic_lock), stringResource(MR.strings.privacy_and_security), showSettingsModal { PrivacySettingsView(it, showSettingsModal, setPerformLA) }, disabled = stopped)
|
||||
SectionView {
|
||||
SettingsActionItem(painterResource(MR.images.ic_light_mode), stringResource(MR.strings.appearance_settings), showSettingsModal { AppearanceView(it) })
|
||||
}
|
||||
SectionDividerSpaced()
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_chat_database)) {
|
||||
SettingsActionItem(painterResource(MR.images.ic_lock), stringResource(MR.strings.your_privacy), showSettingsModal { PrivacySettingsView(it, showSettingsModal, setPerformLA) }, disabled = stopped)
|
||||
DatabaseItem(encrypted, passphraseSaved, showSettingsModal { DatabaseView() }, stopped)
|
||||
}
|
||||
SectionDividerSpaced()
|
||||
|
||||
SectionView {
|
||||
SettingsActionItem(painterResource(MR.images.ic_help), stringResource(MR.strings.help_and_support), showSettingsModal { HelpAndSupportView(it, userDisplayName, showModal, showCustomModal, showVersion) })
|
||||
SettingsActionItem(painterResource(MR.images.ic_ios_share), stringResource(MR.strings.migrate_from_device_to_another_device), { withAuth(generalGetString(MR.strings.auth_open_migration_to_another_device), generalGetString(MR.strings.auth_log_in_using_credential)) { ModalManager.fullscreen.showCustomModal { close -> MigrateFromDeviceView(close) } } }, disabled = stopped)
|
||||
SettingsActionItem(painterResource(MR.images.ic_code), stringResource(MR.strings.advanced_settings), showSettingsModal { AdvancedSettingsView(it, showModal, showSettingsModal, showCustomModal, withAuth) })
|
||||
}
|
||||
|
||||
SectionDividerSpaced()
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_help)) {
|
||||
SettingsActionItem(painterResource(MR.images.ic_help), stringResource(MR.strings.how_to_use_simplex_chat), showModal { HelpView(userDisplayName ?: "") }, disabled = stopped)
|
||||
SettingsActionItem(painterResource(MR.images.ic_add), stringResource(MR.strings.whats_new), showCustomModal { _, close -> WhatsNewView(viaSettings = true, close = close) }, disabled = stopped)
|
||||
SettingsActionItem(painterResource(MR.images.ic_info), stringResource(MR.strings.about_simplex_chat), showModal { SimpleXInfo(it, onboarding = false) })
|
||||
if (!chatModel.desktopNoUserNoRemote) {
|
||||
SettingsActionItem(painterResource(MR.images.ic_tag), stringResource(MR.strings.chat_with_the_founder), { uriHandler.openVerifiedSimplexUri(simplexTeamUri) }, textColor = MaterialTheme.colors.primary, disabled = stopped)
|
||||
}
|
||||
SettingsActionItem(painterResource(MR.images.ic_mail), stringResource(MR.strings.send_us_an_email), { uriHandler.openUriCatching("mailto:chat@simplex.chat") }, textColor = MaterialTheme.colors.primary)
|
||||
}
|
||||
SectionDividerSpaced()
|
||||
|
||||
SectionView(stringResource(MR.strings.settings_section_title_support)) {
|
||||
if (!BuildConfigCommon.ANDROID_BUNDLE) {
|
||||
ContributeItem(uriHandler)
|
||||
}
|
||||
RateAppItem(uriHandler)
|
||||
StarOnGithubItem(uriHandler)
|
||||
}
|
||||
SectionDividerSpaced()
|
||||
|
||||
SettingsSectionApp(showSettingsModal, showVersion, withAuth)
|
||||
SectionBottomSpacer()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
expect fun SettingsSectionApp(
|
||||
showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
|
||||
showVersion: () -> Unit,
|
||||
withAuth: (title: String, desc: String, block: () -> Unit) -> Unit
|
||||
)
|
||||
|
||||
@Composable private fun DatabaseItem(encrypted: Boolean, saved: Boolean, openDatabaseView: () -> Unit, stopped: Boolean) {
|
||||
SectionItemView(openDatabaseView) {
|
||||
Row(
|
||||
@@ -160,11 +121,11 @@ expect fun SettingsSectionApp(
|
||||
Row(Modifier.weight(1f), verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
painterResource(MR.images.ic_database),
|
||||
contentDescription = stringResource(MR.strings.database_passphrase_and_export),
|
||||
contentDescription = stringResource(MR.strings.chat_data),
|
||||
tint = if (encrypted && (appPlatform.isAndroid || !saved)) MaterialTheme.colors.secondary else WarningOrange,
|
||||
)
|
||||
TextIconSpaced(false)
|
||||
Text(stringResource(MR.strings.database_passphrase_and_export))
|
||||
Text(stringResource(MR.strings.chat_data))
|
||||
}
|
||||
if (stopped) {
|
||||
Icon(
|
||||
@@ -208,46 +169,6 @@ fun ChatLockItem(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable private fun ContributeItem(uriHandler: UriHandler) {
|
||||
SectionItemView({ uriHandler.openExternalLink("https://github.com/simplex-chat/simplex-chat#contribute") }) {
|
||||
Icon(
|
||||
painterResource(MR.images.ic_keyboard),
|
||||
contentDescription = "GitHub",
|
||||
tint = MaterialTheme.colors.secondary,
|
||||
)
|
||||
TextIconSpaced()
|
||||
Text(generalGetString(MR.strings.contribute), color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable private fun RateAppItem(uriHandler: UriHandler) {
|
||||
SectionItemView({
|
||||
runCatching { uriHandler.openUriCatching("market://details?id=chat.simplex.app") }
|
||||
.onFailure { uriHandler.openUriCatching("https://play.google.com/store/apps/details?id=chat.simplex.app") }
|
||||
}
|
||||
) {
|
||||
Icon(
|
||||
painterResource(MR.images.ic_star),
|
||||
contentDescription = "Google Play",
|
||||
tint = MaterialTheme.colors.secondary,
|
||||
)
|
||||
TextIconSpaced()
|
||||
Text(generalGetString(MR.strings.rate_the_app), color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable private fun StarOnGithubItem(uriHandler: UriHandler) {
|
||||
SectionItemView({ uriHandler.openExternalLink("https://github.com/simplex-chat/simplex-chat") }) {
|
||||
Icon(
|
||||
painter = painterResource(MR.images.ic_github),
|
||||
contentDescription = "GitHub",
|
||||
tint = MaterialTheme.colors.secondary,
|
||||
)
|
||||
TextIconSpaced()
|
||||
Text(generalGetString(MR.strings.star_on_github), color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable fun ChatConsoleItem(showTerminal: () -> Unit) {
|
||||
SectionItemView(showTerminal) {
|
||||
Icon(
|
||||
@@ -486,7 +407,6 @@ fun PreviewSettingsLayout() {
|
||||
stopped = false,
|
||||
encrypted = false,
|
||||
passphraseSaved = false,
|
||||
notificationsMode = remember { mutableStateOf(NotificationsMode.OFF) },
|
||||
userDisplayName = "Alice",
|
||||
setPerformLA = { _ -> },
|
||||
showModal = { {} },
|
||||
|
||||
@@ -1548,6 +1548,13 @@
|
||||
<string name="settings_section_title_files">Files</string>
|
||||
<string name="settings_section_title_delivery_receipts">Send delivery receipts to</string>
|
||||
<string name="settings_section_title_contact_requests_from_groups">Contact requests from groups</string>
|
||||
<string name="settings_section_title_about">About</string>
|
||||
<string name="settings_section_title_contact">Contact</string>
|
||||
<string name="settings_section_title_support_project">Support the project</string>
|
||||
<string name="chat_data">Chat data</string>
|
||||
<string name="help_and_support">Help & support</string>
|
||||
<string name="more_privacy">More privacy</string>
|
||||
<string name="advanced_settings">Advanced settings</string>
|
||||
<string name="settings_restart_app">Restart</string>
|
||||
<string name="settings_shutdown">Shutdown</string>
|
||||
<string name="settings_developer_tools">Developer tools</string>
|
||||
|
||||
+5
-12
@@ -1,27 +1,21 @@
|
||||
package chat.simplex.common.views.usersettings
|
||||
|
||||
import SectionView
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.runtime.*
|
||||
import chat.simplex.common.model.ChatController.appPrefs
|
||||
import chat.simplex.common.model.ChatModel
|
||||
import chat.simplex.common.platform.AppUpdatesChannel
|
||||
import chat.simplex.common.ui.theme.DEFAULT_PADDING_HALF
|
||||
import chat.simplex.common.platform.*
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.res.MR
|
||||
import dev.icerock.moko.resources.compose.painterResource
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
|
||||
@Composable
|
||||
actual fun SettingsSectionApp(
|
||||
actual fun AdvancedSettingsAppSection(
|
||||
showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit),
|
||||
showVersion: () -> Unit,
|
||||
withAuth: (title: String, desc: String, block: () -> Unit) -> Unit
|
||||
withAuth: (title: String, desc: String, block: () -> Unit) -> Unit,
|
||||
) {
|
||||
SectionView(stringResource(MR.strings.settings_section_title_app)) {
|
||||
SectionView {
|
||||
SettingsActionItem(painterResource(MR.images.ic_code), stringResource(MR.strings.settings_developer_tools), showSettingsModal { DeveloperView(withAuth) })
|
||||
val selectedChannel = remember { appPrefs.appUpdateChannel.state }
|
||||
val values = AppUpdatesChannel.entries.map { it to it.text }
|
||||
@@ -29,6 +23,5 @@ actual fun SettingsSectionApp(
|
||||
appPrefs.appUpdateChannel.set(it)
|
||||
setupUpdateChecker()
|
||||
}
|
||||
AppVersionItem(showVersion)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user