diff --git a/README.md b/README.md index d4103fd10..66465926d 100644 --- a/README.md +++ b/README.md @@ -119,19 +119,22 @@ Join our translators to help SimpleX grow! |locale|language |contributor|[Android](https://play.google.com/store/apps/details?id=chat.simplex.app) and [iOS](https://apps.apple.com/us/app/simplex-chat/id1605771084)|[website](https://simplex.chat)|Github docs| |:----:|:-------:|:---------:|:---------:|:---------:|:---------:| |🇬🇧 en|English | |✓|✓|✓|✓| -|ar|العربية |[jermanuts](https://github.com/jermanuts)||[![website](https://hosted.weblate.org/widgets/simplex-chat/ar/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/ar/)|| -|🇧🇬 bg|Български |-|[![android app](https://hosted.weblate.org/widgets/simplex-chat/bg/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/bg/)
-||| +|ar|العربية |[jermanuts](https://github.com/jermanuts)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/ar/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/ar/)
-|[![website](https://hosted.weblate.org/widgets/simplex-chat/ar/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/ar/)|| +|🇧🇬 bg|Български | |[![android app](https://hosted.weblate.org/widgets/simplex-chat/bg/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/bg/)
[![ios app](https://hosted.weblate.org/widget/simplex-chat/ios/bg/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/bg/)||| |🇨🇿 cs|Čeština |[zen0bit](https://github.com/zen0bit)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/cs/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/cs/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/cs/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/cs/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/cs/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/cs/)|[✓](https://github.com/simplex-chat/simplex-chat/tree/master/docs/lang/cs)| |🇩🇪 de|Deutsch |[mlanp](https://github.com/mlanp)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/de/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/de/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/de/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/de/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/de/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/de/)|| |🇪🇸 es|Español |[Mateyhv](https://github.com/Mateyhv)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/es/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/es/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/es/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/es/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/es/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/es/)|| +|🇫🇮 fi|Suomi | |[![android app](https://hosted.weblate.org/widgets/simplex-chat/fi/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/fi/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/fi/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/fi/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/fi/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/fi/)|| |🇫🇷 fr|Français |[ishi_sama](https://github.com/ishi-sama)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/fr/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/fr/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/fr/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/fr/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/fr/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/fr/)|[✓](https://github.com/simplex-chat/simplex-chat/tree/master/docs/lang/fr)| +|🇮🇱 he|עִברִית | |[![android app](https://hosted.weblate.org/widgets/simplex-chat/he/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/he/)
-||| |🇮🇹 it|Italiano |[unbranched](https://github.com/unbranched)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/it/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/it/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/it/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/it/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/it/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/it/)|| -|🇯🇵 ja|Japanese ||[![android app](https://hosted.weblate.org/widgets/simplex-chat/ja/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/ja/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/ja/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/ja/)||| +|🇯🇵 ja|日本語 | |[![android app](https://hosted.weblate.org/widgets/simplex-chat/ja/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/ja/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/ja/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/ja/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/ja/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/ja/)|| |🇳🇱 nl|Nederlands|[mika-nl](https://github.com/mika-nl)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/nl/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/nl/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/nl/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/nl/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/nl/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/nl/)|| |🇵🇱 pl|Polski |[BxOxSxS](https://github.com/BxOxSxS)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/pl/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/pl/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/pl/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/pl/)||| |🇧🇷 pt-BR|Português||[![android app](https://hosted.weblate.org/widgets/simplex-chat/pt_BR/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/)
-|[![website](https://hosted.weblate.org/widgets/simplex-chat/pt_BR/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/pt_BR/)|| |🇷🇺 ru|Русский ||[![android app](https://hosted.weblate.org/widgets/simplex-chat/ru/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/ru/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/ru/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/ru/)||| |🇹🇭 th|ภาษาไทย |[titapa-punpun](https://github.com/titapa-punpun)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/th/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/th/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/th/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/th/)||| +|🇺🇦 uk|Українська| |[![android app](https://hosted.weblate.org/widgets/simplex-chat/uk/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/uk/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/uk/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/uk/)|[![website](https://hosted.weblate.org/widgets/simplex-chat/uk/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/uk/)|| |🇨🇳 zh-CHS|简体中文|[sith-on-mars](https://github.com/sith-on-mars)

[Float-hu](https://github.com/Float-hu)|[![android app](https://hosted.weblate.org/widgets/simplex-chat/zh_Hans/android/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/)
[![ios app](https://hosted.weblate.org/widgets/simplex-chat/zh_Hans/ios/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/ios/zh_Hans/)
 |

[![website](https://hosted.weblate.org/widgets/simplex-chat/zh_Hans/website/svg-badge.svg)](https://hosted.weblate.org/projects/simplex-chat/website/zh_Hans/)|| Languages in progress: Arabic, Japanese, Korean, Portuguese and [others](https://hosted.weblate.org/projects/simplex-chat/#languages). We will be adding more languages as some of the already added are completed – please suggest new languages, review the [translation guide](./docs/TRANSLATIONS.md) and get in touch with us! @@ -227,24 +230,18 @@ You can use SimpleX with your own servers and still communicate with people usin ## News and updates -Recent updates: +Recent and important updates: -[July 22, 2023. SimpleX Chat: v5.2 released with message delivery receipts](./blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md). +[Sep 25, 2023. SimpleX Chat v5.3 released: desktop app, local file encryption, improved groups and directory service](./blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.md). + +[Jul 22, 2023. SimpleX Chat: v5.2 released with message delivery receipts](./blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md). [May 23, 2023. SimpleX Chat: v5.1 released with message reactions and self-destruct passcode](./blog/20230523-simplex-chat-v5-1-message-reactions-self-destruct-passcode.md). [Apr 22, 2023. SimpleX Chat: vision and funding, v5.0 released with videos and files up to 1gb](./blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md). -[Mar 28, 2023. v4.6 released - with Android 8+ and ARMv7a support, hidden profiles, community moderation, improved audio/video calls and reduced battery usage](./blog/20230328-simplex-chat-v4-6-hidden-profiles.md). - [Mar 1, 2023. SimpleX File Transfer Protocol – send large files efficiently, privately and securely, soon to be integrated into SimpleX Chat apps.](./blog/20230301-simplex-file-transfer-protocol.md). -[Feb 4, 2023. v4.5 released - with multiple user profiles, message draft, transport isolation and Italian interface](./blog/20230204-simplex-chat-v4-5-user-chat-profiles.md). - -[Jan 3, 2023. v4.4 released - with disappearing messages, "live" messages, connection security verifications, GIFs and stickers and with French interface language](./blog/20230103-simplex-chat-v4.4-disappearing-messages.md). - -[Dec 6, 2022. November reviews and v4.3 released - with instant voice messages, irreversible deletion of sent messages and improved server configuration](./blog/20221206-simplex-chat-v4.3-voice-messages.md). - [Nov 8, 2022. Security audit by Trail of Bits, the new website and v4.2 released](./blog/20221108-simplex-chat-v4.2-security-audit-new-website.md). [Sep 28, 2022. v4.0: encrypted local chat database and many other changes](./blog/20220928-simplex-chat-v4-encrypted-database.md). @@ -290,18 +287,20 @@ What is already implemented: 3. [Double ratchet](./docs/GLOSSARY.md#double-ratchet-algorithm) end-to-end encryption in each conversation between two users (or group members). This is the same algorithm that is used in Signal and many other messaging apps; it provides OTR messaging with [forward secrecy](./docs/GLOSSARY.md#forward-secrecy) (each message is encrypted by its own ephemeral key) and [break-in recovery](./docs/GLOSSARY.md#post-compromise-security) (the keys are frequently re-negotiated as part of the message exchange). Two pairs of Curve448 keys are used for the initial [key agreement](./docs/GLOSSARY.md#key-agreement-protocol), initiating party passes these keys via the connection link, accepting side - in the header of the confirmation message. 4. Additional layer of encryption using NaCL cryptobox for the messages delivered from the server to the recipient. This layer avoids having any ciphertext in common between sent and received traffic of the server inside TLS (and there are no identifiers in common as well). 5. Several levels of [content padding](./docs/GLOSSARY.md#message-padding) to frustrate message size attacks. -6. Starting from v2 of SMP protocol (the current version is v4) all message metadata, including the time when the message was received by the server (rounded to a second) is sent to the recipients inside an encrypted envelope, so even if TLS is compromised it cannot be observed. +6. All message metadata, including the time when the message was received by the server (rounded to a second) is sent to the recipients inside an encrypted envelope, so even if TLS is compromised it cannot be observed. 7. Only TLS 1.2/1.3 are allowed for client-server connections, limited to cryptographic algorithms: CHACHA20POLY1305_SHA256, Ed25519/Ed448, Curve25519/Curve448. 8. To protect against replay attacks SimpleX servers require [tlsunique channel binding](https://www.rfc-editor.org/rfc/rfc5929.html) as session ID in each client command signed with per-queue ephemeral key. 9. To protect your IP address all SimpleX Chat clients support accessing messaging servers via Tor - see [v3.1 release announcement](./blog/20220808-simplex-chat-v3.1-chat-groups.md) for more details. 10. Local database encryption with passphrase - your contacts, groups and all sent and received messages are stored encrypted. If you used SimpleX Chat before v4.0 you need to enable the encryption via the app settings. 11. Transport isolation - different TCP connections and Tor circuits are used for traffic of different user profiles, optionally - for different contacts and group member connections. 12. Manual messaging queue rotations to move conversation to another SMP relay. +13. Sending end-to-end encrypted files using [XFTP protocol](https://simplex.chat/blog/20230301-simplex-file-transfer-protocol.html). +14. Local files encryption, except videos (to be added later). We plan to add: -1. Local files encryption. Currently the images and files you send and receive are stored in the app unencrypted, you can delete them via `Settings / Database passphrase & export`. This is currently in progress. -2. Senders' SMP relays and recipients' XFTP relays to reduce traffic and conceal IP addresses from the relays chosen, and potentially controlled, by another party. +1. Senders' SMP relays and recipients' XFTP relays to reduce traffic and conceal IP addresses from the relays chosen, and potentially controlled, by another party. +2. Post-quantum resistant key exchange in double ratchet protocol. 3. Automatic message queue rotation and redundancy. Currently the queues created between two users are used until the queue is manually changed by the user or contact is deleted. We are planning to add automatic queue rotation to make these identifiers temporary and rotate based on some schedule TBC (e.g., every X messages, or every X hours/days). 4. Message "mixing" - adding latency to message delivery, to protect against traffic correlation by message time. 5. Reproducible builds – this is the limitation of the development stack, but we will be investing into solving this problem. Users can still build all applications and services from the source code. @@ -365,22 +364,26 @@ Please also join [#simplex-devs](https://simplex.chat/contact#/?v=1-2&smp=smp%3A - ✅ Message editing history - ✅ Reduced battery and traffic usage in large groups. - ✅ Message delivery confirmation (with sender opt-out per contact). -- 🏗 Desktop client. +- ✅ Desktop client. +- ✅ Encryption of local files stored in the app. +- 🏗 Using mobile profiles from the desktop app. +- Message delivery relay for senders (to conceal IP address from the recipients' servers and to reduce the traffic). +- Post-quantum resistant key exchange in double ratchet protocol. +- Large groups, communities and public channels. +- Privacy & security slider - a simple way to set all settings at once. +- Improve sending videos (including encryption of locally stored videos). +- Improve experience for the new users. - SMP queue redundancy and rotation (manual is supported). - Include optional message into connection request sent via contact address. -- Local app files encryption. - Improved navigation and search in the conversation (expand and scroll to quoted message, scroll to search results, etc.). -- Large groups, communities and public channels. - Feeds/broadcasts. - Ephemeral/disappearing/OTR conversations with the existing contacts. - Privately share your location. - Web widgets for custom interactivity in the chats. - Programmable chat automations / rules (automatic replies/forward/deletion/sending, reminders, etc.). -- Supporting the same profile on multiple devices. - Privacy-preserving identity server for optional DNS-based contact/group addresses to simplify connection and discovery, but not used to deliver messages: - keep all your contacts and groups even if you lose the domain. - the server doesn't have information about your contacts and groups. -- Message delivery relay for senders (to conceal IP address from the recipients' servers and to reduce the traffic). - High capacity multi-node SMP relays. ## Disclaimers diff --git a/apps/ios/Shared/Views/Chat/ChatItemView.swift b/apps/ios/Shared/Views/Chat/ChatItemView.swift index 5ec61a8c2..a79047ebc 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemView.swift @@ -60,6 +60,7 @@ struct ChatItemContentView: View { var chatInfo: ChatInfo var chatItem: ChatItem var msgContentView: () -> Content + @AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false var body: some View { switch chatItem.content { @@ -69,7 +70,12 @@ struct ChatItemContentView: View { case .rcvDeleted: deletedItemView() case let .sndCall(status, duration): callItemView(status, duration) case let .rcvCall(status, duration): callItemView(status, duration) - case let .rcvIntegrityError(msgError): IntegrityErrorItemView(msgError: msgError, chatItem: chatItem) + case let .rcvIntegrityError(msgError): + if developerTools { + IntegrityErrorItemView(msgError: msgError, chatItem: chatItem) + } else { + ZStack {} + } case let .rcvDecryptionError(msgDecryptError, msgCount): CIRcvDecryptionError(msgDecryptError: msgDecryptError, msgCount: msgCount, chatItem: chatItem) case let .rcvGroupInvitation(groupInvitation, memberRole): groupInvitationItemView(groupInvitation, memberRole) case let .sndGroupInvitation(groupInvitation, memberRole): groupInvitationItemView(groupInvitation, memberRole) diff --git a/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c index eb4714710..dbfee7025 100644 --- a/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c +++ b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c @@ -60,7 +60,7 @@ Java_chat_simplex_common_platform_CoreKt_chatMigrateInit(JNIEnv *env, __unused j jstring res = (*env)->NewStringUTF(env, chat_migrate_init(_dbPath, _dbKey, _confirm, &_ctrl)); (*env)->ReleaseStringUTFChars(env, dbPath, _dbPath); (*env)->ReleaseStringUTFChars(env, dbKey, _dbKey); - (*env)->ReleaseStringUTFChars(env, dbKey, _confirm); + (*env)->ReleaseStringUTFChars(env, confirm, _confirm); // Creating array of Object's (boxed values can be passed, eg. Long instead of long) jobjectArray ret = (jobjectArray)(*env)->NewObjectArray(env, 2, (*env)->FindClass(env, "java/lang/Object"), NULL); diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt index e13439e18..596a7426a 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt @@ -394,6 +394,7 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId: } }, onComposed, + developerTools = chatModel.controller.appPrefs.developerTools.get(), ) } } @@ -435,6 +436,7 @@ fun ChatLayout( changeNtfsState: (Boolean, currentValue: MutableState) -> Unit, onSearchValueChanged: (String) -> Unit, onComposed: suspend (chatId: String) -> Unit, + developerTools: Boolean, ) { val scope = rememberCoroutineScope() val attachmentDisabled = remember { derivedStateOf { composeState.value.attachmentDisabled } } @@ -500,7 +502,7 @@ fun ChatLayout( useLinkPreviews, linkMode, showMemberInfo, loadPrevMessages, deleteMessage, receiveFile, cancelFile, joinGroup, acceptCall, acceptFeature, openDirectChat, updateContactStats, updateMemberStats, syncContactConnection, syncMemberConnection, findModelChat, findModelMember, - setReaction, showItemDetails, markRead, setFloatingButton, onComposed, + setReaction, showItemDetails, markRead, setFloatingButton, onComposed, developerTools, ) } } @@ -695,6 +697,7 @@ fun BoxWithConstraintsScope.ChatItemsList( markRead: (CC.ItemRange, unreadCountAfter: Int?) -> Unit, setFloatingButton: (@Composable () -> Unit) -> Unit, onComposed: suspend (chatId: String) -> Unit, + developerTools: Boolean, ) { val listState = rememberLazyListState() val scope = rememberCoroutineScope() @@ -831,7 +834,7 @@ fun BoxWithConstraintsScope.ChatItemsList( ) { MemberImage(member) } - ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = {}, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, getConnectedMemberNames = ::getConnectedMemberNames) + ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = {}, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, getConnectedMemberNames = ::getConnectedMemberNames, developerTools = developerTools) } } } else { @@ -840,7 +843,7 @@ fun BoxWithConstraintsScope.ChatItemsList( .padding(start = 8.dp + MEMBER_IMAGE_SIZE + 4.dp, end = if (voiceWithTransparentBack) 12.dp else 66.dp) .then(swipeableModifier) ) { - ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = {}, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, getConnectedMemberNames = ::getConnectedMemberNames) + ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = {}, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, getConnectedMemberNames = ::getConnectedMemberNames, developerTools = developerTools) } } } @@ -850,7 +853,7 @@ fun BoxWithConstraintsScope.ChatItemsList( .padding(start = if (voiceWithTransparentBack) 12.dp else 104.dp, end = 12.dp) .then(swipeableModifier) ) { - ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = {}, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails) + ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = {}, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, developerTools = developerTools) } } } else { // direct message @@ -861,7 +864,7 @@ fun BoxWithConstraintsScope.ChatItemsList( end = if (sent || voiceWithTransparentBack) 12.dp else 76.dp, ).then(swipeableModifier) ) { - ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = joinGroup, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails) + ChatItemView(chat.chatInfo, cItem, composeState, provider, useLinkPreviews = useLinkPreviews, linkMode = linkMode, deleteMessage = deleteMessage, receiveFile = receiveFile, cancelFile = cancelFile, joinGroup = joinGroup, acceptCall = acceptCall, acceptFeature = acceptFeature, openDirectChat = openDirectChat, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember, scrollToItem = scrollToItem, setReaction = setReaction, showItemDetails = showItemDetails, developerTools = developerTools) } } @@ -1300,6 +1303,7 @@ fun PreviewChatLayout() { changeNtfsState = { _, _ -> }, onSearchValueChanged = {}, onComposed = {}, + developerTools = false, ) } } @@ -1368,6 +1372,7 @@ fun PreviewGroupChatLayout() { changeNtfsState = { _, _ -> }, onSearchValueChanged = {}, onComposed = {}, + developerTools = false, ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt index 98811260d..e1d45ffb3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/item/ChatItemView.kt @@ -64,6 +64,7 @@ fun ChatItemView( setReaction: (ChatInfo, ChatItem, Boolean, MsgReaction) -> Unit, showItemDetails: (ChatInfo, ChatItem) -> Unit, getConnectedMemberNames: (() -> List)? = null, + developerTools: Boolean, ) { val uriHandler = LocalUriHandler.current val sent = cItem.chatDir.sent @@ -343,7 +344,11 @@ fun ChatItemView( is CIContent.RcvDeleted -> DeletedItem() is CIContent.SndCall -> CallItem(c.status, c.duration) is CIContent.RcvCall -> CallItem(c.status, c.duration) - is CIContent.RcvIntegrityError -> IntegrityErrorItemView(c.msgError, cItem, cInfo.timedMessagesTTL) + is CIContent.RcvIntegrityError -> if (developerTools) { + IntegrityErrorItemView(c.msgError, cItem, cInfo.timedMessagesTTL) + } else { + Box(Modifier.size(0.dp)) {} + } is CIContent.RcvDecryptionError -> CIRcvDecryptionError(c.msgDecryptError, c.msgCount, cInfo, cItem, updateContactStats = updateContactStats, updateMemberStats = updateMemberStats, syncContactConnection = syncContactConnection, syncMemberConnection = syncMemberConnection, findModelChat = findModelChat, findModelMember = findModelMember) is CIContent.RcvGroupInvitation -> CIGroupInvitationView(cItem, c.groupInvitation, c.memberRole, joinGroup = joinGroup, chatIncognito = cInfo.incognito) is CIContent.SndGroupInvitation -> CIGroupInvitationView(cItem, c.groupInvitation, c.memberRole, joinGroup = joinGroup, chatIncognito = cInfo.incognito) @@ -583,6 +588,7 @@ fun PreviewChatItemView() { findModelMember = { null }, setReaction = { _, _, _, _ -> }, showItemDetails = { _, _ -> }, + developerTools = false, ) } } @@ -613,6 +619,7 @@ fun PreviewChatItemViewDeletedContent() { findModelMember = { null }, setReaction = { _, _, _, _ -> }, showItemDetails = { _, _ -> }, + developerTools = false, ) } } diff --git a/apps/multiplatform/desktop/build.gradle.kts b/apps/multiplatform/desktop/build.gradle.kts index 39d08e046..a4e8207a1 100644 --- a/apps/multiplatform/desktop/build.gradle.kts +++ b/apps/multiplatform/desktop/build.gradle.kts @@ -153,102 +153,106 @@ afterEvaluate { tasks.create("cmakeBuildAndCopy") { dependsOn("cmakeBuild") val copyDetails = mutableMapOf>() - copy { - from("${project(":desktop").buildDir}/cmake/main/linux-amd64", "$cppPath/desktop/libs/linux-x86_64", "$cppPath/desktop/libs/linux-x86_64/deps") - into("src/jvmMain/resources/libs/linux-x86_64") - include("*.so*") - eachFile { - path = name - } - includeEmptyDirs = false - duplicatesStrategy = DuplicatesStrategy.INCLUDE - } - copy { - val destinationDir = "src/jvmMain/resources/libs/linux-x86_64/vlc" - from("$cppPath/desktop/libs/linux-x86_64/deps/vlc") - into(destinationDir) - includeEmptyDirs = false - duplicatesStrategy = DuplicatesStrategy.INCLUDE - copyIfNeeded(destinationDir, copyDetails) - } - copy { - from("${project(":desktop").buildDir}/cmake/main/linux-aarch64", "$cppPath/desktop/libs/linux-aarch64", "$cppPath/desktop/libs/linux-aarch64/deps") - into("src/jvmMain/resources/libs/linux-aarch64") - include("*.so*") - eachFile { - path = name - } - includeEmptyDirs = false - duplicatesStrategy = DuplicatesStrategy.INCLUDE - } - copy { - val destinationDir = "src/jvmMain/resources/libs/linux-aarch64/vlc" - from("$cppPath/desktop/libs/linux-aarch64/deps/vlc") - into(destinationDir) - includeEmptyDirs = false - duplicatesStrategy = DuplicatesStrategy.INCLUDE - copyIfNeeded(destinationDir, copyDetails) - } - copy { - from("${project(":desktop").buildDir}/cmake/main/win-amd64", "$cppPath/desktop/libs/windows-x86_64", "$cppPath/desktop/libs/windows-x86_64/deps") - into("src/jvmMain/resources/libs/windows-x86_64") - include("*.dll") - eachFile { - path = name - } - includeEmptyDirs = false - duplicatesStrategy = DuplicatesStrategy.INCLUDE - } - copy { - val destinationDir = "src/jvmMain/resources/libs/windows-x86_64/vlc" - from("$cppPath/desktop/libs/windows-x86_64/deps/vlc") - into(destinationDir) - includeEmptyDirs = false - duplicatesStrategy = DuplicatesStrategy.INCLUDE - copyIfNeeded(destinationDir, copyDetails) - } - copy { - from("${project(":desktop").buildDir}/cmake/main/mac-x86_64", "$cppPath/desktop/libs/mac-x86_64", "$cppPath/desktop/libs/mac-x86_64/deps") - into("src/jvmMain/resources/libs/mac-x86_64") - include("*.dylib") - eachFile { - path = name - } - includeEmptyDirs = false - duplicatesStrategy = DuplicatesStrategy.INCLUDE - } - copy { - val destinationDir = "src/jvmMain/resources/libs/mac-x86_64/vlc" - from("$cppPath/desktop/libs/mac-x86_64/deps/vlc") - into(destinationDir) - includeEmptyDirs = false - duplicatesStrategy = DuplicatesStrategy.INCLUDE - copyIfNeeded(destinationDir, copyDetails) - } - copy { - from("${project(":desktop").buildDir}/cmake/main/mac-aarch64", "$cppPath/desktop/libs/mac-aarch64", "$cppPath/desktop/libs/mac-aarch64/deps") - into("src/jvmMain/resources/libs/mac-aarch64") - include("*.dylib") - eachFile { - path = name - } - includeEmptyDirs = false - duplicatesStrategy = DuplicatesStrategy.INCLUDE - } - copy { - val destinationDir = "src/jvmMain/resources/libs/mac-aarch64/vlc" - from("$cppPath/desktop/libs/mac-aarch64/deps/vlc") - into(destinationDir) - includeEmptyDirs = false - duplicatesStrategy = DuplicatesStrategy.INCLUDE - copyIfNeeded(destinationDir, copyDetails) - } doLast { - copyDetails.forEach { (destinationDir, details) -> - details.forEach { detail -> - val target = File(projectDir.absolutePath + File.separator + destinationDir + File.separator + detail.path) - if (target.exists()) { - target.setLastModified(detail.lastModified) + copy { + from("${project(":desktop").buildDir}/cmake/main/linux-amd64", "$cppPath/desktop/libs/linux-x86_64", "$cppPath/desktop/libs/linux-x86_64/deps") + into("src/jvmMain/resources/libs/linux-x86_64") + include("*.so*") + eachFile { + path = name + } + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + copy { + val destinationDir = "src/jvmMain/resources/libs/linux-x86_64/vlc" + from("$cppPath/desktop/libs/linux-x86_64/deps/vlc") + into(destinationDir) + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + copyIfNeeded(destinationDir, copyDetails) + } + copy { + from("${project(":desktop").buildDir}/cmake/main/linux-aarch64", "$cppPath/desktop/libs/linux-aarch64", "$cppPath/desktop/libs/linux-aarch64/deps") + into("src/jvmMain/resources/libs/linux-aarch64") + include("*.so*") + eachFile { + path = name + } + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + copy { + val destinationDir = "src/jvmMain/resources/libs/linux-aarch64/vlc" + from("$cppPath/desktop/libs/linux-aarch64/deps/vlc") + into(destinationDir) + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + copyIfNeeded(destinationDir, copyDetails) + } + copy { + from("${project(":desktop").buildDir}/cmake/main/win-amd64", "$cppPath/desktop/libs/windows-x86_64", "$cppPath/desktop/libs/windows-x86_64/deps") + into("src/jvmMain/resources/libs/windows-x86_64") + include("*.dll") + eachFile { + path = name + } + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + copy { + val destinationDir = "src/jvmMain/resources/libs/windows-x86_64/vlc" + from("$cppPath/desktop/libs/windows-x86_64/deps/vlc") + into(destinationDir) + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + copyIfNeeded(destinationDir, copyDetails) + } + copy { + from("${project(":desktop").buildDir}/cmake/main/mac-x86_64", "$cppPath/desktop/libs/mac-x86_64", "$cppPath/desktop/libs/mac-x86_64/deps") + into("src/jvmMain/resources/libs/mac-x86_64") + include("*.dylib") + eachFile { + path = name + } + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + copy { + val destinationDir = "src/jvmMain/resources/libs/mac-x86_64/vlc" + from("$cppPath/desktop/libs/mac-x86_64/deps/vlc") + into(destinationDir) + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + copyIfNeeded(destinationDir, copyDetails) + } + copy { + from("${project(":desktop").buildDir}/cmake/main/mac-aarch64", "$cppPath/desktop/libs/mac-aarch64", "$cppPath/desktop/libs/mac-aarch64/deps") + into("src/jvmMain/resources/libs/mac-aarch64") + include("*.dylib") + eachFile { + path = name + } + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + copy { + val destinationDir = "src/jvmMain/resources/libs/mac-aarch64/vlc" + from("$cppPath/desktop/libs/mac-aarch64/deps/vlc") + into(destinationDir) + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + copyIfNeeded(destinationDir, copyDetails) + } + } + afterEvaluate { + doLast { + copyDetails.forEach { (destinationDir, details) -> + details.forEach { detail -> + val target = File(projectDir.absolutePath + File.separator + destinationDir + File.separator + detail.path) + if (target.exists()) { + target.setLastModified(detail.lastModified) + } } } } diff --git a/blog/20230301-simplex-file-transfer-protocol.md b/blog/20230301-simplex-file-transfer-protocol.md index 08fec86ad..0008dd6b9 100644 --- a/blog/20230301-simplex-file-transfer-protocol.md +++ b/blog/20230301-simplex-file-transfer-protocol.md @@ -4,6 +4,7 @@ title: "SimpleX File Transfer Protocol - a new protocol for sending large files date: 2023-03-01 preview: CLI and relays implementing the new XFTP protocol are released - you can use them now! image: images/20230301-xftp.jpg +imageWide: true permalink: "/blog/20230301-simplex-file-transfer-protocol.html" --- diff --git a/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md b/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md index 93572dba3..0a6612493 100644 --- a/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md +++ b/blog/20230422-simplex-chat-vision-funding-v5-videos-files-passcode.md @@ -63,7 +63,7 @@ To accelerate product development and growth we will be raising a seed funding t ### Send videos and files up to 1gb! - + In the beginning of March [we released servers and command-line utility to send and receive files via XFTP protocol](./20230301-simplex-file-transfer-protocol.md) - a very private and secure protocol that sends end-to-end encrypted files in chunks, protecting meta-data better than any alternatives we know of. @@ -88,7 +88,7 @@ Now you can choose whether to use faster and more convenient system biometric au ### Networking improvements - + Two small improvements to the app networking capabilities were added in this version. diff --git a/blog/20230523-simplex-chat-v5-1-message-reactions-self-destruct-passcode.md b/blog/20230523-simplex-chat-v5-1-message-reactions-self-destruct-passcode.md index e898763e1..0cdbe2831 100644 --- a/blog/20230523-simplex-chat-v5-1-message-reactions-self-destruct-passcode.md +++ b/blog/20230523-simplex-chat-v5-1-message-reactions-self-destruct-passcode.md @@ -36,7 +36,7 @@ Also, we added Japanese and Portuguese (Brazil)* interface languages, ## Message reactions - + No idea why it took us so long to add them – finally we have them, and they are great. @@ -50,7 +50,7 @@ The next app version will allow prohibiting the reactions per conversation, as y ### Voice messages: up to 5 minutes, better quality, playback control - + Since [v4.3](./20221206-simplex-chat-v4.3-voice-messages.md#instant-voice-messages) voice messages were sent in small 16kb chunks, so we had to limit them to 30-40 seconds for better user experience, as sending larger files would require the sender to be online. @@ -66,7 +66,7 @@ This version allows to configure the time for messages to disappear more granula ### Message editing history - + I [wrote previously](./20221206-simplex-chat-v4.3-voice-messages.md#irreversible-message-deletion) why we decided to require the recipient concent before the messages can be fully deleted by the sender - in short, it is to support recipient's data sovereignty and prevent the possibility of offensive messages being removed without any trace. By default, when the sender deletes the message it is marked as deleted, rather than fully deleted, and you can reveal the original message. @@ -74,7 +74,7 @@ You've found the workaround for it of course - it's enough to simply edit the me ## Customize and share color themes - + Android app now allows choosing between three color themes - Light, Dark and SimpleX (a dark blue theme). You can customize any theme by setting 9 different colors used in the app, including titles, menus, accent colors and colors for sent and received messages. @@ -82,7 +82,7 @@ You can share your theme with other users by exporting it to a file and sending ## Self-destruct passcode - + This is something many of you asked before - when asked to enter the app passcode under duress, to be able to enter a special self-destruct code that would remove the app data. This feature is offered in many security tools, and now you can configure it in SimpleX Chat as well. diff --git a/blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md b/blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md index 42c08245f..759587821 100644 --- a/blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md +++ b/blog/20230722-simplex-chat-v5-2-message-delivery-receipts.md @@ -38,7 +38,7 @@ permalink: "/blog/20230722-simplex-chat-v5-2-message-delivery-receipts.html" ### Message delivery receipts - + Most messaging apps add two ticks to sent messages – the first one to show that the message is accepted by the server, and the second – that it is delivered to the recipient's device. It confirms that the network is functioning, and that the message is not lost or delayed. SimpleX Chat now has this feature too! @@ -48,7 +48,7 @@ To avoid compromising your privacy, sending delivery receipts is disabled for al ### Filter favorite and unread chats - + You can now mark your contacts and groups as _favorite_, to be able to find them faster. With filter enabled, you will only see favorite chats, chats that contain unread messages and also any unaccepted group invitations and contact requests. @@ -58,13 +58,13 @@ Active SimpleX Chat users know how broken the current group experience is, and t #### What is this in reply to? - + A major problem is that you can see replies to the messages you've not seen before - this would happen both when you just join the group, and didn't connect to most other members, and also when other new members join the group and they didn't yet connect to you – so literally all the time, and the bigger the group gets, the worse it becomes. While this problem cannot be solved without major group protocol changes, at least there is now ability to see the original message that was replied to via the message information. #### How to connect to this member? - + To simplify direct connections with other group members, you can now share your SimpleX address via your chat profile, and group members can send you a contact request even if the group does not allow direct messages. diff --git a/blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.md b/blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.md index ba076295c..2aa8a7bc0 100644 --- a/blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.md +++ b/blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.md @@ -2,14 +2,130 @@ layout: layouts/article.html title: "SimpleX Chat v5.3 released: desktop app, local file encryption and improved groups with directory service" date: 2023-09-25 -# image: images/20230925-desktop-app.png -# previewBody: blog_previews/20230722.html +image: /docs/images/simplex-desktop-light.png +imageWide: true +previewBody: blog_previews/20230925.html permalink: "/blog/20230925-simplex-chat-v5-3-desktop-app-local-file-encryption-directory-service.html" -draft: true --- # SimpleX Chat v5.3 released: desktop app, local file encryption and improved groups **Published:** September 25, 2023 -This is a placeholder for the release announcement +**What's new in v5.3:** +- [new desktop app!](#multiplatform-desktop-app)! +- [directory service and other group improvements](#group-directory-service-and-other-group-improvements). +- [encrypted local files and media with forward secrecy](#encrypted-local-files-and-media-with-forward-secrecy). +- [simplified incognito mode](#simplified-incognito-mode). + +There are a lot of other improvements and fixes in this release: +- improved app responsiveness and stability. +- app memory usage is reduced by 40%. +- new privacy settings: show last messages & save draft. +- fixes: + - bug preventing group members connecting (it will only help the new connections). + - playing videos on full screen**. + - screen reader for messages**. + - reduced background crashes**. + +Also, we added 6 new interface languages: Arabic*, Bulgarian, Finnish, Hebrew*, Thai and Ukrainian - thanks to [our users and Weblate](https://github.com/simplex-chat/simplex-chat#help-translating-simplex-chat). + +\* Android app. + +\*\* iOS app. + +## Multiplatform desktop app + + + +Thanks a lot to everybody who was testing the desktop app since July – it really helped to make it stable! + +To use desktop app you need to **create a new profile**. As SimpleX platform has no user accounts, it's not as simple as for centralized apps to access the same profile from two devices. + +The next app version will allow using your mobile profile from desktop app. For now, as a workaround, you can join groups from both mobile and desktop devices, and use small groups instead of direct conversations. + +When you start the app first time, you will be offered to **set database passphrase** – you have to memorize it, as there is no way to recover it. If you skip it, a random passphrase will be generated and stored on your desktop device as plaintext (unencrypted) – you can change it later. + +Other limitations of the desktop app: +- you cannot send voice messages. +- there is no support for calls yet. + +## Group directory service and other group improvements + + + +Directory service provides a way to search for public groups submitted by the users. To use it, you need to connect to it via SimpleX Chat, as you would connect to any other contact, and type some words to search. + +You can also create and register your group, with some limitations explained [here](../docs/DIRECTORY.md). + +Other group improvements in this release: + +- you can send delivery receipts to the groups up to 20 members. + +- if the group settings allow it, you can send direct messages to group members even after you deleted the contact. + +- connections between members are made faster, and the bug that prevented the connections in some cases is fixed in this release. + +The next release will reduce the time it takes to send messages to the group, especially when there are many members or when you have a slow device storage. + +## Encrypted local files and media with forward secrecy + + + +All messages, files and media sent via SimpleX Chat were always end-to-end encrypted from the very beginning. SimpleX Chat uses double-ratchet algorithm with encrypted message headers, for the best possible meta-data protection. + +You contacts, groups and messages are stored in the local database on your device, and this database was encrypted from [v4.0 released a year ago](./20220928-simplex-chat-v4-encrypted-database.md). + +But until this version all files and media in the app storage were not encrypted, and when you exported the chat archive, they were unencrypted there as well. + +From v5.3 all files and media (except videos, for now) are encrypted with a random symmetric key - in many cases they are encrypted before they are written to the storage. Local file encryption can be disabled via Privacy & Security settings, for example, if you need to access the files from the storage outside of the app. + +In addition to the videos that are stored unencrypted, there are other rare scenarios when the received files may be unencrypted in this release. Files have an open or closed lock icons to indicate whether they were encrypted locally. These limitations will be addressed in the next release. In any case, all files and media are always sent end-to-end encrypted, without any exceptions. + +The keys used to encrypt files locally are associated with the messages and stored in the encrypted database. If you delete a message with the attached file or media, the key will be irreversibly deleted as well. Even if an attacker gains access to your database passphrase later and to the copy of the encrypted file, they won't be able to decrypt the file. + +This approach provides forward secrecy for locally stored files, unlike file encryption schemes used in some other apps when the same passphrase is used for all files. + +## Simplified incognito mode + + + +Incognito mode was [added a year ago](./20220901-simplex-chat-v3.2-incognito-mode.md) to improve anonymity of your profile, but it was confusing for some users - it was a global setting, but it only affected the new connections. + +It is now simpler to use - you can decide whether to connect to a contact or join a group using your main profile at a point when you create an invitation link or connect via a link or QR code. + +When you are connecting to people your know you usually want to share your main profile, and when connecting to public groups or strangers, you may prefer to use a random profile. + +## SimpleX platform + +Some links to answer the most common questions: + +[SimpleX Chat security assessment](./20221108-simplex-chat-v4.2-security-audit-new-website.md). + +[How can SimpleX deliver messages without user identifiers](https://simplex.chat/#how-simplex-works). + +[What are the risks to have identifiers assigned to the users](https://simplex.chat/#why-ids-bad-for-privacy). + +[Technical details and limitations](https://github.com/simplex-chat/simplex-chat#privacy-technical-details-and-limitations). + +[How SimpleX is different from Session, Matrix, Signal, etc.](https://github.com/simplex-chat/simplex-chat/blob/stable/README.md#frequently-asked-questions). + +Visit our [website](https://simplex.chat) to learn more. + +## Help us with donations + +Huge thank you to everybody who donated to SimpleX Chat! + +We are prioritizing users privacy and security - it would be impossible without your support. + +Our pledge to our users is that SimpleX protocols are and will remain open, and in public domain, - so anybody can build the future implementations of the clients and the servers. We are building SimpleX platform based on the same principles as email and web, but much more private and secure. + +Your donations help us raise more funds – any amount, even the price of the cup of coffee, makes a big difference for us. + +See [this section](https://github.com/simplex-chat/simplex-chat/tree/master#help-us-with-donations) for the ways to donate. + +Thank you, + +Evgeny + +SimpleX Chat founder diff --git a/blog/images/20230925-directory.png b/blog/images/20230925-directory.png new file mode 100644 index 000000000..d5a2f2668 Binary files /dev/null and b/blog/images/20230925-directory.png differ diff --git a/blog/images/20230925-encrypted.png b/blog/images/20230925-encrypted.png new file mode 100644 index 000000000..0c482264b Binary files /dev/null and b/blog/images/20230925-encrypted.png differ diff --git a/blog/images/20230925-incognito.png b/blog/images/20230925-incognito.png new file mode 100644 index 000000000..949f36e74 Binary files /dev/null and b/blog/images/20230925-incognito.png differ diff --git a/docs/DOWNLOADS.md b/docs/DOWNLOADS.md index 4d120b671..83fa18f97 100644 --- a/docs/DOWNLOADS.md +++ b/docs/DOWNLOADS.md @@ -7,6 +7,8 @@ revision: 20.09.2023 | Updated 20.09.2023 | Languages: EN | # Download SimpleX apps +The latest version is v5.3. + - [desktop](#desktop-app) - [mobile](#mobile-apps) - [terminal](#terminal-console-app) (console) @@ -15,13 +17,11 @@ revision: 20.09.2023 desktop app -The latest version of desktop app is v5.3-beta.9 (1.6.0 in the app). - Using the same profile as on mobile device is not yet supported – you need to create a separate profile to use desktop apps. -**Linux**: [AppImage](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex-desktop-x86_64.AppImage) (most Linux distros), [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex-desktop-ubuntu-20_04-x86_64.deb) (and Debian-based distros), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex-desktop-ubuntu-22_04-x86_64.deb). +**Linux**: [AppImage](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex-desktop-x86_64.AppImage) (most Linux distros), [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex-desktop-ubuntu-20_04-x86_64.deb) (and Debian-based distros), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex-desktop-ubuntu-22_04-x86_64.deb). -**Mac**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex-desktop-macos-x86_64.dmg) (Intel), [aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex-desktop-macos-aarch64.dmg) (Apple Silicon). +**Mac**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex-desktop-macos-x86_64.dmg) (Intel), [aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex-desktop-macos-aarch64.dmg) (Apple Silicon). **Windows**: coming soon. @@ -29,14 +29,14 @@ Using the same profile as on mobile device is not yet supported – you need to **iOS**: [App store](https://apps.apple.com/us/app/simplex-chat/id1605771084) (v5.2.3), [TestFlight](https://testflight.apple.com/join/DWuT2LQu) (v5.3-beta.9). -**Android**: [Play store](https://play.google.com/store/apps/details?id=chat.simplex.app), [F-Droid](https://simplex.chat/fdroid/), [APK aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex.apk), [APK armv7](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex-armv7a.apk). +**Android**: [Play store](https://play.google.com/store/apps/details?id=chat.simplex.app), [F-Droid](https://simplex.chat/fdroid/), [APK aarch64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex.apk), [APK armv7](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex-armv7a.apk). ## Terminal (console) app See [Using terminal app](/docs/CLI.md). -**Linux**: [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex-chat-ubuntu-20_04-x86-64), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex-chat-ubuntu-22_04-x86-64). +**Linux**: [Ubuntu 20.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex-chat-ubuntu-20_04-x86-64), [Ubuntu 22.04](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex-chat-ubuntu-22_04-x86-64). -**Mac** [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex-chat-macos-x86-64), aarch64 - [compile from source](./CLI.md#). +**Mac** [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex-chat-macos-x86-64), aarch64 - [compile from source](./CLI.md#). -**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0-beta.9/simplex-chat-windows-x86-64). +**Windows**: [x86_64](https://github.com/simplex-chat/simplex-chat/releases/download/v5.3.0/simplex-chat-windows-x86-64). diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index 1f0d631cb..f4ae569e1 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -1553,7 +1553,7 @@ createMemberContactInvited contactId <- createContactUpdateMember currentTs userPreferences ctConn <- createMemberContactConn_ db user connIds gInfo mConn contactId subMode let mergedPreferences = contactUserPreferences user userPreferences preferences $ connIncognito ctConn - mCt' = Contact {contactId, localDisplayName = memberLDN, profile = memberProfile, activeConn = ctConn, viaGroup = Nothing, contactUsed = True, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Just groupMemberId, contactGrpInvSent = False} + mCt' = Contact {contactId, localDisplayName = memberLDN, profile = memberProfile, activeConn = ctConn, viaGroup = Nothing, contactUsed = True, chatSettings = defaultChatSettings, userPreferences, mergedPreferences, createdAt = currentTs, updatedAt = currentTs, chatTs = Just currentTs, contactGroupMemberId = Nothing, contactGrpInvSent = False} m' = m {memberContactId = Just contactId} pure (mCt', m') where diff --git a/website/src/_includes/blog_previews/20230925.html b/website/src/_includes/blog_previews/20230925.html new file mode 100644 index 000000000..9fb062639 --- /dev/null +++ b/website/src/_includes/blog_previews/20230925.html @@ -0,0 +1,14 @@ +

v5.3 is released:

+ +
    +
  • new desktop app! 💻
  • +
  • encrypt locally storead files & media
  • +
  • directory service and other group improvements
  • +
  • simplified incognito mode
  • +
  • better app responsiveness and stability, and 40% reduced memory usage.
  • +
  • new privacy settings: show last messages & save draft.
  • +
+ +

Also, our users added 6 new interface languages - Arabic*, Bulgarian, Finnish, Hebrew*, Thai and Ukrainian.

+ +

* Android app only.

diff --git a/website/src/blog.html b/website/src/blog.html index d0d4e6cba..11f057ce7 100644 --- a/website/src/blog.html +++ b/website/src/blog.html @@ -44,7 +44,9 @@ active_blog: true
{% if blog.data.image %} {% if blog.data.imageBottom %} - + + {% elif blog.data.imageWide %} + {% else %} {% endif %} diff --git a/website/src/css/blog.css b/website/src/css/blog.css index e7b90b485..adec9ab04 100644 --- a/website/src/css/blog.css +++ b/website/src/css/blog.css @@ -188,29 +188,26 @@ h3::before { outline: none; } -p, -a, h1, h2, h3, h4, h5, -h6, -li, -ul, -ol, -span, -div, -blockquote, -pre, -code { +h6{ clear: both; } #article p img { - float: left; + display: inline-block; } #article img { - margin-bottom: 1.5rem; + margin: 0.5rem 0 1rem 0; +} + +@media (min-width: 1024px) { + #article .float-to-left{ + float: left; + margin-right: 3rem; + } } \ No newline at end of file