From 4b0046a60b7caca2625b5252287cd9f53041ef29 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sun, 22 Jan 2023 18:34:01 +0000 Subject: [PATCH] mobile: show version information (#1820) * mobile: show version information * export localizations --- .../java/chat/simplex/app/model/SimpleXAPI.kt | 23 ++++++++++ .../app/views/usersettings/SettingsView.kt | 20 ++++++--- .../app/views/usersettings/VersionInfoView.kt | 29 ++++++++++++ .../app/src/main/res/values/strings.xml | 6 +++ apps/ios/Shared/Model/SimpleXAPI.swift | 6 +++ .../Views/UserSettings/SettingsView.swift | 7 ++- .../Views/UserSettings/VersionView.swift | 43 ++++++++++++++++++ .../de.xcloc/Localized Contents/de.xliff | 20 +++++++++ .../en.xcloc/Localized Contents/en.xliff | 25 +++++++++++ .../fr.xcloc/Localized Contents/fr.xliff | 20 +++++++++ .../it.xcloc/Localized Contents/it.xliff | 20 +++++++++ .../ru.xcloc/Localized Contents/ru.xliff | 21 ++++++++- apps/ios/SimpleX.xcodeproj/project.pbxproj | 44 ++++++++++--------- .../xcschemes/SimpleX (iOS).xcscheme | 1 - apps/ios/SimpleXChat/APITypes.swift | 13 ++++++ 15 files changed, 269 insertions(+), 29 deletions(-) create mode 100644 apps/android/app/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt create mode 100644 apps/ios/Shared/Views/UserSettings/VersionView.swift diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index d65489149f..bd49ec5bdf 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -995,6 +995,16 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a } } + suspend fun apiGetVersion(): CoreVersionInfo? { + val r = sendCmd(CC.ShowVersion()) + return if (r is CR.VersionInfo) { + r.versionInfo + } else { + Log.e(TAG, "apiGetVersion bad response: ${r.responseType} ${r.details}") + null + } + } + private fun networkErrorAlert(r: CR): Boolean { return when { r is CR.ChatCmdError && r.chatError is ChatError.ChatErrorAgent @@ -1612,6 +1622,7 @@ sealed class CC { class ApiChatRead(val type: ChatType, val id: Long, val range: ItemRange): CC() class ApiChatUnread(val type: ChatType, val id: Long, val unreadChat: Boolean): CC() class ReceiveFile(val fileId: Long, val inline: Boolean): CC() + class ShowVersion(): CC() val cmdString: String get() = when (this) { is Console -> cmd @@ -1683,6 +1694,7 @@ sealed class CC { is ApiChatRead -> "/_read chat ${chatRef(type, id)} from=${range.from} to=${range.to}" is ApiChatUnread -> "/_unread chat ${chatRef(type, id)} ${onOff(unreadChat)}" is ReceiveFile -> "/freceive $fileId inline=${onOff(inline)}" + is ShowVersion -> "/version" } val cmdType: String get() = when (this) { @@ -1755,6 +1767,7 @@ sealed class CC { is ApiChatRead -> "apiChatRead" is ApiChatUnread -> "apiChatUnread" is ReceiveFile -> "receiveFile" + is ShowVersion -> "showVersion" } class ItemRange(val from: Long, val to: Long) @@ -2733,6 +2746,7 @@ sealed class CR { @Serializable @SerialName("callEnded") class CallEnded(val contact: Contact): CR() @Serializable @SerialName("newContactConnection") class NewContactConnection(val connection: PendingContactConnection): CR() @Serializable @SerialName("contactConnectionDeleted") class ContactConnectionDeleted(val connection: PendingContactConnection): CR() + @Serializable @SerialName("versionInfo") class VersionInfo(val versionInfo: CoreVersionInfo): CR() @Serializable @SerialName("cmdOk") class CmdOk: CR() @Serializable @SerialName("chatCmdError") class ChatCmdError(val chatError: ChatError): CR() @Serializable @SerialName("chatError") class ChatRespError(val chatError: ChatError): CR() @@ -2831,6 +2845,7 @@ sealed class CR { is CallEnded -> "callEnded" is NewContactConnection -> "newContactConnection" is ContactConnectionDeleted -> "contactConnectionDeleted" + is VersionInfo -> "versionInfo" is CmdOk -> "cmdOk" is ChatCmdError -> "chatCmdError" is ChatRespError -> "chatError" @@ -2930,6 +2945,7 @@ sealed class CR { is CallEnded -> "contact: ${contact.id}" is NewContactConnection -> json.encodeToString(connection) is ContactConnectionDeleted -> json.encodeToString(connection) + is VersionInfo -> json.encodeToString(versionInfo) is CmdOk -> noDetails() is ChatCmdError -> chatError.string is ChatRespError -> chatError.string @@ -2987,6 +3003,13 @@ class AutoAccept(val acceptIncognito: Boolean, val autoReply: MsgContent?) { } } +@Serializable +data class CoreVersionInfo( + val version: String, + val buildTimestamp: String, + val simplexmqVersion: String, + val simplexmqCommit: String +) @Serializable sealed class ChatError { diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt index c64bb12b11..f2c9446187 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/SettingsView.kt @@ -5,6 +5,7 @@ import SectionItemView import SectionSpacer import SectionView import android.content.res.Configuration +import android.icu.util.VersionInfo import androidx.compose.foundation.* import androidx.compose.foundation.layout.* import androidx.compose.material.* @@ -57,7 +58,14 @@ fun SettingsView(chatModel: ChatModel, setPerformLA: (Boolean) -> Unit) { showSettingsModal = { modalView -> { ModalManager.shared.showModal(true) { modalView(chatModel) } } }, showCustomModal = { modalView -> { ModalManager.shared.showCustomModal { close -> modalView(chatModel, close) } } }, showTerminal = { ModalManager.shared.showCustomModal { close -> TerminalView(chatModel, close) } }, -// showVideoChatPrototype = { ModalManager.shared.showCustomModal { close -> CallViewDebug(close) } }, + showVersion = { + withApi { + val info = chatModel.controller.apiGetVersion() + if (info != null) { + ModalManager.shared.showModal { VersionInfoView(info) } + } + } + } ) } } @@ -89,7 +97,7 @@ fun SettingsLayout( showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), showCustomModal: (@Composable (ChatModel, () -> Unit) -> Unit) -> (() -> Unit), showTerminal: () -> Unit, -// showVideoChatPrototype: () -> Unit + showVersion: () -> Unit ) { val uriHandler = LocalUriHandler.current Surface(Modifier.fillMaxSize().verticalScroll(rememberScrollState())) { @@ -170,7 +178,7 @@ fun SettingsLayout( } // SettingsActionItem(Icons.Outlined.Science, stringResource(R.string.settings_experimental_features), showSettingsModal { ExperimentalFeaturesView(it, enableCalls) }) // SectionDivider() - AppVersionItem() + AppVersionItem(showVersion) } } } @@ -345,8 +353,8 @@ fun MaintainIncognitoState(chatModel: ChatModel) { } } -@Composable private fun AppVersionItem() { - SectionItemView() { +@Composable private fun AppVersionItem(showVersion: () -> Unit) { + SectionItemView(showVersion) { Text("v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})") } } @@ -491,7 +499,7 @@ fun PreviewSettingsLayout() { showSettingsModal = { {} }, showCustomModal = { {} }, showTerminal = {}, -// showVideoChatPrototype = {} + showVersion = {} ) } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt new file mode 100644 index 0000000000..80a32c0858 --- /dev/null +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/VersionInfoView.kt @@ -0,0 +1,29 @@ +package chat.simplex.app.views.usersettings + +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.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import chat.simplex.app.BuildConfig +import chat.simplex.app.R +import chat.simplex.app.model.CoreVersionInfo +import chat.simplex.app.ui.theme.DEFAULT_PADDING +import chat.simplex.app.views.helpers.AppBarTitle + +@Composable +fun VersionInfoView(info: CoreVersionInfo) { + Column( + Modifier.padding(horizontal = DEFAULT_PADDING), + horizontalAlignment = Alignment.Start + ) { + AppBarTitle(stringResource(R.string.app_version_title), false) + Text(String.format(stringResource(R.string.app_version_name), BuildConfig.VERSION_NAME)) + Text(String.format(stringResource(R.string.app_version_code), BuildConfig.VERSION_CODE)) + Text(String.format(stringResource(R.string.core_version), info.version)) + Text(String.format(stringResource(R.string.core_build_timestamp), info.buildTimestamp)) + Text(String.format(stringResource(R.string.core_simplexmq_version), info.simplexmqVersion, info.simplexmqCommit.substring(startIndex = 0, endIndex = 7))) + } +} diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml index f6f3a605f8..6e73a07e20 100644 --- a/apps/android/app/src/main/res/values/strings.xml +++ b/apps/android/app/src/main/res/values/strings.xml @@ -479,6 +479,12 @@ Onion hosts will not be used. Onion hosts will be required for connection. Appearance + App version + App version: v%s + App build: %s + Core version: v%s + Core built at: %s + simplexmq: v%s (%2s) Create address diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 8cf06ba065..0af9c0d6c7 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -851,6 +851,12 @@ func apiGetGroupLink(_ groupId: Int64) throws -> String? { } } +func apiGetVersion() throws -> CoreVersionInfo { + let r = chatSendCmdSync(.showVersion) + if case let .versionInfo(info) = r { return info } + throw r +} + func initializeChat(start: Bool, dbKey: String? = nil) throws { logger.debug("initializeChat") let m = ChatModel.shared diff --git a/apps/ios/Shared/Views/UserSettings/SettingsView.swift b/apps/ios/Shared/Views/UserSettings/SettingsView.swift index f41c022dc3..2180a36c7d 100644 --- a/apps/ios/Shared/Views/UserSettings/SettingsView.swift +++ b/apps/ios/Shared/Views/UserSettings/SettingsView.swift @@ -271,7 +271,12 @@ struct SettingsView: View { // } label: { // settingsRow("gauge") { Text("Experimental features") } // } - Text("v\(appVersion ?? "?") (\(appBuild ?? "?"))") + NavigationLink { + VersionView() + .navigationBarTitle("App version") + } label: { + Text("v\(appVersion ?? "?") (\(appBuild ?? "?"))") + } } } .navigationTitle("Your settings") diff --git a/apps/ios/Shared/Views/UserSettings/VersionView.swift b/apps/ios/Shared/Views/UserSettings/VersionView.swift new file mode 100644 index 0000000000..9f13e4a95b --- /dev/null +++ b/apps/ios/Shared/Views/UserSettings/VersionView.swift @@ -0,0 +1,43 @@ +// +// VersionView.swift +// SimpleXChat +// +// Created by Evgeny on 22/01/2023. +// Copyright © 2023 SimpleX Chat. All rights reserved. +// + +import SwiftUI +import SimpleXChat + +struct VersionView: View { + @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)") + Text("Core built at: \(info.buildTimestamp)") + 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) + } + } + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) + .padding() + .onAppear { + do { + versionInfo = try apiGetVersion() + } catch let error { + logger.error("apiGetVersion error: \(responseError(error))") + } + } + } +} + +struct VersionView_Previews: PreviewProvider { + static var previews: some View { + VersionView() + } +} 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 f359101580..fb5e7947dc 100644 --- a/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff +++ b/apps/ios/SimpleX Localizations/de.xcloc/Localized Contents/de.xliff @@ -463,11 +463,23 @@ Anruf annehmen No comment provided by engineer. + + App build: %@ + No comment provided by engineer. + App icon App Icon No comment provided by engineer. + + App version + No comment provided by engineer. + + + App version: v%@ + No comment provided by engineer. + Appearance Design @@ -828,6 +840,14 @@ Kopieren chat item action + + Core built at: %@ + No comment provided by engineer. + + + Core version: v%@ + No comment provided by engineer. + Create Erstellen 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 847b3e2878..1e707f082e 100644 --- a/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff +++ b/apps/ios/SimpleX Localizations/en.xcloc/Localized Contents/en.xliff @@ -463,11 +463,26 @@ Answer call No comment provided by engineer. + + App build: %@ + App build: %@ + No comment provided by engineer. + App icon App icon No comment provided by engineer. + + App version + App version + No comment provided by engineer. + + + App version: v%@ + App version: v%@ + No comment provided by engineer. + Appearance Appearance @@ -828,6 +843,16 @@ Copy chat item action + + Core built at: %@ + Core built at: %@ + No comment provided by engineer. + + + Core version: v%@ + Core version: v%@ + No comment provided by engineer. + Create Create 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 f35a16ed3a..573377773c 100644 --- a/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff +++ b/apps/ios/SimpleX Localizations/fr.xcloc/Localized Contents/fr.xliff @@ -463,11 +463,23 @@ Répondre à l'appel No comment provided by engineer. + + App build: %@ + No comment provided by engineer. + App icon Icône de l'app No comment provided by engineer. + + App version + No comment provided by engineer. + + + App version: v%@ + No comment provided by engineer. + Appearance Apparence @@ -828,6 +840,14 @@ Copier chat item action + + Core built at: %@ + No comment provided by engineer. + + + Core version: v%@ + No comment provided by engineer. + Create Créer 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 5841619864..290beb8a9a 100644 --- a/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff +++ b/apps/ios/SimpleX Localizations/it.xcloc/Localized Contents/it.xliff @@ -463,11 +463,23 @@ Rispondi alla chiamata No comment provided by engineer. + + App build: %@ + No comment provided by engineer. + App icon Icona app No comment provided by engineer. + + App version + No comment provided by engineer. + + + App version: v%@ + No comment provided by engineer. + Appearance Aspetto @@ -828,6 +840,14 @@ Copia chat item action + + Core built at: %@ + No comment provided by engineer. + + + Core version: v%@ + No comment provided by engineer. + Create Crea 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 af7aa75f75..133021d01c 100644 --- a/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff +++ b/apps/ios/SimpleX Localizations/ru.xcloc/Localized Contents/ru.xliff @@ -463,11 +463,23 @@ Принять звонок No comment provided by engineer. + + App build: %@ + No comment provided by engineer. + App icon Иконка No comment provided by engineer. + + App version + No comment provided by engineer. + + + App version: v%@ + No comment provided by engineer. + Appearance Интерфейс @@ -828,6 +840,14 @@ Скопировать chat item action + + Core built at: %@ + No comment provided by engineer. + + + Core version: v%@ + No comment provided by engineer. + Create Создать @@ -2275,7 +2295,6 @@ We will be adding server redundancy to prevent lost messages. PING count - Количество PING No comment provided by engineer. diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index 4f000ced74..3268cc17c7 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -48,6 +48,12 @@ 5C5E5D3B2824468B00B0488A /* ActiveCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5E5D3A2824468B00B0488A /* ActiveCallView.swift */; }; 5C5F2B6D27EBC3FE006A9D5F /* ImagePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5F2B6C27EBC3FE006A9D5F /* ImagePicker.swift */; }; 5C5F2B7027EBC704006A9D5F /* ProfileImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5F2B6F27EBC704006A9D5F /* ProfileImage.swift */; }; + 5C65F33C297D3D9700B67AF3 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C65F337297D3D9700B67AF3 /* libgmpxx.a */; }; + 5C65F33D297D3D9700B67AF3 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C65F338297D3D9700B67AF3 /* libgmp.a */; }; + 5C65F33E297D3D9700B67AF3 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C65F339297D3D9700B67AF3 /* libffi.a */; }; + 5C65F33F297D3D9700B67AF3 /* libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C65F33A297D3D9700B67AF3 /* libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r-ghc8.10.7.a */; }; + 5C65F340297D3D9700B67AF3 /* libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C65F33B297D3D9700B67AF3 /* libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r.a */; }; + 5C65F343297D45E100B67AF3 /* VersionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C65F341297D3F3600B67AF3 /* VersionView.swift */; }; 5C6AD81327A834E300348BD7 /* NewChatButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C6AD81227A834E300348BD7 /* NewChatButton.swift */; }; 5C6BA667289BD954009B8ECC /* DismissSheets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C6BA666289BD954009B8ECC /* DismissSheets.swift */; }; 5C7031162953C97F00150A12 /* CIFeaturePreferenceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7031152953C97F00150A12 /* CIFeaturePreferenceView.swift */; }; @@ -97,11 +103,6 @@ 5CB9250D27A9432000ACCCDD /* ChatListNavLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CB9250C27A9432000ACCCDD /* ChatListNavLink.swift */; }; 5CBD285A295711D700EC2CF4 /* ImageUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CBD2859295711D700EC2CF4 /* ImageUtils.swift */; }; 5CBD285C29575B8E00EC2CF4 /* WhatsNewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CBD285B29575B8E00EC2CF4 /* WhatsNewView.swift */; }; - 5CBDFB57297A883C00E723C8 /* libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CBDFB52297A883C00E723C8 /* libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca.a */; }; - 5CBDFB58297A883C00E723C8 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CBDFB53297A883C00E723C8 /* libgmpxx.a */; }; - 5CBDFB59297A883C00E723C8 /* libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CBDFB54297A883C00E723C8 /* libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca-ghc8.10.7.a */; }; - 5CBDFB5A297A883C00E723C8 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CBDFB55297A883C00E723C8 /* libffi.a */; }; - 5CBDFB5B297A883C00E723C8 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CBDFB56297A883C00E723C8 /* libgmp.a */; }; 5CBE6C12294487F7002D9531 /* VerifyCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CBE6C11294487F7002D9531 /* VerifyCodeView.swift */; }; 5CBE6C142944CC12002D9531 /* ScanCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CBE6C132944CC12002D9531 /* ScanCodeView.swift */; }; 5CC1C99227A6C7F5000D9FF6 /* QRCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CC1C99127A6C7F5000D9FF6 /* QRCode.swift */; }; @@ -265,6 +266,12 @@ 5C5E5D3C282447AB00B0488A /* CallTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallTypes.swift; sourceTree = ""; }; 5C5F2B6C27EBC3FE006A9D5F /* ImagePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImagePicker.swift; sourceTree = ""; }; 5C5F2B6F27EBC704006A9D5F /* ProfileImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileImage.swift; sourceTree = ""; }; + 5C65F337297D3D9700B67AF3 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; + 5C65F338297D3D9700B67AF3 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; + 5C65F339297D3D9700B67AF3 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; + 5C65F33A297D3D9700B67AF3 /* libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r-ghc8.10.7.a"; sourceTree = ""; }; + 5C65F33B297D3D9700B67AF3 /* libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r.a"; sourceTree = ""; }; + 5C65F341297D3F3600B67AF3 /* VersionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionView.swift; sourceTree = ""; }; 5C6AD81227A834E300348BD7 /* NewChatButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewChatButton.swift; sourceTree = ""; }; 5C6BA666289BD954009B8ECC /* DismissSheets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DismissSheets.swift; sourceTree = ""; }; 5C7031152953C97F00150A12 /* CIFeaturePreferenceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIFeaturePreferenceView.swift; sourceTree = ""; }; @@ -327,11 +334,6 @@ 5CBD285829565D2600EC2CF4 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = ""; }; 5CBD2859295711D700EC2CF4 /* ImageUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageUtils.swift; sourceTree = ""; }; 5CBD285B29575B8E00EC2CF4 /* WhatsNewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WhatsNewView.swift; sourceTree = ""; }; - 5CBDFB52297A883C00E723C8 /* libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca.a"; sourceTree = ""; }; - 5CBDFB53297A883C00E723C8 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; - 5CBDFB54297A883C00E723C8 /* libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca-ghc8.10.7.a"; sourceTree = ""; }; - 5CBDFB55297A883C00E723C8 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - 5CBDFB56297A883C00E723C8 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; 5CBE6C11294487F7002D9531 /* VerifyCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerifyCodeView.swift; sourceTree = ""; }; 5CBE6C132944CC12002D9531 /* ScanCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanCodeView.swift; sourceTree = ""; }; 5CC1C99127A6C7F5000D9FF6 /* QRCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCode.swift; sourceTree = ""; }; @@ -424,12 +426,12 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5CBDFB58297A883C00E723C8 /* libgmpxx.a in Frameworks */, - 5CBDFB5B297A883C00E723C8 /* libgmp.a in Frameworks */, - 5CBDFB5A297A883C00E723C8 /* libffi.a in Frameworks */, + 5C65F33C297D3D9700B67AF3 /* libgmpxx.a in Frameworks */, + 5C65F340297D3D9700B67AF3 /* libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r.a in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, - 5CBDFB59297A883C00E723C8 /* libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca-ghc8.10.7.a in Frameworks */, - 5CBDFB57297A883C00E723C8 /* libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca.a in Frameworks */, + 5C65F33D297D3D9700B67AF3 /* libgmp.a in Frameworks */, + 5C65F33F297D3D9700B67AF3 /* libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r-ghc8.10.7.a in Frameworks */, + 5C65F33E297D3D9700B67AF3 /* libffi.a in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -488,11 +490,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - 5CBDFB55297A883C00E723C8 /* libffi.a */, - 5CBDFB56297A883C00E723C8 /* libgmp.a */, - 5CBDFB53297A883C00E723C8 /* libgmpxx.a */, - 5CBDFB54297A883C00E723C8 /* libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca-ghc8.10.7.a */, - 5CBDFB52297A883C00E723C8 /* libHSsimplex-chat-4.4.4-GH5mduSQmlJ14EbWq6Ljca.a */, + 5C65F339297D3D9700B67AF3 /* libffi.a */, + 5C65F338297D3D9700B67AF3 /* libgmp.a */, + 5C65F337297D3D9700B67AF3 /* libgmpxx.a */, + 5C65F33A297D3D9700B67AF3 /* libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r-ghc8.10.7.a */, + 5C65F33B297D3D9700B67AF3 /* libHSsimplex-chat-4.4.4-696z0wvJHN7Hvtog9MKb6r.a */, ); path = Libraries; sourceTree = ""; @@ -642,6 +644,7 @@ 5CB2084E28DA4B4800D024EC /* RTCServers.swift */, 5C3F1D592844B4DE00EC8A82 /* ExperimentalFeaturesView.swift */, 64F1CC3A28B39D8600CD1FB1 /* IncognitoHelp.swift */, + 5C65F341297D3F3600B67AF3 /* VersionView.swift */, ); path = UserSettings; sourceTree = ""; @@ -993,6 +996,7 @@ 5C00164428A26FBC0094D739 /* ContextMenu.swift in Sources */, 5C3A88D127DF57800060F1C2 /* FramedItemView.swift in Sources */, 5CB924E427A8683A00ACCCDD /* UserAddress.swift in Sources */, + 5C65F343297D45E100B67AF3 /* VersionView.swift in Sources */, 64F1CC3B28B39D8600CD1FB1 /* IncognitoHelp.swift in Sources */, 5CB0BA90282713D900B3292C /* SimpleXInfo.swift in Sources */, 5C063D2727A4564100AEC577 /* ChatPreviewView.swift in Sources */, diff --git a/apps/ios/SimpleX.xcodeproj/xcshareddata/xcschemes/SimpleX (iOS).xcscheme b/apps/ios/SimpleX.xcodeproj/xcshareddata/xcschemes/SimpleX (iOS).xcscheme index 8b60dc4fae..6a1d4192e6 100644 --- a/apps/ios/SimpleX.xcodeproj/xcshareddata/xcschemes/SimpleX (iOS).xcscheme +++ b/apps/ios/SimpleX.xcodeproj/xcshareddata/xcschemes/SimpleX (iOS).xcscheme @@ -44,7 +44,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - enableAddressSanitizer = "YES" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index fc1576dec5..66d3cd138b 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -89,6 +89,7 @@ public enum ChatCommand { case apiChatRead(type: ChatType, id: Int64, itemRange: (Int64, Int64)) case apiChatUnread(type: ChatType, id: Int64, unreadChat: Bool) case receiveFile(fileId: Int64, inline: Bool) + case showVersion case string(String) public var cmdString: String { @@ -174,6 +175,7 @@ public enum ChatCommand { case let .apiChatRead(type, id, itemRange: (from, to)): return "/_read chat \(ref(type, id)) from=\(from) to=\(to)" case let .apiChatUnread(type, id, unreadChat): return "/_unread chat \(ref(type, id)) \(onOff(unreadChat))" case let .receiveFile(fileId, inline): return "/freceive \(fileId) inline=\(onOff(inline))" + case .showVersion: return "/version" case let .string(str): return str } } @@ -257,6 +259,7 @@ public enum ChatCommand { case .apiChatRead: return "apiChatRead" case .apiChatUnread: return "apiChatUnread" case .receiveFile: return "receiveFile" + case .showVersion: return "showVersion" case .string: return "console command" } } @@ -399,6 +402,7 @@ public enum ChatResponse: Decodable, Error { case ntfMessages(connEntity: ConnectionEntity?, msgTs: Date?, ntfMessages: [NtfMsgInfo]) case newContactConnection(connection: PendingContactConnection) case contactConnectionDeleted(connection: PendingContactConnection) + case versionInfo(versionInfo: CoreVersionInfo) case cmdOk case chatCmdError(chatError: ChatError) case chatError(chatError: ChatError) @@ -502,6 +506,7 @@ public enum ChatResponse: Decodable, Error { case .ntfMessages: return "ntfMessages" case .newContactConnection: return "newContactConnection" case .contactConnectionDeleted: return "contactConnectionDeleted" + case .versionInfo: return "versionInfo" case .cmdOk: return "cmdOk" case .chatCmdError: return "chatCmdError" case .chatError: return "chatError" @@ -608,6 +613,7 @@ public enum ChatResponse: Decodable, Error { case let .ntfMessages(connEntity, msgTs, ntfMessages): return "connEntity: \(String(describing: connEntity))\nmsgTs: \(String(describing: msgTs))\nntfMessages: \(String(describing: ntfMessages))" case let .newContactConnection(connection): return String(describing: connection) case let .contactConnectionDeleted(connection): return String(describing: connection) + case let .versionInfo(versionInfo): return String(describing: versionInfo) case .cmdOk: return noDetails case let .chatCmdError(chatError): return String(describing: chatError) case let .chatError(chatError): return String(describing: chatError) @@ -1001,6 +1007,13 @@ public enum NotificationPreviewMode: String, SelectableItem { public static var values: [NotificationPreviewMode] = [.message, .contact, .hidden] } +public struct CoreVersionInfo: Decodable { + public var version: String + public var buildTimestamp: String + public var simplexmqVersion: String + public var simplexmqCommit: String +} + public func decodeJSON(_ json: String) -> T? { if let data = json.data(using: .utf8) { return try? jsonDecoder.decode(T.self, from: data)