From 5695bb9d46327a9239db20d5b4e27b1145bac422 Mon Sep 17 00:00:00 2001 From: sh <37271604+shumvgolove@users.noreply.github.com> Date: Sat, 8 Jun 2024 14:42:12 +0000 Subject: [PATCH 01/23] docs: change smp webpage path (#4307) --- docs/SERVER.md | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/docs/SERVER.md b/docs/SERVER.md index 426dbff6b3..c2cb486375 100644 --- a/docs/SERVER.md +++ b/docs/SERVER.md @@ -331,7 +331,7 @@ disconnect: off [WEB] # Set path to generate static mini-site for server information and qr codes/links -static_path: +static_path: /var/opt/simplex/www # Run an embedded server on this port # Onion sites can use any port and register it in the hidden service config. @@ -601,13 +601,7 @@ SMP-server versions starting from `v5.8.0-beta.0` can be configured to PROXY smp SMP-server versions starting from `v5.8.0` can be configured to serve Web page with server information that can include admin info, server info, provider info, etc. Run the following commands as `root` user. -1. Create folder to store webserver static files and assign correct permissions: - - ```sh - mkdir -p /var/www/smp-server-web && chown smp:smp /var/www/smp-server-web - ``` - -2. Add the following to your smp-server configuration (please modify fields in [INFORMATION] section to include relevant information): +1. Add the following to your smp-server configuration (please modify fields in [INFORMATION] section to include relevant information): ```sh vim /etc/opt/simplex/smp-server.ini @@ -615,7 +609,7 @@ SMP-server versions starting from `v5.8.0` can be configured to serve Web page w ```ini [WEB] - static_path: /var/www/smp-server-web + static_path: /var/opt/simplex/www [INFORMATION] # AGPLv3 license requires that you make any source code modifications @@ -656,7 +650,7 @@ SMP-server versions starting from `v5.8.0` can be configured to serve Web page w hosting_country: ``` -3. Install the webserver. For easy deployment we'll describe the installtion process of [Caddy](https://caddyserver.com) webserver on Ubuntu server: +2. Install the webserver. For easy deployment we'll describe the installtion process of [Caddy](https://caddyserver.com) webserver on Ubuntu server: 1. Install the packages: @@ -684,7 +678,7 @@ SMP-server versions starting from `v5.8.0` can be configured to serve Web page w [Full Caddy instllation instructions](https://caddyserver.com/docs/install) -4. Replace Caddy configuration with the following (don't forget to replace ``): +3. Replace Caddy configuration with the following (don't forget to replace ``): ```sh vim /etc/caddy/Caddyfile @@ -692,20 +686,20 @@ SMP-server versions starting from `v5.8.0` can be configured to serve Web page w ```caddy { - root * /var/www/simplex + root * /var/opt/simplex/www file_server } ``` -5. Enable and start Caddy service: +4. Enable and start Caddy service: ```sh systemctl enable --now caddy ``` -6. Upgrade your smp-server to latest version - [Updating your smp server](#updating-your-smp-server) +5. Upgrade your smp-server to latest version - [Updating your smp server](#updating-your-smp-server) -7. Access the webpage you've deployed from your browser. You should see the smp-server information that you've provided in your ini file. +6. Access the webpage you've deployed from your browser. You should see the smp-server information that you've provided in your ini file. ## Documentation From ea1c5da65d51af86d18efed610942388923d9fbd Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Mon, 10 Jun 2024 19:05:53 +0700 Subject: [PATCH 02/23] desktop: change thread who responsible for writting settings (#4311) --- .../chat/simplex/common/platform/Resources.desktop.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt index a966c0a4e2..9d39753f23 100644 --- a/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt +++ b/apps/multiplatform/common/src/desktopMain/kotlin/chat/simplex/common/platform/Resources.desktop.kt @@ -14,8 +14,10 @@ import com.russhwolf.settings.* import dev.icerock.moko.resources.ImageResource import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.desc.desc +import kotlinx.coroutines.* import java.io.File import java.util.* +import java.util.concurrent.Executors @Composable actual fun font(name: String, res: String, weight: FontWeight, style: FontStyle): Font = @@ -59,8 +61,11 @@ private val settingsThemesProps = Properties() .also { props -> try { settingsThemesFile.reader().use { props.load(it) } } catch (e: Exception) { /**/ } } -actual val settings: Settings = PropertiesSettings(settingsProps) { withApi { settingsFile.writer().use { settingsProps.store(it, "") } } } -actual val settingsThemes: Settings = PropertiesSettings(settingsThemesProps) { withApi { settingsThemesFile.writer().use { settingsThemesProps.store(it, "") } } } + +private val settingsWriterThread = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + +actual val settings: Settings = PropertiesSettings(settingsProps) { CoroutineScope(settingsWriterThread).launch { settingsFile.writer().use { settingsProps.store(it, "") } } } +actual val settingsThemes: Settings = PropertiesSettings(settingsThemesProps) { CoroutineScope(settingsWriterThread).launch { settingsThemesFile.writer().use { settingsThemesProps.store(it, "") } } } actual fun windowOrientation(): WindowOrientation = if (simplexWindowState.windowState.size.width > simplexWindowState.windowState.size.height) { From c52f9baefa1306e0930d7e545f8a0a8a2e933df2 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:11:35 +0400 Subject: [PATCH 03/23] desktop: close chat view when chat is stopped (#4313) --- .../kotlin/chat/simplex/common/views/database/DatabaseView.kt | 3 +++ 1 file changed, 3 insertions(+) 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 8549f6abe2..ca0a6f2f93 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 @@ -448,6 +448,9 @@ private fun stopChat(m: ChatModel, progressIndicator: MutableState? = n progressIndicator?.value = true stopChatAsync(m) platform.androidChatStopped() + // close chat view for desktop + chatModel.chatId.value = null + ModalManager.end.closeModals() onStop?.invoke() } catch (e: Error) { m.chatRunning.value = true From ce55c84b960563c9a859a847e1c2786a45eb40d2 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 10 Jun 2024 17:58:53 +0400 Subject: [PATCH 04/23] core: differentiate RCP error in view, test (#4310) --- cabal.project | 2 +- scripts/nix/sha256map.nix | 2 +- src/Simplex/Chat/View.hs | 15 +++++++++++---- tests/RemoteTests.hs | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/cabal.project b/cabal.project index 92437c6c8e..a3d8c16890 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: da620c388a853cb8612cc695aed5cff6900a916b + tag: bb1d31e459337f5d2de05f4495ff50d0a8788dff source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index f9e42a4359..b3858de700 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."da620c388a853cb8612cc695aed5cff6900a916b" = "0zv4qn50plz1v87xh2zv0j73mz173d5p9vy5cg1v5i8yjlm14srf"; + "https://github.com/simplex-chat/simplexmq.git"."bb1d31e459337f5d2de05f4495ff50d0a8788dff" = "1nbd80anzh2k5hnf330vlcda0zdn2lzlcnjmi3qz2jdkmmzcc3b6"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index ac5f84e5e5..d1f3625e18 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -54,8 +54,9 @@ import qualified Simplex.FileTransfer.Transport as XFTP import Simplex.Messaging.Agent.Client (ProtocolTestFailure (..), ProtocolTestStep (..), SubscriptionsInfo (..)) import Simplex.Messaging.Agent.Env.SQLite (NetworkConfig (..)) import Simplex.Messaging.Agent.Protocol +import Simplex.Messaging.Agent.Protocol (AgentErrorType (RCP)) import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..)) -import Simplex.Messaging.Client (SMPProxyMode (..), SMPProxyFallback) +import Simplex.Messaging.Client (SMPProxyFallback, SMPProxyMode (..)) import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..)) import qualified Simplex.Messaging.Crypto.Ratchet as CR @@ -67,7 +68,7 @@ import qualified Simplex.Messaging.Protocol as SMP import Simplex.Messaging.Transport.Client (TransportHost (..)) import Simplex.Messaging.Util (safeDecodeUtf8, tshow) import Simplex.Messaging.Version hiding (version) -import Simplex.RemoteControl.Types (RCCtrlAddress (..)) +import Simplex.RemoteControl.Types (RCCtrlAddress (..), RCErrorType (..)) import System.Console.ANSI.Types type CurrentTime = UTCTime @@ -350,7 +351,7 @@ responseToView hu@(currentRH, user_) ChatConfig {logLevel, showReactions, showRe ] CRRemoteCtrlConnected RemoteCtrlInfo {remoteCtrlId = rcId, ctrlDeviceName} -> ["remote controller " <> sShow rcId <> " session started with " <> plain ctrlDeviceName] - CRRemoteCtrlStopped {} -> ["remote controller stopped"] + CRRemoteCtrlStopped {rcStopReason} -> viewRemoteCtrlStopped rcStopReason CRContactPQEnabled u c (CR.PQEncryption pqOn) -> ttyUser u [ttyContact' c <> ": " <> (if pqOn then "quantum resistant" else "standard") <> " end-to-end encryption enabled"] CRSQLResult rows -> map plain rows CRSlowSQLQueries {chatQueries, agentQueries} -> @@ -1843,7 +1844,7 @@ viewCallAnswer ct WebRTCSession {rtcSession = answer, rtcIceCandidates = iceCand [ ttyContact' ct <> " continued the WebRTC call", "To connect, please paste the data below in your browser window you opened earlier and click Connect button", "", - viewJSON WCCallAnswer {answer, iceCandidates} + viewJSON WCCallAnswer {answer, iceCandidates} ] callMediaStr :: CallType -> StyledString @@ -1914,6 +1915,12 @@ viewRemoteCtrl CtrlAppInfo {deviceName, appVersionRange = AppVersionRange _ (App | otherwise = "" showCompatible = if compatible then "" else ", " <> bold' "not compatible" +viewRemoteCtrlStopped :: RemoteCtrlStopReason -> [StyledString] +viewRemoteCtrlStopped = \case + RCSRConnectionFailed (ChatErrorAgent (RCP RCEIdentity) _) -> + ["remote controller stopped: this link was used with another controller, please create a new link on the host"] + _ -> ["remote controller stopped"] + viewChatError :: Bool -> ChatLogLevel -> Bool -> ChatError -> [StyledString] viewChatError isCmd logLevel testView = \case ChatError err -> case err of diff --git a/tests/RemoteTests.hs b/tests/RemoteTests.hs index ac6fa7b23a..3f1bad613a 100644 --- a/tests/RemoteTests.hs +++ b/tests/RemoteTests.hs @@ -119,7 +119,7 @@ remoteHandshakeRejectTest = testChat3 aliceProfile aliceDesktopProfile bobProfil inv <- getTermLine desktop mobileBob ##> ("/connect remote ctrl " <> inv) mobileBob <## ("connecting new remote controller: My desktop, v" <> versionNumber) - mobileBob <## "remote controller stopped" + mobileBob <## "remote controller stopped: this link was used with another controller, please create a new link on the host" -- the server remains active after rejecting invalid client mobile ##> ("/connect remote ctrl " <> inv) From d244338b13ea93e1d9fb12f09bd40438ada76307 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:18:05 +0400 Subject: [PATCH 05/23] ui: differentiate remote ctrl errors, better error texts (#4302) --- apps/ios/Shared/Model/SimpleXAPI.swift | 18 +++++- .../RemoteAccess/ConnectDesktopView.swift | 28 +++++---- apps/ios/SimpleXChat/APITypes.swift | 2 +- .../chat/simplex/common/model/SimpleXAPI.kt | 57 +++++++++++++++---- .../common/views/remote/ConnectDesktopView.kt | 19 +++++++ .../commonMain/resources/MR/base/strings.xml | 3 + 6 files changed, 103 insertions(+), 24 deletions(-) diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index a828e1348d..49152283ee 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -1957,12 +1957,28 @@ func processReceivedMsg(_ res: ChatResponse) async { let state = UIRemoteCtrlSessionState.connected(remoteCtrl: remoteCtrl, sessionCode: m.remoteCtrlSession?.sessionCode ?? "") m.remoteCtrlSession = m.remoteCtrlSession?.updateState(state) } - case .remoteCtrlStopped: + case let .remoteCtrlStopped(_, rcStopReason): // This delay is needed to cancel the session that fails on network failure, // e.g. when user did not grant permission to access local network yet. if let sess = m.remoteCtrlSession { await MainActor.run { m.remoteCtrlSession = nil + dismissAllSheets() { + switch rcStopReason { + case .connectionFailed(.errorAgent(.RCP(.identity))): + AlertManager.shared.showAlertMsg( + title: "Connection with desktop stopped", + message: "This link was used with another mobile device, please create a new link on the desktop." + ) + default: + AlertManager.shared.showAlert(Alert( + title: Text("Connection with desktop stopped"), + message: Text("Please check that mobile and desktop are connected to the same local network, and that desktop firewall allows the connection.\nPlease share any other issues with the developers."), + primaryButton: .default(Text("Ok")), + secondaryButton: .default(Text("Copy error")) { UIPasteboard.general.string = String(describing: rcStopReason) } + )) + } + } } if case .connected = sess.sessionState { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { diff --git a/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift b/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift index 3059b049a3..1d47d9a936 100644 --- a/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift +++ b/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift @@ -181,23 +181,27 @@ struct ConnectDesktopView: View { } private func connectingDesktopView(_ session: RemoteCtrlSession, _ rc: RemoteCtrlInfo?) -> some View { - List { - Section("Connecting to desktop") { - ctrlDeviceNameText(session, rc) - ctrlDeviceVersionText(session) - } + ZStack { + List { + Section("Connecting to desktop") { + ctrlDeviceNameText(session, rc) + ctrlDeviceVersionText(session) + } - if let sessCode = session.sessionCode { - Section("Session code") { - sessionCodeText(sessCode) + if let sessCode = session.sessionCode { + Section("Session code") { + sessionCodeText(sessCode) + } + } + + Section { + disconnectButton() } } + .navigationTitle("Connecting to desktop") - Section { - disconnectButton() - } + ProgressView().scaleEffect(2) } - .navigationTitle("Connecting to desktop") } private func searchingDesktopView() -> some View { diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index a3545972d4..7b0a0a6646 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -980,7 +980,7 @@ public enum ChatResponse: Decodable, Error { case let .remoteCtrlConnecting(remoteCtrl_, ctrlAppInfo, appVersion): return "remoteCtrl_:\n\(String(describing: remoteCtrl_))\nctrlAppInfo:\n\(String(describing: ctrlAppInfo))\nappVersion: \(appVersion)" case let .remoteCtrlSessionCode(remoteCtrl_, sessionCode): return "remoteCtrl_:\n\(String(describing: remoteCtrl_))\nsessionCode: \(sessionCode)" case let .remoteCtrlConnected(remoteCtrl): return String(describing: remoteCtrl) - case .remoteCtrlStopped: return noDetails + case let .remoteCtrlStopped(rcsState, rcStopReason): return "rcsState: \(String(describing: rcsState))\nrcStopReason: \(String(describing: rcStopReason))" case let .contactPQEnabled(u, contact, pqEnabled): return withUser(u, "contact: \(String(describing: contact))\npqEnabled: \(pqEnabled)") case let .versionInfo(versionInfo, chatMigrations, agentMigrations): return "\(String(describing: versionInfo))\n\nchat migrations: \(chatMigrations.map(\.upName))\n\nagent migrations: \(agentMigrations.map(\.upName))" case .cmdOk: return noDetails diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index 839792e61c..c55ea0a871 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -1,9 +1,18 @@ package chat.simplex.common.model +import SectionItemView +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text import chat.simplex.common.views.helpers.* import androidx.compose.runtime.* +import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.style.TextAlign import chat.simplex.common.model.ChatController.getNetCfg import chat.simplex.common.model.ChatController.setNetCfg import chat.simplex.common.model.ChatModel.updatingChatsMutex @@ -12,7 +21,6 @@ import dev.icerock.moko.resources.compose.painterResource import chat.simplex.common.platform.* import chat.simplex.common.ui.theme.* import chat.simplex.common.views.call.* -import chat.simplex.common.views.chat.group.toggleShowMemberMessages import chat.simplex.common.views.migration.MigrationFileLinkData import chat.simplex.common.views.onboarding.OnboardingStage import chat.simplex.common.views.usersettings.* @@ -20,6 +28,7 @@ import com.charleskorn.kaml.Yaml import com.charleskorn.kaml.YamlConfiguration import chat.simplex.res.MR import com.russhwolf.settings.Settings +import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.* import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.sync.withLock @@ -2194,15 +2203,43 @@ object ChatController { val sess = chatModel.remoteCtrlSession.value if (sess != null) { chatModel.remoteCtrlSession.value = null + ModalManager.fullscreen.closeModals() fun showAlert(chatError: ChatError) { - AlertManager.shared.showAlertMsg( - generalGetString(MR.strings.remote_ctrl_was_disconnected_title), - if (chatError is ChatError.ChatErrorRemoteCtrl) { - chatError.remoteCtrlError.localizedString - } else { - generalGetString(MR.strings.remote_ctrl_disconnected_with_reason).format(chatError.string) - } - ) + when { + r.rcStopReason is RemoteCtrlStopReason.ConnectionFailed + && r.rcStopReason.chatError is ChatError.ChatErrorAgent + && r.rcStopReason.chatError.agentError is AgentErrorType.RCP + && r.rcStopReason.chatError.agentError.rcpErr is RCErrorType.IDENTITY -> + AlertManager.shared.showAlertMsg( + title = generalGetString(MR.strings.remote_ctrl_was_disconnected_title), + text = generalGetString(MR.strings.remote_ctrl_connection_stopped_identity_desc) + ) + else -> + AlertManager.shared.showAlertDialogButtonsColumn( + title = generalGetString(MR.strings.remote_ctrl_was_disconnected_title), + text = if (chatError is ChatError.ChatErrorRemoteCtrl) { + chatError.remoteCtrlError.localizedString + } else { + generalGetString(MR.strings.remote_ctrl_connection_stopped_desc) + }, + buttons = { + Column { + SectionItemView({ + AlertManager.shared.hideAlert() + }) { + Text(stringResource(MR.strings.ok), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary) + } + val clipboard = LocalClipboardManager.current + SectionItemView({ + clipboard.setText(AnnotatedString(json.encodeToString(r.rcStopReason))) + AlertManager.shared.hideAlert() + }) { + Text(stringResource(MR.strings.copy_error), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary) + } + } + } + ) + } } when (r.rcStopReason) { is RemoteCtrlStopReason.DiscoveryFailed -> showAlert(r.rcStopReason.chatError) @@ -4716,7 +4753,7 @@ sealed class CR { (if (remoteCtrl_ == null) "null" else json.encodeToString(remoteCtrl_)) + "\nsessionCode: $sessionCode" is RemoteCtrlConnected -> json.encodeToString(remoteCtrl) - is RemoteCtrlStopped -> noDetails() + is RemoteCtrlStopped -> "rcsState: $rcsState\nrcsStopReason: $rcStopReason" is ContactPQAllowed -> withUser(user, "contact: ${contact.id}\npqEncryption: $pqEncryption") is ContactPQEnabled -> withUser(user, "contact: ${contact.id}\npqEnabled: $pqEnabled") is VersionInfo -> "version ${json.encodeToString(versionInfo)}\n\n" + diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt index 76f522c614..d201ac482a 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectDesktopView.kt @@ -15,6 +15,7 @@ import androidx.compose.material.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.snapshots.SnapshotStateList +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalClipboardManager @@ -166,6 +167,24 @@ private fun ConnectingDesktop(session: RemoteCtrlSession, rc: RemoteCtrlInfo?) { SectionView { DisconnectButton(onClick = ::disconnectDesktop) } + + ProgressIndicator() +} + +@Composable +private fun ProgressIndicator() { + Box( + Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator( + Modifier + .padding(horizontal = 2.dp) + .size(30.dp), + color = MaterialTheme.colors.secondary, + strokeWidth = 3.dp + ) + } } @Composable 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 71218732d6..b896c4e980 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -1921,6 +1921,9 @@ Connection stopped %s with the reason: %s]]> Disconnected with the reason: %s + Please check that mobile and desktop are connected to the same local network, and that desktop firewall allows the connection.\nPlease share any other issues with the developers. + This link was used with another mobile device, please create a new link on the desktop. + Copy error Disconnect desktop? Only one device can work at the same time Use from desktop in mobile app and scan QR code.]]> From d5529031ee3be37d6d6ff5519e92819091e1fb5a Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 11 Jun 2024 00:33:10 +0700 Subject: [PATCH 06/23] android, desktop: socks proxy toggle enhancements (#4312) --- .../views/usersettings/NetworkAndServers.kt | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt index 5898ccb657..61c8e1b75f 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/NetworkAndServers.kt @@ -28,6 +28,7 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.common.model.* +import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.platform.* import chat.simplex.common.ui.theme.* import chat.simplex.common.views.chat.item.ClickableText @@ -58,6 +59,8 @@ fun NetworkAndServersView() { smpProxyFallback = smpProxyFallback, proxyPort = proxyPort, toggleSocksProxy = { enable -> + val def = NetCfg.defaults + val proxyDef = NetCfg.proxyDefaults if (enable) { AlertManager.shared.showAlertDialog( title = generalGetString(MR.strings.network_enable_socks), @@ -65,7 +68,19 @@ fun NetworkAndServersView() { confirmText = generalGetString(MR.strings.confirm_verb), onConfirm = { withBGApi { - val conf = NetCfg.proxyDefaults.withHostPort(chatModel.controller.appPrefs.networkProxyHostPort.get()) + var conf = controller.getNetCfg().withHostPort(controller.appPrefs.networkProxyHostPort.get()) + if (conf.tcpConnectTimeout == def.tcpConnectTimeout) { + conf = conf.copy(tcpConnectTimeout = proxyDef.tcpConnectTimeout) + } + if (conf.tcpTimeout == def.tcpTimeout) { + conf = conf.copy(tcpTimeout = proxyDef.tcpTimeout) + } + if (conf.tcpTimeoutPerKb == def.tcpTimeoutPerKb) { + conf = conf.copy(tcpTimeoutPerKb = proxyDef.tcpTimeoutPerKb) + } + if (conf.rcvConcurrency == def.rcvConcurrency) { + conf = conf.copy(rcvConcurrency = proxyDef.rcvConcurrency) + } chatModel.controller.apiSetNetworkConfig(conf) chatModel.controller.setNetCfg(conf) networkUseSocksProxy.value = true @@ -80,7 +95,19 @@ fun NetworkAndServersView() { confirmText = generalGetString(MR.strings.confirm_verb), onConfirm = { withBGApi { - val conf = NetCfg.defaults + var conf = controller.getNetCfg().copy(socksProxy = null) + if (conf.tcpConnectTimeout == proxyDef.tcpConnectTimeout) { + conf = conf.copy(tcpConnectTimeout = def.tcpConnectTimeout) + } + if (conf.tcpTimeout == proxyDef.tcpTimeout) { + conf = conf.copy(tcpTimeout = def.tcpTimeout) + } + if (conf.tcpTimeoutPerKb == proxyDef.tcpTimeoutPerKb) { + conf = conf.copy(tcpTimeoutPerKb = def.tcpTimeoutPerKb) + } + if (conf.rcvConcurrency == proxyDef.rcvConcurrency) { + conf = conf.copy(rcvConcurrency = def.rcvConcurrency) + } chatModel.controller.apiSetNetworkConfig(conf) chatModel.controller.setNetCfg(conf) networkUseSocksProxy.value = false From a5bf3cbca88f297d7ad34bc8c355abbccffd05e4 Mon Sep 17 00:00:00 2001 From: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com> Date: Mon, 10 Jun 2024 17:33:27 +0000 Subject: [PATCH 07/23] v5.6 -> v5.8 (#4308) --- docs/DOWNLOADS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DOWNLOADS.md b/docs/DOWNLOADS.md index 0432b0f92e..fcbe5d0446 100644 --- a/docs/DOWNLOADS.md +++ b/docs/DOWNLOADS.md @@ -7,7 +7,7 @@ revision: 11.02.2024 | Updated 23.03.2024 | Languages: EN | # Download SimpleX apps -The latest stable version is v5.6. +The latest stable version is v5.8. You can get the latest beta releases from [GitHub](https://github.com/simplex-chat/simplex-chat/releases). From 1573b7af13c2c2a056313ee75b7ebc3d2cd886e4 Mon Sep 17 00:00:00 2001 From: Diogo Date: Tue, 11 Jun 2024 06:29:53 +0100 Subject: [PATCH 08/23] ios: prevented error on desktop in lack of camera permissions (#4306) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 💡 moved ScannerInView to separate module made it more extensible and ready to be reused * fix: 🐛 prevented error on desktop in lack of camera permissions right now, connect to desktop functionality was failing if you didn't accept permissions before jumping to this screen for the first time. In here I did pick from other sections where cases of no permissions or unknown permissions were correctly handled and did reuse the same mechanism * chore: 🤖 reverted file move * chore: 🤖 reverted class change * chore: 🤖 reverted uncessary change * chore: 🤖 removed leftover --- apps/ios/Shared/Views/NewChat/NewChatView.swift | 4 +++- .../Shared/Views/RemoteAccess/ConnectDesktopView.swift | 10 ++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/apps/ios/Shared/Views/NewChat/NewChatView.swift b/apps/ios/Shared/Views/NewChat/NewChatView.swift index 7ece4fdee6..442f933ace 100644 --- a/apps/ios/Shared/Views/NewChat/NewChatView.swift +++ b/apps/ios/Shared/Views/NewChat/NewChatView.swift @@ -367,11 +367,12 @@ struct ScannerInView: View { @Binding var showQRCodeScanner: Bool let processQRCode: (_ resp: Result) -> Void @State private var cameraAuthorizationStatus: AVAuthorizationStatus? + var scanMode: ScanMode = .continuous var body: some View { Group { if showQRCodeScanner, case .authorized = cameraAuthorizationStatus { - CodeScannerView(codeTypes: [.qr], scanMode: .continuous, completion: processQRCode) + CodeScannerView(codeTypes: [.qr], scanMode: scanMode, completion: processQRCode) .aspectRatio(1, contentMode: .fit) .cornerRadius(12) .listRowBackground(Color.clear) @@ -436,6 +437,7 @@ struct ScannerInView: View { } } + private func linkTextView(_ link: String) -> some View { Text(link) .lineLimit(1) diff --git a/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift b/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift index 1d47d9a936..c749e09ca8 100644 --- a/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift +++ b/apps/ios/Shared/Views/RemoteAccess/ConnectDesktopView.swift @@ -333,16 +333,10 @@ struct ConnectDesktopView: View { } } } - + private func scanDesctopAddressView() -> some View { Section("Scan QR code from desktop") { - CodeScannerView(codeTypes: [.qr], scanMode: .oncePerCode, completion: processDesktopQRCode) - .aspectRatio(1, contentMode: .fit) - .cornerRadius(12) - .listRowBackground(Color.clear) - .listRowSeparator(.hidden) - .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) - .padding(.horizontal) + ScannerInView(showQRCodeScanner: $showQRCodeScanner, processQRCode: processDesktopQRCode, scanMode: .oncePerCode) } } From 40bd5dc2dac43ff0b38f0ab1266ad8b694ad9648 Mon Sep 17 00:00:00 2001 From: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com> Date: Sun, 16 Jun 2024 15:19:43 +0000 Subject: [PATCH 09/23] web: update copyright year 2023->2024 (#4297) * Update copyright year * Update ar.json * Update bg.json * Update cs.json * Update de.json * Update es.json * Update fr.json * Update hu.json * Update it.json * Update ja.json * Update nl.json * Update pl.json * Update pt_BR.json * Update ru.json --- website/langs/ar.json | 2 +- website/langs/bg.json | 2 +- website/langs/cs.json | 2 +- website/langs/de.json | 2 +- website/langs/en.json | 2 +- website/langs/es.json | 2 +- website/langs/fr.json | 2 +- website/langs/hu.json | 4 ++-- website/langs/it.json | 2 +- website/langs/ja.json | 2 +- website/langs/nl.json | 2 +- website/langs/pl.json | 2 +- website/langs/pt_BR.json | 2 +- website/langs/ru.json | 2 +- 14 files changed, 15 insertions(+), 15 deletions(-) diff --git a/website/langs/ar.json b/website/langs/ar.json index 3551ffd31f..956b55e72c 100644 --- a/website/langs/ar.json +++ b/website/langs/ar.json @@ -31,7 +31,7 @@ "simplex-explained-tab-2-p-1": "لكل اتصال، تستخدم قائمتي انتظار منفصلتين للمُراسلة لإرسال واستلام الرسائل عبر خوادم مختلفة.", "simplex-explained-tab-2-p-2": "تقوم الخوادم بتمرير الرسائل في اتجاه واحد فقط، دون الحصول على الصورة الكاملة لمُحادثات المستخدم أو اتصالاته.", "simplex-explained-tab-3-p-1": "تحتوي الخوادم على بيانات اعتماد مجهولة منفصلة لكل قائمة انتظار، ولا تعرف المستخدمين الذين ينتمون إليهم.", - "copyright-label": "مشروع مفتوح المصدر © SimpleX 2020-2023", + "copyright-label": "مشروع مفتوح المصدر © SimpleX 2020-2024", "simplex-chat-protocol": "بروتوكول دردشة SimpleX", "developers": "المطورين", "hero-subheader": "أول نظام مُراسلة
دون معرّفات مُستخدم", diff --git a/website/langs/bg.json b/website/langs/bg.json index b70a6882e4..963f850e53 100644 --- a/website/langs/bg.json +++ b/website/langs/bg.json @@ -21,7 +21,7 @@ "smp-protocol": "СМП Протокол", "chat-protocol": "Чат протокол", "donate": "Дарете", - "copyright-label": "© 2020-2023 SimpleX | Проект с отворен код", + "copyright-label": "© 2020-2024 SimpleX | Проект с отворен код", "simplex-chat-protocol": "SimpleX Чат протокол", "terminal-cli": "Системна конзола", "terms-and-privacy-policy": "Условия и политика за поверителност", diff --git a/website/langs/cs.json b/website/langs/cs.json index b8777eea38..674351f63a 100644 --- a/website/langs/cs.json +++ b/website/langs/cs.json @@ -25,7 +25,7 @@ "smp-protocol": "SMP protokol", "chat-protocol": "Chat protokol", "donate": "Darovat", - "copyright-label": "© 2020-2023 SimpleX | Projekt s otevřeným zdrojovým kódem", + "copyright-label": "© 2020-2024 SimpleX | Projekt s otevřeným zdrojovým kódem", "simplex-chat-protocol": "SimpleX Chat protokol", "terminal-cli": "Terminálové rozhraní příkazového řádku", "terms-and-privacy-policy": "Podmínky a zásady ochrany osobních údajů", diff --git a/website/langs/de.json b/website/langs/de.json index 0972423887..7dec07e8e9 100644 --- a/website/langs/de.json +++ b/website/langs/de.json @@ -21,7 +21,7 @@ "smp-protocol": "SMP Protokoll", "chat-bot-example": "Beispiel für einen Chatbot", "donate": "Spenden", - "copyright-label": "© 2020-2023 SimpleX | Open-Source Projekt", + "copyright-label": "© 2020-2024 SimpleX | Open-Source Projekt", "chat-protocol": "Chat Protokoll", "simplex-chat-protocol": "SimpleX Chat Protokoll", "terminal-cli": "Terminal Kommandozeilen-Schnittstelle", diff --git a/website/langs/en.json b/website/langs/en.json index 4e0b04bcbd..89bd17f5d4 100644 --- a/website/langs/en.json +++ b/website/langs/en.json @@ -21,7 +21,7 @@ "smp-protocol": "SMP protocol", "chat-protocol": "Chat protocol", "donate": "Donate", - "copyright-label": "© 2020-2023 SimpleX | Open-Source Project", + "copyright-label": "© 2020-2024 SimpleX | Open-Source Project", "simplex-chat-protocol": "SimpleX Chat protocol", "terminal-cli": "Terminal CLI", "terms-and-privacy-policy": "Privacy Policy", diff --git a/website/langs/es.json b/website/langs/es.json index d8f9c29c26..f91ab5a92a 100644 --- a/website/langs/es.json +++ b/website/langs/es.json @@ -10,7 +10,7 @@ "simplex-explained-tab-3-p-2": "El usuario puede mejorar aún más la privacidad de sus metadatos haciendo uso de la red Tor para acceder a los servidores, evitando así la correlación por dirección IP.", "smp-protocol": "Protocolo SMP", "donate": "Donación", - "copyright-label": "© 2020-2023 SimpleX | Proyecto de Código Abierto", + "copyright-label": "© 2020-2024 SimpleX | Proyecto de Código Abierto", "simplex-chat-protocol": "Protocolo de SimpleX Chat", "terms-and-privacy-policy": "Términos y Política de Privacidad", "hero-header": "Privacidad redefinida", diff --git a/website/langs/fr.json b/website/langs/fr.json index 7ead7882db..7a59ead53f 100644 --- a/website/langs/fr.json +++ b/website/langs/fr.json @@ -21,7 +21,7 @@ "smp-protocol": "Protocole SMP", "chat-protocol": "Protocole de chat", "donate": "Faire un don", - "copyright-label": "© 2020-2023 SimpleX | Projet Open-Source", + "copyright-label": "© 2020-2024 SimpleX | Projet Open-Source", "simplex-chat-protocol": "Protocole SimpleX Chat", "terminal-cli": "Terminal CLI", "terms-and-privacy-policy": "Politique de confidentialité", diff --git a/website/langs/hu.json b/website/langs/hu.json index 1c860fa023..b4aa44f12e 100644 --- a/website/langs/hu.json +++ b/website/langs/hu.json @@ -20,7 +20,7 @@ "smp-protocol": "SMP protokoll", "chat-protocol": "Csevegés protokoll", "donate": "Támogatás", - "copyright-label": "© 2020-2023 SimpleX | Nyílt forráskódú projekt", + "copyright-label": "© 2020-2024 SimpleX | Nyílt forráskódú projekt", "simplex-chat-protocol": "SimpleX Chat protokoll", "terminal-cli": "Terminál CLI", "terms-and-privacy-policy": "Adatvédelmi irányelvek", @@ -256,4 +256,4 @@ "simplex-chat-via-f-droid": "SimpleX Chat az F-Droidon keresztül", "simplex-chat-repo": "SimpleX Chat tároló", "stable-and-beta-versions-built-by-developers": "A fejlesztők által készített stabil és béta verziók" -} \ No newline at end of file +} diff --git a/website/langs/it.json b/website/langs/it.json index 64d3b4b8a4..ffbb28903a 100644 --- a/website/langs/it.json +++ b/website/langs/it.json @@ -10,7 +10,7 @@ "simplex-explained-tab-3-p-1": "I server hanno credenziali anonime separate per ogni coda e non sanno a quali utenti appartengano.", "chat-protocol": "Protocollo di chat", "donate": "Dona", - "copyright-label": "© 2020-2023 SimpleX | Progetto Open-Source", + "copyright-label": "© 2020-2024 SimpleX | Progetto Open-Source", "simplex-chat-protocol": "Protocollo di SimpleX Chat", "terminal-cli": "Terminale CLI", "terms-and-privacy-policy": "Informativa sulla privacy", diff --git a/website/langs/ja.json b/website/langs/ja.json index 4b30104615..48aaa41493 100644 --- a/website/langs/ja.json +++ b/website/langs/ja.json @@ -52,7 +52,7 @@ "chat-protocol": "チャットプロトコル", "chat-bot-example": "チャットボットの例", "donate": "寄付", - "copyright-label": "© 2020-2023 SimpleX | Open-Source Project", + "copyright-label": "© 2020-2024 SimpleX | Open-Source Project", "hero-p-1": "他のアプリにはユーザー ID があります: Signal、Matrix、Session、Briar、Jami、Cwtch など。
SimpleX にはありません。乱数さえもありません
これにより、プライバシーが大幅に向上します。", "copy-the-command-below-text": "以下のコマンドをコピーしてチャットで使用します:", "simplex-private-card-9-point-1": "各メッセージ キューは、異なる送信アドレスと受信アドレスを使用してメッセージを一方向に渡します。", diff --git a/website/langs/nl.json b/website/langs/nl.json index 4f6724e3ff..1d6dc4c2df 100644 --- a/website/langs/nl.json +++ b/website/langs/nl.json @@ -17,7 +17,7 @@ "chat-bot-example": "Chatbot voorbeeld", "smp-protocol": "SMP protocol", "donate": "Doneer", - "copyright-label": "© 2020-2023 SimpleX | Open-sourceproject", + "copyright-label": "© 2020-2024 SimpleX | Open-sourceproject", "simplex-chat-protocol": "SimpleX Chat protocol", "terminal-cli": "Terminal CLI", "terms-and-privacy-policy": "Privacybeleid", diff --git a/website/langs/pl.json b/website/langs/pl.json index 510915831d..e976be8295 100644 --- a/website/langs/pl.json +++ b/website/langs/pl.json @@ -15,7 +15,7 @@ "smp-protocol": "Protokół SMP", "chat-protocol": "Protokół czatu", "donate": "Darowizna", - "copyright-label": "© 2020-2023 SimpleX | Projekt Open-Source", + "copyright-label": "© 2020-2024 SimpleX | Projekt Open-Source", "simplex-chat-protocol": "Protokół SimpleX Chat", "terminal-cli": "Terminal CLI", "terms-and-privacy-policy": "Polityka prywatności", diff --git a/website/langs/pt_BR.json b/website/langs/pt_BR.json index 1bb21372e6..784e9e7ca0 100644 --- a/website/langs/pt_BR.json +++ b/website/langs/pt_BR.json @@ -25,7 +25,7 @@ "smp-protocol": "Protocolo SMP", "chat-protocol": "Protocolo de bate-papo", "donate": "Doar", - "copyright-label": "© 2020-2023 SimpleX | Projeto de Código Livre", + "copyright-label": "© 2020-2024 SimpleX | Projeto de Código Livre", "simplex-chat-protocol": "Protocolo Chat SimpleX", "terminal-cli": "CLI Terminal", "hero-header": "Privacidade redefinida", diff --git a/website/langs/ru.json b/website/langs/ru.json index 4a9100c76d..c9a435409d 100644 --- a/website/langs/ru.json +++ b/website/langs/ru.json @@ -1,6 +1,6 @@ { "copy-the-command-below-text": "скопируйте приведенную ниже команду и используйте ее в чате:", - "copyright-label": "© 2020-2023 SimpleX | Проект с открытым исходным кодом", + "copyright-label": "© 2020-2024 SimpleX | Проект с открытым исходным кодом", "chat-bot-example": "Пример Чат бота", "simplex-private-card-9-point-1": "Каждая очередь сообщений передает сообщения в одном направлении с разными адресами отправки и получения.", "simplex-private-card-1-point-2": "Криптобокс NaCL в каждой очереди для предотвращения корреляции трафика между очередями сообщений, в случае компрометации TLS.", From d3274b28ba4d4af2b19c80164811853887fa6cce Mon Sep 17 00:00:00 2001 From: "M. Sarmad Qadeer" Date: Sun, 16 Jun 2024 20:23:40 +0500 Subject: [PATCH 10/23] web: glossary fix (#4298) --- website/.eleventy.js | 4 +-- website/src/_includes/layouts/article.html | 3 +- website/src/_includes/layouts/doc.html | 3 +- website/src/_includes/layouts/privacy.html | 3 +- website/src/css/blog.css | 4 +++ website/src/css/style.css | 34 ++++++++++++++-------- website/src/js/script.js | 9 ++++++ 7 files changed, 43 insertions(+), 17 deletions(-) diff --git a/website/.eleventy.js b/website/.eleventy.js index a0a35f3366..a3b94643e8 100644 --- a/website/.eleventy.js +++ b/website/.eleventy.js @@ -404,6 +404,7 @@ module.exports = function (ty) { // this condition works if the link is a valid website file const fileContent = fs.readFileSync(linkFile, 'utf8') parsed.path = (matter(fileContent).data?.permalink || parsed.path).replace(/\.md$/, ".html").toLowerCase() + return parsed.path } else if (!fs.existsSync(linkFile)) { linkFile = linkFile.replace('/website/src', '') if (fs.existsSync(linkFile)) { @@ -413,13 +414,12 @@ module.exports = function (ty) { index = linkFile.indexOf(keyword) linkFile = linkFile.substring(index + keyword.length) parsed.path = `${githubUrl}${linkFile}` + return parsed.path } else { // if the link is not a valid website file or project file throw new Error(`Broken link: ${parsed.path} in ${hostFile}`) } } - - return uri.serialize(parsed) } }).use(markdownItAnchor, { slugify: (str) => diff --git a/website/src/_includes/layouts/article.html b/website/src/_includes/layouts/article.html index 783b6ece7c..4550aa96d7 100644 --- a/website/src/_includes/layouts/article.html +++ b/website/src/_includes/layouts/article.html @@ -38,10 +38,11 @@
-
{{ content | safe }}
+
{{ content | applyGlossary | safe }}
{% include "footer.html" %} + diff --git a/website/src/_includes/layouts/doc.html b/website/src/_includes/layouts/doc.html index 091f98bdc7..66ec7f022b 100644 --- a/website/src/_includes/layouts/doc.html +++ b/website/src/_includes/layouts/doc.html @@ -108,7 +108,7 @@ -
{{ content | safe }}
+
{{ content | applyGlossary | safe }}
@@ -117,6 +117,7 @@ {% include "footer.html" %} + diff --git a/website/src/_includes/layouts/privacy.html b/website/src/_includes/layouts/privacy.html index 7527852694..fcaa9964e3 100644 --- a/website/src/_includes/layouts/privacy.html +++ b/website/src/_includes/layouts/privacy.html @@ -33,10 +33,11 @@ {% include "navbar.html" %}
-
{{ content | safe }}
+
{{ content | applyGlossary | safe }}
{% include "footer.html" %} + diff --git a/website/src/css/blog.css b/website/src/css/blog.css index 897fbafb10..a5d1ae0a1a 100644 --- a/website/src/css/blog.css +++ b/website/src/css/blog.css @@ -217,6 +217,10 @@ h6 { float: right; margin-left: 3rem; } + + #article .float-right{ + margin-left: 3rem; + } } @media (max-width:768px) { diff --git a/website/src/css/style.css b/website/src/css/style.css index 71eb56fa67..b60c32e3dd 100644 --- a/website/src/css/style.css +++ b/website/src/css/style.css @@ -760,14 +760,15 @@ p a{ } .tooltip-title{ - margin-bottom: 0.5rem; - color: #0197FF; - font-weight: 600; - font-size: 1.1rem; + margin: 0 !important; + margin-bottom: 0.5rem !important; + color: #0197FF !important; + font-weight: 600 !important; + font-size: 1.1rem !important; } .dark .tooltip-title{ - color: #70F0F9; + color: #70F0F9 !important; } .glossary-tooltip .read-more-btn{ @@ -850,13 +851,18 @@ p a{ } .glossary-overlay .overlay-card .overlay-title{ - font-size: 1.875rem; - line-height: 2.25rem; - font-weight: 700; - margin-bottom: 1rem; - margin-bottom: 1.5rem; - --tw-text-opacity: 1; - color: rgb(1 151 255 / var(--tw-text-opacity)); + font-size: 1.875rem !important; + line-height: 2.25rem !important; + font-weight: 700 !important; + margin: 0 !important; + padding: 0 !important; + margin-bottom: 1.5rem !important; + --tw-text-opacity: 1 !important; + color: rgb(1 151 255 / var(--tw-text-opacity)) !important; +} + +.glossary-overlay .overlay-card .overlay-title::after{ + background-color: transparent !important; } .glossary-overlay .overlay-card .overlay-content{ @@ -872,6 +878,10 @@ p a{ color: #fff; } +.glossary-overlay .overlay-card .overlay-content p{ + margin: 0 !important; +} + .close-overlay-btn{ fill: #3F484B; position: fixed; diff --git a/website/src/js/script.js b/website/src/js/script.js index 5f863f48ee..abf7779ad3 100644 --- a/website/src/js/script.js +++ b/website/src/js/script.js @@ -1,3 +1,5 @@ +const uniqueSwiperContainer = document.querySelector('.unique-swiper') +if (uniqueSwiperContainer) { const uniqueSwiper = new Swiper('.unique-swiper', { slidesPerView: 1, spaceBetween: 80, @@ -23,12 +25,15 @@ const uniqueSwiper = new Swiper('.unique-swiper', { prevEl: '.unique-swiper-button-prev', }, }); +} const isMobile = { Android: () => navigator.userAgent.match(/Android/i), iOS: () => navigator.userAgent.match(/iPhone|iPad|iPod/i) }; +const privateSwiperContainer = document.querySelector('.private-swiper') +if (privateSwiperContainer) { const privateSwiper = new Swiper('.private-swiper', { slidesPerView: 1, slidesPerGroup: 1, @@ -79,7 +84,10 @@ const privateSwiper = new Swiper('.private-swiper', { } } }); +} +const simplexExplainedSwiperContainer = document.querySelector('.simplex-explained-swiper') +if (simplexExplainedSwiperContainer){ const simplexExplainedSwiper = new Swiper(".simplex-explained-swiper", { slidesPerView: 1, spaceBetween: 80, @@ -112,6 +120,7 @@ const simplexExplainedSwiper = new Swiper(".simplex-explained-swiper", { } } }); +} function closeOverlay(e) { e.target.closest('.overlay').classList.remove('flex'); From 7cd35b9068b16b65d7d896f131659ed11d2a479f Mon Sep 17 00:00:00 2001 From: "M. Sarmad Qadeer" Date: Mon, 17 Jun 2024 02:22:53 +0500 Subject: [PATCH 11/23] web: design fixes eg: blog titles & link wrap (#4305) Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> --- website/src/blog.html | 2 +- website/src/css/style.css | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/website/src/blog.html b/website/src/blog.html index 11f057ce70..571b240451 100644 --- a/website/src/blog.html +++ b/website/src/blog.html @@ -58,7 +58,7 @@ active_blog: true
-

+

{{ blog.data.title | safe }}

diff --git a/website/src/css/style.css b/website/src/css/style.css index b60c32e3dd..a33c13d9c5 100644 --- a/website/src/css/style.css +++ b/website/src/css/style.css @@ -46,6 +46,10 @@ img{ -ms-user-select: none; /* For Internet Explorer and Edge */ } +a{ + word-wrap: break-word; +} + /* #comparison::before { display: block; content: " "; From c4083e00c5f61afcae5b396efb2b682a728482eb Mon Sep 17 00:00:00 2001 From: "M. Sarmad Qadeer" Date: Mon, 17 Jun 2024 02:31:36 +0500 Subject: [PATCH 12/23] web: update feed (#4255) * web: update feed * change date filter in feed.rss --- website/src/blogs-atom-feed.njk | 25 ++++++++++++++----------- website/src/blogs-rss-feed.njk | 4 ++-- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/website/src/blogs-atom-feed.njk b/website/src/blogs-atom-feed.njk index 11e1d72a7a..68f396ae40 100644 --- a/website/src/blogs-atom-feed.njk +++ b/website/src/blogs-atom-feed.njk @@ -11,28 +11,31 @@ metadata: email: chat@simplex.chat --- - + + {{ metadata.url }} + + {{ metadata.title }} {{ metadata.subtitle }} - - {{ collections.blogs | getNewestCollectionItemDate | dateToRfc3339 }} - {{ metadata.url }} {{ metadata.author.name }} {{ metadata.author.email }} {%- for blog in collections.blogs | reverse %} {%- if not blog.data.draft %} - {%- set absolutePostUrl = blog.url | absoluteUrl(metadata.url) %} + {%- set absolutePostUrl = blog.data.permalink | absoluteUrl(metadata.url) %} + {{ blog.data.permalink | absoluteUrl(metadata.url) }} + + {{ blog.data.date | dateToRfc3339 }} + {{ blog.data.title }} - - {# {{ blog.date | dateToRfc3339 }} #} - {{ blog.data.date.toUTCString().split(' ').slice(1, 4).join(' ') }} - {{ absolutePostUrl }} - {{ blog.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }} - {# {{ blog.templateContent | striptags | truncate(200) }} #} + {{ blog.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }} + + {{ metadata.author.name }} + {{ metadata.author.email }} + {%- endif %} {%- endfor %} diff --git a/website/src/blogs-rss-feed.njk b/website/src/blogs-rss-feed.njk index 54b63e088c..a2e675ec40 100644 --- a/website/src/blogs-rss-feed.njk +++ b/website/src/blogs-rss-feed.njk @@ -26,8 +26,8 @@ metadata: {{ absolutePostUrl }} {{ blog.templateContent | htmlToAbsoluteUrls(absolutePostUrl) }} {# {{ blog.templateContent | striptags | truncate(200) }} #} - {# {{ blog.data.date | dateToRfc822 }} #} - {{ blog.data.date.toUTCString().split(' ').slice(1, 4).join(' ') }} + {{ blog.data.date | dateToRfc822 }} + {# {{ blog.data.date.toUTCString().split(' ').slice(1, 4).join(' ') }} #} {{ metadata.author.name }} {{ absolutePostUrl }} From bcd510c9137c6f18ad48d7c8c837b6689ada5fb8 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Sun, 16 Jun 2024 20:24:37 -0700 Subject: [PATCH 13/23] cli: option to confirm up migrations (#4150) * cli: option to confirm up migrations * fix test --- src/Simplex/Chat.hs | 7 ++++--- src/Simplex/Chat/Mobile.hs | 3 ++- src/Simplex/Chat/Options.hs | 12 ++++++++++-- tests/ChatClient.hs | 3 ++- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 82f4ce84cd..0f1beacbbe 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -218,11 +218,12 @@ newChatController :: ChatDatabase -> Maybe User -> ChatConfig -> ChatOpts -> Boo newChatController ChatDatabase {chatStore, agentStore} user - cfg@ChatConfig {agentConfig = aCfg, defaultServers, inlineFiles, deviceNameForRemote} - ChatOpts {coreOptions = CoreChatOpts {smpServers, xftpServers, simpleNetCfg, logLevel, logConnections, logServerHosts, logFile, tbqSize, highlyAvailable}, deviceName, optFilesFolder, optTempDirectory, showReactions, allowInstantFiles, autoAcceptFileSize} + cfg@ChatConfig {agentConfig = aCfg, defaultServers, inlineFiles, deviceNameForRemote, confirmMigrations} + ChatOpts {coreOptions = CoreChatOpts {smpServers, xftpServers, simpleNetCfg, logLevel, logConnections, logServerHosts, logFile, tbqSize, highlyAvailable, yesToUpMigrations}, deviceName, optFilesFolder, optTempDirectory, showReactions, allowInstantFiles, autoAcceptFileSize} backgroundMode = do let inlineFiles' = if allowInstantFiles || autoAcceptFileSize > 0 then inlineFiles else inlineFiles {sendChunks = 0, receiveInstant = False} - config = cfg {logLevel, showReactions, tbqSize, subscriptionEvents = logConnections, hostEvents = logServerHosts, defaultServers = configServers, inlineFiles = inlineFiles', autoAcceptFileSize, highlyAvailable} + confirmMigrations' = if confirmMigrations == MCConsole && yesToUpMigrations then MCYesUp else confirmMigrations + config = cfg {logLevel, showReactions, tbqSize, subscriptionEvents = logConnections, hostEvents = logServerHosts, defaultServers = configServers, inlineFiles = inlineFiles', autoAcceptFileSize, highlyAvailable, confirmMigrations = confirmMigrations'} firstTime = dbNew chatStore currentUser <- newTVarIO user currentRemoteHost <- newTVarIO Nothing diff --git a/src/Simplex/Chat/Mobile.hs b/src/Simplex/Chat/Mobile.hs index 486e0d62f3..57b0ee6c17 100644 --- a/src/Simplex/Chat/Mobile.hs +++ b/src/Simplex/Chat/Mobile.hs @@ -198,7 +198,8 @@ mobileChatOpts dbFilePrefix = logAgent = Nothing, logFile = Nothing, tbqSize = 1024, - highlyAvailable = False + highlyAvailable = False, + yesToUpMigrations = False }, deviceName = Nothing, chatCmd = "", diff --git a/src/Simplex/Chat/Options.hs b/src/Simplex/Chat/Options.hs index f441afd2b3..14e5603976 100644 --- a/src/Simplex/Chat/Options.hs +++ b/src/Simplex/Chat/Options.hs @@ -62,7 +62,8 @@ data CoreChatOpts = CoreChatOpts logAgent :: Maybe LogLevel, logFile :: Maybe FilePath, tbqSize :: Natural, - highlyAvailable :: Bool + highlyAvailable :: Bool, + yesToUpMigrations :: Bool } data ChatCmdLog = CCLAll | CCLMessages | CCLNone @@ -204,6 +205,12 @@ coreChatOptsP appDir defaultDbFileName = do ( long "ha" <> help "Run as a highly available client (this may increase traffic in groups)" ) + yesToUpMigrations <- + switch + ( long "--yes-migrate" + <> short 'y' + <> help "Automatically confirm \"up\" database migrations" + ) pure CoreChatOpts { dbFilePrefix, @@ -217,7 +224,8 @@ coreChatOptsP appDir defaultDbFileName = do logAgent = if logAgent || logLevel == CLLDebug then Just $ agentLogLevel logLevel else Nothing, logFile, tbqSize, - highlyAvailable + highlyAvailable, + yesToUpMigrations } where useTcpTimeout p t = 1000000 * if t > 0 then t else maybe 7 (const 15) p diff --git a/tests/ChatClient.hs b/tests/ChatClient.hs index ceb3988ff9..efca493002 100644 --- a/tests/ChatClient.hs +++ b/tests/ChatClient.hs @@ -101,7 +101,8 @@ testCoreOpts = logAgent = Nothing, logFile = Nothing, tbqSize = 16, - highlyAvailable = False + highlyAvailable = False, + yesToUpMigrations = False } getTestOpts :: Bool -> ScrubbedBytes -> ChatOpts From a58522ef152008e26ca2068fcb50b2f6b7656db2 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Mon, 17 Jun 2024 11:52:55 +0400 Subject: [PATCH 14/23] core: api to reconnect single server (#4317) --- cabal.project | 2 +- scripts/nix/sha256map.nix | 2 +- src/Simplex/Chat.hs | 4 ++++ src/Simplex/Chat/Controller.hs | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cabal.project b/cabal.project index a3d8c16890..5a607b257d 100644 --- a/cabal.project +++ b/cabal.project @@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: bb1d31e459337f5d2de05f4495ff50d0a8788dff + tag: 8a3b72458f917e9867f4e3640dda0fa1827ff6cf source-repository-package type: git diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index b3858de700..fc8833ee31 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."bb1d31e459337f5d2de05f4495ff50d0a8788dff" = "1nbd80anzh2k5hnf330vlcda0zdn2lzlcnjmi3qz2jdkmmzcc3b6"; + "https://github.com/simplex-chat/simplexmq.git"."8a3b72458f917e9867f4e3640dda0fa1827ff6cf" = "1mmxdaj563kjmlkacxdnq62n6mzw9khampzaqghnk6iiwzdig0qy"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 0f1beacbbe..c45526dfd5 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -1358,6 +1358,9 @@ processChatCommand' vr = \case pure $ CRNetworkConfig cfg APISetNetworkInfo info -> lift (withAgent' (`setUserNetworkInfo` info)) >> ok_ ReconnectAllServers -> withUser' $ \_ -> lift (withAgent' reconnectAllServers) >> ok_ + ReconnectServer userId srv -> withUserId userId $ \user -> do + lift (withAgent' $ \a -> reconnectSMPServer a (aUserId user) srv) + ok_ APISetChatSettings (ChatRef cType chatId) chatSettings -> withUser $ \user -> case cType of CTDirect -> do ct <- withStore $ \db -> do @@ -7411,6 +7414,7 @@ chatCommandP = "/_network " *> (APISetNetworkConfig <$> jsonP), ("/network " <|> "/net ") *> (SetNetworkConfig <$> netCfgP), ("/network" <|> "/net") $> APIGetNetworkConfig, + "/reconnect " *> (ReconnectServer <$> A.decimal <* A.space <*> strP), "/reconnect" $> ReconnectAllServers, "/_settings " *> (APISetChatSettings <$> chatRefP <* A.space <*> jsonP), "/_member settings #" *> (APISetMemberSettings <$> A.decimal <* A.space <*> A.decimal <* A.space <*> jsonP), diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 102d6575e6..04f360cc3e 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -355,6 +355,7 @@ data ChatCommand | SetNetworkConfig SimpleNetCfg | APISetNetworkInfo UserNetworkInfo | ReconnectAllServers + | ReconnectServer UserId SMPServer | APISetChatSettings ChatRef ChatSettings | APISetMemberSettings GroupId GroupMemberId GroupMemberSettings | APIContactInfo ContactId From d9a61af401477486e896f1b4f301af636e79ba6c Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 18 Jun 2024 10:37:45 +0400 Subject: [PATCH 15/23] core: fix preference application (#4330) --- src/Simplex/Chat.hs | 82 +++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index c45526dfd5..4611b5c2d7 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -104,7 +104,7 @@ import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..), Migrati import Simplex.Messaging.Agent.Store.SQLite.DB (SlowQueryStats (..)) import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB import qualified Simplex.Messaging.Agent.Store.SQLite.Migrations as Migrations -import Simplex.Messaging.Client (ProxyClientError (..), NetworkConfig (..), defaultNetworkConfig) +import Simplex.Messaging.Client (NetworkConfig (..), ProxyClientError (..), defaultNetworkConfig) import qualified Simplex.Messaging.Crypto as C import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..)) import qualified Simplex.Messaging.Crypto.File as CF @@ -763,28 +763,31 @@ processChatCommand' vr = \case _ -> throwChatError CEInvalidChatItemUpdate CChatItem SMDRcv _ -> throwChatError CEInvalidChatItemUpdate CTGroup -> withGroupLock "updateChatItem" chatId $ do - Group gInfo@GroupInfo {groupId} ms <- withStore $ \db -> getGroup db vr user chatId + Group gInfo@GroupInfo {groupId, membership} ms <- withStore $ \db -> getGroup db vr user chatId assertUserGroupRole gInfo GRAuthor - cci <- withStore $ \db -> getGroupCIWithReactions db user gInfo itemId - case cci of - CChatItem SMDSnd ci@ChatItem {meta = CIMeta {itemSharedMsgId, itemTimed, itemLive, editable}, content = ciContent} -> do - case (ciContent, itemSharedMsgId, editable) of - (CISndMsgContent oldMC, Just itemSharedMId, True) -> do - let changed = mc /= oldMC - if changed || fromMaybe False itemLive - then do - (SndMessage {msgId}, _) <- sendGroupMessage user gInfo ms (XMsgUpdate itemSharedMId mc (ttl' <$> itemTimed) (justTrue . (live &&) =<< itemLive)) - ci' <- withStore' $ \db -> do - currentTs <- liftIO getCurrentTime - when changed $ - addInitialAndNewCIVersions db itemId (chatItemTs' ci, oldMC) (currentTs, mc) - let edited = itemLive /= Just True - updateGroupChatItem db user groupId ci (CISndMsgContent mc) edited live $ Just msgId - startUpdatedTimedItemThread user (ChatRef CTGroup groupId) ci ci' - pure $ CRChatItemUpdated user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci') - else pure $ CRChatItemNotChanged user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci) - _ -> throwChatError CEInvalidChatItemUpdate - CChatItem SMDRcv _ -> throwChatError CEInvalidChatItemUpdate + if prohibitedSimplexLinks gInfo membership mc + then pure $ chatCmdError (Just user) ("feature not allowed " <> T.unpack (groupFeatureNameText GFSimplexLinks)) + else do + cci <- withStore $ \db -> getGroupCIWithReactions db user gInfo itemId + case cci of + CChatItem SMDSnd ci@ChatItem {meta = CIMeta {itemSharedMsgId, itemTimed, itemLive, editable}, content = ciContent} -> do + case (ciContent, itemSharedMsgId, editable) of + (CISndMsgContent oldMC, Just itemSharedMId, True) -> do + let changed = mc /= oldMC + if changed || fromMaybe False itemLive + then do + (SndMessage {msgId}, _) <- sendGroupMessage user gInfo ms (XMsgUpdate itemSharedMId mc (ttl' <$> itemTimed) (justTrue . (live &&) =<< itemLive)) + ci' <- withStore' $ \db -> do + currentTs <- liftIO getCurrentTime + when changed $ + addInitialAndNewCIVersions db itemId (chatItemTs' ci, oldMC) (currentTs, mc) + let edited = itemLive /= Just True + updateGroupChatItem db user groupId ci (CISndMsgContent mc) edited live $ Just msgId + startUpdatedTimedItemThread user (ChatRef CTGroup groupId) ci ci' + pure $ CRChatItemUpdated user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci') + else pure $ CRChatItemNotChanged user (AChatItem SCTGroup SMDSnd (GroupChat gInfo) ci) + _ -> throwChatError CEInvalidChatItemUpdate + CChatItem SMDRcv _ -> throwChatError CEInvalidChatItemUpdate CTLocal -> do (nf@NoteFolder {noteFolderId}, cci) <- withStore $ \db -> (,) <$> getNoteFolder db user chatId <*> getLocalChatItem db user chatId itemId case cci of @@ -2922,9 +2925,13 @@ prohibitedGroupContent :: GroupInfo -> GroupMember -> MsgContent -> Maybe f -> M prohibitedGroupContent gInfo m mc file_ | isVoice mc && not (groupFeatureMemberAllowed SGFVoice m gInfo) = Just GFVoice | not (isVoice mc) && isJust file_ && not (groupFeatureMemberAllowed SGFFiles m gInfo) = Just GFFiles - | not (groupFeatureMemberAllowed SGFSimplexLinks m gInfo) && containsFormat isSimplexLink (parseMarkdown $ msgContentText mc) = Just GFSimplexLinks + | prohibitedSimplexLinks gInfo m mc = Just GFSimplexLinks | otherwise = Nothing +prohibitedSimplexLinks :: GroupInfo -> GroupMember -> MsgContent -> Bool +prohibitedSimplexLinks gInfo m mc = + not (groupFeatureMemberAllowed SGFSimplexLinks m gInfo) && containsFormat isSimplexLink (parseMarkdown $ msgContentText mc) + roundedFDCount :: Int -> Int roundedFDCount n | n <= 0 = 4 @@ -3218,7 +3225,7 @@ receiveViaCompleteFD user fileId RcvFileDescr {fileDescrText, fileDescrComplete} forM_ aci_ $ \aci -> toView $ CRChatItemUpdated user aci throwChatError $ CEFileNotApproved fileId unknownSrvs -getNetworkConfig :: CM' NetworkConfig +getNetworkConfig :: CM' NetworkConfig getNetworkConfig = withAgent' $ liftIO . getNetworkConfig' resetRcvCIFileStatus :: User -> FileTransferId -> CIFileStatus 'MDRcv -> CM (Maybe AChatItem) @@ -5254,18 +5261,21 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = groupMsgToView gInfo ci' {reactions} groupMessageUpdate :: GroupInfo -> GroupMember -> SharedMsgId -> MsgContent -> RcvMessage -> UTCTime -> Maybe Int -> Maybe Bool -> CM () - groupMessageUpdate gInfo@GroupInfo {groupId} m@GroupMember {groupMemberId, memberId} sharedMsgId mc msg@RcvMessage {msgId} brokerTs ttl_ live_ = - updateRcvChatItem `catchCINotFound` \_ -> do - -- This patches initial sharedMsgId into chat item when locally deleted chat item - -- received an update from the sender, so that it can be referenced later (e.g. by broadcast delete). - -- Chat item and update message which created it will have different sharedMsgId in this case... - let timed_ = rcvGroupCITimed gInfo ttl_ - ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg (Just sharedMsgId) brokerTs content Nothing timed_ live - ci' <- withStore' $ \db -> do - createChatItemVersion db (chatItemId' ci) brokerTs mc - ci' <- updateGroupChatItem db user groupId ci content True live Nothing - blockedMember m ci' $ markGroupChatItemBlocked db user gInfo ci' - toView $ CRChatItemUpdated user (AChatItem SCTGroup SMDRcv (GroupChat gInfo) ci') + groupMessageUpdate gInfo@GroupInfo {groupId} m@GroupMember {groupMemberId, memberId} sharedMsgId mc msg@RcvMessage {msgId} brokerTs ttl_ live_ + | prohibitedSimplexLinks gInfo m mc = + messageWarning $ "x.msg.update ignored: feature not allowed " <> groupFeatureNameText GFSimplexLinks + | otherwise = do + updateRcvChatItem `catchCINotFound` \_ -> do + -- This patches initial sharedMsgId into chat item when locally deleted chat item + -- received an update from the sender, so that it can be referenced later (e.g. by broadcast delete). + -- Chat item and update message which created it will have different sharedMsgId in this case... + let timed_ = rcvGroupCITimed gInfo ttl_ + ci <- saveRcvChatItem' user (CDGroupRcv gInfo m) msg (Just sharedMsgId) brokerTs content Nothing timed_ live + ci' <- withStore' $ \db -> do + createChatItemVersion db (chatItemId' ci) brokerTs mc + ci' <- updateGroupChatItem db user groupId ci content True live Nothing + blockedMember m ci' $ markGroupChatItemBlocked db user gInfo ci' + toView $ CRChatItemUpdated user (AChatItem SCTGroup SMDRcv (GroupChat gInfo) ci') where content = CIRcvMsgContent mc live = fromMaybe False live_ From 6c4c9b172c0d2480056e300851f4ad891460a0e7 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Tue, 18 Jun 2024 23:44:33 +0400 Subject: [PATCH 16/23] core: fix markdown check (#4334) * core: fix markdown * more tests * enable tests --------- Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> --- src/Simplex/Chat.hs | 6 +++++- src/Simplex/Chat/Markdown.hs | 4 ---- tests/ChatTests/Profiles.hs | 11 ++++++++++- tests/MarkdownTests.hs | 7 +++++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 4611b5c2d7..c46eed70e1 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -2930,7 +2930,11 @@ prohibitedGroupContent gInfo m mc file_ prohibitedSimplexLinks :: GroupInfo -> GroupMember -> MsgContent -> Bool prohibitedSimplexLinks gInfo m mc = - not (groupFeatureMemberAllowed SGFSimplexLinks m gInfo) && containsFormat isSimplexLink (parseMarkdown $ msgContentText mc) + not (groupFeatureMemberAllowed SGFSimplexLinks m gInfo) + && maybe False (any ftIsSimplexLink) (parseMaybeMarkdownList $ msgContentText mc) + where + ftIsSimplexLink :: FormattedText -> Bool + ftIsSimplexLink FormattedText {format} = maybe False isSimplexLink format roundedFDCount :: Int -> Int roundedFDCount n diff --git a/src/Simplex/Chat/Markdown.hs b/src/Simplex/Chat/Markdown.hs index d3b9ea52f1..d7c6d31fc8 100644 --- a/src/Simplex/Chat/Markdown.hs +++ b/src/Simplex/Chat/Markdown.hs @@ -144,10 +144,6 @@ markdownToList (m1 :|: m2) = markdownToList m1 <> markdownToList m2 parseMarkdown :: Text -> Markdown parseMarkdown s = fromRight (unmarked s) $ A.parseOnly (markdownP <* A.endOfInput) s -containsFormat :: (Format -> Bool) -> Markdown -> Bool -containsFormat p (Markdown f _) = maybe False p f -containsFormat p (m1 :|: m2) = containsFormat p m1 || containsFormat p m2 - isSimplexLink :: Format -> Bool isSimplexLink = \case SimplexLink {} -> True; diff --git a/tests/ChatTests/Profiles.hs b/tests/ChatTests/Profiles.hs index 3d92a73313..c1388072ab 100644 --- a/tests/ChatTests/Profiles.hs +++ b/tests/ChatTests/Profiles.hs @@ -2032,10 +2032,19 @@ testGroupPrefsSimplexLinksForRole = testChat3 aliceProfile bobProfile cathProfil threadDelay 1000000 bob ##> "/c" inv <- getInvitation bob - bob ##> ("#team " <> inv) + bob ##> ("#team \"" <> inv <> "\\ntest\"") + bob <## "bad chat command: feature not allowed SimpleX links" + bob ##> ("/_send #1 json {\"msgContent\": {\"type\": \"text\", \"text\": \"" <> inv <> "\\ntest\"}}") bob <## "bad chat command: feature not allowed SimpleX links" (alice inv <> "\\ntest\"") + bob <# ("@alice " <> inv) + bob <## "test" + alice <# ("bob> " <> inv) + alice <## "test" + bob ##> "#team <- @alice https://simplex.chat" + bob <## "bad chat command: feature not allowed SimpleX links" alice #> ("#team " <> inv) bob <# ("#team alice> " <> inv) cath <# ("#team alice> " <> inv) diff --git a/tests/MarkdownTests.hs b/tests/MarkdownTests.hs index d2d15dc166..a279201bea 100644 --- a/tests/MarkdownTests.hs +++ b/tests/MarkdownTests.hs @@ -210,3 +210,10 @@ multilineMarkdownList = describe "multiline markdown" do parseMaybeMarkdownList "http://simplex.chat\ntext 1\ntext 2\nhttp://app.simplex.chat" `shouldBe` Just [uri' "http://simplex.chat", "\ntext 1\ntext 2\n", uri' "http://app.simplex.chat"] it "no markdown" do parseMaybeMarkdownList "not a\nmarkdown" `shouldBe` Nothing + let inv = "/invitation#/?v=1&smp=smp%3A%2F%2F1234-w%3D%3D%40smp.simplex.im%3A5223%2F3456-w%3D%3D%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAjiswwI3O_NlS8Fk3HJUW870EY2bAwmttMBsvRB9eV3o%253D&e2e=v%3D2%26x3dh%3DMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D%2CMEIwBQYDK2VvAzkAmKuSYeQ_m0SixPDS8Wq8VBaTS1cW-Lp0n0h4Diu-kUpR-qXx4SDJ32YGEFoGFGSbGPry5Ychr6U%3D" + it "multiline with simplex link" do + parseMaybeMarkdownList ("https://simplex.chat" <> inv <> "\ntext") + `shouldBe` Just + [ FormattedText (Just $ SimplexLink XLInvitation ("simplex:" <> inv) ["smp.simplex.im"]) ("https://simplex.chat" <> inv), + "\ntext" + ] From 0198c1f110560fb19427ada118b28494e46aeca9 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Tue, 18 Jun 2024 23:12:27 +0100 Subject: [PATCH 17/23] core: 5.8.1.0 --- package.yaml | 2 +- simplex-chat.cabal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.yaml b/package.yaml index 2e73355d6f..15f9c5bfa1 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: simplex-chat -version: 5.8.0.5 +version: 5.8.1.0 #synopsis: #description: homepage: https://github.com/simplex-chat/simplex-chat#readme diff --git a/simplex-chat.cabal b/simplex-chat.cabal index 5c4e9cd53f..f8ab75568b 100644 --- a/simplex-chat.cabal +++ b/simplex-chat.cabal @@ -5,7 +5,7 @@ cabal-version: 1.12 -- see: https://github.com/sol/hpack name: simplex-chat -version: 5.8.0.5 +version: 5.8.1.0 category: Web, System, Services, Cryptography homepage: https://github.com/simplex-chat/simplex-chat#readme author: simplex.chat From d993381d31e9f607a73bde2ef8ad019add77413a Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Tue, 18 Jun 2024 23:44:58 +0100 Subject: [PATCH 18/23] Revert "web: glossary fix (#4298)" This reverts commit d3274b28ba4d4af2b19c80164811853887fa6cce. --- website/.eleventy.js | 4 +-- website/src/_includes/layouts/article.html | 3 +- website/src/_includes/layouts/doc.html | 3 +- website/src/_includes/layouts/privacy.html | 3 +- website/src/css/blog.css | 4 --- website/src/css/style.css | 34 ++++++++-------------- website/src/js/script.js | 9 ------ 7 files changed, 17 insertions(+), 43 deletions(-) diff --git a/website/.eleventy.js b/website/.eleventy.js index a3b94643e8..a0a35f3366 100644 --- a/website/.eleventy.js +++ b/website/.eleventy.js @@ -404,7 +404,6 @@ module.exports = function (ty) { // this condition works if the link is a valid website file const fileContent = fs.readFileSync(linkFile, 'utf8') parsed.path = (matter(fileContent).data?.permalink || parsed.path).replace(/\.md$/, ".html").toLowerCase() - return parsed.path } else if (!fs.existsSync(linkFile)) { linkFile = linkFile.replace('/website/src', '') if (fs.existsSync(linkFile)) { @@ -414,12 +413,13 @@ module.exports = function (ty) { index = linkFile.indexOf(keyword) linkFile = linkFile.substring(index + keyword.length) parsed.path = `${githubUrl}${linkFile}` - return parsed.path } else { // if the link is not a valid website file or project file throw new Error(`Broken link: ${parsed.path} in ${hostFile}`) } } + + return uri.serialize(parsed) } }).use(markdownItAnchor, { slugify: (str) => diff --git a/website/src/_includes/layouts/article.html b/website/src/_includes/layouts/article.html index 4550aa96d7..783b6ece7c 100644 --- a/website/src/_includes/layouts/article.html +++ b/website/src/_includes/layouts/article.html @@ -38,11 +38,10 @@

-
{{ content | applyGlossary | safe }}
+
{{ content | safe }}
{% include "footer.html" %} - diff --git a/website/src/_includes/layouts/doc.html b/website/src/_includes/layouts/doc.html index 66ec7f022b..091f98bdc7 100644 --- a/website/src/_includes/layouts/doc.html +++ b/website/src/_includes/layouts/doc.html @@ -108,7 +108,7 @@
-
{{ content | applyGlossary | safe }}
+
{{ content | safe }}
@@ -117,7 +117,6 @@ {% include "footer.html" %} - diff --git a/website/src/_includes/layouts/privacy.html b/website/src/_includes/layouts/privacy.html index fcaa9964e3..7527852694 100644 --- a/website/src/_includes/layouts/privacy.html +++ b/website/src/_includes/layouts/privacy.html @@ -33,11 +33,10 @@ {% include "navbar.html" %}
-
{{ content | applyGlossary | safe }}
+
{{ content | safe }}
{% include "footer.html" %} - diff --git a/website/src/css/blog.css b/website/src/css/blog.css index a5d1ae0a1a..897fbafb10 100644 --- a/website/src/css/blog.css +++ b/website/src/css/blog.css @@ -217,10 +217,6 @@ h6 { float: right; margin-left: 3rem; } - - #article .float-right{ - margin-left: 3rem; - } } @media (max-width:768px) { diff --git a/website/src/css/style.css b/website/src/css/style.css index a33c13d9c5..475eddc404 100644 --- a/website/src/css/style.css +++ b/website/src/css/style.css @@ -764,15 +764,14 @@ p a{ } .tooltip-title{ - margin: 0 !important; - margin-bottom: 0.5rem !important; - color: #0197FF !important; - font-weight: 600 !important; - font-size: 1.1rem !important; + margin-bottom: 0.5rem; + color: #0197FF; + font-weight: 600; + font-size: 1.1rem; } .dark .tooltip-title{ - color: #70F0F9 !important; + color: #70F0F9; } .glossary-tooltip .read-more-btn{ @@ -855,18 +854,13 @@ p a{ } .glossary-overlay .overlay-card .overlay-title{ - font-size: 1.875rem !important; - line-height: 2.25rem !important; - font-weight: 700 !important; - margin: 0 !important; - padding: 0 !important; - margin-bottom: 1.5rem !important; - --tw-text-opacity: 1 !important; - color: rgb(1 151 255 / var(--tw-text-opacity)) !important; -} - -.glossary-overlay .overlay-card .overlay-title::after{ - background-color: transparent !important; + font-size: 1.875rem; + line-height: 2.25rem; + font-weight: 700; + margin-bottom: 1rem; + margin-bottom: 1.5rem; + --tw-text-opacity: 1; + color: rgb(1 151 255 / var(--tw-text-opacity)); } .glossary-overlay .overlay-card .overlay-content{ @@ -882,10 +876,6 @@ p a{ color: #fff; } -.glossary-overlay .overlay-card .overlay-content p{ - margin: 0 !important; -} - .close-overlay-btn{ fill: #3F484B; position: fixed; diff --git a/website/src/js/script.js b/website/src/js/script.js index abf7779ad3..5f863f48ee 100644 --- a/website/src/js/script.js +++ b/website/src/js/script.js @@ -1,5 +1,3 @@ -const uniqueSwiperContainer = document.querySelector('.unique-swiper') -if (uniqueSwiperContainer) { const uniqueSwiper = new Swiper('.unique-swiper', { slidesPerView: 1, spaceBetween: 80, @@ -25,15 +23,12 @@ const uniqueSwiper = new Swiper('.unique-swiper', { prevEl: '.unique-swiper-button-prev', }, }); -} const isMobile = { Android: () => navigator.userAgent.match(/Android/i), iOS: () => navigator.userAgent.match(/iPhone|iPad|iPod/i) }; -const privateSwiperContainer = document.querySelector('.private-swiper') -if (privateSwiperContainer) { const privateSwiper = new Swiper('.private-swiper', { slidesPerView: 1, slidesPerGroup: 1, @@ -84,10 +79,7 @@ const privateSwiper = new Swiper('.private-swiper', { } } }); -} -const simplexExplainedSwiperContainer = document.querySelector('.simplex-explained-swiper') -if (simplexExplainedSwiperContainer){ const simplexExplainedSwiper = new Swiper(".simplex-explained-swiper", { slidesPerView: 1, spaceBetween: 80, @@ -120,7 +112,6 @@ const simplexExplainedSwiper = new Swiper(".simplex-explained-swiper", { } } }); -} function closeOverlay(e) { e.target.closest('.overlay').classList.remove('flex'); From e19c14b2490b2cf4a8a14eb3d06df260d66b030a Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Wed, 19 Jun 2024 10:12:22 +0100 Subject: [PATCH 19/23] ios: update core library to 5.8.1 --- apps/ios/SimpleX.xcodeproj/project.pbxproj | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index a1e2eeb66b..e68ec8fc27 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -24,11 +24,6 @@ 5C029EAA283942EA004A9677 /* CallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C029EA9283942EA004A9677 /* CallController.swift */; }; 5C05DF532840AA1D00C683F9 /* CallSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C05DF522840AA1D00C683F9 /* CallSettings.swift */; }; 5C063D2727A4564100AEC577 /* ChatPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C063D2627A4564100AEC577 /* ChatPreviewView.swift */; }; - 5C0EA13B2C0B176B00AD2E5E /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C0EA1362C0B176B00AD2E5E /* libgmp.a */; }; - 5C0EA13C2C0B176B00AD2E5E /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C0EA1372C0B176B00AD2E5E /* libgmpxx.a */; }; - 5C0EA13D2C0B176B00AD2E5E /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C0EA1382C0B176B00AD2E5E /* libffi.a */; }; - 5C0EA13E2C0B176B00AD2E5E /* libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C0EA1392C0B176B00AD2E5E /* libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc-ghc9.6.3.a */; }; - 5C0EA13F2C0B176B00AD2E5E /* libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C0EA13A2C0B176B00AD2E5E /* libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc.a */; }; 5C10D88828EED12E00E58BF0 /* ContactConnectionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C10D88728EED12E00E58BF0 /* ContactConnectionInfo.swift */; }; 5C10D88A28F187F300E58BF0 /* FullScreenMediaView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C10D88928F187F300E58BF0 /* FullScreenMediaView.swift */; }; 5C116CDC27AABE0400E66D01 /* ContactRequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */; }; @@ -197,6 +192,11 @@ D741547A29AF90B00022400A /* PushKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D741547929AF90B00022400A /* PushKit.framework */; }; D77B92DC2952372200A5A1CC /* SwiftyGif in Frameworks */ = {isa = PBXBuildFile; productRef = D77B92DB2952372200A5A1CC /* SwiftyGif */; }; D7F0E33929964E7E0068AF69 /* LZString in Frameworks */ = {isa = PBXBuildFile; productRef = D7F0E33829964E7E0068AF69 /* LZString */; }; + E5D68D3F2C22D78C00CBA347 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5D68D3A2C22D78C00CBA347 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a */; }; + E5D68D402C22D78C00CBA347 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5D68D3B2C22D78C00CBA347 /* libffi.a */; }; + E5D68D412C22D78C00CBA347 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5D68D3C2C22D78C00CBA347 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c-ghc9.6.3.a */; }; + E5D68D422C22D78C00CBA347 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5D68D3D2C22D78C00CBA347 /* libgmp.a */; }; + E5D68D432C22D78C00CBA347 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5D68D3E2C22D78C00CBA347 /* libgmpxx.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -273,11 +273,6 @@ 5C029EA9283942EA004A9677 /* CallController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallController.swift; sourceTree = ""; }; 5C05DF522840AA1D00C683F9 /* CallSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallSettings.swift; sourceTree = ""; }; 5C063D2627A4564100AEC577 /* ChatPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatPreviewView.swift; sourceTree = ""; }; - 5C0EA1362C0B176B00AD2E5E /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; - 5C0EA1372C0B176B00AD2E5E /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; - 5C0EA1382C0B176B00AD2E5E /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - 5C0EA1392C0B176B00AD2E5E /* libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc-ghc9.6.3.a"; sourceTree = ""; }; - 5C0EA13A2C0B176B00AD2E5E /* libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc.a"; sourceTree = ""; }; 5C10D88728EED12E00E58BF0 /* ContactConnectionInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactConnectionInfo.swift; sourceTree = ""; }; 5C10D88928F187F300E58BF0 /* FullScreenMediaView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FullScreenMediaView.swift; sourceTree = ""; }; 5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactRequestView.swift; sourceTree = ""; }; @@ -492,6 +487,11 @@ D741547729AF89AF0022400A /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/StoreKit.framework; sourceTree = DEVELOPER_DIR; }; D741547929AF90B00022400A /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.1.sdk/System/Library/Frameworks/PushKit.framework; sourceTree = DEVELOPER_DIR; }; D7AA2C3429A936B400737B40 /* MediaEncryption.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; name = MediaEncryption.playground; path = Shared/MediaEncryption.playground; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + E5D68D3A2C22D78C00CBA347 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a"; sourceTree = ""; }; + E5D68D3B2C22D78C00CBA347 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; + E5D68D3C2C22D78C00CBA347 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c-ghc9.6.3.a"; sourceTree = ""; }; + E5D68D3D2C22D78C00CBA347 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; + E5D68D3E2C22D78C00CBA347 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -529,13 +529,13 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5C0EA13C2C0B176B00AD2E5E /* libgmpxx.a in Frameworks */, + E5D68D412C22D78C00CBA347 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c-ghc9.6.3.a in Frameworks */, 5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */, - 5C0EA13B2C0B176B00AD2E5E /* libgmp.a in Frameworks */, - 5C0EA13D2C0B176B00AD2E5E /* libffi.a in Frameworks */, - 5C0EA13F2C0B176B00AD2E5E /* libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc.a in Frameworks */, 5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */, - 5C0EA13E2C0B176B00AD2E5E /* libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc-ghc9.6.3.a in Frameworks */, + E5D68D3F2C22D78C00CBA347 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a in Frameworks */, + E5D68D422C22D78C00CBA347 /* libgmp.a in Frameworks */, + E5D68D402C22D78C00CBA347 /* libffi.a in Frameworks */, + E5D68D432C22D78C00CBA347 /* libgmpxx.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -601,11 +601,11 @@ 5C764E5C279C70B7000C6508 /* Libraries */ = { isa = PBXGroup; children = ( - 5C0EA1382C0B176B00AD2E5E /* libffi.a */, - 5C0EA1362C0B176B00AD2E5E /* libgmp.a */, - 5C0EA1372C0B176B00AD2E5E /* libgmpxx.a */, - 5C0EA1392C0B176B00AD2E5E /* libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc-ghc9.6.3.a */, - 5C0EA13A2C0B176B00AD2E5E /* libHSsimplex-chat-5.8.0.5-Idqi6HXqzzs2zrnyZtMyhc.a */, + E5D68D3B2C22D78C00CBA347 /* libffi.a */, + E5D68D3D2C22D78C00CBA347 /* libgmp.a */, + E5D68D3E2C22D78C00CBA347 /* libgmpxx.a */, + E5D68D3C2C22D78C00CBA347 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c-ghc9.6.3.a */, + E5D68D3A2C22D78C00CBA347 /* libHSsimplex-chat-5.8.1.0-GEbUSGuGADZH0bnStuks0c.a */, ); path = Libraries; sourceTree = ""; From 6ba82c8c3989bdbe7a0d9e5fd5d4f0054113f187 Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:49:44 +0400 Subject: [PATCH 20/23] ios: check preferences before forward (#4336) * ios: check preferences before forward * rework * clean up * shorter message --------- Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> --- .../Views/Chat/ChatItemForwardingView.swift | 62 +++++++++++++++---- .../Chat/ComposeMessage/ComposeView.swift | 7 ++- apps/ios/SimpleXChat/ChatTypes.swift | 9 +++ 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift b/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift index 7237711a2a..fd89c7e3ec 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift @@ -19,6 +19,7 @@ struct ChatItemForwardingView: View { @State private var searchText: String = "" @FocusState private var searchFocused + @State private var alert: SomeAlert? = nil var body: some View { NavigationView { @@ -35,6 +36,12 @@ struct ChatItemForwardingView: View { } } } + .alert(item: $alert) { a in + switch a { + case let .someAlert(alert, _): + return alert + } + } } @ViewBuilder private func forwardListView() -> some View { @@ -49,7 +56,7 @@ struct ChatItemForwardingView: View { let chats = s == "" ? chatsToForwardTo : chatsToForwardTo.filter { filterChatSearched($0, s) } ForEach(chats) { chat in Divider() - forwardListNavLinkView(chat) + forwardListChatView(chat) .disabled(chatModel.deletedChats.contains(chat.chatInfo.id)) } } @@ -102,31 +109,62 @@ struct ChatItemForwardingView: View { } } + private func prohibitedByPref(_ chat: Chat) -> Bool { + // preference checks should match checks in compose view + let simplexLinkProhibited = hasSimplexLink && !chat.groupFeatureEnabled(.simplexLinks) + let fileProhibited = (ci.content.msgContent?.isMediaOrFileAttachment ?? false) && !chat.groupFeatureEnabled(.files) + let voiceProhibited = (ci.content.msgContent?.isVoice ?? false) && !chat.chatInfo.featureEnabled(.voice) + return switch chat.chatInfo { + case .direct: voiceProhibited + case .group: simplexLinkProhibited || fileProhibited || voiceProhibited + case .local: false + case .contactRequest: false + case .contactConnection: false + case .invalidJSON: false + } + } + + private var hasSimplexLink: Bool { + guard let mcText = ci.content.msgContent?.text else { return false } + guard let parsedMsg = parseSimpleXMarkdown(mcText) else { return false } + return parsedMsgHasSimplexLink(parsedMsg) + } + private func emptyList() -> some View { Text("No filtered chats") .foregroundColor(.secondary) .frame(maxWidth: .infinity) } - @ViewBuilder private func forwardListNavLinkView(_ chat: Chat) -> some View { + @ViewBuilder private func forwardListChatView(_ chat: Chat) -> some View { Button { - dismiss() - if chat.id == fromChatInfo.id { - composeState = ComposeState( - message: composeState.message, - preview: composeState.linkPreview != nil ? composeState.preview : .noPreview, - contextItem: .forwardingItem(chatItem: ci, fromChatInfo: fromChatInfo) - ) + if prohibitedByPref(chat) { + alert = .someAlert( + alert: mkAlert( + title: "Cannot forward message", + message: "Selected chat preferences prohibit this message." + ), + id: "forward prohibited by preferences" + ) } else { - composeState = ComposeState.init(forwardingItem: ci, fromChatInfo: fromChatInfo) - chatModel.chatId = chat.id + dismiss() + if chat.id == fromChatInfo.id { + composeState = ComposeState( + message: composeState.message, + preview: composeState.linkPreview != nil ? composeState.preview : .noPreview, + contextItem: .forwardingItem(chatItem: ci, fromChatInfo: fromChatInfo) + ) + } else { + composeState = ComposeState.init(forwardingItem: ci, fromChatInfo: fromChatInfo) + chatModel.chatId = chat.id + } } } label: { HStack { ChatInfoImage(chat: chat, size: 30) .padding(.trailing, 2) Text(chat.chatInfo.chatViewName) - .foregroundColor(.primary) + .foregroundColor(prohibitedByPref(chat) ? .secondary : .primary) .lineLimit(1) if chat.chatInfo.incognito { Spacer() diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift index 3f1824cd6a..8a0ad9a023 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/ComposeView.swift @@ -286,6 +286,7 @@ struct ComposeView: View { if chat.chatInfo.contact?.nextSendGrpInv ?? false { ContextInvitingContactMemberView() } + // preference checks should match checks in forwarding list let simplexLinkProhibited = hasSimplexLink && !chat.groupFeatureEnabled(.simplexLinks) let fileProhibited = composeState.attachmentPreview && !chat.groupFeatureEnabled(.files) let voiceProhibited = composeState.voicePreview && !chat.chatInfo.featureEnabled(.voice) @@ -1065,7 +1066,7 @@ struct ComposeView: View { } else { nil } - let simplexLink = parsedMsg.contains(where: { ft in ft.format?.isSimplexLink ?? false }) + let simplexLink = parsedMsgHasSimplexLink(parsedMsg) return (url, simplexLink) } @@ -1105,6 +1106,10 @@ struct ComposeView: View { } } +func parsedMsgHasSimplexLink(_ parsedMsg: [FormattedText]) -> Bool { + parsedMsg.contains(where: { ft in ft.format?.isSimplexLink ?? false }) +} + struct ComposeView_Previews: PreviewProvider { static var previews: some View { let chat = Chat(chatInfo: ChatInfo.sampleData.direct, chatItems: []) diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index 4c62fe4c8b..1f58ee2363 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -3438,6 +3438,15 @@ public enum MsgContent: Equatable { } } + public var isMediaOrFileAttachment: Bool { + switch self { + case .image: true + case .video: true + case .file: true + default: false + } + } + var cmdString: String { "json \(encodeJSON(self))" } From 0fa8d772140001a3ba8e0db775cc8386e1a47fc9 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin Date: Wed, 19 Jun 2024 12:51:56 +0100 Subject: [PATCH 21/23] ios: fix search disappearing in forward view (#4337) * ios: fix search disappearing in forward view * update * diff * refactor * use List --- .../Views/Chat/ChatItemForwardingView.swift | 102 +++++++++--------- .../Shared/Views/NewChat/NewChatView.swift | 23 ++-- 2 files changed, 58 insertions(+), 67 deletions(-) diff --git a/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift b/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift index fd89c7e3ec..f90653534c 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemForwardingView.swift @@ -19,7 +19,9 @@ struct ChatItemForwardingView: View { @State private var searchText: String = "" @FocusState private var searchFocused - @State private var alert: SomeAlert? = nil + @State private var alert: SomeAlert? + @State private var hasSimplexLink_: Bool? + private let chatsToForwardTo = filterChatsToForwardTo() var body: some View { NavigationView { @@ -36,53 +38,29 @@ struct ChatItemForwardingView: View { } } } - .alert(item: $alert) { a in - switch a { - case let .someAlert(alert, _): - return alert - } - } + .alert(item: $alert) { $0.alert } } @ViewBuilder private func forwardListView() -> some View { VStack(alignment: .leading) { - let chatsToForwardTo = filterChatsToForwardTo() if !chatsToForwardTo.isEmpty { - ScrollView { - LazyVStack(alignment: .leading, spacing: 8) { - searchFieldView(text: $searchText, focussed: $searchFocused) - .padding(.leading, 2) - let s = searchText.trimmingCharacters(in: .whitespaces).localizedLowercase - let chats = s == "" ? chatsToForwardTo : chatsToForwardTo.filter { filterChatSearched($0, s) } - ForEach(chats) { chat in - Divider() - forwardListChatView(chat) - .disabled(chatModel.deletedChats.contains(chat.chatInfo.id)) - } + List { + searchFieldView(text: $searchText, focussed: $searchFocused) + .padding(.leading, 2) + let s = searchText.trimmingCharacters(in: .whitespaces).localizedLowercase + let chats = s == "" ? chatsToForwardTo : chatsToForwardTo.filter { foundChat($0, s) } + ForEach(chats) { chat in + forwardListChatView(chat) + .disabled(chatModel.deletedChats.contains(chat.chatInfo.id)) } - .padding(.horizontal) - .padding(.vertical, 8) - .background(Color(uiColor: .systemBackground)) - .cornerRadius(12) - .padding(.horizontal) } - .background(Color(.systemGroupedBackground)) } else { emptyList() } } } - private func filterChatsToForwardTo() -> [Chat] { - var filteredChats = chatModel.chats.filter({ canForwardToChat($0) }) - if let index = filteredChats.firstIndex(where: { $0.chatInfo.chatType == .local }) { - let privateNotes = filteredChats.remove(at: index) - filteredChats.insert(privateNotes, at: 0) - } - return filteredChats - } - - private func filterChatSearched(_ chat: Chat, _ searchStr: String) -> Bool { + private func foundChat(_ chat: Chat, _ searchStr: String) -> Bool { let cInfo = chat.chatInfo return switch cInfo { case let .direct(contact): @@ -98,17 +76,6 @@ struct ChatItemForwardingView: View { } } - private func canForwardToChat(_ chat: Chat) -> Bool { - switch chat.chatInfo { - case let .direct(contact): contact.sendMsgEnabled && !contact.nextSendGrpInv - case let .group(groupInfo): groupInfo.sendMsgEnabled - case let .local(noteFolder): noteFolder.sendMsgEnabled - case .contactRequest: false - case .contactConnection: false - case .invalidJSON: false - } - } - private func prohibitedByPref(_ chat: Chat) -> Bool { // preference checks should match checks in compose view let simplexLinkProhibited = hasSimplexLink && !chat.groupFeatureEnabled(.simplexLinks) @@ -125,9 +92,16 @@ struct ChatItemForwardingView: View { } private var hasSimplexLink: Bool { - guard let mcText = ci.content.msgContent?.text else { return false } - guard let parsedMsg = parseSimpleXMarkdown(mcText) else { return false } - return parsedMsgHasSimplexLink(parsedMsg) + if let hasSimplexLink_ { return hasSimplexLink_ } + let r = + if let mcText = ci.content.msgContent?.text, + let parsedMsg = parseSimpleXMarkdown(mcText) { + parsedMsgHasSimplexLink(parsedMsg) + } else { + false + } + hasSimplexLink_ = r + return r } private func emptyList() -> some View { @@ -135,11 +109,12 @@ struct ChatItemForwardingView: View { .foregroundColor(.secondary) .frame(maxWidth: .infinity) } - + @ViewBuilder private func forwardListChatView(_ chat: Chat) -> some View { + let prohibited = prohibitedByPref(chat) Button { - if prohibitedByPref(chat) { - alert = .someAlert( + if prohibited { + alert = SomeAlert( alert: mkAlert( title: "Cannot forward message", message: "Selected chat preferences prohibit this message." @@ -164,7 +139,7 @@ struct ChatItemForwardingView: View { ChatInfoImage(chat: chat, size: 30) .padding(.trailing, 2) Text(chat.chatInfo.chatViewName) - .foregroundColor(prohibitedByPref(chat) ? .secondary : .primary) + .foregroundColor(prohibited ? .secondary : .primary) .lineLimit(1) if chat.chatInfo.incognito { Spacer() @@ -180,6 +155,27 @@ struct ChatItemForwardingView: View { } } +private func filterChatsToForwardTo() -> [Chat] { + var filteredChats = ChatModel.shared.chats.filter { c in + c.chatInfo.chatType != .local && canForwardToChat(c) + } + if let privateNotes = ChatModel.shared.chats.first(where: { $0.chatInfo.chatType == .local }) { + filteredChats.insert(privateNotes, at: 0) + } + return filteredChats +} + +private func canForwardToChat(_ chat: Chat) -> Bool { + switch chat.chatInfo { + case let .direct(contact): contact.sendMsgEnabled && !contact.nextSendGrpInv + case let .group(groupInfo): groupInfo.sendMsgEnabled + case let .local(noteFolder): noteFolder.sendMsgEnabled + case .contactRequest: false + case .contactConnection: false + case .invalidJSON: false + } +} + #Preview { ChatItemForwardingView( ci: ChatItem.getSample(1, .directSnd, .now, "hello"), diff --git a/apps/ios/Shared/Views/NewChat/NewChatView.swift b/apps/ios/Shared/Views/NewChat/NewChatView.swift index 442f933ace..4b1f72345a 100644 --- a/apps/ios/Shared/Views/NewChat/NewChatView.swift +++ b/apps/ios/Shared/Views/NewChat/NewChatView.swift @@ -11,14 +11,9 @@ import SimpleXChat import CodeScanner import AVFoundation -enum SomeAlert: Identifiable { - case someAlert(alert: Alert, id: String) - - var id: String { - switch self { - case let .someAlert(_, id): return id - } - } +struct SomeAlert: Identifiable { + var alert: Alert + var id: String } private enum NewChatViewAlert: Identifiable { @@ -142,8 +137,8 @@ struct NewChatView: View { switch(a) { case let .planAndConnectAlert(alert): return planAndConnectAlert(alert, dismiss: true, cleanup: { pastedLink = "" }) - case let .newChatSomeAlert(.someAlert(alert, _)): - return alert + case let .newChatSomeAlert(a): + return a.alert } } } @@ -181,7 +176,7 @@ struct NewChatView: View { await MainActor.run { creatingConnReq = false if let apiAlert = apiAlert { - alert = .newChatSomeAlert(alert: .someAlert(alert: apiAlert, id: "createInvitation error")) + alert = .newChatSomeAlert(alert: SomeAlert(alert: apiAlert, id: "createInvitation error")) } } } @@ -315,7 +310,7 @@ private struct ConnectView: View { // showQRCodeScanner = false connect(pastedLink) } else { - alert = .newChatSomeAlert(alert: .someAlert( + alert = .newChatSomeAlert(alert: SomeAlert( alert: mkAlert(title: "Invalid link", message: "The text you pasted is not a SimpleX link."), id: "pasteLinkView: code is not a SimpleX link" )) @@ -338,14 +333,14 @@ private struct ConnectView: View { if strIsSimplexLink(r.string) { connect(link) } else { - alert = .newChatSomeAlert(alert: .someAlert( + alert = .newChatSomeAlert(alert: SomeAlert( alert: mkAlert(title: "Invalid QR code", message: "The code you scanned is not a SimpleX link QR code."), id: "processQRCode: code is not a SimpleX link" )) } case let .failure(e): logger.error("processQRCode QR code error: \(e.localizedDescription)") - alert = .newChatSomeAlert(alert: .someAlert( + alert = .newChatSomeAlert(alert: SomeAlert( alert: mkAlert(title: "Invalid QR code", message: "Error scanning code: \(e.localizedDescription)"), id: "processQRCode: failure" )) From 89e65c2fc138bc6212e06be9667e1ea3ba3170dc Mon Sep 17 00:00:00 2001 From: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com> Date: Wed, 19 Jun 2024 18:53:45 +0400 Subject: [PATCH 22/23] multiplatform: check preferences before share/forward (#4338) --- .../chat/simplex/common/model/ChatModel.kt | 14 +++++ .../views/chatlist/ShareListNavLinkView.kt | 54 +++++++++++++++---- .../common/views/chatlist/ShareListView.kt | 54 +++++++++++++++++-- .../commonMain/resources/MR/base/strings.xml | 2 + 4 files changed, 110 insertions(+), 14 deletions(-) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt index 89af46edb5..0ebe77e524 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt @@ -2925,6 +2925,20 @@ sealed class MsgContent { @Serializable(with = MsgContentSerializer::class) class MCFile(override val text: String): MsgContent() @Serializable(with = MsgContentSerializer::class) class MCUnknown(val type: String? = null, override val text: String, val json: JsonElement): MsgContent() + val isVoice: Boolean get() = + when (this) { + is MCVoice -> true + else -> false + } + + val isMediaOrFileAttachment: Boolean get() = + when (this) { + is MCImage -> true + is MCVideo -> true + is MCFile -> true + else -> false + } + val cmdString: String get() = if (this is MCUnknown) "json $json" else "json ${json.encodeToString(this)}" } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListNavLinkView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListNavLinkView.kt index 1de1e40afb..91dffeb7c8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListNavLinkView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListNavLinkView.kt @@ -9,30 +9,55 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import chat.simplex.common.views.helpers.ProfileImage import chat.simplex.common.model.* import chat.simplex.common.ui.theme.* +import chat.simplex.common.views.helpers.* import chat.simplex.res.MR @Composable -fun ShareListNavLinkView(chat: Chat, chatModel: ChatModel) { +fun ShareListNavLinkView( + chat: Chat, + chatModel: ChatModel, + isMediaOrFileAttachment: Boolean, + isVoice: Boolean, + hasSimplexLink: Boolean +) { val stopped = chatModel.chatRunning.value == false when (chat.chatInfo) { - is ChatInfo.Direct -> + is ChatInfo.Direct -> { + val voiceProhibited = isVoice && !chat.chatInfo.featureEnabled(ChatFeature.Voice) ShareListNavLinkLayout( - chatLinkPreview = { SharePreviewView(chat) }, - click = { directChatAction(chat.remoteHostId, chat.chatInfo.contact, chatModel) }, + chatLinkPreview = { SharePreviewView(chat, disabled = voiceProhibited) }, + click = { + if (voiceProhibited) { + showForwardProhibitedByPrefAlert() + } else { + directChatAction(chat.remoteHostId, chat.chatInfo.contact, chatModel) + } + }, stopped ) - is ChatInfo.Group -> + } + is ChatInfo.Group -> { + val simplexLinkProhibited = hasSimplexLink && !chat.groupFeatureEnabled(GroupFeature.SimplexLinks) + val fileProhibited = isMediaOrFileAttachment && !chat.groupFeatureEnabled(GroupFeature.Files) + val voiceProhibited = isVoice && !chat.chatInfo.featureEnabled(ChatFeature.Voice) + val prohibitedByPref = simplexLinkProhibited || fileProhibited || voiceProhibited ShareListNavLinkLayout( - chatLinkPreview = { SharePreviewView(chat) }, - click = { groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel) }, + chatLinkPreview = { SharePreviewView(chat, disabled = prohibitedByPref) }, + click = { + if (prohibitedByPref) { + showForwardProhibitedByPrefAlert() + } else { + groupChatAction(chat.remoteHostId, chat.chatInfo.groupInfo, chatModel) + } + }, stopped ) + } is ChatInfo.Local -> ShareListNavLinkLayout( - chatLinkPreview = { SharePreviewView(chat) }, + chatLinkPreview = { SharePreviewView(chat, disabled = false) }, click = { noteFolderChatAction(chat.remoteHostId, chat.chatInfo.noteFolder) }, stopped ) @@ -40,6 +65,13 @@ fun ShareListNavLinkView(chat: Chat, chatModel: ChatModel) { } } +private fun showForwardProhibitedByPrefAlert() { + AlertManager.shared.showAlertMsg( + title = generalGetString(MR.strings.cannot_share_message_alert_title), + text = generalGetString(MR.strings.cannot_share_message_alert_text), + ) +} + @Composable private fun ShareListNavLinkLayout( chatLinkPreview: @Composable () -> Unit, @@ -53,7 +85,7 @@ private fun ShareListNavLinkLayout( } @Composable -private fun SharePreviewView(chat: Chat) { +private fun SharePreviewView(chat: Chat, disabled: Boolean) { Row( Modifier.fillMaxSize(), horizontalArrangement = Arrangement.SpaceBetween, @@ -70,7 +102,7 @@ private fun SharePreviewView(chat: Chat) { } Text( chat.chatInfo.chatViewName, maxLines = 1, overflow = TextOverflow.Ellipsis, - color = if (chat.chatInfo.incognito) Indigo else Color.Unspecified + color = if (disabled) MaterialTheme.colors.secondary else if (chat.chatInfo.incognito) Indigo else Color.Unspecified ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListView.kt index a36930f5ce..69382d9fde 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ShareListView.kt @@ -31,13 +31,44 @@ fun ShareListView(chatModel: ChatModel, settingsState: SettingsViewState, stoppe scaffoldState = scaffoldState, topBar = { Column { ShareListToolbar(chatModel, userPickerState, stopped) { searchInList = it.trim() } } }, ) { + val sharedContent = chatModel.sharedContent.value + var isMediaOrFileAttachment = false + var isVoice = false + var hasSimplexLink = false + when (sharedContent) { + is SharedContent.Text -> + hasSimplexLink = hasSimplexLink(sharedContent.text) + is SharedContent.Media -> { + isMediaOrFileAttachment = true + hasSimplexLink = hasSimplexLink(sharedContent.text) + } + is SharedContent.File -> { + isMediaOrFileAttachment = true + hasSimplexLink = hasSimplexLink(sharedContent.text) + } + is SharedContent.Forward -> { + val mc = sharedContent.chatItem.content.msgContent + if (mc != null) { + isMediaOrFileAttachment = mc.isMediaOrFileAttachment + isVoice = mc.isVoice + hasSimplexLink = hasSimplexLink(mc.text) + } + } + null -> {} + } Box(Modifier.padding(it)) { Column( modifier = Modifier .fillMaxSize() ) { if (chatModel.chats.isNotEmpty()) { - ShareList(chatModel, search = searchInList) + ShareList( + chatModel, + search = searchInList, + isMediaOrFileAttachment = isMediaOrFileAttachment, + isVoice = isVoice, + hasSimplexLink = hasSimplexLink + ) } else { EmptyList() } @@ -54,6 +85,11 @@ fun ShareListView(chatModel: ChatModel, settingsState: SettingsViewState, stoppe } } +private fun hasSimplexLink(msg: String): Boolean { + val parsedMsg = parseToMarkdown(msg) ?: return false + return parsedMsg.any { ft -> ft.format is Format.SimplexLink } +} + @Composable private fun EmptyList() { Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { @@ -141,7 +177,13 @@ private fun ShareListToolbar(chatModel: ChatModel, userPickerState: MutableState } @Composable -private fun ShareList(chatModel: ChatModel, search: String) { +private fun ShareList( + chatModel: ChatModel, + search: String, + isMediaOrFileAttachment: Boolean, + isVoice: Boolean, + hasSimplexLink: Boolean +) { val chats by remember(search) { derivedStateOf { val sorted = chatModel.chats.toList().sortedByDescending { it.chatInfo is ChatInfo.Local } @@ -156,7 +198,13 @@ private fun ShareList(chatModel: ChatModel, search: String) { modifier = Modifier.fillMaxWidth() ) { items(chats) { chat -> - ShareListNavLinkView(chat, chatModel) + ShareListNavLinkView( + chat, + chatModel, + isMediaOrFileAttachment = isMediaOrFileAttachment, + isVoice = isVoice, + hasSimplexLink = hasSimplexLink + ) } } } 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 b896c4e980..996ecb11da 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -358,6 +358,8 @@ Share media… Share file… Forward message… + Cannot send message + Selected chat preferences prohibit this message. Attach From 85dc467f74a46b88112bcb20a2b909eb82846923 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Wed, 19 Jun 2024 23:41:23 +0100 Subject: [PATCH 23/23] 5.8.1: ios 225, android 221, desktop 54 --- apps/ios/SimpleX.xcodeproj/project.pbxproj | 24 +++++++++++----------- apps/multiplatform/gradle.properties | 8 ++++---- scripts/android/compress-and-sign-apk.sh | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index e68ec8fc27..8907938f52 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -1552,7 +1552,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 225; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1577,7 +1577,7 @@ "@executable_path/Frameworks", ); LLVM_LTO = YES_THIN; - MARKETING_VERSION = 5.8; + MARKETING_VERSION = 5.8.1; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_NAME = SimpleX; SDKROOT = iphoneos; @@ -1601,7 +1601,7 @@ CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 225; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; @@ -1626,7 +1626,7 @@ "@executable_path/Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.8; + MARKETING_VERSION = 5.8.1; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app; PRODUCT_NAME = SimpleX; SDKROOT = iphoneos; @@ -1687,7 +1687,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 225; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; GCC_OPTIMIZATION_LEVEL = s; @@ -1702,7 +1702,7 @@ "@executable_path/../../Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.8; + MARKETING_VERSION = 5.8.1; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1724,7 +1724,7 @@ CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 225; DEVELOPMENT_TEAM = 5NN7GUYB6T; ENABLE_BITCODE = NO; ENABLE_CODE_COVERAGE = NO; @@ -1739,7 +1739,7 @@ "@executable_path/../../Frameworks", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.8; + MARKETING_VERSION = 5.8.1; PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -1761,7 +1761,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 225; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1787,7 +1787,7 @@ "$(PROJECT_DIR)/Libraries/sim", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.8; + MARKETING_VERSION = 5.8.1; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; @@ -1812,7 +1812,7 @@ CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES; CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 224; + CURRENT_PROJECT_VERSION = 225; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5NN7GUYB6T; DYLIB_COMPATIBILITY_VERSION = 1; @@ -1838,7 +1838,7 @@ "$(PROJECT_DIR)/Libraries/sim", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.8; + MARKETING_VERSION = 5.8.1; PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; diff --git a/apps/multiplatform/gradle.properties b/apps/multiplatform/gradle.properties index 66178aa557..ecf038c8a5 100644 --- a/apps/multiplatform/gradle.properties +++ b/apps/multiplatform/gradle.properties @@ -26,11 +26,11 @@ android.enableJetifier=true kotlin.mpp.androidSourceSetLayoutVersion=2 kotlin.jvm.target=11 -android.version_name=5.8 -android.version_code=219 +android.version_name=5.8.1 +android.version_code=221 -desktop.version_name=5.8 -desktop.version_code=53 +desktop.version_name=5.8.1 +desktop.version_code=54 kotlin.version=1.9.23 gradle.plugin.version=8.2.0 diff --git a/scripts/android/compress-and-sign-apk.sh b/scripts/android/compress-and-sign-apk.sh index e46b8a54f1..74d59203c4 100755 --- a/scripts/android/compress-and-sign-apk.sh +++ b/scripts/android/compress-and-sign-apk.sh @@ -47,7 +47,7 @@ for ORIG_NAME in "${ORIG_NAMES[@]}"; do #(cd apk && 7z a -r -mx=0 -tzip ../$ORIG_NAME resources.arsc) ALL_TOOLS=("$sdk_dir"/build-tools/*/) - BIN_DIR="${ALL_TOOLS[1]}" + BIN_DIR="${ALL_TOOLS[${#ALL_TOOLS[@]}-1]}" "$BIN_DIR"/zipalign -p -f 4 "$ORIG_NAME" "$ORIG_NAME"-2