diff --git a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift index a3e6d2ee2f..4690bf82a8 100644 --- a/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift +++ b/apps/ios/Shared/Views/NewChat/NewChatMenuButton.swift @@ -129,7 +129,7 @@ struct NewChatSheet: View { .modifier(ThemedBackground(grouped: true)) .navigationBarTitleDisplayMode(.large) } label: { - Label("Create public channel (BETA)", systemImage: "antenna.radiowaves.left.and.right") + Label("Create public channel", systemImage: "antenna.radiowaves.left.and.right") } } diff --git a/apps/ios/product/views/new-chat.md b/apps/ios/product/views/new-chat.md index 2ab5f9ba8f..1ab84c098a 100644 --- a/apps/ios/product/views/new-chat.md +++ b/apps/ios/product/views/new-chat.md @@ -81,7 +81,7 @@ Accessed via `NewChatMenuButton` dropdown: ## Create Channel (`AddChannelView`) -Accessed via `NewChatMenuButton` dropdown: "Create channel (BETA)" with antenna icon (`antenna.radiowaves.left.and.right.circle.fill`). +Accessed via `NewChatMenuButton` dropdown: "Create public channel" with antenna icon (`antenna.radiowaves.left.and.right.circle.fill`). ### Three-Step Channel Creation Wizard diff --git a/apps/ios/spec/client/navigation.md b/apps/ios/spec/client/navigation.md index 22985c6fe1..920780cc0f 100644 --- a/apps/ios/spec/client/navigation.md +++ b/apps/ios/spec/client/navigation.md @@ -299,7 +299,7 @@ Migration state (`ChatModel.migrationState != nil`) takes precedence over onboar ### Entry Point -`NewChatMenuButton` includes a NavigationLink "Create channel (BETA)" with antenna icon, navigating to `AddChannelView`. +`NewChatMenuButton` includes a NavigationLink "Create public channel" with antenna icon, navigating to `AddChannelView`. ### Three-Step Wizard diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt index 2419b11c6c..4d97e3a054 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt @@ -201,7 +201,7 @@ private fun ModalData.NewChatSheetLayout( ), Triple( painterResource(MR.images.ic_bigtop_updates), - stringResource(MR.strings.create_channel_beta_button), + stringResource(MR.strings.create_channel_button), createChannel, ) ) diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml index 516b095d3d..ecf6efc8a9 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ar/strings.xml @@ -2577,7 +2577,6 @@ يتصل أنشئ قناة عامة أنشئ قناة عامة - أنشئ قناة عامة (تجريبي) ينشئ قناة %d أحداث القناة فك ترميز الرابط 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 04f87049f0..aac84c7bfe 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml @@ -3104,7 +3104,6 @@ Create public channel Create public channel - Create public channel (BETA) Channel name Creating channel Error creating channel diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml index 81198bef5c..11b2c53765 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/cs/strings.xml @@ -2608,7 +2608,6 @@ Připojení přes odkaz nebo QR kód Vytvořit veřejný kanál Vytvořit veřejný kanál - Vytvořit veřejný kanál (BETA) Vytvořte odkaz Vytvořte si veřejnou adresu Vytvářím kanál diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml index fc19c45391..e58f178796 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/de/strings.xml @@ -2663,7 +2663,6 @@ Verbinde Öffentlichen Kanal erstellen Öffentlichen Kanal erstellen - Öffentlichen Kanal erstellen (BETA) Kanal wird erstellt Link dekodieren Kanal löschen diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml index ebabb20c95..bc3aa165a9 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/es/strings.xml @@ -2600,7 +2600,6 @@ Conexión fallida Crear canal público Crear canal público - Crear canal público (BETA) Creando canal %d eventos del canal Eliminar canal diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml index 7e4319bb9d..6eb41ac5bf 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/hu/strings.xml @@ -2535,7 +2535,6 @@ kapcsolódás Nyilvános csatorna létrehozása Nyilvános csatorna létrehozása - Nyilvános csatorna létrehozása (BÉTA) Csatorna létrehozása törölve sikertelen diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/in/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/in/strings.xml index af40969ba4..db40539996 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/in/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/in/strings.xml @@ -2606,7 +2606,6 @@ Buat halaman web untuk menampilkan pratinjau saluran Anda kepada pengunjung sebelum mereka berlangganan. Anda dapat menghostingnya sendiri atau menggunakan layanan hosting statis apa pun. Buat saluran publik Buat saluran publik - Buat saluran publik (BETA) Buat tautan Anda Buat alamat publik Anda Sedang membuat saluran diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml index fe896c099f..7cc2b79ec6 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/it/strings.xml @@ -2593,7 +2593,6 @@ in connessione Crea canale pubblico Crea canale pubblico - Crea canale pubblico (BETA) Creazione canale Decodifica il link Elimina canale diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml index af51c80196..bc2c1adb97 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ja/strings.xml @@ -2784,7 +2784,6 @@ 全員に対して購読者をブロックしますか? 公開チャンネルを作成 公開チャンネルを作成 - 公開チャンネルを作成(ベータ) チャンネル名 チャンネルを作成中 チャンネルの作成エラー diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml index 350898bc9b..ce35d9d590 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/ru/strings.xml @@ -2648,7 +2648,6 @@ соединяется Создать публичный канал Создать публичный канал - Создать публичный канал (БЕТА) Создание канала %d событий канала Удалить канал diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml index 66d4c14219..3ab01c75eb 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/tr/strings.xml @@ -2615,7 +2615,6 @@ Abone olmadan önce ziyaretçilere kanalınızın önizlemesini göstermek için bir web sayfası oluşturun. Kendiniz barındırın veya herhangi bir statik barındırma kullanın. Herkese açık kanal oluşturun Herkese açık kanal oluşturun - Herkese açık kanal oluşturma (BETA) Adresinizi oluşturun Bağlantınızı oluşturun Herkese açık adresinizi oluşturun diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml index 1b48209724..3b1f427021 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/uk/strings.xml @@ -2628,7 +2628,6 @@ Створіть веб-сторінку, на якій відвідувачам буде показано попередній перегляд вашого каналу ще до того, як вони підпишуться. Розмістіть її на власному хостингу або скористайтеся будь-яким сервісом статичного хостингу. Створити публічний канал Створити публічний канал - Створити публічний канал (BETA) Створити своє посилання Створити свою публічну адресу Канал створюється diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml index 5f8354a5a2..5409bc736c 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rCN/strings.xml @@ -2579,7 +2579,6 @@ 正在连接 创建公开频道 创建公开频道 - 创建公开频道(测试版) 正在创建频道 解码链接 删除频道 diff --git a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml index aff70780e0..11cb52d580 100644 --- a/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml +++ b/apps/multiplatform/common/src/commonMain/resources/MR/zh-rTW/strings.xml @@ -2809,7 +2809,6 @@ 要對全部封鎖訂閱者嗎? 建立公開頻道 建立公開頻道 - 建立公開頻道(BETA) 頻道名稱 正在建立頻道 建立頻道時發生錯誤 diff --git a/packages/simplex-chat-nodejs/src/api.ts b/packages/simplex-chat-nodejs/src/api.ts index 77c87d899b..958304a8ea 100644 --- a/packages/simplex-chat-nodejs/src/api.ts +++ b/packages/simplex-chat-nodejs/src/api.ts @@ -689,7 +689,7 @@ export class ChatApi { * Network usage: interactive. */ async apiConnectPlan(userId: number, connectionLink: string): Promise<[T.ConnectionPlan, T.CreatedConnLink]> { - const r = await this.sendChatCmd(CC.APIConnectPlan.cmdString({userId, connectionLink, resolveKnown: false})) + const r = await this.sendChatCmd(CC.APIConnectPlan.cmdString({userId, connectTarget: connectionLink, resolveMode: T.PlanResolveMode.Unknown})) if (r.type === "connectionPlan") return [r.connectionPlan, r.connLink] throw new ChatCommandError("error getting connect plan", r) } @@ -708,7 +708,7 @@ export class ChatApi { * Network usage: interactive. */ async apiConnectActiveUser(connLink: string): Promise { - const r = await this.sendChatCmd(CC.Connect.cmdString({incognito: false, connLink_: connLink})) + const r = await this.sendChatCmd(CC.Connect.cmdString({incognito: false, connTarget_: connLink})) return this.handleConnectResult(r) } @@ -867,7 +867,7 @@ export class ChatApi { * Network usage: no. */ async apiCreateActiveUser(profile?: T.Profile): Promise { - const r = await this.sendChatCmd(CC.CreateActiveUser.cmdString({newUser: {profile, pastTimestamp: false, userChatRelay: false}})) + const r = await this.sendChatCmd(CC.CreateActiveUser.cmdString({newUser: {profile, pastTimestamp: false, userChatRelay: false, clientService: false}})) if (r.type === "activeUser") return r.user throw new ChatCommandError("unexpected response", r) } diff --git a/packages/simplex-chat-python/src/simplex_chat/api.py b/packages/simplex-chat-python/src/simplex_chat/api.py index e5b885fc17..51de063329 100644 --- a/packages/simplex-chat-python/src/simplex_chat/api.py +++ b/packages/simplex-chat-python/src/simplex_chat/api.py @@ -467,7 +467,7 @@ class ChatApi: ) -> tuple[T.ConnectionPlan, T.CreatedConnLink]: r = await self.send_chat_cmd( CC.APIConnectPlan_cmd_string( - {"userId": user_id, "connectionLink": connection_link, "resolveKnown": False} + {"userId": user_id, "connectTarget": connection_link, "resolveMode": "unknown"} ) ) if r["type"] == "connectionPlan": @@ -488,7 +488,7 @@ class ChatApi: async def api_connect_active_user(self, conn_link: str) -> ConnReqType: r = await self.send_chat_cmd( - CC.Connect_cmd_string({"incognito": False, "connLink_": conn_link}) + CC.Connect_cmd_string({"incognito": False, "connTarget_": conn_link}) ) return self._handle_connect_result(r) @@ -642,7 +642,7 @@ class ChatApi: raise async def api_create_active_user(self, profile: T.Profile | None = None) -> T.User: - new_user: T.NewUser = {"pastTimestamp": False, "userChatRelay": False} + new_user: T.NewUser = {"pastTimestamp": False, "userChatRelay": False, "clientService": False} if profile is not None: new_user["profile"] = profile r = await self.send_chat_cmd(CC.CreateActiveUser_cmd_string({"newUser": new_user})) diff --git a/packages/simplex-chat-python/tests/test_native_cache.py b/packages/simplex-chat-python/tests/test_native_cache.py index 30a1f43e2a..55084eeae8 100644 --- a/packages/simplex-chat-python/tests/test_native_cache.py +++ b/packages/simplex-chat-python/tests/test_native_cache.py @@ -4,6 +4,7 @@ from pathlib import Path import pytest from simplex_chat._native import _cache_root, _resolve_libs_dir, _download +from simplex_chat._version import LIBS_VERSION def test_cache_root_linux(tmp_path, monkeypatch): @@ -41,7 +42,7 @@ def test_resolve_downloads_when_missing(tmp_path, monkeypatch): monkeypatch.setattr("simplex_chat._native._download", fake_download) libs_dir = _resolve_libs_dir("sqlite") - assert libs_dir == tmp_path / "simplex-chat" / "v6.5.2" / "sqlite" + assert libs_dir == tmp_path / "simplex-chat" / f"v{LIBS_VERSION}" / "sqlite" assert called["backend"] == "sqlite" assert (libs_dir / "libsimplex.so").exists() @@ -49,7 +50,7 @@ def test_resolve_downloads_when_missing(tmp_path, monkeypatch): def test_resolve_uses_cache_on_second_call(tmp_path, monkeypatch): monkeypatch.setenv("XDG_CACHE_HOME", str(tmp_path)) monkeypatch.setattr("sys.platform", "linux") - cached = tmp_path / "simplex-chat" / "v6.5.2" / "sqlite" + cached = tmp_path / "simplex-chat" / f"v{LIBS_VERSION}" / "sqlite" cached.mkdir(parents=True) (cached / "libsimplex.so").touch() # Should NOT call _download — use the cached file. diff --git a/packages/simplex-chat-python/tests/test_native_url.py b/packages/simplex-chat-python/tests/test_native_url.py index b27c3e09cf..df96fff8ae 100644 --- a/packages/simplex-chat-python/tests/test_native_url.py +++ b/packages/simplex-chat-python/tests/test_native_url.py @@ -1,6 +1,7 @@ from unittest.mock import patch import pytest from simplex_chat._native import _platform_tag, _libs_url, _libname +from simplex_chat._version import LIBS_VERSION @patch("sys.platform", "linux") @@ -42,7 +43,7 @@ def test_url_sqlite(_): assert ( _libs_url("sqlite") == "https://github.com/simplex-chat/simplex-chat-libs/releases/download/" - "v6.5.2/simplex-chat-libs-linux-x86_64.zip" + f"v{LIBS_VERSION}/simplex-chat-libs-linux-x86_64.zip" ) @@ -51,5 +52,5 @@ def test_url_postgres(_): assert ( _libs_url("postgres") == "https://github.com/simplex-chat/simplex-chat-libs/releases/download/" - "v6.5.2/simplex-chat-libs-linux-x86_64-postgres.zip" + f"v{LIBS_VERSION}/simplex-chat-libs-linux-x86_64-postgres.zip" ) diff --git a/src/Simplex/Chat/Library/Internal.hs b/src/Simplex/Chat/Library/Internal.hs index e6787f818b..52b2824728 100644 --- a/src/Simplex/Chat/Library/Internal.hs +++ b/src/Simplex/Chat/Library/Internal.hs @@ -2996,9 +2996,12 @@ createContactsFeatureItems user cts chatDir ciFeature ciOffer getPref = do cup = getContactUserPreference f cups cup' = getContactUserPreference f cups' +groupFeatures :: GroupInfo -> [AGroupFeature] +groupFeatures g = if useRelays' g then channelGroupFeatures else allGroupFeatures + createGroupFeatureChangedItems :: MsgDirectionI d => User -> ChatDirection 'CTGroup d -> (GroupFeature -> GroupPreference -> Maybe Int -> Maybe GroupMemberRole -> CIContent d) -> GroupInfo -> GroupInfo -> CM () -createGroupFeatureChangedItems user cd ciContent GroupInfo {fullGroupPreferences = gps} GroupInfo {fullGroupPreferences = gps'} = - forM_ allGroupFeatures $ \(AGF f) -> do +createGroupFeatureChangedItems user cd ciContent GroupInfo {fullGroupPreferences = gps} g'@GroupInfo {fullGroupPreferences = gps'} = + forM_ (groupFeatures g') $ \(AGF f) -> do let state = groupFeatureState $ getGroupPreference f gps pref' = getGroupPreference f gps' state'@(_, param', role') = groupFeatureState pref' @@ -3012,8 +3015,8 @@ createGroupFeatureItems :: MsgDirectionI d => User -> ChatDirection 'CTGroup d - createGroupFeatureItems user cd ciContent g = createGroupFeatureItems_ user cd False ciContent g >>= toView . CEvtNewChatItems user createGroupFeatureItems_ :: MsgDirectionI d => User -> ChatDirection 'CTGroup d -> ShowGroupAsSender -> (GroupFeature -> GroupPreference -> Maybe Int -> Maybe GroupMemberRole -> CIContent d) -> GroupInfo -> CM [AChatItem] -createGroupFeatureItems_ user cd showGroupAsSender ciContent GroupInfo {fullGroupPreferences} = - forM allGroupFeatures $ \(AGF f) -> do +createGroupFeatureItems_ user cd showGroupAsSender ciContent g@GroupInfo {fullGroupPreferences} = + forM (groupFeatures g) $ \(AGF f) -> do let p = getGroupPreference f fullGroupPreferences (_, param, role) = groupFeatureState p createChatItem user cd showGroupAsSender (ciContent (toGroupFeature f) (toGroupPreference p) param role) Nothing Nothing Nothing diff --git a/src/Simplex/Chat/Types/Preferences.hs b/src/Simplex/Chat/Types/Preferences.hs index be189379c9..64eaab2a4e 100644 --- a/src/Simplex/Chat/Types/Preferences.hs +++ b/src/Simplex/Chat/Types/Preferences.hs @@ -236,11 +236,8 @@ groupFeatureMemberAllowed' feature role prefs = let pref = getGroupPreference feature prefs in getField @"enable" pref == FEOn && maybe True (role >=) (getField @"role" pref) --- TODO: some preferences are channel-only (e.g., comments) and should not generate --- UI items or be configurable in regular groups. Currently they are simply excluded --- from this list. When more channel-only or group-only preferences are added, --- consider adding a scope property to GroupFeatureI (e.g., GFScopeAll | GFScopeChannel | GFScopeGroup) --- and filtering at the call sites in createGroupFeatureItems_ / createGroupFeatureChangedItems. +-- Sessions and comments are channel-only features not shown in any client yet, +-- so they are omitted from generated feature items entirely. allGroupFeatures :: [AGroupFeature] allGroupFeatures = [ AGF SGFTimedMessages, @@ -255,6 +252,26 @@ allGroupFeatures = AGF SGFSupport ] +-- Channels (public groups) show a subset of group features. Direct messages, voice, +-- files, SimpleX links and member reports are group-only and excluded in channels. +channelGroupFeatures :: [AGroupFeature] +channelGroupFeatures = filter (\(AGF f) -> groupFeatureInChannel (toGroupFeature f)) allGroupFeatures + +groupFeatureInChannel :: GroupFeature -> Bool +groupFeatureInChannel = \case + GFTimedMessages -> True + GFDirectMessages -> False + GFFullDelete -> True + GFReactions -> True + GFVoice -> False + GFFiles -> False + GFSimplexLinks -> False + GFReports -> False + GFHistory -> True + GFSupport -> True + GFSessions -> False + GFComments -> False + groupPrefSel :: SGroupFeature f -> GroupPreferences -> Maybe (GroupFeaturePreference f) groupPrefSel f GroupPreferences {timedMessages, directMessages, fullDelete, reactions, voice, files, simplexLinks, reports, history, support, sessions, comments} = case f of SGFTimedMessages -> timedMessages diff --git a/tests/ChatTests/Utils.hs b/tests/ChatTests/Utils.hs index a613a13df6..12511ea53b 100644 --- a/tests/ChatTests/Utils.hs +++ b/tests/ChatTests/Utils.hs @@ -312,17 +312,16 @@ groupFeatures'' dir = ((1, "chat banner"), Nothing, Nothing) : ((dir, e2eeInfoNo groupFeatures_ :: Int -> Bool -> [((Int, String), Maybe (Int, String), Maybe String)] groupFeatures_ dir isChannel = - [ ((dir, "Disappearing messages: off"), Nothing, Nothing), - ((dir, "Direct messages: on"), Nothing, Nothing), - ((dir, "Full deletion: off"), Nothing, Nothing), - ((dir, "Message reactions: on"), Nothing, Nothing), - ((dir, "Voice messages: on"), Nothing, Nothing), - ((dir, "Files and media: on"), Nothing, Nothing), - ((dir, "SimpleX links: on"), Nothing, Nothing), - ((dir, "Member reports: on"), Nothing, Nothing), - ((dir, "Recent history: on"), Nothing, Nothing), - ((dir, "Chat with admins: " <> (if isChannel then "off" else "on")), Nothing, Nothing) - ] + [((dir, "Disappearing messages: off"), Nothing, Nothing)] + <> [((dir, "Direct messages: on"), Nothing, Nothing) | not isChannel] + <> [((dir, "Full deletion: off"), Nothing, Nothing)] + <> [((dir, "Message reactions: on"), Nothing, Nothing)] + <> [((dir, "Voice messages: on"), Nothing, Nothing) | not isChannel] + <> [((dir, "Files and media: on"), Nothing, Nothing) | not isChannel] + <> [((dir, "SimpleX links: on"), Nothing, Nothing) | not isChannel] + <> [((dir, "Member reports: on"), Nothing, Nothing) | not isChannel] + <> [((dir, "Recent history: on"), Nothing, Nothing)] + <> [((dir, "Chat with admins: " <> (if isChannel then "off" else "on")), Nothing, Nothing)] businessGroupFeatures :: [(Int, String)] businessGroupFeatures = map (\(a, _, _) -> a) $ businessGroupFeatures'' 0 diff --git a/website/src/credits/whitepaper.pdf b/website/src/credits/whitepaper.pdf index fb278b4b5c..7742e65601 100644 Binary files a/website/src/credits/whitepaper.pdf and b/website/src/credits/whitepaper.pdf differ