diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 06afe8941..bcfae2e8c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -167,9 +167,7 @@ jobs: if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'macos-latest' shell: bash run: | - scripts/desktop/build-lib-mac.sh - cd apps/multiplatform - ./gradlew packageDmg + scripts/desktop/build-desktop-mac-ci.sh echo "::set-output name=package_path::$(echo $PWD/release/main/dmg/SimpleX-*.dmg)" - name: Linux upload desktop package to release diff --git a/apps/multiplatform/build.gradle.kts b/apps/multiplatform/build.gradle.kts index bd5da47a1..5e0ae5eb4 100644 --- a/apps/multiplatform/build.gradle.kts +++ b/apps/multiplatform/build.gradle.kts @@ -1,6 +1,5 @@ -import org.gradle.initialization.Environment.Properties import java.io.File -import java.io.FileInputStream +import java.util.* buildscript { val prop = java.util.Properties().apply { @@ -26,6 +25,17 @@ buildscript { extra.set("compression.level", (prop["compression.level"] as String?)?.toIntOrNull() ?: 0) // NOTE: If you need a different version of something, provide it in `local.properties` // like so: compose.version=123, or gradle.plugin.version=1.2.3, etc + + + /** Mac signing and notarization */ + // You can specify `compose.desktop.mac.*` keys and values from the right side of the command in `$HOME/.gradle/gradle.properties`. + // This will be project-independent setup without requiring to have `local.properties` file + extra.set("desktop.mac.signing.identity", prop["desktop.mac.signing.identity"] ?: extra["compose.desktop.mac.signing.identity"]) + extra.set("desktop.mac.signing.keychain", prop["desktop.mac.signing.keychain"] ?: extra["compose.desktop.mac.signing.keychain"]) + extra.set("desktop.mac.notarization.apple_id", prop["desktop.mac.notarization.apple_id"] ?: extra["compose.desktop.mac.notarization.appleID"]) + extra.set("desktop.mac.notarization.password", prop["desktop.mac.notarization.password"] ?: extra["compose.desktop.mac.notarization.password"]) + extra.set("desktop.mac.notarization.team_id", prop["desktop.mac.notarization.team_id"] ?: extra["compose.desktop.mac.notarization.ascProvider"]) + repositories { google() mavenCentral() diff --git a/apps/multiplatform/desktop/build.gradle.kts b/apps/multiplatform/desktop/build.gradle.kts index 1d463a9de..dc4aa89fb 100644 --- a/apps/multiplatform/desktop/build.gradle.kts +++ b/apps/multiplatform/desktop/build.gradle.kts @@ -65,6 +65,23 @@ compose { iconFile.set(project.file("src/jvmMain/resources/distribute/simplex.icns")) appCategory = "public.app-category.social-networking" bundleID = "chat.simplex.app" + val identity = rootProject.extra["desktop.mac.signing.identity"] as String? + val keychain = rootProject.extra["desktop.mac.signing.keychain"] as String? + val appleId = rootProject.extra["desktop.mac.notarization.apple_id"] as String? + val password = rootProject.extra["desktop.mac.notarization.password"] as String? + val teamId = rootProject.extra["desktop.mac.notarization.team_id"] as String? + if (identity != null && keychain != null && appleId != null && password != null) { + signing { + sign.set(true) + this.identity.set(identity) + this.keychain.set(keychain) + } + notarization { + this.appleID.set(appleId) + this.password.set(password) + this.ascProvider.set(teamId) + } + } } val os = System.getProperty("os.name", "generic").toLowerCaseAsciiOnly() if (os.contains("mac") || os.contains("win")) { diff --git a/apps/multiplatform/local.properties.example b/apps/multiplatform/local.properties.example new file mode 100644 index 000000000..8fa9a4796 --- /dev/null +++ b/apps/multiplatform/local.properties.example @@ -0,0 +1,10 @@ +compression.level=0 +enable_debuggable=true +application_id.suffix=.debug +app.name=SimpleX Debug + +#desktop.mac.signing.identity=SimpleX Chat Ltd +#desktop.mac.signing.keychain=/path/to/simplex.keychain +#desktop.mac.notarization.apple_id=example@example.com +#desktop.mac.notarization.password=12345678 +#desktop.mac.notarization.team_id=XXXXXXXXXX diff --git a/cabal.project b/cabal.project index ce3867fca..84969148a 100644 --- a/cabal.project +++ b/cabal.project @@ -9,7 +9,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: ed0542822749a871d00ac028582ec45a256ba53c + tag: dc65197cfd1276a28bbc542d78c761eb68742186 source-repository-package type: git diff --git a/docs/rfcs/2023-08-26-ios-notifications.md b/docs/rfcs/2023-08-26-ios-notifications.md new file mode 100644 index 000000000..74ee58932 --- /dev/null +++ b/docs/rfcs/2023-08-26-ios-notifications.md @@ -0,0 +1,26 @@ +# Problem + +iOS notifications are not stable, and crash in the background for many users. The reason for that is concurrent database access from the main app and from NSE processes. While there are measures preventing NSE execution while the main app is running, there is nothing preventing continued NSE execution after the app returns to the foreground. + +While iOS creates a new instance of the notification service class for each incoming mutable notification, it re-uses the same process. + +In addition to that, while NSE avoids subscribing to the existing connections to avoid disrupting the subscriptions from the main app, it can create new connections, specifically for legacy file transfers (not important) and for member connections (very important), so the NSE may continue receiving the messages from these new connections, creating database contention, and at the same time the main app won't subscribe to these connections until it is restarted. + +# Possible solutions + +We could consider using WAL mode to increase SQLite concurrency, but it means that WAL files have to be included in the database archive, which is currently not done. It is unclear if it can only be one or multiple files. + +We should also consider some mechanism of suspending NSE when the app returns to the foreground, e.g. via: +- checking the shared preference in message reception loop, although it may be too late to prevent the database contention. +- checking the shared preference frequently and suspending the core, but it can be expensive. +- using Mach messages to communicate to NSE that app is resumed so it can suspend itself. + +The problem with connection subscriptions can be addressed in this way: + +1. Any connections created in NSE will use additional parameter in all APIs to avoid creating subscriptions. +2. The information about these connections will be stored in the database as "requiring subscription". +3. The main app will subscribe to them when it is resumed. + +This is similar to how XFTP files are marked as "to be received" when the message is received by NSE. + +If this is agreed, then this require changing the whole stack, including SMP protocol, as currently the subscription is done automatically when the connection is created. diff --git a/package.yaml b/package.yaml index cd74b83cf..9d6ae07fd 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: simplex-chat -version: 5.3.0.5 +version: 5.3.0.6 #synopsis: #description: homepage: https://github.com/simplex-chat/simplex-chat#readme diff --git a/scripts/desktop/build-desktop-mac-ci.sh b/scripts/desktop/build-desktop-mac-ci.sh new file mode 100755 index 000000000..d11dfccb5 --- /dev/null +++ b/scripts/desktop/build-desktop-mac-ci.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -e + +trap "rm apps/multiplatform/local.properties; rm /tmp/simplex.keychain" EXIT +echo "desktop.mac.signing.identity=Developer ID Application: SimpleX Chat Ltd (5NN7GUYB6T)" >> apps/multiplatform/local.properties +echo "desktop.mac.signing.keychain=/tmp/simplex.keychain" >> apps/multiplatform/local.properties +echo "desktop.mac.notarization.apple_id=$APPLE_SIMPLEX_NOTARIZATION_APPLE_ID" >> apps/multiplatform/local.properties +echo "desktop.mac.notarization.password=$APPLE_SIMPLEX_NOTARIZATION_PASSWORD" >> apps/multiplatform/local.properties +echo "desktop.mac.notarization.team_id=5NN7GUYB6T" >> apps/multiplatform/local.properties +echo "$APPLE_SIMPLEX_SIGNING_KEYCHAIN" | base64 --decode - > /tmp/simplex.keychain + +scripts/desktop/build-lib-mac.sh +cd apps/multiplatform +./gradlew packageDmg +./gradlew notarizeDmg diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 01feb32b3..0d1bde019 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."ed0542822749a871d00ac028582ec45a256ba53c" = "13lk8vkwiv2c37ab6q6myyh3cbnjmiircjyd2llz7fc03gp9qzzh"; + "https://github.com/simplex-chat/simplexmq.git"."dc65197cfd1276a28bbc542d78c761eb68742186" = "06n1hhvgwi16byw3wwglmgii5yk5wlmr5qc1is6cvnj5pgyvv7qk"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/kazu-yamamoto/http2.git"."b5a1b7200cf5bc7044af34ba325284271f6dff25" = "0dqb50j57an64nf4qcf5vcz4xkd1vzvghvf8bk529c1k30r9nfzb"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "0kiwhvml42g9anw4d2v0zd1fpc790pj9syg5x3ik4l97fnkbbwpp"; diff --git a/simplex-chat.cabal b/simplex-chat.cabal index a970777d8..8cb3ee466 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.3.0.5 +version: 5.3.0.6 category: Web, System, Services, Cryptography homepage: https://github.com/simplex-chat/simplex-chat#readme author: simplex.chat diff --git a/stack.yaml b/stack.yaml index 656ebff6c..ddfd26c28 100644 --- a/stack.yaml +++ b/stack.yaml @@ -49,7 +49,7 @@ extra-deps: # - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561 # - ../simplexmq - github: simplex-chat/simplexmq - commit: ed0542822749a871d00ac028582ec45a256ba53c + commit: dc65197cfd1276a28bbc542d78c761eb68742186 - github: kazu-yamamoto/http2 commit: b5a1b7200cf5bc7044af34ba325284271f6dff25 # - ../direct-sqlcipher