diff --git a/apps/ios/Shared/Views/Database/DatabaseView.swift b/apps/ios/Shared/Views/Database/DatabaseView.swift index d5d70abaea..278893a669 100644 --- a/apps/ios/Shared/Views/Database/DatabaseView.swift +++ b/apps/ios/Shared/Views/Database/DatabaseView.swift @@ -110,33 +110,88 @@ struct DatabaseView: View { } Section { - settingsRow( - stopped ? "exclamationmark.octagon.fill" : "play.fill", - color: stopped ? .red : .green - ) { - Toggle( - stopped ? "Chat is stopped" : "Chat is running", - isOn: $runChat - ) - .onChange(of: runChat) { _ in - if runChat { - DatabaseView.startChat($runChat, $progressIndicator) - } else if !stoppingChat { - stoppingChat = false - alert = .stopChat - } - } - } - } header: { - Text("Run chat") - .foregroundColor(theme.colors.secondary) - } footer: { - if case .documents = dbContainer { - Text("Database will be migrated when the app restarts") - .foregroundColor(theme.colors.secondary) - } + NavigationLink("Database passphrase & export", destination: databaseManagementView) } + Section { + Button(m.users.count > 1 ? "Delete files for all chat profiles" : "Delete all files", role: .destructive) { + alert = .deleteFilesAndMedia + } + .disabled(progressIndicator || appFilesCountAndSize?.0 == 0) + } header: { + Text("Files & media") + .foregroundColor(theme.colors.secondary) + } footer: { + if let (fileCount, size) = appFilesCountAndSize { + if fileCount == 0 { + Text("No received or sent files") + .foregroundColor(theme.colors.secondary) + } else { + Text("\(fileCount) file(s) with total size of \(ByteCountFormatter.string(fromByteCount: Int64(size), countStyle: .binary))") + .foregroundColor(theme.colors.secondary) + } + } + } + } + .onAppear { + runChat = m.chatRunning ?? true + appFilesCountAndSize = directoryFileCountAndSize(getAppFilesDirectory()) + currentChatItemTTL = chatItemTTL + } + .onChange(of: chatItemTTL) { ttl in + if ttl < currentChatItemTTL { + alert = .setChatItemTTL(ttl: ttl) + } else if ttl != currentChatItemTTL { + setCiTTL(ttl) + } + } + .alert(item: $alert) { item in databaseAlert(item) } + .fileImporter( + isPresented: $showFileImporter, + allowedContentTypes: [.zip], + allowsMultipleSelection: false + ) { result in + if case let .success(files) = result, let fileURL = files.first { + importedArchivePath = fileURL + alert = .importArchive + } + } + } + + private func runChatToggleView() -> some View { + Section { + let stopped = m.chatRunning == false + settingsRow( + stopped ? "exclamationmark.octagon.fill" : "play.fill", + color: stopped ? .red : .green + ) { + Toggle( + stopped ? "Chat is stopped" : "Chat is running", + isOn: $runChat + ) + .onChange(of: runChat) { _ in + if runChat { + DatabaseView.startChat($runChat, $progressIndicator) + } else if !stoppingChat { + stoppingChat = false + alert = .stopChat + } + } + } + } header: { + Text("Run chat") + .foregroundColor(theme.colors.secondary) + } footer: { + if case .documents = dbContainer { + Text("Database will be migrated when the app restarts") + .foregroundColor(theme.colors.secondary) + } + } + } + + private func databaseManagementView() -> some View { + List { + let stopped = m.chatRunning == false Section { let unencrypted = m.chatDbEncrypted == false let color: Color = unencrypted ? .orange : theme.colors.secondary @@ -194,49 +249,9 @@ struct DatabaseView: View { } } - Section { - Button(m.users.count > 1 ? "Delete files for all chat profiles" : "Delete all files", role: .destructive) { - alert = .deleteFilesAndMedia - } - .disabled(progressIndicator || appFilesCountAndSize?.0 == 0) - } header: { - Text("Files & media") - .foregroundColor(theme.colors.secondary) - } footer: { - if let (fileCount, size) = appFilesCountAndSize { - if fileCount == 0 { - Text("No received or sent files") - .foregroundColor(theme.colors.secondary) - } else { - Text("\(fileCount) file(s) with total size of \(ByteCountFormatter.string(fromByteCount: Int64(size), countStyle: .binary))") - .foregroundColor(theme.colors.secondary) - } - } - } - } - .onAppear { - runChat = m.chatRunning ?? true - appFilesCountAndSize = directoryFileCountAndSize(getAppFilesDirectory()) - currentChatItemTTL = chatItemTTL - } - .onChange(of: chatItemTTL) { ttl in - if ttl < currentChatItemTTL { - alert = .setChatItemTTL(ttl: ttl) - } else if ttl != currentChatItemTTL { - setCiTTL(ttl) - } - } - .alert(item: $alert) { item in databaseAlert(item) } - .fileImporter( - isPresented: $showFileImporter, - allowedContentTypes: [.zip], - allowsMultipleSelection: false - ) { result in - if case let .success(files) = result, let fileURL = files.first { - importedArchivePath = fileURL - alert = .importArchive - } + runChatToggleView() } + .modifier(ThemedBackground(grouped: true)) } private func databaseAlert(_ alertItem: DatabaseAlert) -> Alert { diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/NetworkAndServers.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/NetworkAndServers.swift index f10b945dc0..24cf088918 100644 --- a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/NetworkAndServers.swift +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/NetworkAndServers.swift @@ -121,16 +121,6 @@ struct NetworkAndServers: View { } } - Section(header: Text("Calls").foregroundColor(theme.colors.secondary)) { - NavigationLink { - RTCServers() - .navigationTitle("Your ICE servers") - .modifier(ThemedBackground(grouped: true)) - } label: { - Text("WebRTC ICE servers") - } - } - Section(header: Text("Network connection").foregroundColor(theme.colors.secondary)) { HStack { Text(m.networkInfo.networkType.text) diff --git a/apps/ios/Shared/Views/UserSettings/NotificationsView.swift b/apps/ios/Shared/Views/UserSettings/NotificationsView.swift index c4d0588987..131eeecef7 100644 --- a/apps/ios/Shared/Views/UserSettings/NotificationsView.swift +++ b/apps/ios/Shared/Views/UserSettings/NotificationsView.swift @@ -63,36 +63,6 @@ struct NotificationsView: View { } } - NavigationLink { - List { - Section { - SelectionListView(list: NotificationPreviewMode.values, selection: $m.notificationPreview) { previewMode in - ntfPreviewModeGroupDefault.set(previewMode) - m.notificationPreview = previewMode - } - } footer: { - VStack(alignment: .leading, spacing: 1) { - Text("You can set lock screen notification preview via settings.") - .foregroundColor(theme.colors.secondary) - Button("Open Settings") { - DispatchQueue.main.async { - UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil) - } - } - } - } - } - .navigationTitle("Show preview") - .modifier(ThemedBackground(grouped: true)) - .navigationBarTitleDisplayMode(.inline) - } label: { - HStack { - Text("Show preview") - Spacer() - Text(m.notificationPreview.label) - } - } - if let server = m.notificationServer { smpServers("Push server", [server], theme.colors.secondary) testTokenButton(server) diff --git a/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift b/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift index 3ae9f0eacd..ad6b2d4454 100644 --- a/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift +++ b/apps/ios/Shared/Views/UserSettings/PrivacySettings.swift @@ -81,30 +81,12 @@ struct PrivacySettings: View { settingsRow("link", color: theme.colors.secondary) { Toggle("Remove link tracking", isOn: $privacySanitizeLinks) } - settingsRow("message", color: theme.colors.secondary) { - Toggle("Show last messages", isOn: $showChatPreviews) - } - settingsRow("rectangle.and.pencil.and.ellipsis", color: theme.colors.secondary) { - Toggle("Message draft", isOn: $saveLastDraft) - } - .onChange(of: saveLastDraft) { saveDraft in - if !saveDraft { - m.draft = nil - m.draftChatId = nil - } - } } header: { Text("Chats") .foregroundColor(theme.colors.secondary) } Section { - settingsRow("lock.doc", color: theme.colors.secondary) { - Toggle("Encrypt local files", isOn: $encryptLocalFiles) - .onChange(of: encryptLocalFiles) { - setEncryptLocalFiles($0) - } - } settingsRow("photo", color: theme.colors.secondary) { Toggle("Auto-accept images", isOn: $autoAcceptImages) .onChange(of: autoAcceptImages) { @@ -126,20 +108,9 @@ struct PrivacySettings: View { } } } - settingsRow("network.badge.shield.half.filled", color: theme.colors.secondary) { - Toggle("Protect IP address", isOn: $askToApproveRelays) - } } header: { Text("Files") .foregroundColor(theme.colors.secondary) - } footer: { - if askToApproveRelays { - Text("The app will ask to confirm downloads from unknown file servers (except .onion).") - .foregroundColor(theme.colors.secondary) - } else { - Text("Without Tor or VPN, your IP address will be visible to file servers.") - .foregroundColor(theme.colors.secondary) - } } Section { @@ -155,45 +126,8 @@ struct PrivacySettings: View { } Section { - settingsRow("person", color: theme.colors.secondary) { - Toggle("Contacts", isOn: $contactReceipts) - } - settingsRow("person.2", color: theme.colors.secondary) { - Toggle("Small groups (max 20)", isOn: $groupReceipts) - } - } header: { - Text("Send delivery receipts to") - .foregroundColor(theme.colors.secondary) - } footer: { - VStack(alignment: .leading) { - Text("These settings are for your current profile **\(m.currentUser?.displayName ?? "")**.") - Text("They can be overridden in contact and group settings.") - } - .foregroundColor(theme.colors.secondary) - .frame(maxWidth: .infinity, alignment: .leading) - } - .confirmationDialog(contactReceiptsDialogTitle, isPresented: $contactReceiptsDialogue, titleVisibility: .visible) { - Button(contactReceipts ? "Enable (keep overrides)" : "Disable (keep overrides)") { - setSendReceiptsContacts(contactReceipts, clearOverrides: false) - } - Button(contactReceipts ? "Enable for all" : "Disable for all", role: .destructive) { - setSendReceiptsContacts(contactReceipts, clearOverrides: true) - } - Button("Cancel", role: .cancel) { - contactReceiptsReset = true - contactReceipts.toggle() - } - } - .confirmationDialog(groupReceiptsDialogTitle, isPresented: $groupReceiptsDialogue, titleVisibility: .visible) { - Button(groupReceipts ? "Enable (keep overrides)" : "Disable (keep overrides)") { - setSendReceiptsGroups(groupReceipts, clearOverrides: false) - } - Button(groupReceipts ? "Enable for all" : "Disable for all", role: .destructive) { - setSendReceiptsGroups(groupReceipts, clearOverrides: true) - } - Button("Cancel", role: .cancel) { - groupReceiptsReset = true - groupReceipts.toggle() + NavigationLink(destination: morePrivacyView) { + settingsRow("ellipsis", color: theme.colors.secondary) { Text("More privacy") } } } } @@ -243,6 +177,132 @@ struct PrivacySettings: View { } } + @ViewBuilder + private func morePrivacyView() -> some View { + List { + Section { + settingsRow("message", color: theme.colors.secondary) { + Toggle("Show last messages", isOn: $showChatPreviews) + } + settingsRow("rectangle.and.pencil.and.ellipsis", color: theme.colors.secondary) { + Toggle("Message draft", isOn: $saveLastDraft) + } + .onChange(of: saveLastDraft) { saveDraft in + if !saveDraft { + m.draft = nil + m.draftChatId = nil + } + } + } header: { + Text("Chats") + .foregroundColor(theme.colors.secondary) + } + + Section { + settingsRow("lock.doc", color: theme.colors.secondary) { + Toggle("Encrypt local files", isOn: $encryptLocalFiles) + .onChange(of: encryptLocalFiles) { + setEncryptLocalFiles($0) + } + } + settingsRow("network.badge.shield.half.filled", color: theme.colors.secondary) { + Toggle("Protect IP address", isOn: $askToApproveRelays) + } + } header: { + Text("Files") + .foregroundColor(theme.colors.secondary) + } footer: { + if askToApproveRelays { + Text("The app will ask to confirm downloads from unknown file servers (except .onion).") + .foregroundColor(theme.colors.secondary) + } else { + Text("Without Tor or VPN, your IP address will be visible to file servers.") + .foregroundColor(theme.colors.secondary) + } + } + + Section { + NavigationLink { + List { + Section { + SelectionListView(list: NotificationPreviewMode.values, selection: $m.notificationPreview) { previewMode in + ntfPreviewModeGroupDefault.set(previewMode) + m.notificationPreview = previewMode + } + } footer: { + VStack(alignment: .leading, spacing: 1) { + Text("You can set lock screen notification preview via settings.") + .foregroundColor(theme.colors.secondary) + Button("Open Settings") { + DispatchQueue.main.async { + UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil) + } + } + } + } + } + .navigationTitle("Show preview") + .modifier(ThemedBackground(grouped: true)) + .navigationBarTitleDisplayMode(.inline) + } label: { + HStack { + Text("Show preview") + Spacer() + Text(m.notificationPreview.label) + } + } + } header: { + Text("Notifications") + .foregroundColor(theme.colors.secondary) + } + + Section { + settingsRow("person", color: theme.colors.secondary) { + Toggle("Contacts", isOn: $contactReceipts) + } + settingsRow("person.2", color: theme.colors.secondary) { + Toggle("Small groups (max 20)", isOn: $groupReceipts) + } + } header: { + Text("Send delivery receipts to") + .foregroundColor(theme.colors.secondary) + } footer: { + VStack(alignment: .leading) { + Text("These settings are for your current profile **\(m.currentUser?.displayName ?? "")**.") + Text("They can be overridden in contact and group settings.") + } + .foregroundColor(theme.colors.secondary) + .frame(maxWidth: .infinity, alignment: .leading) + } + .confirmationDialog(contactReceiptsDialogTitle, isPresented: $contactReceiptsDialogue, titleVisibility: .visible) { + Button(contactReceipts ? "Enable (keep overrides)" : "Disable (keep overrides)") { + setSendReceiptsContacts(contactReceipts, clearOverrides: false) + } + Button(contactReceipts ? "Enable for all" : "Disable for all", role: .destructive) { + setSendReceiptsContacts(contactReceipts, clearOverrides: true) + } + Button("Cancel", role: .cancel) { + contactReceiptsReset = true + contactReceipts.toggle() + } + } + .confirmationDialog(groupReceiptsDialogTitle, isPresented: $groupReceiptsDialogue, titleVisibility: .visible) { + Button(groupReceipts ? "Enable (keep overrides)" : "Disable (keep overrides)") { + setSendReceiptsGroups(groupReceipts, clearOverrides: false) + } + Button(groupReceipts ? "Enable for all" : "Disable for all", role: .destructive) { + setSendReceiptsGroups(groupReceipts, clearOverrides: true) + } + Button("Cancel", role: .cancel) { + groupReceiptsReset = true + groupReceipts.toggle() + } + } + } + .navigationTitle("More privacy") + .modifier(ThemedBackground(grouped: true)) + } + private func setEncryptLocalFiles(_ enable: Bool) { do { try apiSetEncryptLocalFiles(enable) diff --git a/apps/ios/Shared/Views/UserSettings/SetDeliveryReceiptsView.swift b/apps/ios/Shared/Views/UserSettings/SetDeliveryReceiptsView.swift index e03dace43d..e46edbc5af 100644 --- a/apps/ios/Shared/Views/UserSettings/SetDeliveryReceiptsView.swift +++ b/apps/ios/Shared/Views/UserSettings/SetDeliveryReceiptsView.swift @@ -69,7 +69,7 @@ struct SetDeliveryReceiptsView: View { Button { AlertManager.shared.showAlert(Alert( title: Text("Delivery receipts are disabled!"), - message: Text("You can enable them later via app Privacy & Security settings."), + message: Text("You can enable them later via app Your privacy settings."), primaryButton: .default(Text("Don't show again")) { m.setDeliveryReceipts = false privacyDeliveryReceiptsSet.set(true) diff --git a/apps/ios/Shared/Views/UserSettings/SettingsView.swift b/apps/ios/Shared/Views/UserSettings/SettingsView.swift index a903329454..93f32a53a6 100644 --- a/apps/ios/Shared/Views/UserSettings/SettingsView.swift +++ b/apps/ios/Shared/Views/UserSettings/SettingsView.swift @@ -290,47 +290,7 @@ struct SettingsView: View { func settingsView() -> some View { List { - let user = chatModel.currentUser - Section(header: Text("Settings").foregroundColor(theme.colors.secondary)) { - NavigationLink { - NotificationsView() - .navigationTitle("Notifications") - .modifier(ThemedBackground(grouped: true)) - } label: { - HStack { - notificationsIcon() - Text("Notifications") - } - } - .disabled(chatModel.chatRunning != true) - - NavigationLink { - NetworkAndServers() - .navigationTitle("Network & servers") - .modifier(ThemedBackground(grouped: true)) - } label: { - settingsRow("externaldrive.connected.to.line.below", color: theme.colors.secondary) { Text("Network & servers") } - } - .disabled(chatModel.chatRunning != true) - - NavigationLink { - CallSettings() - .navigationTitle("Your calls") - .modifier(ThemedBackground(grouped: true)) - } label: { - settingsRow("video", color: theme.colors.secondary) { Text("Audio & video calls") } - } - .disabled(chatModel.chatRunning != true) - - NavigationLink { - PrivacySettings() - .navigationTitle("Your privacy") - .modifier(ThemedBackground(grouped: true)) - } label: { - settingsRow("lock", color: theme.colors.secondary) { Text("Privacy & security") } - } - .disabled(chatModel.chatRunning != true) - + Section(header: Text(verbatim: "").foregroundColor(theme.colors.secondary)) { if UIApplication.shared.supportsAlternateIcons { NavigationLink { AppearanceSettings() @@ -341,10 +301,24 @@ struct SettingsView: View { } .disabled(chatModel.chatRunning != true) } - } - Section(header: Text("Chat database").foregroundColor(theme.colors.secondary)) { + NavigationLink { + PrivacySettings() + .navigationTitle("Your privacy") + .modifier(ThemedBackground(grouped: true)) + } label: { + settingsRow("lock", color: theme.colors.secondary) { Text("Your privacy") } + } + .disabled(chatModel.chatRunning != true) + + NavigationLink { + helpAndSupportView + } label: { + settingsRow("questionmark", color: theme.colors.secondary) { Text("Help & support") } + } + chatDatabaseRow() + NavigationLink { MigrateFromDevice(showProgressOnSettings: $showProgress) .toolbar { @@ -360,6 +334,58 @@ struct SettingsView: View { } } + Section(header: Text("Advanced settings").foregroundColor(theme.colors.secondary)) { + NavigationLink { + NetworkAndServers() + .navigationTitle("Network & servers") + .modifier(ThemedBackground(grouped: true)) + } label: { + settingsRow("externaldrive.connected.to.line.below", color: theme.colors.secondary) { Text("Network & servers") } + } + .disabled(chatModel.chatRunning != true) + + NavigationLink { + NotificationsView() + .navigationTitle("Notifications") + .modifier(ThemedBackground(grouped: true)) + } label: { + HStack { + notificationsIcon() + Text("Notifications") + } + } + .disabled(chatModel.chatRunning != true) + + NavigationLink { + CallSettings() + .navigationTitle("Your calls") + .modifier(ThemedBackground(grouped: true)) + } label: { + settingsRow("video", color: theme.colors.secondary) { Text("Audio & video calls") } + } + .disabled(chatModel.chatRunning != true) + + NavigationLink { + VersionView() + .navigationBarTitle("App version") + .modifier(ThemedBackground()) + } label: { + Text(verbatim: "v\(appVersion ?? "?")") + } + } + } + .navigationTitle("Your settings") + .modifier(ThemedBackground(grouped: true)) + .onDisappear { + chatModel.showingTerminal = false + chatModel.terminalItems = [] + } + } + + @ViewBuilder + private var helpAndSupportView: some View { + List { + let user = chatModel.currentUser Section(header: Text("Help").foregroundColor(theme.colors.secondary)) { if let user = user { NavigationLink { @@ -378,6 +404,7 @@ struct SettingsView: View { } label: { settingsRow("plus", color: theme.colors.secondary) { Text("What's new") } } + NavigationLink { SimpleXInfo(onboarding: false) .navigationBarTitle("", displayMode: .inline) @@ -386,6 +413,9 @@ struct SettingsView: View { } label: { settingsRow("info", color: theme.colors.secondary) { Text("About SimpleX Chat") } } + } + + Section(header: Text("Contact").foregroundColor(theme.colors.secondary)) { settingsRow("number", color: theme.colors.secondary) { Button("Send questions and ideas") { dismiss() @@ -398,7 +428,7 @@ struct SettingsView: View { settingsRow("envelope", color: theme.colors.secondary) { Text("[Send us email](mailto:chat@simplex.chat)") } } - Section(header: Text("Support SimpleX Chat").foregroundColor(theme.colors.secondary)) { + Section(header: Text("Support the project").foregroundColor(theme.colors.secondary)) { settingsRow("keyboard", color: theme.colors.secondary) { ExternalLink("Contribute", destination: URL(string: "https://github.com/simplex-chat/simplex-chat#contribute")!) } @@ -421,42 +451,21 @@ struct SettingsView: View { } } } - - Section(header: Text("Develop").foregroundColor(theme.colors.secondary)) { - NavigationLink { - DeveloperView() - .navigationTitle("Developer tools") - .modifier(ThemedBackground(grouped: true)) - } label: { - settingsRow("chevron.left.forwardslash.chevron.right", color: theme.colors.secondary) { Text("Developer tools") } - } - NavigationLink { - VersionView() - .navigationBarTitle("App version") - .modifier(ThemedBackground()) - } label: { - Text("v\(appVersion ?? "?") (\(appBuild ?? "?"))") - } - } } - .navigationTitle("Your settings") + .navigationTitle("Help & support") .modifier(ThemedBackground(grouped: true)) - .onDisappear { - chatModel.showingTerminal = false - chatModel.terminalItems = [] - } } - + private func chatDatabaseRow() -> some View { NavigationLink { DatabaseView(dismissSettingsSheet: dismiss, chatItemTTL: chatModel.chatItemTTL) - .navigationTitle("Your chat database") + .navigationTitle("Chat data") .modifier(ThemedBackground(grouped: true)) } label: { let color: Color = chatModel.chatDbEncrypted == false ? .orange : theme.colors.secondary settingsRow("internaldrive", color: color) { HStack { - Text("Database passphrase & export") + Text("Chat data") Spacer() if chatModel.chatRunning == false { Image(systemName: "exclamationmark.octagon.fill").foregroundColor(.red) diff --git a/apps/ios/Shared/Views/UserSettings/VersionView.swift b/apps/ios/Shared/Views/UserSettings/VersionView.swift index 0fc2b4cb3e..e30c11699e 100644 --- a/apps/ios/Shared/Views/UserSettings/VersionView.swift +++ b/apps/ios/Shared/Views/UserSettings/VersionView.swift @@ -10,21 +10,33 @@ import SwiftUI import SimpleXChat struct VersionView: View { + @EnvironmentObject var theme: AppTheme @State var versionInfo: CoreVersionInfo? var body: some View { - VStack(alignment: .leading) { - Text("App version: v\(appVersion ?? "?")") - Text("App build: \(appBuild ?? "?")") - if let info = versionInfo { - Text("Core version: v\(info.version)") - if let v = try? AttributedString(markdown: "simplexmq: v\(info.simplexmqVersion) ([\(info.simplexmqCommit.prefix(7))](https://github.com/simplex-chat/simplexmq/commit/\(info.simplexmqCommit)))") { - Text(v) + List { + Section { + Text("App version: v\(appVersion ?? "?")") + Text("App build: \(appBuild ?? "?")") + if let info = versionInfo { + Text("Core version: v\(info.version)") + if let v = try? AttributedString(markdown: "simplexmq: v\(info.simplexmqVersion) ([\(info.simplexmqCommit.prefix(7))](https://github.com/simplex-chat/simplexmq/commit/\(info.simplexmqCommit)))") { + Text(v) + } + } + } + + Section { + NavigationLink { + DeveloperView() + .navigationTitle("Developer") + .modifier(ThemedBackground(grouped: true)) + } label: { + Text("Developer") } } } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) - .padding() .onAppear { do { versionInfo = try apiGetVersion() diff --git a/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff b/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff index 427430b833..bd8d6a17ef 100644 --- a/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff +++ b/apps/ios/SimpleX Localizations/ar.xcloc/Localized Contents/ar.xliff @@ -1157,8 +1157,8 @@ يطور No comment provided by engineer. - - Developer tools + + Developer أدوات المطور No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff index 364cee97e5..89d5014c95 100644 --- a/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff +++ b/apps/ios/SimpleX Localizations/bg.xcloc/Localized Contents/bg.xliff @@ -3014,8 +3014,8 @@ alert button Developer options No comment provided by engineer. - - Developer tools + + Developer Инструменти за разработчици No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/bn.xcloc/Localized Contents/bn.xliff b/apps/ios/SimpleX Localizations/bn.xcloc/Localized Contents/bn.xliff index fbda1abd29..bdb0c0ce24 100644 --- a/apps/ios/SimpleX Localizations/bn.xcloc/Localized Contents/bn.xliff +++ b/apps/ios/SimpleX Localizations/bn.xcloc/Localized Contents/bn.xliff @@ -1223,8 +1223,8 @@ Develop No comment provided by engineer. - - Developer tools + + Developer No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff index 5ba29ec846..f7beecf4ba 100644 --- a/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff +++ b/apps/ios/SimpleX Localizations/cs.xcloc/Localized Contents/cs.xliff @@ -2904,8 +2904,8 @@ alert button Developer options No comment provided by engineer. - - Developer tools + + Developer Nástroje pro vývojáře No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff index 797a489c92..822c13649e 100644 --- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff +++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff @@ -3130,8 +3130,8 @@ alert button Optionen für Entwickler No comment provided by engineer. - - Developer tools + + Developer Entwicklertools No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/el.xcloc/Localized Contents/el.xliff b/apps/ios/SimpleX Localizations/el.xcloc/Localized Contents/el.xliff index 7a560bb41b..181f51eb99 100644 --- a/apps/ios/SimpleX Localizations/el.xcloc/Localized Contents/el.xliff +++ b/apps/ios/SimpleX Localizations/el.xcloc/Localized Contents/el.xliff @@ -1100,8 +1100,8 @@ Available in v5.1 Develop No comment provided by engineer. - - Developer tools + + Developer No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff index c108dcc904..bd498d53e3 100644 --- a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff +++ b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff @@ -3140,9 +3140,9 @@ alert button Developer options No comment provided by engineer. - - Developer tools - Developer tools + + Developer + Developer No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff index d93e692a63..60de758c9c 100644 --- a/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff +++ b/apps/ios/SimpleX Localizations/es.xcloc/Localized Contents/es.xliff @@ -3130,8 +3130,8 @@ alert button Opciones desarrollador No comment provided by engineer. - - Developer tools + + Developer Herramientas desarrollo No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff index 5656516b7d..c818fdc472 100644 --- a/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff +++ b/apps/ios/SimpleX Localizations/fi.xcloc/Localized Contents/fi.xliff @@ -2791,8 +2791,8 @@ alert button Developer options No comment provided by engineer. - - Developer tools + + Developer Kehittäjätyökalut No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff index 3ea0859d76..4d1616df20 100644 --- a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff +++ b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff @@ -3039,8 +3039,8 @@ alert button Options pour les développeurs No comment provided by engineer. - - Developer tools + + Developer Outils du développeur No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/he.xcloc/Localized Contents/he.xliff b/apps/ios/SimpleX Localizations/he.xcloc/Localized Contents/he.xliff index f94d6cefd8..a22d30dd73 100644 --- a/apps/ios/SimpleX Localizations/he.xcloc/Localized Contents/he.xliff +++ b/apps/ios/SimpleX Localizations/he.xcloc/Localized Contents/he.xliff @@ -1356,8 +1356,8 @@ Available in v5.1 לְפַתֵחַ No comment provided by engineer. - - Developer tools + + Developer כלי מפתחים No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff b/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff index 2aa945f603..33fe9a0e9c 100644 --- a/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff +++ b/apps/ios/SimpleX Localizations/hr.xcloc/Localized Contents/hr.xliff @@ -1012,8 +1012,8 @@ Develop No comment provided by engineer. - - Developer tools + + Developer No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff b/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff index 129436ecb0..11b447dc2b 100644 --- a/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff +++ b/apps/ios/SimpleX Localizations/hu.xcloc/Localized Contents/hu.xliff @@ -3130,8 +3130,8 @@ alert button Fejlesztői beállítások No comment provided by engineer. - - Developer tools + + Developer Fejlesztői eszközök No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff index 469da88ce2..876cdb10bb 100644 --- a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff +++ b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff @@ -3130,8 +3130,8 @@ alert button Opzioni sviluppatore No comment provided by engineer. - - Developer tools + + Developer Strumenti di sviluppo No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff index 13396b13a4..ff0d085c08 100644 --- a/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff +++ b/apps/ios/SimpleX Localizations/ja.xcloc/Localized Contents/ja.xliff @@ -2891,8 +2891,8 @@ alert button 開発者向けの設定 No comment provided by engineer. - - Developer tools + + Developer 開発ツール No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff b/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff index ca51a875c7..01b5e2b9a2 100644 --- a/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff +++ b/apps/ios/SimpleX Localizations/ko.xcloc/Localized Contents/ko.xliff @@ -1141,8 +1141,8 @@ Develop No comment provided by engineer. - - Developer tools + + Developer No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff b/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff index 4b51d66a34..5aa2a98854 100644 --- a/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff +++ b/apps/ios/SimpleX Localizations/lt.xcloc/Localized Contents/lt.xliff @@ -1005,8 +1005,8 @@ Develop No comment provided by engineer. - - Developer tools + + Developer No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff index 9f1818fba9..a7670a4475 100644 --- a/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff +++ b/apps/ios/SimpleX Localizations/nl.xcloc/Localized Contents/nl.xliff @@ -3040,8 +3040,8 @@ alert button Ontwikkelaars opties No comment provided by engineer. - - Developer tools + + Developer Ontwikkel gereedschap No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff index 2644708927..a60b5891d4 100644 --- a/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff +++ b/apps/ios/SimpleX Localizations/pl.xcloc/Localized Contents/pl.xliff @@ -3063,8 +3063,8 @@ alert button Opcje deweloperskie No comment provided by engineer. - - Developer tools + + Developer Narzędzia deweloperskie No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/pt-BR.xcloc/Localized Contents/pt-BR.xliff b/apps/ios/SimpleX Localizations/pt-BR.xcloc/Localized Contents/pt-BR.xliff index d9af0624bf..032a33ff62 100644 --- a/apps/ios/SimpleX Localizations/pt-BR.xcloc/Localized Contents/pt-BR.xliff +++ b/apps/ios/SimpleX Localizations/pt-BR.xcloc/Localized Contents/pt-BR.xliff @@ -1179,8 +1179,8 @@ Desenvolver No comment provided by engineer. - - Developer tools + + Developer Ferramentas de desenvolvimento No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/pt.xcloc/Localized Contents/pt.xliff b/apps/ios/SimpleX Localizations/pt.xcloc/Localized Contents/pt.xliff index e4fac55bcb..3905130e84 100644 --- a/apps/ios/SimpleX Localizations/pt.xcloc/Localized Contents/pt.xliff +++ b/apps/ios/SimpleX Localizations/pt.xcloc/Localized Contents/pt.xliff @@ -1203,8 +1203,8 @@ Available in v5.1 Develop No comment provided by engineer. - - Developer tools + + Developer No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff index a3971c0325..22df6680f6 100644 --- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff +++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff @@ -3130,8 +3130,8 @@ alert button Опции разработчика No comment provided by engineer. - - Developer tools + + Developer Инструменты разработчика No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff index cd2e30977d..11d6b28091 100644 --- a/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff +++ b/apps/ios/SimpleX Localizations/th.xcloc/Localized Contents/th.xliff @@ -2779,8 +2779,8 @@ alert button Developer options No comment provided by engineer. - - Developer tools + + Developer เครื่องมือสำหรับนักพัฒนา No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff index 1189b53e3c..b673b609b9 100644 --- a/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff +++ b/apps/ios/SimpleX Localizations/tr.xcloc/Localized Contents/tr.xliff @@ -3066,8 +3066,8 @@ alert button Geliştirici seçenekleri No comment provided by engineer. - - Developer tools + + Developer Geliştirici araçları No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff index 49f9e21eda..3c0c6ef8de 100644 --- a/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff +++ b/apps/ios/SimpleX Localizations/uk.xcloc/Localized Contents/uk.xliff @@ -3050,8 +3050,8 @@ alert button Можливості для розробників No comment provided by engineer. - - Developer tools + + Developer Інструменти для розробників No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff index 8823f17204..9001375615 100644 --- a/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff +++ b/apps/ios/SimpleX Localizations/zh-Hans.xcloc/Localized Contents/zh-Hans.xliff @@ -3060,8 +3060,8 @@ alert button 开发者选项 No comment provided by engineer. - - Developer tools + + Developer 开发者工具 No comment provided by engineer. diff --git a/apps/ios/SimpleX Localizations/zh-Hant.xcloc/Localized Contents/zh-Hant.xliff b/apps/ios/SimpleX Localizations/zh-Hant.xcloc/Localized Contents/zh-Hant.xliff index 0e4e383b52..ebd6f4da71 100644 --- a/apps/ios/SimpleX Localizations/zh-Hant.xcloc/Localized Contents/zh-Hant.xliff +++ b/apps/ios/SimpleX Localizations/zh-Hant.xcloc/Localized Contents/zh-Hant.xliff @@ -1148,8 +1148,8 @@ 開發 No comment provided by engineer. - - Developer tools + + Developer 開發者工具 No comment provided by engineer. diff --git a/apps/ios/SimpleX SE/ShareModel.swift b/apps/ios/SimpleX SE/ShareModel.swift index 18f3e2c344..9790e5944f 100644 --- a/apps/ios/SimpleX SE/ShareModel.swift +++ b/apps/ios/SimpleX SE/ShareModel.swift @@ -75,7 +75,7 @@ class ShareModel: ObservableObject { func setup(context: NSExtensionContext) { if appLocalAuthEnabledGroupDefault.get() && !allowShareExtensionGroupDefault.get() { - errorAlert = ErrorAlert(title: "App is locked!", message: "You can allow sharing in Privacy & Security / SimpleX Lock settings.") + errorAlert = ErrorAlert(title: "App is locked!", message: "You can allow sharing in Your privacy / SimpleX Lock settings.") return } if let item = context.inputItems.first as? NSExtensionItem, diff --git a/apps/ios/SimpleX SE/de.lproj/Localizable.strings b/apps/ios/SimpleX SE/de.lproj/Localizable.strings index df368686e8..1d2e5a4b01 100644 --- a/apps/ios/SimpleX SE/de.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/de.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "Falsches Datenbank-Passwort"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Sie können das Teilen in den Einstellungen zu Datenschutz & Sicherheit / SimpleX-Sperre erlauben."; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "Sie können das Teilen in den Einstellungen zu Datenschutz & Sicherheit / SimpleX-Sperre erlauben."; diff --git a/apps/ios/SimpleX SE/es.lproj/Localizable.strings b/apps/ios/SimpleX SE/es.lproj/Localizable.strings index 4cc5029537..5bb42b4f0a 100644 --- a/apps/ios/SimpleX SE/es.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/es.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "Contraseña incorrecta de la base de datos"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Puedes dar permiso para compartir en Privacidad y Seguridad / Bloque SimpleX."; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "Puedes dar permiso para compartir en Privacidad y Seguridad / Bloque SimpleX."; diff --git a/apps/ios/SimpleX SE/fr.lproj/Localizable.strings b/apps/ios/SimpleX SE/fr.lproj/Localizable.strings index 46a458b471..6b492ee882 100644 --- a/apps/ios/SimpleX SE/fr.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/fr.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "Mauvaise phrase secrète pour la base de données"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Vous pouvez autoriser le partage dans les paramètres Confidentialité et sécurité / SimpleX Lock."; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "Vous pouvez autoriser le partage dans les paramètres Confidentialité et sécurité / SimpleX Lock."; diff --git a/apps/ios/SimpleX SE/hu.lproj/Localizable.strings b/apps/ios/SimpleX SE/hu.lproj/Localizable.strings index 3aad39c5d1..dae06b1d73 100644 --- a/apps/ios/SimpleX SE/hu.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/hu.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "Érvénytelen adatbázis-jelmondat"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "A megosztást az Adatvédelem és biztonság / SimpleX-zár menüben engedélyezheti."; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "A megosztást az Adatvédelem és biztonság / SimpleX-zár menüben engedélyezheti."; diff --git a/apps/ios/SimpleX SE/it.lproj/Localizable.strings b/apps/ios/SimpleX SE/it.lproj/Localizable.strings index e3d34650a3..3b27092f24 100644 --- a/apps/ios/SimpleX SE/it.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/it.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "Password del database sbagliata"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Puoi consentire la condivisione in Privacy e sicurezza / impostazioni di SimpleX Lock."; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "Puoi consentire la condivisione in Privacy e sicurezza / impostazioni di SimpleX Lock."; diff --git a/apps/ios/SimpleX SE/nl.lproj/Localizable.strings b/apps/ios/SimpleX SE/nl.lproj/Localizable.strings index e5d2487b54..050cb1a735 100644 --- a/apps/ios/SimpleX SE/nl.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/nl.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "Verkeerde database wachtwoord"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "U kunt delen toestaan in de instellingen voor Privacy en beveiliging / SimpleX Lock."; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "U kunt delen toestaan in de instellingen voor Privacy en beveiliging / SimpleX Lock."; diff --git a/apps/ios/SimpleX SE/pl.lproj/Localizable.strings b/apps/ios/SimpleX SE/pl.lproj/Localizable.strings index c563431c28..0755e1e374 100644 --- a/apps/ios/SimpleX SE/pl.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/pl.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "Nieprawidłowe hasło bazy danych"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Możesz zezwolić na udostępnianie w ustawieniach Prywatność i bezpieczeństwo / Blokada SimpleX."; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "Możesz zezwolić na udostępnianie w ustawieniach Prywatność i bezpieczeństwo / Blokada SimpleX."; diff --git a/apps/ios/SimpleX SE/ru.lproj/Localizable.strings b/apps/ios/SimpleX SE/ru.lproj/Localizable.strings index e4c8c000d4..90a5841738 100644 --- a/apps/ios/SimpleX SE/ru.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/ru.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "Неправильный пароль базы данных"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Вы можете разрешить функцию Поделиться в настройках Конфиденциальности / Блокировка SimpleX."; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "Вы можете разрешить функцию Поделиться в настройках Конфиденциальности / Блокировка SimpleX."; diff --git a/apps/ios/SimpleX SE/tr.lproj/Localizable.strings b/apps/ios/SimpleX SE/tr.lproj/Localizable.strings index baef71c127..69b122832d 100644 --- a/apps/ios/SimpleX SE/tr.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/tr.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "Yanlış veritabanı parolası"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Gizlilik ve Güvenlik / SimpleX Lock ayarlarından paylaşıma izin verebilirsiniz."; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "Gizlilik ve Güvenlik / SimpleX Lock ayarlarından paylaşıma izin verebilirsiniz."; diff --git a/apps/ios/SimpleX SE/uk.lproj/Localizable.strings b/apps/ios/SimpleX SE/uk.lproj/Localizable.strings index a6da81185e..7574470d01 100644 --- a/apps/ios/SimpleX SE/uk.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/uk.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "Неправильна ключова фраза до бази даних"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "Ви можете дозволити спільний доступ у налаштуваннях Конфіденційність і безпека / SimpleX Lock."; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "Ви можете дозволити спільний доступ у налаштуваннях Конфіденційність і безпека / SimpleX Lock."; diff --git a/apps/ios/SimpleX SE/zh-Hans.lproj/Localizable.strings b/apps/ios/SimpleX SE/zh-Hans.lproj/Localizable.strings index 362e2edb74..fc046ab087 100644 --- a/apps/ios/SimpleX SE/zh-Hans.lproj/Localizable.strings +++ b/apps/ios/SimpleX SE/zh-Hans.lproj/Localizable.strings @@ -107,5 +107,5 @@ "Wrong database passphrase" = "数据库密码错误"; /* No comment provided by engineer. */ -"You can allow sharing in Privacy & Security / SimpleX Lock settings." = "您可以在 \"隐私与安全\"/\"SimpleX Lock \"设置中允许共享。"; +"You can allow sharing in Your privacy / SimpleX Lock settings." = "您可以在 \"隐私与安全\"/\"SimpleX Lock \"设置中允许共享。"; diff --git a/apps/ios/bg.lproj/Localizable.strings b/apps/ios/bg.lproj/Localizable.strings index ec869e05b4..68f2cfe502 100644 --- a/apps/ios/bg.lproj/Localizable.strings +++ b/apps/ios/bg.lproj/Localizable.strings @@ -1659,7 +1659,7 @@ alert button */ "Develop" = "Разработване"; /* No comment provided by engineer. */ -"Developer tools" = "Инструменти за разработчици"; +"Developer" = "Инструменти за разработчици"; /* No comment provided by engineer. */ "Device" = "Устройство"; @@ -3217,7 +3217,7 @@ alert button */ "Preview" = "Визуализация"; /* No comment provided by engineer. */ -"Privacy & security" = "Поверителност и сигурност"; +"Your privacy" = "Поверителност и сигурност"; /* No comment provided by engineer. */ "Private filenames" = "Поверителни имена на файлове"; @@ -4452,7 +4452,7 @@ server test failure */ "You can enable later via Settings" = "Можете да активирате по-късно през Настройки"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Можете да ги активирате по-късно през настройките за \"Поверителност и сигурност\" на приложението."; +"You can enable them later via app Your privacy settings." = "Можете да ги активирате по-късно през настройките за \"Поверителност и сигурност\" на приложението."; /* No comment provided by engineer. */ "You can give another try." = "Можете да опитате още веднъж."; diff --git a/apps/ios/cs.lproj/Localizable.strings b/apps/ios/cs.lproj/Localizable.strings index fc4b3f0fc6..0b74ef9504 100644 --- a/apps/ios/cs.lproj/Localizable.strings +++ b/apps/ios/cs.lproj/Localizable.strings @@ -1306,7 +1306,7 @@ alert button */ "Develop" = "Vyvinout"; /* No comment provided by engineer. */ -"Developer tools" = "Nástroje pro vývojáře"; +"Developer" = "Nástroje pro vývojáře"; /* No comment provided by engineer. */ "Device" = "Zařízení"; @@ -2578,7 +2578,7 @@ alert button */ "Preview" = "Náhled"; /* No comment provided by engineer. */ -"Privacy & security" = "Ochrana osobních údajů a zabezpečení"; +"Your privacy" = "Ochrana osobních údajů a zabezpečení"; /* No comment provided by engineer. */ "Private filenames" = "Soukromé názvy souborů"; @@ -3543,7 +3543,7 @@ server test failure */ "You can enable later via Settings" = "Můžete povolit později v Nastavení"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Můžete je povolit později v nastavení Soukromí & Bezpečnosti aplikace"; +"You can enable them later via app Your privacy settings." = "Můžete je povolit později v nastavení Soukromí & Bezpečnosti aplikace"; /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "Profil uživatele můžete skrýt nebo ztlumit - přejeďte prstem doprava."; diff --git a/apps/ios/de.lproj/Localizable.strings b/apps/ios/de.lproj/Localizable.strings index 2c4e37791b..80246b727b 100644 --- a/apps/ios/de.lproj/Localizable.strings +++ b/apps/ios/de.lproj/Localizable.strings @@ -2064,7 +2064,7 @@ alert button */ "Developer options" = "Optionen für Entwickler"; /* No comment provided by engineer. */ -"Developer tools" = "Entwicklertools"; +"Developer" = "Entwicklertools"; /* No comment provided by engineer. */ "Device" = "Gerät"; @@ -4533,7 +4533,7 @@ alert button */ "Previously connected servers" = "Bisher verbundene Server"; /* No comment provided by engineer. */ -"Privacy & security" = "Datenschutz & Sicherheit"; +"Your privacy" = "Datenschutz & Sicherheit"; /* No comment provided by engineer. */ "Privacy for your customers." = "Schutz der Privatsphäre Ihrer Kunden."; @@ -6759,7 +6759,7 @@ server test failure */ "You can enable later via Settings" = "Sie können diese später in den Einstellungen aktivieren"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Sie können diese später in den Datenschutz & Sicherheits-Einstellungen der App aktivieren."; +"You can enable them later via app Your privacy settings." = "Sie können diese später in den Datenschutz & Sicherheits-Einstellungen der App aktivieren."; /* No comment provided by engineer. */ "You can give another try." = "Sie können es nochmal probieren."; diff --git a/apps/ios/es.lproj/Localizable.strings b/apps/ios/es.lproj/Localizable.strings index cf03ae6dbf..e0611c0afc 100644 --- a/apps/ios/es.lproj/Localizable.strings +++ b/apps/ios/es.lproj/Localizable.strings @@ -2064,7 +2064,7 @@ alert button */ "Developer options" = "Opciones desarrollador"; /* No comment provided by engineer. */ -"Developer tools" = "Herramientas desarrollo"; +"Developer" = "Herramientas desarrollo"; /* No comment provided by engineer. */ "Device" = "Dispositivo"; @@ -4533,7 +4533,7 @@ alert button */ "Previously connected servers" = "Servidores conectados previamente"; /* No comment provided by engineer. */ -"Privacy & security" = "Seguridad y Privacidad"; +"Your privacy" = "Seguridad y Privacidad"; /* No comment provided by engineer. */ "Privacy for your customers." = "Privacidad para tus clientes."; @@ -6759,7 +6759,7 @@ server test failure */ "You can enable later via Settings" = "Puedes activar más tarde en Configuración"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Puedes activarlos más tarde en la configuración de Privacidad y Seguridad."; +"You can enable them later via app Your privacy settings." = "Puedes activarlos más tarde en la configuración de Privacidad y Seguridad."; /* No comment provided by engineer. */ "You can give another try." = "Puedes intentarlo de nuevo."; diff --git a/apps/ios/fi.lproj/Localizable.strings b/apps/ios/fi.lproj/Localizable.strings index 3b1bd6523c..36b516374e 100644 --- a/apps/ios/fi.lproj/Localizable.strings +++ b/apps/ios/fi.lproj/Localizable.strings @@ -982,7 +982,7 @@ alert button */ "Develop" = "Kehitä"; /* No comment provided by engineer. */ -"Developer tools" = "Kehittäjätyökalut"; +"Developer" = "Kehittäjätyökalut"; /* No comment provided by engineer. */ "Device" = "Laite"; @@ -2232,7 +2232,7 @@ new chat action */ "Preview" = "Esikatselu"; /* No comment provided by engineer. */ -"Privacy & security" = "Yksityisyys ja turvallisuus"; +"Your privacy" = "Yksityisyys ja turvallisuus"; /* No comment provided by engineer. */ "Private filenames" = "Yksityiset tiedostonimet"; @@ -3179,7 +3179,7 @@ server test failure */ "You can enable later via Settings" = "Voit ottaa käyttöön myöhemmin asetusten kautta"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Voit ottaa ne käyttöön myöhemmin sovelluksen Yksityisyys & Turvallisuus -asetuksista."; +"You can enable them later via app Your privacy settings." = "Voit ottaa ne käyttöön myöhemmin sovelluksen Yksityisyys & Turvallisuus -asetuksista."; /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "Voit piilottaa tai mykistää käyttäjäprofiilin pyyhkäisemällä sitä oikealle."; diff --git a/apps/ios/fr.lproj/Localizable.strings b/apps/ios/fr.lproj/Localizable.strings index 91cd6f3078..98cdb4aec8 100644 --- a/apps/ios/fr.lproj/Localizable.strings +++ b/apps/ios/fr.lproj/Localizable.strings @@ -1745,7 +1745,7 @@ alert button */ "Developer options" = "Options pour les développeurs"; /* No comment provided by engineer. */ -"Developer tools" = "Outils du développeur"; +"Developer" = "Outils du développeur"; /* No comment provided by engineer. */ "Device" = "Appareil"; @@ -3742,7 +3742,7 @@ alert button */ "Previously connected servers" = "Serveurs précédemment connectés"; /* No comment provided by engineer. */ -"Privacy & security" = "Vie privée et sécurité"; +"Your privacy" = "Vie privée et sécurité"; /* No comment provided by engineer. */ "Privacy for your customers." = "Respect de la vie privée de vos clients."; @@ -5448,7 +5448,7 @@ server test failure */ "You can enable later via Settings" = "Vous pouvez l'activer ultérieurement via Paramètres"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Vous pouvez les activer ultérieurement via les paramètres de Confidentialité et Sécurité de l'application."; +"You can enable them later via app Your privacy settings." = "Vous pouvez les activer ultérieurement via les paramètres de Confidentialité et Sécurité de l'application."; /* No comment provided by engineer. */ "You can give another try." = "Vous pouvez faire un nouvel essai."; diff --git a/apps/ios/hu.lproj/Localizable.strings b/apps/ios/hu.lproj/Localizable.strings index 029fb9edd5..362d9157fd 100644 --- a/apps/ios/hu.lproj/Localizable.strings +++ b/apps/ios/hu.lproj/Localizable.strings @@ -2064,7 +2064,7 @@ alert button */ "Developer options" = "Fejlesztői beállítások"; /* No comment provided by engineer. */ -"Developer tools" = "Fejlesztői eszközök"; +"Developer" = "Fejlesztői eszközök"; /* No comment provided by engineer. */ "Device" = "Eszköz"; @@ -4533,7 +4533,7 @@ alert button */ "Previously connected servers" = "Korábban kapcsolódott kiszolgálók"; /* No comment provided by engineer. */ -"Privacy & security" = "Adatvédelem és biztonság"; +"Your privacy" = "Adatvédelem és biztonság"; /* No comment provided by engineer. */ "Privacy for your customers." = "Saját ügyfeleinek adatvédelme."; @@ -6759,7 +6759,7 @@ server test failure */ "You can enable later via Settings" = "Később engedélyezheti a beállításokban"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Később engedélyezheti őket az „Adatvédelem és biztonság” menüben."; +"You can enable them later via app Your privacy settings." = "Később engedélyezheti őket az „Adatvédelem és biztonság” menüben."; /* No comment provided by engineer. */ "You can give another try." = "Megpróbálhatja még egyszer."; diff --git a/apps/ios/it.lproj/Localizable.strings b/apps/ios/it.lproj/Localizable.strings index c882eb662c..8d4fa3532b 100644 --- a/apps/ios/it.lproj/Localizable.strings +++ b/apps/ios/it.lproj/Localizable.strings @@ -2064,7 +2064,7 @@ alert button */ "Developer options" = "Opzioni sviluppatore"; /* No comment provided by engineer. */ -"Developer tools" = "Strumenti di sviluppo"; +"Developer" = "Strumenti di sviluppo"; /* No comment provided by engineer. */ "Device" = "Dispositivo"; @@ -4533,7 +4533,7 @@ alert button */ "Previously connected servers" = "Server precedentemente connessi"; /* No comment provided by engineer. */ -"Privacy & security" = "Privacy e sicurezza"; +"Your privacy" = "Privacy e sicurezza"; /* No comment provided by engineer. */ "Privacy for your customers." = "Privacy per i tuoi clienti."; @@ -6759,7 +6759,7 @@ server test failure */ "You can enable later via Settings" = "Puoi attivarle più tardi nelle impostazioni"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Puoi attivarle più tardi nelle impostazioni di privacy e sicurezza dell'app."; +"You can enable them later via app Your privacy settings." = "Puoi attivarle più tardi nelle impostazioni di privacy e sicurezza dell'app."; /* No comment provided by engineer. */ "You can give another try." = "Puoi fare un altro tentativo."; diff --git a/apps/ios/ja.lproj/Localizable.strings b/apps/ios/ja.lproj/Localizable.strings index 35d8732e3f..b88eb10414 100644 --- a/apps/ios/ja.lproj/Localizable.strings +++ b/apps/ios/ja.lproj/Localizable.strings @@ -1270,7 +1270,7 @@ alert button */ "Developer options" = "開発者向けの設定"; /* No comment provided by engineer. */ -"Developer tools" = "開発ツール"; +"Developer" = "開発ツール"; /* No comment provided by engineer. */ "Device" = "端末"; @@ -2533,7 +2533,7 @@ alert button */ "Preview" = "プレビュー"; /* No comment provided by engineer. */ -"Privacy & security" = "プライバシーとセキュリティ"; +"Your privacy" = "プライバシーとセキュリティ"; /* No comment provided by engineer. */ "Private filenames" = "プライベートなファイル名"; @@ -3459,7 +3459,7 @@ server test failure */ "You can enable later via Settings" = "あとで設定から有効にできます"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "あとでアプリのプライバシーとセキュリティの設定から有効にすることができます。"; +"You can enable them later via app Your privacy settings." = "あとでアプリのプライバシーとセキュリティの設定から有効にすることができます。"; /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "ユーザープロファイルを右にスワイプすると、非表示またはミュートにすることができます。"; diff --git a/apps/ios/nl.lproj/Localizable.strings b/apps/ios/nl.lproj/Localizable.strings index 407665bbec..1c776a7bbe 100644 --- a/apps/ios/nl.lproj/Localizable.strings +++ b/apps/ios/nl.lproj/Localizable.strings @@ -1773,7 +1773,7 @@ alert button */ "Developer options" = "Ontwikkelaars opties"; /* No comment provided by engineer. */ -"Developer tools" = "Ontwikkel gereedschap"; +"Developer" = "Ontwikkel gereedschap"; /* No comment provided by engineer. */ "Device" = "Apparaat"; @@ -3929,7 +3929,7 @@ alert button */ "Previously connected servers" = "Eerder verbonden servers"; /* No comment provided by engineer. */ -"Privacy & security" = "Privacy en beveiliging"; +"Your privacy" = "Privacy en beveiliging"; /* No comment provided by engineer. */ "Privacy for your customers." = "Privacy voor uw klanten."; @@ -5777,7 +5777,7 @@ server test failure */ "You can enable later via Settings" = "U kunt later inschakelen via Instellingen"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "U kunt ze later inschakelen via de privacy- en beveiligingsinstellingen van de app."; +"You can enable them later via app Your privacy settings." = "U kunt ze later inschakelen via de privacy- en beveiligingsinstellingen van de app."; /* No comment provided by engineer. */ "You can give another try." = "Je kunt het nog een keer proberen."; diff --git a/apps/ios/pl.lproj/Localizable.strings b/apps/ios/pl.lproj/Localizable.strings index 8905300160..9cc6eca252 100644 --- a/apps/ios/pl.lproj/Localizable.strings +++ b/apps/ios/pl.lproj/Localizable.strings @@ -1845,7 +1845,7 @@ alert button */ "Developer options" = "Opcje deweloperskie"; /* No comment provided by engineer. */ -"Developer tools" = "Narzędzia deweloperskie"; +"Developer" = "Narzędzia deweloperskie"; /* No comment provided by engineer. */ "Device" = "Urządzenie"; @@ -4131,7 +4131,7 @@ alert button */ "Previously connected servers" = "Wcześniej połączone serwery"; /* No comment provided by engineer. */ -"Privacy & security" = "Prywatność i bezpieczeństwo"; +"Your privacy" = "Prywatność i bezpieczeństwo"; /* No comment provided by engineer. */ "Privacy for your customers." = "Prywatność dla Twoich klientów."; @@ -6135,7 +6135,7 @@ server test failure */ "You can enable later via Settings" = "Możesz włączyć później w Ustawieniach"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Możesz je włączyć później w ustawieniach Prywatności i Bezpieczeństwa aplikacji."; +"You can enable them later via app Your privacy settings." = "Możesz je włączyć później w ustawieniach Prywatności i Bezpieczeństwa aplikacji."; /* No comment provided by engineer. */ "You can give another try." = "Możesz spróbować ponownie."; diff --git a/apps/ios/product/README.md b/apps/ios/product/README.md index 107c0e6569..fd25b09d01 100644 --- a/apps/ios/product/README.md +++ b/apps/ios/product/README.md @@ -101,7 +101,7 @@ End-to-end encrypted audio and video communication. | Call history | Call events displayed as chat items | `Shared/Views/Chat/ChatItem/CICallItemView.swift` | | Incoming call view | Dedicated UI for incoming call notifications | `Shared/Views/Call/IncomingCallView.swift` | -### 5. Privacy & Security +### 5. Your privacy Encryption, authentication, and privacy controls. diff --git a/apps/ios/product/views/settings.md b/apps/ios/product/views/settings.md index 3cc4da5d2b..7e7f653910 100644 --- a/apps/ios/product/views/settings.md +++ b/apps/ios/product/views/settings.md @@ -4,7 +4,7 @@ ## Purpose -Configure all aspects of app behavior including notifications, network/servers, privacy, appearance, database management, call settings, and developer tools. Accessed from the UserPicker sheet on the chat list. +Configure all aspects of app behavior including notifications, network/servers, privacy, appearance, database management, call settings, and Developer. Accessed from the UserPicker sheet on the chat list. ## Route / Navigation @@ -22,7 +22,7 @@ Configure all aspects of app behavior including notifications, network/servers, | Notifications | `bolt` (color varies by token status) | `NotificationsView` | Push notification mode and preview settings | | Network & servers | `externaldrive.connected.to.line.below` | `NetworkAndServers` | SMP/XFTP servers, proxy, .onion hosts, advanced network | | Audio & video calls | `video` | `CallSettings` | WebRTC relay policy, ICE servers, CallKit options | -| Privacy & security | `lock` | `PrivacySettings` | SimpleX Lock, screen protection, delivery receipts, auto-accept | +| Your privacy | `lock` | `PrivacySettings` | SimpleX Lock, screen protection, delivery receipts, auto-accept | | Appearance | `sun.max` | `AppearanceSettings` | Theme, language, wallpapers, chat bubbles, toolbar opacity | All rows disabled when `chatModel.chatRunning != true`. Appearance row only shown when `UIApplication.shared.supportsAlternateIcons`. @@ -77,7 +77,7 @@ Adding a relay: `NewChatRelayView` form with name, address, test, and enable tog Server validation (`validateServers_`) now returns both errors and warnings. -#### Privacy & Security (`PrivacySettings`) +#### Your privacy (`PrivacySettings`) | Setting | Description | |---|---| @@ -152,7 +152,7 @@ Database row shows exclamation octagon icon in red when `chatRunning == false`. | Row | Icon | Destination | Description | |---|---|---|---| -| Developer tools | `chevron.left.forwardslash.chevron.right` | `DeveloperView` | Chat console/terminal, log level, confirm DB upgrades | +| Developer | `chevron.left.forwardslash.chevron.right` | `DeveloperView` | Chat console/terminal, log level, confirm DB upgrades | | App version | (none) | `VersionView` | Shows "v{version} ({build})" | ## Loading / Error States diff --git a/apps/ios/ru.lproj/Localizable.strings b/apps/ios/ru.lproj/Localizable.strings index 9f79b5dea0..042359dd7e 100644 --- a/apps/ios/ru.lproj/Localizable.strings +++ b/apps/ios/ru.lproj/Localizable.strings @@ -2064,7 +2064,7 @@ alert button */ "Developer options" = "Опции разработчика"; /* No comment provided by engineer. */ -"Developer tools" = "Инструменты разработчика"; +"Developer" = "Разработчик"; /* No comment provided by engineer. */ "Device" = "Устройство"; @@ -4533,7 +4533,7 @@ alert button */ "Previously connected servers" = "Ранее подключенные серверы"; /* No comment provided by engineer. */ -"Privacy & security" = "Конфиденциальность"; +"Your privacy" = "Конфиденциальность"; /* No comment provided by engineer. */ "Privacy for your customers." = "Конфиденциальность для ваших покупателей."; @@ -6759,7 +6759,7 @@ server test failure */ "You can enable later via Settings" = "Вы можете включить их позже в Настройках"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Вы можете включить их позже в настройках Конфиденциальности."; +"You can enable them later via app Your privacy settings." = "Вы можете включить их позже в настройках Конфиденциальности."; /* No comment provided by engineer. */ "You can give another try." = "Вы можете попробовать ещё раз."; diff --git a/apps/ios/th.lproj/Localizable.strings b/apps/ios/th.lproj/Localizable.strings index cc3abea189..62bf4d3d59 100644 --- a/apps/ios/th.lproj/Localizable.strings +++ b/apps/ios/th.lproj/Localizable.strings @@ -946,7 +946,7 @@ alert button */ "Develop" = "พัฒนา"; /* No comment provided by engineer. */ -"Developer tools" = "เครื่องมือสำหรับนักพัฒนา"; +"Developer" = "เครื่องมือสำหรับนักพัฒนา"; /* No comment provided by engineer. */ "Device" = "อุปกรณ์"; @@ -2172,7 +2172,7 @@ new chat action */ "Preview" = "ดูตัวอย่าง"; /* No comment provided by engineer. */ -"Privacy & security" = "ความเป็นส่วนตัวและความปลอดภัย"; +"Your privacy" = "ความเป็นส่วนตัวและความปลอดภัย"; /* No comment provided by engineer. */ "Private filenames" = "ชื่อไฟล์ส่วนตัว"; @@ -3089,7 +3089,7 @@ server test failure */ "You can enable later via Settings" = "คุณสามารถเปิดใช้งานในภายหลังผ่านการตั้งค่า"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "คุณสามารถเปิดใช้งานได้ในภายหลังผ่านการตั้งค่าความเป็นส่วนตัวและความปลอดภัยของแอป"; +"You can enable them later via app Your privacy settings." = "คุณสามารถเปิดใช้งานได้ในภายหลังผ่านการตั้งค่าความเป็นส่วนตัวและความปลอดภัยของแอป"; /* No comment provided by engineer. */ "You can hide or mute a user profile - swipe it to the right." = "คุณสามารถซ่อนหรือปิดเสียงโปรไฟล์ผู้ใช้ - ปัดไปทางขวา"; diff --git a/apps/ios/tr.lproj/Localizable.strings b/apps/ios/tr.lproj/Localizable.strings index e06989afee..8dfc23078c 100644 --- a/apps/ios/tr.lproj/Localizable.strings +++ b/apps/ios/tr.lproj/Localizable.strings @@ -1859,7 +1859,7 @@ alert button */ "Developer options" = "Geliştirici seçenekleri"; /* No comment provided by engineer. */ -"Developer tools" = "Geliştirici araçları"; +"Developer" = "Geliştirici araçları"; /* No comment provided by engineer. */ "Device" = "Cihaz"; @@ -4099,7 +4099,7 @@ alert button */ "Previously connected servers" = "Önceden bağlanılmış sunucular"; /* No comment provided by engineer. */ -"Privacy & security" = "Gizlilik & güvenlik"; +"Your privacy" = "Gizlilik & güvenlik"; /* No comment provided by engineer. */ "Privacy for your customers." = "Müşterileriniz için gizlilik."; @@ -6064,7 +6064,7 @@ server test failure */ "You can enable later via Settings" = "Daha sonra Ayarlardan etkinleştirebilirsin"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Daha sonra uygulamanın Gizlilik ve Güvenlik ayarlarından etkinleştirebilirsiniz."; +"You can enable them later via app Your privacy settings." = "Daha sonra uygulamanın Gizlilik ve Güvenlik ayarlarından etkinleştirebilirsiniz."; /* No comment provided by engineer. */ "You can give another try." = "Bir kez daha deneyebilirsiniz."; diff --git a/apps/ios/uk.lproj/Localizable.strings b/apps/ios/uk.lproj/Localizable.strings index 4a21eb4ae8..ff2f64e2ed 100644 --- a/apps/ios/uk.lproj/Localizable.strings +++ b/apps/ios/uk.lproj/Localizable.strings @@ -1806,7 +1806,7 @@ alert button */ "Developer options" = "Можливості для розробників"; /* No comment provided by engineer. */ -"Developer tools" = "Інструменти для розробників"; +"Developer" = "Інструменти для розробників"; /* No comment provided by engineer. */ "Device" = "Пристрій"; @@ -4019,7 +4019,7 @@ alert button */ "Previously connected servers" = "Раніше підключені сервери"; /* No comment provided by engineer. */ -"Privacy & security" = "Конфіденційність і безпека"; +"Your privacy" = "Конфіденційність і безпека"; /* No comment provided by engineer. */ "Privacy for your customers." = "Конфіденційність для ваших клієнтів."; @@ -5966,7 +5966,7 @@ server test failure */ "You can enable later via Settings" = "Ви можете увімкнути пізніше в Налаштуваннях"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "Ви можете увімкнути їх пізніше в налаштуваннях конфіденційності та безпеки програми."; +"You can enable them later via app Your privacy settings." = "Ви можете увімкнути їх пізніше в налаштуваннях конфіденційності та безпеки програми."; /* No comment provided by engineer. */ "You can give another try." = "Ви можете спробувати ще раз."; diff --git a/apps/ios/zh-Hans.lproj/Localizable.strings b/apps/ios/zh-Hans.lproj/Localizable.strings index 13be5125ea..f3138230f9 100644 --- a/apps/ios/zh-Hans.lproj/Localizable.strings +++ b/apps/ios/zh-Hans.lproj/Localizable.strings @@ -1836,7 +1836,7 @@ alert button */ "Developer options" = "开发者选项"; /* No comment provided by engineer. */ -"Developer tools" = "开发者工具"; +"Developer" = "开发者工具"; /* No comment provided by engineer. */ "Device" = "设备"; @@ -4107,7 +4107,7 @@ alert button */ "Previously connected servers" = "以前连接的服务器"; /* No comment provided by engineer. */ -"Privacy & security" = "隐私和安全"; +"Your privacy" = "隐私和安全"; /* No comment provided by engineer. */ "Privacy for your customers." = "客户隐私。"; @@ -6093,7 +6093,7 @@ server test failure */ "You can enable later via Settings" = "您可以稍后在设置中启用它"; /* No comment provided by engineer. */ -"You can enable them later via app Privacy & Security settings." = "您可以稍后通过应用程序的 \"隐私与安全 \"设置启用它们。"; +"You can enable them later via app Your privacy settings." = "您可以稍后通过应用程序的 \"隐私与安全 \"设置启用它们。"; /* No comment provided by engineer. */ "You can give another try." = "你可以再试一次。"; 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/SettingsView.android.kt index 04b59732dd..5e9706d713 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/SettingsView.android.kt @@ -1,7 +1,15 @@ package chat.simplex.common.views.usersettings +import SectionItemView import SectionView +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign import chat.simplex.common.model.ChatModel import chat.simplex.common.platform.* import chat.simplex.common.views.helpers.* @@ -11,19 +19,19 @@ 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)) { - 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) }) + SectionView { SettingsActionItem(painterResource(MR.images.ic_code), stringResource(MR.strings.settings_developer_tools), showSettingsModal { DeveloperView(withAuth) }) - AppVersionItem(showVersion) } } +@Composable +actual fun AppShutdownItem() { + SettingsActionItem(painterResource(MR.images.ic_power_settings_new), stringResource(MR.strings.settings_shutdown), ::shutdownAppAlert) +} fun restartApp() { ProcessPhoenix.triggerRebirth(androidAppContext) @@ -36,11 +44,28 @@ private fun shutdownApp() { Runtime.getRuntime().exit(0) } -private fun shutdownAppAlert(onConfirm: () -> Unit) { - AlertManager.shared.showAlertDialog( +private fun shutdownAppAlert() { + AlertManager.shared.showAlertDialogButtonsColumn( title = generalGetString(MR.strings.shutdown_alert_question), text = generalGetString(MR.strings.shutdown_alert_desc), - destructive = true, - onConfirm = onConfirm + buttons = { + Column { + SectionItemView({ AlertManager.shared.hideAlert() }) { + Text(stringResource(MR.strings.cancel_verb), Modifier.fillMaxWidth(), textAlign = TextAlign.Center) + } + SectionItemView({ + AlertManager.shared.hideAlert() + restartApp() + }) { + Text(stringResource(MR.strings.settings_restart_app), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary) + } + SectionItemView({ + AlertManager.shared.hideAlert() + shutdownApp() + }) { + Text(stringResource(MR.strings.settings_shutdown), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red) + } + } + } ) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt index 648a0eb8e7..80f97d1caf 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt @@ -44,29 +44,8 @@ fun DatabaseView() { val prefs = m.controller.appPrefs val useKeychain = remember { mutableStateOf(prefs.storeDBPassphrase.get()) } val chatLastStart = remember { mutableStateOf(prefs.chatLastStart.get()) } - val chatArchiveFile = remember { mutableStateOf(null) } val stopped = remember { m.chatRunning }.value == false - val saveArchiveLauncher = rememberFileChooserLauncher(false) { to: URI? -> - val archive = chatArchiveFile.value - if (archive != null && to != null) { - copyFileToFile(File(archive), to) {} - } - // delete no matter the database was exported or canceled the export process - if (archive != null) { - File(archive).delete() - chatArchiveFile.value = null - } - } val appFilesCountAndSize = remember { mutableStateOf(directoryFileCountAndSize(appFilesDir.absolutePath)) } - val importArchiveLauncher = rememberFileChooserLauncher(true) { to: URI? -> - if (to != null) { - importArchiveAlert { - stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) { - importArchive(to, appFilesCountAndSize, progressIndicator, false) - } - } - } - } val chatItemTTL = remember { mutableStateOf(m.chatItemTTL.value) } Box( Modifier.fillMaxSize(), @@ -79,27 +58,10 @@ fun DatabaseView() { useKeychain.value, m.chatDbEncrypted.value, m.controller.appPrefs.storeDBPassphrase.state.value, - m.controller.appPrefs.initialRandomDBPassphrase, - importArchiveLauncher, appFilesCountAndSize, chatItemTTL, user, m.users, - startChat = { startChat(m, chatLastStart, m.chatDbChanged, progressIndicator) }, - stopChatAlert = { stopChatAlert(m, progressIndicator) }, - exportArchive = { - stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) { - exportArchive(m, progressIndicator, chatArchiveFile, saveArchiveLauncher) - } - }, - deleteChatAlert = { - deleteChatAlert { - stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) { - deleteChat(m, progressIndicator) - true - } - } - }, deleteAppFilesAndMedia = { deleteFilesAndMediaAlert { stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) { @@ -120,12 +82,9 @@ fun DatabaseView() { setCiTTL(m, rhId, chatItemTTL, progressIndicator, appFilesCountAndSize) } }, - disconnectAllHosts = { - val connected = chatModel.remoteHosts.filter { it.sessionState is RemoteHostSessionState.Connected } - connected.forEachIndexed { index, h -> - controller.stopRemoteHostAndReloadHosts(h, index == connected.lastIndex && chatModel.connectedToRemote()) - } - } + showDatabaseManagement = { + ModalManager.start.showModal(cardScreen = true) { DatabaseManagementView() } + }, ) if (progressIndicator.value) { Box( @@ -151,24 +110,18 @@ fun DatabaseLayout( useKeyChain: Boolean, chatDbEncrypted: Boolean?, passphraseSaved: Boolean, - initialRandomDBPassphrase: SharedPreference, - importArchiveLauncher: FileChooserLauncher, appFilesCountAndSize: MutableState>, chatItemTTL: MutableState, currentUser: User?, users: List, - startChat: () -> Unit, - stopChatAlert: () -> Unit, - exportArchive: () -> Unit, - deleteChatAlert: () -> Unit, deleteAppFilesAndMedia: () -> Unit, onChatItemTTLSelected: (ChatItemTTL?) -> Unit, - disconnectAllHosts: () -> Unit, + showDatabaseManagement: () -> Unit, ) { val operationsDisabled = progressIndicator && !chatModel.desktopNoUserNoRemote ColumnWithScrollBar { - AppBarTitle(stringResource(MR.strings.your_chat_database)) + AppBarTitle(stringResource(MR.strings.chat_data)) if (!chatModel.desktopNoUserNoRemote) { SectionView(stringResource(MR.strings.messages_section_title)) { @@ -187,79 +140,17 @@ fun DatabaseLayout( ) SectionDividerSpaced() } - val toggleEnabled = remember { chatModel.remoteHosts }.none { it.sessionState is RemoteHostSessionState.Connected } - if (chatModel.localUserCreated.value == true) { - // still show the toggle in case database was stopped when the user opened this screen because it can be in the following situations: - // - database was stopped after migration and the app relaunched - // - something wrong happened with database operations and the database couldn't be launched when it should - SectionView(stringResource(MR.strings.run_chat_section)) { - if (!toggleEnabled) { - SectionItemView(disconnectAllHosts) { - Text(generalGetString(MR.strings.disconnect_remote_hosts), Modifier.fillMaxWidth(), color = WarningOrange) - } - } - RunChatSetting(stopped, toggleEnabled && !progressIndicator, startChat, stopChatAlert) - } - if (stopped) SectionTextFooter(stringResource(MR.strings.you_must_use_the_most_recent_version_of_database)) - SectionDividerSpaced() - } - SectionView(stringResource(MR.strings.chat_database_section)) { - if (chatModel.localUserCreated.value != true && !toggleEnabled) { - SectionItemView(disconnectAllHosts) { - Text(generalGetString(MR.strings.disconnect_remote_hosts), Modifier.fillMaxWidth(), color = WarningOrange) - } - } + SectionView { val unencrypted = chatDbEncrypted == false SettingsActionItem( if (unencrypted) painterResource(MR.images.ic_lock_open_right) else if (useKeyChain) painterResource(MR.images.ic_vpn_key_filled) else painterResource(MR.images.ic_lock), - stringResource(MR.strings.database_passphrase), - click = { ModalManager.start.showModal(cardScreen = true) { DatabaseEncryptionView(chatModel, false) } }, + stringResource(MR.strings.database_passphrase_and_export), + click = showDatabaseManagement, iconColor = if (unencrypted || (appPlatform.isDesktop && passphraseSaved)) WarningOrange else MaterialTheme.colors.secondary, disabled = operationsDisabled ) - if (appPlatform.isDesktop) { - SettingsActionItem( - painterResource(MR.images.ic_folder_open), - stringResource(MR.strings.open_database_folder), - ::desktopOpenDatabaseDir, - disabled = operationsDisabled - ) - } - SettingsActionItem( - painterResource(MR.images.ic_ios_share), - stringResource(MR.strings.export_database), - click = { - if (initialRandomDBPassphrase.get()) { - exportProhibitedAlert() - ModalManager.start.showModal { - DatabaseEncryptionView(chatModel, false) - } - } else { - exportArchive() - } - }, - textColor = MaterialTheme.colors.primary, - iconColor = MaterialTheme.colors.primary, - disabled = operationsDisabled - ) - SettingsActionItem( - painterResource(MR.images.ic_download), - stringResource(MR.strings.import_database), - { withLongRunningApi { importArchiveLauncher.launch("application/zip") } }, - textColor = Color.Red, - iconColor = Color.Red, - disabled = operationsDisabled - ) - SettingsActionItem( - painterResource(MR.images.ic_delete_forever), - stringResource(MR.strings.delete_database), - deleteChatAlert, - textColor = Color.Red, - iconColor = Color.Red, - disabled = operationsDisabled - ) } SectionDividerSpaced() @@ -287,6 +178,155 @@ fun DatabaseLayout( } } +@Composable +fun DatabaseManagementView() { + val m = chatModel + val progressIndicator = remember { mutableStateOf(false) } + val prefs = m.controller.appPrefs + val useKeychain = remember { mutableStateOf(prefs.storeDBPassphrase.get()) } + val chatLastStart = remember { mutableStateOf(prefs.chatLastStart.get()) } + val chatArchiveFile = remember { mutableStateOf(null) } + val stopped = remember { m.chatRunning }.value == false + val saveArchiveLauncher = rememberFileChooserLauncher(false) { to: URI? -> + val archive = chatArchiveFile.value + if (archive != null && to != null) { + copyFileToFile(File(archive), to) {} + } + // delete no matter the database was exported or canceled the export process + if (archive != null) { + File(archive).delete() + chatArchiveFile.value = null + } + } + val appFilesCountAndSize = remember { mutableStateOf(directoryFileCountAndSize(appFilesDir.absolutePath)) } + val importArchiveLauncher = rememberFileChooserLauncher(true) { to: URI? -> + if (to != null) { + importArchiveAlert { + stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) { + importArchive(to, appFilesCountAndSize, progressIndicator, false) + } + } + } + } + val operationsDisabled = progressIndicator.value && !m.desktopNoUserNoRemote + + Box(Modifier.fillMaxSize()) { + ColumnWithScrollBar { + AppBarTitle(stringResource(MR.strings.database_passphrase_and_export)) + + val toggleEnabled = remember { chatModel.remoteHosts }.none { it.sessionState is RemoteHostSessionState.Connected } + val disconnectAllHosts = { + val connected = chatModel.remoteHosts.filter { it.sessionState is RemoteHostSessionState.Connected } + connected.forEachIndexed { index, h -> + controller.stopRemoteHostAndReloadHosts(h, index == connected.lastIndex && chatModel.connectedToRemote()) + } + } + SectionView(stringResource(MR.strings.chat_database_section)) { + if (chatModel.localUserCreated.value != true && !toggleEnabled) { + SectionItemView(disconnectAllHosts) { + Text(generalGetString(MR.strings.disconnect_remote_hosts), Modifier.fillMaxWidth(), color = WarningOrange) + } + } + val unencrypted = m.chatDbEncrypted.value == false + SettingsActionItem( + if (unencrypted) painterResource(MR.images.ic_lock_open_right) else if (useKeychain.value) painterResource(MR.images.ic_vpn_key_filled) + else painterResource(MR.images.ic_lock), + stringResource(MR.strings.database_passphrase), + click = { ModalManager.start.showModal(cardScreen = true) { DatabaseEncryptionView(chatModel, false) } }, + iconColor = if (unencrypted || (appPlatform.isDesktop && prefs.storeDBPassphrase.state.value)) WarningOrange else MaterialTheme.colors.secondary, + disabled = operationsDisabled + ) + if (appPlatform.isDesktop) { + SettingsActionItem( + painterResource(MR.images.ic_folder_open), + stringResource(MR.strings.open_database_folder), + ::desktopOpenDatabaseDir, + disabled = operationsDisabled + ) + } + SettingsActionItem( + painterResource(MR.images.ic_ios_share), + stringResource(MR.strings.export_database), + click = { + if (prefs.initialRandomDBPassphrase.get()) { + exportProhibitedAlert() + ModalManager.start.showModal { + DatabaseEncryptionView(chatModel, false) + } + } else { + stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) { + exportArchive(m, progressIndicator, chatArchiveFile, saveArchiveLauncher) + } + } + }, + textColor = MaterialTheme.colors.primary, + iconColor = MaterialTheme.colors.primary, + disabled = operationsDisabled + ) + SettingsActionItem( + painterResource(MR.images.ic_download), + stringResource(MR.strings.import_database), + { withLongRunningApi { importArchiveLauncher.launch("application/zip") } }, + textColor = Color.Red, + iconColor = Color.Red, + disabled = operationsDisabled + ) + SettingsActionItem( + painterResource(MR.images.ic_delete_forever), + stringResource(MR.strings.delete_database), + { + deleteChatAlert { + stopChatRunBlockStartChat(stopped, chatLastStart, progressIndicator) { + deleteChat(m, progressIndicator) + true + } + } + }, + textColor = Color.Red, + iconColor = Color.Red, + disabled = operationsDisabled + ) + } + + if (chatModel.localUserCreated.value == true) { + SectionDividerSpaced() + // still show the toggle in case database was stopped when the user opened this screen because it can be in the following situations: + // - database was stopped after migration and the app relaunched + // - something wrong happened with database operations and the database couldn't be launched when it should + SectionView(stringResource(MR.strings.run_chat_section)) { + if (!toggleEnabled) { + SectionItemView(disconnectAllHosts) { + Text(generalGetString(MR.strings.disconnect_remote_hosts), Modifier.fillMaxWidth(), color = WarningOrange) + } + } + RunChatSetting( + stopped, + toggleEnabled && !progressIndicator.value, + startChat = { startChat(m, chatLastStart, m.chatDbChanged, progressIndicator) }, + stopChatAlert = { stopChatAlert(m, progressIndicator) } + ) + } + if (stopped) SectionTextFooter(stringResource(MR.strings.you_must_use_the_most_recent_version_of_database)) + } + SectionBottomSpacer() + } + if (progressIndicator.value) { + Box( + Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + Modifier + .padding(horizontal = 2.dp) + .size(30.dp), + color = MaterialTheme.colors.secondary, + strokeWidth = 2.5.dp + ) + } + } + } +} + private fun setChatItemTTLAlert( m: ChatModel, rhId: Long?, selectedChatItemTTL: MutableState, progressIndicator: MutableState, @@ -832,19 +872,13 @@ fun PreviewDatabaseLayout() { useKeyChain = false, chatDbEncrypted = false, passphraseSaved = false, - initialRandomDBPassphrase = SharedPreference({ true }, {}), - importArchiveLauncher = rememberFileChooserLauncher(true) {}, appFilesCountAndSize = remember { mutableStateOf(0 to 0L) }, chatItemTTL = remember { mutableStateOf(ChatItemTTL.None) }, currentUser = User.sampleData, users = listOf(UserInfo.sampleData), - startChat = {}, - stopChatAlert = {}, - exportArchive = {}, - deleteChatAlert = {}, deleteAppFilesAndMedia = {}, onChatItemTTLSelected = {}, - disconnectAllHosts = {}, + showDatabaseManagement = {}, ) } } 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..91324bb39a 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,43 +24,28 @@ 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 -> + showNotificationsMode = { 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) - } + NotificationsModeView(chatModel.controller.appPrefs.notificationsMode.state) { changeNotificationsMode(it, chatModel) } } }, ) } -enum class CurrentPage { - NOTIFICATIONS_MODE, NOTIFICATION_PREVIEW_MODE -} - @Composable fun NotificationsSettingsLayout( notificationsMode: State, - notificationPreviewMode: State, - showPage: (CurrentPage) -> Unit, + showNotificationsMode: () -> Unit, ) { val modes = remember { notificationModes() } - val previewModes = remember { notificationPreviewModes() } ColumnWithScrollBar { AppBarTitle(stringResource(MR.strings.notifications)) SectionView(null) { if (appPlatform == AppPlatform.ANDROID) { - SettingsActionItemWithContent(null, stringResource(MR.strings.settings_notifications_mode_title), { showPage(CurrentPage.NOTIFICATIONS_MODE) }) { + SettingsActionItemWithContent(null, stringResource(MR.strings.settings_notifications_mode_title), showNotificationsMode) { Text( modes.firstOrNull { it.value == notificationsMode.value }?.title ?: "", maxLines = 1, @@ -69,14 +54,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..c0b822dbb4 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 @@ -37,17 +37,15 @@ import chat.simplex.res.MR @Composable fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit, close: () -> Unit) { - val user = chatModel.currentUser.value val stopped = chatModel.chatRunning.value == false + val showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit) = { modalView -> { ModalManager.start.showModal(settings = true, cardScreen = true) { modalView(chatModel) } } } SettingsLayout( 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) } } }, - showSettingsModal = { modalView -> { ModalManager.start.showModal(settings = true, cardScreen = true) { modalView(chatModel) } } }, + showSettingsModal = showSettingsModal, showSettingsModalWithSearch = { modalView -> ModalManager.start.showCustomModal { close -> val search = rememberSaveable { mutableStateOf("") } @@ -62,12 +60,7 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit, close: ( }, showCustomModal = { modalView -> { ModalManager.start.showCustomModal { close -> modalView(chatModel, close) } } }, showVersion = { - withBGApi { - val info = chatModel.controller.apiGetVersion() - if (info != null) { - ModalManager.start.showModal { VersionInfoView(info) } - } - } + ModalManager.start.showModal(cardScreen = true) { VersionInfoView(showSettingsModal, ::doWithAuth) } }, withAuth = ::doWithAuth, ) @@ -84,8 +77,6 @@ fun SettingsLayout( stopped: Boolean, encrypted: Boolean, passphraseSaved: Boolean, - notificationsMode: State, - userDisplayName: String?, setPerformLA: (Boolean) -> Unit, showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), @@ -98,30 +89,52 @@ fun SettingsLayout( LaunchedEffect(Unit) { hideKeyboard(view) } - val uriHandler = LocalUriHandler.current + val notificationsMode = remember { chatModel.controller.appPrefs.notificationsMode.state } 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) + SettingsActionItem(painterResource(MR.images.ic_help), stringResource(MR.strings.help_and_support), showSettingsModal { HelpAndSupportView(it, showModal, showCustomModal) }) DatabaseItem(encrypted, passphraseSaved, showSettingsModal { DatabaseView() }, stopped) 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) } - SectionDividerSpaced() + SectionView(stringResource(MR.strings.advanced_settings)) { + 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) + AppShutdownItem() + AppVersionItem(showVersion) + } + SectionBottomSpacer() + } +} + +@Composable +fun HelpAndSupportView( + chatModel: ChatModel, + showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), + showCustomModal: (@Composable ModalData.(ChatModel, () -> Unit) -> Unit) -> (() -> Unit), +) { + val uriHandler = LocalUriHandler.current + val stopped = chatModel.chatRunning.value == false + val userDisplayName = chatModel.currentUser.value?.displayName ?: "" + 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_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) }) + } + 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) } @@ -129,27 +142,29 @@ fun SettingsLayout( } SectionDividerSpaced() - SectionView(stringResource(MR.strings.settings_section_title_support)) { + SectionView(stringResource(MR.strings.settings_section_title_support_project)) { if (!BuildConfigCommon.ANDROID_BUNDLE) { ContributeItem(uriHandler) } - RateAppItem(uriHandler) + if (appPlatform.isAndroid) { + RateAppItem(uriHandler) + } StarOnGithubItem(uriHandler) } - SectionDividerSpaced() - - SettingsSectionApp(showSettingsModal, showVersion, withAuth) SectionBottomSpacer() } } @Composable -expect fun SettingsSectionApp( +expect 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, ) +// Shutdown is only available on Android; on desktop the app is closed via the window. +@Composable +expect fun AppShutdownItem() + @Composable private fun DatabaseItem(encrypted: Boolean, saved: Boolean, openDatabaseView: () -> Unit, stopped: Boolean) { SectionItemView(openDatabaseView) { Row( @@ -160,11 +175,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,7 +223,7 @@ fun ChatLockItem( } } -@Composable private fun ContributeItem(uriHandler: UriHandler) { +@Composable fun ContributeItem(uriHandler: UriHandler) { SectionItemView({ uriHandler.openExternalLink("https://github.com/simplex-chat/simplex-chat#contribute") }) { Icon( painterResource(MR.images.ic_keyboard), @@ -220,7 +235,7 @@ fun ChatLockItem( } } -@Composable private fun RateAppItem(uriHandler: UriHandler) { +@Composable 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") } @@ -236,7 +251,7 @@ fun ChatLockItem( } } -@Composable private fun StarOnGithubItem(uriHandler: UriHandler) { +@Composable fun StarOnGithubItem(uriHandler: UriHandler) { SectionItemView({ uriHandler.openExternalLink("https://github.com/simplex-chat/simplex-chat") }) { Icon( painter = painterResource(MR.images.ic_github), @@ -486,8 +501,6 @@ fun PreviewSettingsLayout() { stopped = false, encrypted = false, passphraseSaved = false, - notificationsMode = remember { mutableStateOf(NotificationsMode.OFF) }, - userDisplayName = "Alice", setPerformLA = { _ -> }, showModal = { {} }, showSettingsModal = { {} }, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt index 52addd146b..5070c3c0aa 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt @@ -1,33 +1,55 @@ package chat.simplex.common.views.usersettings +import SectionBottomSpacer +import SectionDividerSpaced +import SectionView +import itemHPadding +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.material.Text -import androidx.compose.runtime.Composable +import androidx.compose.runtime.* import androidx.compose.ui.Modifier import dev.icerock.moko.resources.compose.stringResource import chat.simplex.common.BuildConfigCommon +import chat.simplex.common.model.ChatModel import chat.simplex.common.model.CoreVersionInfo import chat.simplex.common.platform.ColumnWithScrollBar import chat.simplex.common.platform.appPlatform -import chat.simplex.common.ui.theme.DEFAULT_PADDING +import chat.simplex.common.platform.chatModel +import chat.simplex.common.ui.theme.DEFAULT_PADDING_HALF import chat.simplex.common.views.helpers.AppBarTitle import chat.simplex.res.MR @Composable -fun VersionInfoView(info: CoreVersionInfo) { - ColumnWithScrollBar( - Modifier.padding(horizontal = DEFAULT_PADDING), - ) { - AppBarTitle(stringResource(MR.strings.app_version_title), withPadding = false) - if (appPlatform.isAndroid) { - Text(String.format(stringResource(MR.strings.app_version_name), BuildConfigCommon.ANDROID_VERSION_NAME)) - Text(String.format(stringResource(MR.strings.app_version_code), BuildConfigCommon.ANDROID_VERSION_CODE)) - } else { - Text(String.format(stringResource(MR.strings.app_version_name), BuildConfigCommon.DESKTOP_VERSION_NAME)) - Text(String.format(stringResource(MR.strings.app_version_code), BuildConfigCommon.DESKTOP_VERSION_CODE)) +fun VersionInfoView( + showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), + withAuth: (title: String, desc: String, block: () -> Unit) -> Unit, +) { + val versionInfo = remember { mutableStateOf(null) } + LaunchedEffect(Unit) { + versionInfo.value = chatModel.controller.apiGetVersion() + } + ColumnWithScrollBar { + AppBarTitle(stringResource(MR.strings.app_version_title)) + SectionView { + Column(Modifier.padding(horizontal = itemHPadding, vertical = DEFAULT_PADDING_HALF)) { + if (appPlatform.isAndroid) { + Text(String.format(stringResource(MR.strings.app_version_name), BuildConfigCommon.ANDROID_VERSION_NAME)) + Text(String.format(stringResource(MR.strings.app_version_code), BuildConfigCommon.ANDROID_VERSION_CODE)) + } else { + Text(String.format(stringResource(MR.strings.app_version_name), BuildConfigCommon.DESKTOP_VERSION_NAME)) + Text(String.format(stringResource(MR.strings.app_version_code), BuildConfigCommon.DESKTOP_VERSION_CODE)) + } + versionInfo.value?.let { info -> + Text(String.format(stringResource(MR.strings.core_version), info.version)) + val simplexmqCommit = if (info.simplexmqCommit.length >= 7) info.simplexmqCommit.substring(startIndex = 0, endIndex = 7) else info.simplexmqCommit + Text(String.format(stringResource(MR.strings.core_simplexmq_version), info.simplexmqVersion, simplexmqCommit)) + } + } } - Text(String.format(stringResource(MR.strings.core_version), info.version)) - val simplexmqCommit = if (info.simplexmqCommit.length >= 7) info.simplexmqCommit.substring(startIndex = 0, endIndex = 7) else info.simplexmqCommit - Text(String.format(stringResource(MR.strings.core_simplexmq_version), info.simplexmqVersion, simplexmqCommit)) + SectionDividerSpaced() + + AdvancedSettingsAppSection(showSettingsModal, withAuth) + SectionBottomSpacer() } } 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 ee79fc0af0..5bca9402a8 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -1555,6 +1555,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 @@ -2681,7 +2688,7 @@ Don\'t enable You can enable later via Settings Delivery receipts are disabled! - You can enable them later via app Privacy & Security settings. + You can enable them later via app Your privacy settings. Error enabling delivery receipts! 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/SettingsView.desktop.kt index 5b4a044df3..174ad63c7a 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/SettingsView.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,8 @@ actual fun SettingsSectionApp( appPrefs.appUpdateChannel.set(it) setupUpdateChecker() } - AppVersionItem(showVersion) } } + +@Composable +actual fun AppShutdownItem() {}