* Translated using Weblate (German)
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/
* Translated using Weblate (Russian)
Currently translated at 97.5% (2829 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ru/
* Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.9% (2898 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/
* Translated using Weblate (Spanish)
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/
* Translated using Weblate (Spanish)
Currently translated at 100.0% (2497 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/es/
* Translated using Weblate (German)
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/
* Translated using Weblate (German)
Currently translated at 100.0% (2497 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/de/
* Translated using Weblate (Italian)
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/
* Translated using Weblate (Arabic)
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/
* Translated using Weblate (French)
Currently translated at 82.3% (2388 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/
* Translated using Weblate (French)
Currently translated at 92.6% (2314 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Translated using Weblate (Hungarian)
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/
* Translated using Weblate (Arabic)
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/
* Translated using Weblate (French)
Currently translated at 83.3% (2416 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/
* Translated using Weblate (French)
Currently translated at 96.2% (2404 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Added translation using Weblate (Slovak)
* Translated using Weblate (Slovak)
Currently translated at 5.0% (146 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/
* Update translation files
Updated by "Remove blank strings" hook in Weblate.
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/
* Translated using Weblate (French)
Currently translated at 97.3% (2431 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Translated using Weblate (Danish)
Currently translated at 31.1% (903 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/da/
* Translated using Weblate (Slovak)
Currently translated at 14.8% (431 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/
* Update translation files
Updated by "Remove blank strings" hook in Weblate.
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/
* Translated using Weblate (French)
Currently translated at 97.4% (2434 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Translated using Weblate (Slovak)
Currently translated at 16.2% (472 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/
* Translated using Weblate (French)
Currently translated at 97.7% (2440 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Translated using Weblate (Danish)
Currently translated at 32.1% (932 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/da/
* Translated using Weblate (Slovak)
Currently translated at 18.1% (527 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/
* Update translation files
Updated by "Remove blank strings" hook in Weblate.
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/
* Translated using Weblate (German)
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/
* Translated using Weblate (German)
Currently translated at 100.0% (2497 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/de/
* Translated using Weblate (French)
Currently translated at 98.7% (2466 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Translated using Weblate (Slovak)
Currently translated at 22.0% (638 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/
* Update translation files
Updated by "Remove blank strings" hook in Weblate.
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/
* Translated using Weblate (French)
Currently translated at 83.3% (2416 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/
* Translated using Weblate (French)
Currently translated at 99.4% (2483 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Translated using Weblate (Slovak)
Currently translated at 22.3% (647 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 82.9% (2405 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (Slovak)
Currently translated at 24.1% (700 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 83.1% (2411 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (French)
Currently translated at 85.7% (2486 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/
* Translated using Weblate (French)
Currently translated at 99.7% (2491 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 92.3% (2678 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (French)
Currently translated at 99.7% (2491 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.2% (2791 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (Slovak)
Currently translated at 26.0% (754 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/
* Update translation files
Updated by "Remove blank strings" hook in Weblate.
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/
* Translated using Weblate (French)
Currently translated at 86.6% (2512 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/
* Translated using Weblate (French)
Currently translated at 99.7% (2492 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.3% (2794 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.8% (2809 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.9% (2811 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (Slovak)
Currently translated at 26.9% (781 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 97.7% (2833 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (French)
Currently translated at 88.8% (2576 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/
* Translated using Weblate (French)
Currently translated at 100.0% (2497 of 2497 strings)
Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* Translated using Weblate (Slovak)
Currently translated at 26.9% (781 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/
* Translated using Weblate (French)
Currently translated at 90.4% (2622 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/
* Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2899 of 2899 strings)
Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/
* ios: bump Xcode version in localization exports
* process translations
* ui: fix translation errors in fr, pt-BR, sk, da and de
Review of the incoming Weblate batch found no malicious or deceptive
translations: every URL, e-mail and format specifier matches the English
source, and there are no bidi overrides, zero-width characters or
homoglyphs. These are accuracy fixes.
Security/privacy wording:
- fr (iOS): "no E2E encryption" was rendered "chiffrement pair-à-pair"
(peer-to-peer). The same file translates "peer-to-peer" that way, so
the E2E warning for chats with admins in public channels read as the
wrong guarantee.
- pt-BR: "We don't store any of your contacts or messages (once
delivered)" lost the first-person commitment and applied "once
delivered" to contacts too; "your profile will be shared via the
address" became a capability rather than a consequence; the
"(your contact can mark them for deletion)" parenthetical was dropped
from both irreversible-deletion descriptions.
- fr + pt-BR: in why_built_p7 the anaphora ("ce pouvoir" / "esse poder")
resolved to the power to identify you rather than the reader's own
power, inverting the sentence. de, it, es, ru, sk and hu all get this
right.
Broken output:
- da: proxy_destination_error_unknown_ca was wrapped in literal quotes
(Android's whitespace-quoting syntax) and carried a double space.
- fr (NSE): "De %d conversations(s)".
- pt-BR: incognito_info_share had lost every diacritic; mark_unread was
indicative instead of imperative.
Terminology and grammar:
- fr: the chat engine was translated as "conversation" on iOS (Start
chat, Stop chat, Stopping chat, Chat migrated, and the multi-device
delivery-failure warning) while Android used "messagerie"; "report"
(a moderation report) was translated as "rapport"; empty-list strings
read "Aucunes conversations".
- pt-BR: "timeout" was dropped from two duration settings; "Proxied
servers", "Reachable toolbar", "Allow downgrade" and "Proxy
authentication" had drifted.
- sk (new locale): ~120 fixes - typos and missing diacritics, Czech
forms (databázi, události, není, jednorázový, language names), gender
and number agreement, and 18 mistranslations including "encryption
agreed" rendered as "allowed", "Non-profit governance" as "vláda"
(government), "embed" as "vsadiť" (to wager) and "Decode link" as a
noun phrase.
- da: "Upgrader" -> "Opgrader", and name resolution described with
"afkode" (decode).
- de: "Privacy was never a feature" had gained a "nur".
Verified after the change: XML well-formed, no duplicate/orphan/removed
keys, format specifiers, markup, URLs and newline counts all match the
English source, iOS .strings and .xliff stay in sync, and no unescaped
apostrophes were introduced.
---------
Co-authored-by: mlanp <github@lang.xyz>
Co-authored-by: Evgeny Poberezkin <e.poberezkin@me.com>
Co-authored-by: Hosted Weblate user 54392 <hamburger2048@users.noreply.hosted.weblate.org>
Co-authored-by: No name <usir.alerts@onionmail.org>
Co-authored-by: Random <random-r@users.noreply.hosted.weblate.org>
Co-authored-by: jonnysemon <jonnysemon@users.noreply.hosted.weblate.org>
Co-authored-by: Ranakan <ranakan.dev@protonmail.ch>
Co-authored-by: summoner001 <summoner@disroot.org>
Co-authored-by: ND <nd@users.noreply.hosted.weblate.org>
Co-authored-by: Martin Kozempel <rado2012mir@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Morten Juhl-Johansen <git@0b.dk>
Co-authored-by: SanctumSaturn <oraculogithub@gmail.com>
Co-authored-by: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com>
* desktop: fix stretched video preview and playback for AV1 videos
libvlc passes the padded size the decoder allocated to the buffer format
callback, not the size of the picture. dav1d pads to a multiple of 128, so
a 1920x1080 AV1 video arrives as 1920x1152, and vlc scales the picture to
fill it - the preview sent with the message, and desktop playback, were
6.7% too tall. H264 pads much less, so it was barely visible there.
Ask for the size of the track being played instead. It is already populated
when the buffer format is negotiated, and matching the track that is playing
matters for files with more than one video track, where the first track is
not necessarily the one being decoded. Falls back to the previous behaviour
when the track is not known.
* plans: desktop video preview aspect ratio
* android, desktop: open group member profile without loading all members
Clicking member avatar in chat loaded the whole member list (apiListMembers)
before showing member profile, and it was repeated on every click - in a group
with 10000 members it takes several seconds.
The full list is not needed to show the profile of one member, so instead the
opened member is added to the model, the same way as in iOS app.
* plans: member profile in large groups
* plans: correct relay warning section - it is not affected by the change
* core, ui: auto-accept group invitations per user profile
Add a per-profile toggle for auto-accepting group invitations, and regroup it
with the existing contact-requests setting under a single Auto-accept section
in Privacy & Security, relabelled "Contact requests in groups".
The join is fully async. processGroupInvitation already had an async accept
path, used when the invitation matches a group link the user opened:
prepareAgentJoin + createMemberConnectionAsync + joinAgentConnectionAsync,
with the outcome reported later against the CFJoinConn command id. Auto-accept
takes that same path instead of going through APIJoinGroup, so it works while
the app is closed and never blocks message processing.
An auto-accepted invitation still records a CIRcvGroupInvitation item in the
chat with the inviting contact, so there is a record of who added the user to
which group.
Two details worth noting for review:
hostContact is reported to clients only for group links. Clients respond to it
by replacing the transient host connection view with the group and removing
that chat - correct for a group link, where the contact is a placeholder, but
wrong for a plain invitation, where it is a real contact.
A resent invitation returns the existing group, because createGroupInvitation
is idempotent on inv_queue_info. The join therefore only runs while the
membership is still GSMemInvited, so a resend cannot open a second connection.
* booldef
* order
* refactor
* update translation key
* query plans
* ios: export translations
---------
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
* directory: identify registration owner by member id to fix incorrect de-listing
The leave/removed/role-changed handlers identified the registration owner by
contact id. A non-owner member can be associated with the owner's contact (via
the contact/member merge), so its departure incorrectly de-listed the group.
Compare by group member id (owner_member_id) instead, falling back to contact
id for registrations recorded before owner_member_id existed.
* fix test, always compare contact ID in owner check
---------
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
* directory: only create group links after approval
* update test
* update messages
* diff
* get group and link in one query
* reduce database reads
* better errors
* typos
* query plans
---------
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
* feat: add simplex-support-bot-light
* feat: package simplex-support-bot-light for docker
* docs: document simplex-support-bot-light
* fix: make a missing config actionable and bounded
* docs: note the attached compose Ctrl+C behaviour
* refactor: use the library for startup and custom data
* refactor: drop the display-name workaround
* style: shorten the startup comment
* build: build the core and the library into the image
* docs: correct where the image type rule comes from
* fix: log what the core said a command got wrong
* build: run the container as the operator's uid
* docs: keep the container uid in .env
* docs: tighten the README
* ui: send dropped .webm as video only when it has a video track
.webm is as commonly an audio-only container as a video one, so the
extension alone cannot tell whether there is a frame to embed. Read the
container to decide: files with a video track are sent as video, the rest
as files.
Only done for files attached without the user saying how to send them
(drag & drop, paste). An explicitly picked video is still sent as one, so
.webm is now listed in the video file picker too.
* plan: send dropped .webm as video only when it has a video track
* android: add google and foss build flavors
* android: get the Google Play account country in the google flavor
* android, desktop: update whats new
* temp: comment out wefunder link
* ui: connect when a SimpleX link is pasted as a markdown hyperlink
* remove comments
Co-authored-by: Evgeny <evgeny@poberezkin.com>
---------
Co-authored-by: Evgeny <evgeny@poberezkin.com>
* android, desktop: fix live message sent to the chat opened after switching
A live message is sent when the chat is switched, but by then this view
already shows the chat that was opened - the effect that sends it runs
with that chat, so the message typed in one chat was sent to another.
The chat the message was composed in is passed to the send, and it is
resolved by the chat id from before the switch. If that chat is no longer
there the message is not sent at all, rather than sent to the chat opened
instead. The draft cleared after sending is the one of that chat too.
* plan: correct references; clear the draft of the chat the message is sent to
* plan: note the blast radius and how to resolve the overlap with #7308
* android, desktop: only pass the chat to what a live message can reach
A live message has no context item, so the forwarding, editing and
reporting branches of the send cannot run for it - they keep using the
chat of the view, and the chat it was composed in is passed only to the
message send, to the update of an already sent live message, and to
clearing the draft after sending.
* android, desktop: give the opened chat its own compose state while the live message is sent
Sending the live message to the chat it was composed in is not enough on
its own: composeState is shared between the chats opened in this view, and
the chat switch branch of KeyChangeEffect is the only one that neither
resets it nor loads the opened chat's draft - the branch that loads a
draft is later in the same if chain and cannot be reached.
sendMessageAsync then made it visible. It runs on Dispatchers.Default, so
its writes land after the switch: the whole composed state (via
cs.copy(liveMessage = null)) and its spinner (sending()) were written to
the compose state of a view that already shows another chat, which then
displayed the text composed in the previous one until the send completed.
The draft it should have shown was still in the model, and the next switch
away dropped it.
- sendMessageAsync takes composed, and sendMessage takes it as null by
default, so only the chat switch passes a state and every other sender
reads it inside the coroutine, where the send read it before. The chat
switch captures it on the main thread before replacing it - otherwise
the send would read the compose state of the chat that was opened and
send its draft to the previous chat.
- checkLinkPreview takes that state too. It re-read composeState rather
than what was passed in, and every text live message reaches it through
updateMsgContent, so it would have rebuilt the message from the opened
chat's draft instead of committing what was composed.
- every composeState write in sendMessageAsync is guarded by
composeIsForSend() (toChat.id == chat.id), which compares the two chats
instead of checking which one is open, so this send never takes the
compose state back if that chat is opened again before it completes.
- the chat switch branch then resets composeState to the opened chat's
draft, or to an empty state, like the branches below it do.
* plan: document the compose state handoff; correct the #7308 overlap resolution
The note on resolving the overlap with #7308 said its cs.liveMessage !=
null clause "already covers the send made by the chat switch". It does
not - in #7308 that clause sits outside the chatIsOpen check, which is
correct only while a live message is always sent to the chat that is
open, the assumption this fix removes. Read as written it exempts the
chat switch send from the guard that protects the opened chat, and a
merge that follows it reintroduces the leak.
Also records what manual test 2 was found failing on, and adds a slow
send variant so the window between the switch and the send completing is
long enough to type in the chat that was opened.
* android, desktop: keep reading the current state where a forward appends it
checkLinkPreview taking the composed state is needed where a live message
reaches it, but the forwarding branch is not one of those - it cannot run
with a chat other than the view's - and forwardItem suspends before it. So
there the captured state is stale by a network round trip, and text typed
while the forward was in flight stopped being appended to the message it
adds, while still being cleared when the send completed.
* plan: correct references and the claims that no longer hold
Line references were against the base this branch forked from, before
#7308 landed. Also: the live message loop no longer exits because the send
clears liveMessage - the chat switch replaces the compose state, on the
main thread, before the send runs; checkLinkPreview is not passed the
captured state everywhere; and chatsCtx.getChat can only return null in a
secondary context, which is not how "the chat is gone" reads.
Adds the two manual checks the review implied: a live message carrying a
link preview, which is what breaks if checkLinkPreview stops reading the
state it was given, and returning to the chat before the send completes.
* android, desktop: narrow the change to what the fix needs
- the draft id a failed message is saved under keeps using chat: that
branch is behind !liveSend, which the send made by a chat switch never
satisfies, so toChat is always chat where it is read;
- the state the chat switch installs no longer carries maxFileSize over.
That field is kept in sync on chat switch by LaunchedEffect(chat.chatInfo),
which is why the branches below this one construct it without one, and
the paths where that effect does not re-run are the ones where the send
overwrites the state anyway;
- sendMessageAsync takes its cs as a parameter rather than aliasing a
separately named one.
* plan: follow the narrowed change
* android, desktop: shorten the comments
The threading mechanism behind cs is explained where it is used, so the
function comment only has to say what it is; the rest is rewording.
* ios, android, desktop: fix message being sent leaking into another chat
Compose state is shared between the chats opened in the same view, and
the send is launched in a scope that outlives the chat, so a send that
was still in flight when the chat was switched put its message (with the
reply context) into the compose state and then the draft of another chat,
and a late success cleared whatever was typed in the meantime.
The message being sent is no longer kept in the compose state when
leaving the chat, and the compose state is only cleared or restored after
sending if it still holds the message that was sent - the same check is
used by the other senders that show progress in the compose. A message
that failed to send is restored in the chat it was composed in, or kept
as its draft when another chat is open (iOS has no failed message
restore, there the message is dropped as before).
* android, desktop: keep only the chat switch fix
Revert the iOS changes and the same check in the three senders that
connect a prepared chat, leaving the fix for the compose state shared
between the chats opened in one view.
* plan: document what the narrowed change leaves to the connect senders
* android, desktop: use the same check where the sending flag is shared
The senders that connect a prepared chat set the same inProgress flag,
so a connect completing after the chat was switched cleared it for a
send started in the chat opened next, and that sent message was then
left in the compose.
* android, desktop: keep the live message clauses inside the open chat check
live and cs.liveMessage != null were alternatives to chatIsOpen, which
holds only while a live message is always sent to the chat that is open.
#7323 removes that: the live message committed by a chat switch is sent
to the chat it was composed in, while this view already shows another
one, so an unguarded clause here clears that chat's compose state - the
leak this fix exists to prevent.
liveSend stays an alternative to inProgress inside the guard, so a live
send behaves exactly as before while its chat is open, and it is excluded
from the restore/draft branch, which would otherwise write a draft on
every failing keystroke send once that chat is no longer open. On this
branch the only behaviour change is a live send completing after its chat
was left, which now leaves the opened chat alone.
Also load the draft of the chat opened next when the compose state is
cleared on switching away from a send in flight: clearState() returns
before the branch that loads a draft, so that draft was never shown, and
being in the slot but in no compose state it was then dropped by
clearPrevDraft on the next chat switch.
* plan: explain why live sends are guarded by the open chat check
Records that the exemption in "Deliberately unchanged" is from a guard
based on inProgress, not from chatIsOpen, and why the earlier form broke
once #7323 sends a live message to a chat other than the one open.
The "Save passphrase in settings/Keychain" label had no weight, so Row
measured it at full available width, the weighted spacer collapsed to 0
and the trailing DefaultSwitch was placed past the row's right edge.
Harmless until #6777: the section card is now inset by CARD_PADDING and
clipped with SectionCardShape, which cut the row from 348dp to 316dp on
the desktop start pane and made the overflowing switch both invisible
and unclickable, since Modifier.clip clips pointer input too. With a
custom passphrase set the toggle is enabled but unreachable, so the
passphrase stays saved in settings and the app never prompts for it on
start.
Give the label weight(1f) and drop the weighted spacer, matching what
SettingsActionItemWithContent does for every other toggle row.
Group chat and its support chats have the same chat id, so a draft saved
in "chat with admins" was restored in the group chat and shown as its draft
in the chat list. Include chat scope in the draft chat id.
Also save the draft when support chat is closed without changing chat id -
in that case KeyChangeEffect that saves drafts doesn't run.