diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/AdvancedSettingsView.android.kt similarity index 90% rename from apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.android.kt rename to apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/AdvancedSettingsView.android.kt index 04b59732dd..174c8d600f 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/views/usersettings/AdvancedSettingsView.android.kt @@ -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() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedSettingsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedSettingsView.kt new file mode 100644 index 0000000000..9b0cc67aba --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/AdvancedSettingsView.kt @@ -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, +) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HelpAndSupportView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HelpAndSupportView.kt new file mode 100644 index 0000000000..c1352bf3f9 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HelpAndSupportView.kt @@ -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) + } +} diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NotificationsSettingsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NotificationsSettingsView.kt index 150b2a38e0..bb5db7f27f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NotificationsSettingsView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NotificationsSettingsView.kt @@ -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, - notificationPreviewMode: State, 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)) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt index 7316c9bd82..cf34fd5a44 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/PrivacySettings.kt @@ -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() } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt index f17d3a6e4b..0afce5b296 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt @@ -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, 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 = { {} }, diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml index e5d313e9ed..a3e86004bf 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -1548,6 +1548,13 @@ Files Send delivery receipts to Contact requests from groups + About + Contact + Support the project + Chat data + Help & support + More privacy + Advanced settings Restart Shutdown Developer tools diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/AdvancedSettingsView.desktop.kt similarity index 66% rename from apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.desktop.kt rename to apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/AdvancedSettingsView.desktop.kt index 5b4a044df3..4cda214bb2 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/views/usersettings/AdvancedSettingsView.desktop.kt @@ -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) } }