diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index c977f5709c..ef37f26097 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -2319,6 +2319,9 @@ SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; + EXPORTED_SYMBOLS_FILE = "$(PROJECT_DIR)/SimpleXChat/exported_symbols.txt"; + STRIP_INSTALLED_PRODUCT = YES; + STRIP_STYLE = "non-global"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; diff --git a/apps/ios/SimpleXChat/exported_symbols.txt b/apps/ios/SimpleXChat/exported_symbols.txt new file mode 100644 index 0000000000..52c3bf83e9 --- /dev/null +++ b/apps/ios/SimpleXChat/exported_symbols.txt @@ -0,0 +1,11 @@ +# Swift mangled symbols (Swift 5+ ABI stable prefix) +_$s* + +# ObjC class/metaclass symbols (for NSObject subclasses) +_OBJC_CLASS_$_* +_OBJC_METACLASS_$_* + +# C API (SimpleX.h bridging header) +_chat_* +_haskell_init* +_hs_init* diff --git a/apps/multiplatform/build.gradle.kts b/apps/multiplatform/build.gradle.kts index a0cd35b3ca..a2e1eb07c3 100644 --- a/apps/multiplatform/build.gradle.kts +++ b/apps/multiplatform/build.gradle.kts @@ -68,7 +68,6 @@ allprojects { repositories { google() mavenCentral() - maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") maven("https://oss.sonatype.org/content/repositories/snapshots") maven("https://jitpack.io") } diff --git a/apps/multiplatform/settings.gradle.kts b/apps/multiplatform/settings.gradle.kts index 40446f1958..50a50d531d 100644 --- a/apps/multiplatform/settings.gradle.kts +++ b/apps/multiplatform/settings.gradle.kts @@ -3,7 +3,6 @@ pluginManagement { google() gradlePluginPortal() mavenCentral() - maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") } plugins { diff --git a/flake.nix b/flake.nix index c130e1a1fd..43f4e8912a 100644 --- a/flake.nix +++ b/flake.nix @@ -93,6 +93,7 @@ for pkg in $out/_pkg/*.a; do chmod +w $pkg ${mac2ios.packages.${system}.mac2ios}/bin/mac2ios $pkg + [[ "$pkg" == *simplex-chat* ]] && ${pkgs.stdenv.cc.targetPrefix}strip -x $pkg chmod -w $pkg done diff --git a/src/Simplex/Chat/Library/Internal.hs b/src/Simplex/Chat/Library/Internal.hs index d6e606b696..6f867ab0f1 100644 --- a/src/Simplex/Chat/Library/Internal.hs +++ b/src/Simplex/Chat/Library/Internal.hs @@ -1328,16 +1328,17 @@ updatePublicGroupData user gInfo -- TODO [relays] owner: set owners on updating link data (multi-owner) groupLinkData :: GroupInfo -> GroupLink -> [GroupRelay] -> (UserConnLinkData 'CMContact, CRClientData) -groupLinkData gInfo@GroupInfo {groupProfile, groupKeys, membership = GroupMember {memberId}, groupSummary = GroupSummary {publicMemberCount}} GroupLink {groupLinkId} groupRelays = +groupLinkData gInfo@GroupInfo {groupProfile, groupSummary = GroupSummary {publicMemberCount}, membership = GroupMember {memberId}, groupKeys} GroupLink {groupLinkId} groupRelays = let direct = not $ useRelays' gInfo relays = mapMaybe (\GroupRelay {relayLink} -> relayLink) groupRelays publicGroupData_ = PublicGroupData <$> publicMemberCount userData = encodeShortLinkData $ GroupShortLinkData {groupProfile, publicGroupData = publicGroupData_} owners = case groupKeys of Just GroupKeys {groupRootKey = GRKPrivate rootPrivKey, memberPrivKey} -> - let ownerPubKey = C.publicKey memberPrivKey - authOwnerSig = C.sign' rootPrivKey $ unMemberId memberId <> C.encodePubKey ownerPubKey - in [OwnerAuth {ownerId = unMemberId memberId, ownerKey = ownerPubKey, authOwnerSig}] + let ownerId = unMemberId memberId + ownerKey = C.publicKey memberPrivKey + authOwnerSig = C.sign' rootPrivKey (ownerId <> C.encodePubKey ownerKey) + in [OwnerAuth {ownerId, ownerKey, authOwnerSig}] _ -> [] userLinkData = UserContactLinkData UserContactData {direct, owners, relays, userData} crClientData = encodeJSON $ CRDataGroup groupLinkId diff --git a/tests/ChatTests/Groups.hs b/tests/ChatTests/Groups.hs index aedbb5e1e9..0685d609e6 100644 --- a/tests/ChatTests/Groups.hs +++ b/tests/ChatTests/Groups.hs @@ -253,6 +253,7 @@ chatGroupTests = do it "should update channel profile (signed)" testChannelUpdateProfileSigned it "should preserve working link after profile update" testChannelLinkAfterProfileUpdate it "should preserve working link after welcome message update" testChannelLinkAfterWelcomeUpdate + it "should preserve owner key in link data after profile update" testChannelOwnerKeyAfterLinkUpdate it "should update channel preferences (signed)" testChannelUpdatePrefsSigned it "should change member role (signed)" testChannelChangeRoleSigned it "should block member for all (signed)" testChannelBlockMemberSigned @@ -8844,6 +8845,56 @@ testChannelLinkAfterWelcomeUpdate ps = bob <# "#team> hi" [cath, dan] *<# "#team> hi [>>]" +testChannelOwnerKeyAfterLinkUpdate :: HasCallStack => TestParams -> IO () +testChannelOwnerKeyAfterLinkUpdate ps = + withNewTestChat ps "alice" aliceProfile $ \alice -> + withNewTestChatOpts ps relayTestOpts "bob" bobProfile $ \bob -> + withNewTestChat ps "cath" cathProfile $ \cath -> + withNewTestChat ps "dan" danProfile $ \dan -> do + (shortLink, fullLink) <- prepareChannel1Relay "team" alice bob + memberJoinChannel "team" [bob] [alice] shortLink fullLink cath + + -- Owner updates channel profile - triggers rebuilding link data. + alice ##> "/gp team my_team My team description" + alice <## "changed to #my_team (My team description)" + concurrentlyN_ + [ do + bob <## "alice updated group #team: (signed)" + bob <## "changed to #my_team (My team description)", + do + cath <## "alice updated group #team: (signed)" + cath <## "changed to #my_team (My team description)" + ] + + threadDelay 100000 + + -- Late subscriber joins via the same channel link after profile update. + alice ##> "/show link #my_team" + (shortLink', fullLink') <- getGroupLinks alice "my_team" GRMember False + shortLink' `shouldBe` shortLink + fullLink' `shouldBe` fullLink + memberJoinChannel "my_team" [bob] [alice] shortLink' fullLink' dan + + -- Verify owner member record in late subscriber's DB has a public key. + ownerKeyPresent <- withCCTransaction dan $ \db -> + DB.query_ db "SELECT COUNT(1) FROM group_members WHERE member_role = 'owner' AND member_pub_key IS NOT NULL" :: IO [[Int]] + ownerKeyPresent `shouldBe` [[1]] + + -- Verify signed event is received by late subscriber. + alice ##> "/gp my_team team" + alice <## "changed to #team" + concurrentlyN_ + [ do + bob <## "alice updated group #my_team: (signed)" + bob <## "changed to #team", + do + cath <## "alice updated group #my_team: (signed)" + cath <## "changed to #team", + do + dan <## "alice updated group #my_team: (signed)" + dan <## "changed to #team" + ] + testChannelUpdatePrefsSigned :: HasCallStack => TestParams -> IO () testChannelUpdatePrefsSigned ps = withNewTestChat ps "alice" aliceProfile $ \alice -> diff --git a/website/src/css/design3.css b/website/src/css/design3.css index ba81d6da4a..5e5be66c2f 100644 --- a/website/src/css/design3.css +++ b/website/src/css/design3.css @@ -216,6 +216,9 @@ html { font-family: GT-Walsheim, Gilroy, Helvetica, sans-serif; } +body { + overflow-x: hidden; +} .dark html, .dark body { @@ -691,7 +694,7 @@ main .section-bg { font-size: calc(var(--sec-vwu) * 1.5); color: #333333; /* Isometric projection: rotate then skew */ - transform: rotate(-30deg) skewX(30.6deg); + transform: rotate(-30deg) skewX(30.6deg) translateX(-50%); transform-origin: 0 0; } @@ -699,10 +702,10 @@ main .section-bg { color: #ffffff; } -.roadmap-label-now { left: 46.54%; top: 88.16%; } -.roadmap-label-1 { left: 59.5%; top: 75.0%; } -.roadmap-label-2 { left: 72.5%; top: 61.8%; } -.roadmap-label-3 { left: 85.5%; top: 48.5%; } +.roadmap-label-now { left: 47.84%; top: 86.87%; } +.roadmap-label-1 { left: 60.8%; top: 73.7%; } +.roadmap-label-2 { left: 73.8%; top: 60.5%; } +.roadmap-label-3 { left: 86.8%; top: 47.2%; } .dark .page-5 { diff --git a/website/src/img/design_3/section-3-desktop.webp b/website/src/img/design_3/section-3-desktop.webp index 3e8305f83f..1a002a52a7 100644 Binary files a/website/src/img/design_3/section-3-desktop.webp and b/website/src/img/design_3/section-3-desktop.webp differ diff --git a/website/src/img/design_3/section-3-mobile.webp b/website/src/img/design_3/section-3-mobile.webp index 30ea2d0ef6..df983644b5 100644 Binary files a/website/src/img/design_3/section-3-mobile.webp and b/website/src/img/design_3/section-3-mobile.webp differ