Commit Graph
1567 Commits
Author SHA1 Message Date
Narasimha-sc 522c27f1f9 fix: compute the settings change's unread contribution from the settings before the call
updateChatSettings read the chat's contribution and unread tag before the
change from the listed chat after apiSetSettings returned. An item event
processed during the call can already carry the new settings (addChatItem
-> updateChatInfo), so before equalled after: the count and the unread tags
kept the chat's old contribution. Before is now the listed chat's stats
with the listed chat's settings from before the call.
2026-10-19 15:07:08 +00:00
Narasimha-sc 9c74c54f3c fix: lower the profile unread count when a loaded chat has fewer unread
Opening a chat replaces its chatStats with the server's on Android and
desktop. When the chat was already listed and the server reports fewer
unread items than the list had (e.g. items expired or were read on
another path), the count now drops by the chat's contribution
difference, like every other stats writer.

A content-filtered initial load of a group returns zero stats when no
unread item matches the filter (otherwise the full counts), so a load
with a content filter doesn't move the count (statsFiltered). A search
never reaches this branch: the core rejects initial pagination with a
search.

It only moves down. A chat from outside the 5000-chat window can be
listed with empty stats before it is opened, while the seed already
counted its unread items; moving up on its first open would count them
twice. Chats the load adds come with the server's stats, which the seed
already counted, so the count stays as it is for them. Upward drift
corrects itself at the next reseed: resume on Android and iOS, a profile
switch, opening the profile picker, or changing the chat item TTL.

If a new item arrives between the load's query and its stats
replacement, the downward move can drop the count below the database
until the next reseed.

iOS keeps the listed chat's stats on load, so there is nothing to move there.
2026-10-19 15:06:31 +00:00
Narasimha-sc 787827c16a Merge branch 'master' into nd/fix-profile-unread-count 2026-10-19 14:54:58 +00:00
Narasimha-sc 8050fc1e9b fix: maintain the profile unread count by the same rule that seeds it
The count is seeded by getUsersInfo, which counts RcvNew items where ntfsEnabled
holds - every item for an unmuted chat, only mentions for a mentions-only one,
none for a muted one. The deltas that maintain it afterwards did not follow that
rule for the active profile: addChatItem incremented for every item regardless
of the chat's notification setting; on Android and desktop the mark-read helpers
subtracted the full unread count, while on iOS Mark read and Clear followed the
mentions-only setting but subtracted the full count for muted chats, and
per-item reads forwarded the raw delta; removeChat left a deleted chat's unread
behind; and changing the setting moved a chat between rules without moving the
count.

Chat.userUnreadCount names what a chat contributes, and it is not a new rule:
totalUnreadCountForAllUsers already computed exactly this inline for the app
badge, and now calls it. The sites that change a chat's stats, its settings or
its presence report the contribution before and after, and the count moves by
the difference - apart from the exceptions noted at the end.

For that to hold the stats it reads have to be maintained, so on Android and
desktop decreaseCounterInPrimaryContext now decrements unreadMentions alongside
unreadCount when the item was a mention. Without it a mentions-only chat's
contribution never moved on any of that function's three paths - a deleted item,
a moderated member item, or an item going from New to Read. iOS already passed
the mention delta on its deletion paths.

This is visible beyond the profile picker, which badges only other profiles: the
desktop tray dot sums the count across profiles including the active one, and on
iOS these same deltas drive the app icon badge. So on iOS, muting a chat with
unread now drops the badge by its contribution, deleting a chat drops it, and a
message in a muted chat no longer raises it - each of which now agrees with
totalUnreadCountForAllUsers, which the badge is also set from.

addChat is deliberately not the mirror of removeChat: adding a chat means it is
being loaded into view, and its items were already counted by the seed, so
counting them again on ChatItemsLoader's addChat would double them. The one
place that removes and re-adds a chat while keeping its items - deleting a
contact in "keep conversation" mode on iOS - now carries its stats across and
restores the contribution explicitly, since the core keeps both the contact row
and its items there and the seed still counts them.

Wherever the chat list is re-read wholesale the counts are re-read with it: both
resume paths, and setting a chat item TTL, which deletes the active profile's
items without per-item events and so leaves its count stale. They are assigned
before the chats, which matters on iOS because updateChats recomputes the app
badge from users there. Reading users is best effort on both
platforms - losing them must not cost us the chats already fetched.

This does not make the count exact. getUsersInfo has no group_scope_tag filter
where the query behind chatStats.unreadCount does, so the seed counts
support-scope items that no client-side rule can, and the count steps up by the
outstanding support unread on each reseed. replaceChat also installs a whole
chatStats without moving the count: on Android and desktop from a snapshot taken
before the API call, in ChatListNavLinkView's markChatRead and markChatUnread
and ChatView's markUnreadChatAsRead, and on iOS from the server in the
receivedContactRequest handler in SimpleXAPI. Settings changes that arrive in
events through updateChatInfo do not move it either.
2026-10-19 14:54:58 +00:00
+9 5b61fd5c99 ui: translations (#7770)
* website: disable badge page temporarily (#7516)

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>

* Translated using Weblate (German)

Currently translated at 100.0% (2921 of 2921 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% (2513 of 2513 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 100.0% (2921 of 2921 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% (2513 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/

* Translated using Weblate (Italian)

Currently translated at 100.0% (2921 of 2921 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Italian)

Currently translated at 100.0% (2513 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/it/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 99.9% (2920 of 2921 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.6% (2911 of 2921 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (2921 of 2921 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (2513 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/

* Translated using Weblate (Azerbaijani)

Currently translated at 32.9% (827 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/az/

* Translated using Weblate (Kurdish)

Currently translated at 29.3% (858 of 2921 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ku/

* Translated using Weblate (Kurdish)

Currently translated at 32.8% (961 of 2921 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ku/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 99.9% (2929 of 2930 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/

* Translated using Weblate (Italian)

Currently translated at 100.0% (2930 of 2930 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (2930 of 2930 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/

* Translated using Weblate (Kurdish)

Currently translated at 38.3% (1123 of 2930 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ku/

* Translated using Weblate (German)

Currently translated at 100.0% (2930 of 2930 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/

* Translated using Weblate (Azerbaijani)

Currently translated at 33.2% (835 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/az/

* Update translation files

Updated by "Cleanup translation files" hook in Weblate.

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 97.6% (2903 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 97.8% (2909 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (2972 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/

* Translated using Weblate (Hungarian)

Currently translated at 100.0% (2513 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/

* Translated using Weblate (Italian)

Currently translated at 98.0% (2913 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Italian)

Currently translated at 100.0% (2972 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 97.9% (2911 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/

* Translated using Weblate (German)

Currently translated at 100.0% (2972 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/

* Translated using Weblate (French)

Currently translated at 99.3% (2952 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/

* Translated using Weblate (Italian)

Currently translated at 100.0% (2972 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Italian)

Currently translated at 100.0% (2513 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/it/

* Translated using Weblate (Arabic)

Currently translated at 97.1% (2888 of 2972 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 99.8% (2967 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/

* Translated using Weblate (Spanish)

Currently translated at 99.0% (2943 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/

* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 99.9% (2971 of 2972 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% (2972 of 2972 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% (2513 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/es/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (2972 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 97.1% (2886 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/

* Translated using Weblate (Azerbaijani)

Currently translated at 37.4% (942 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/az/

* Translated using Weblate (French)

Currently translated at 100.0% (2972 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/

* Translated using Weblate (Czech)

Currently translated at 90.8% (2701 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/cs/

* Translated using Weblate (Azerbaijani)

Currently translated at 42.6% (1071 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/az/

* Translated using Weblate (Czech)

Currently translated at 91.0% (2705 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/cs/

* Translated using Weblate (Czech)

Currently translated at 50.2% (1264 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/cs/

* Translated using Weblate (Azerbaijani)

Currently translated at 45.2% (1136 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/az/

* Translated using Weblate (Azerbaijani)

Currently translated at 45.3% (1140 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/az/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2972 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt_BR/

* Translated using Weblate (Azerbaijani)

Currently translated at 46.2% (1162 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/az/

* Translated using Weblate (Portuguese)

Currently translated at 37.2% (1108 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt/

* Translated using Weblate (Portuguese)

Currently translated at 40.1% (1193 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt/

* Translated using Weblate (Portuguese)

Currently translated at 40.2% (1195 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pt/

* Translated using Weblate (Slovak)

Currently translated at 36.6% (1089 of 2972 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/sk/

* Translated using Weblate (Azerbaijani)

Currently translated at 47.0% (1183 of 2513 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/az/

* android, desktop: remove unused translations

* ui: fix translations (stale badge texts, missing placeholder, inverted and verbless strings)

- de, es, fr, hu, it, pt-BR, zh-Hans: re-translate badge strings from the current English (#7544 rewrote them after they were translated), restore the %1$s detail in badges_error_bad_service_response
- es, pt-BR: badges_savings is a discount, not "store"
- zh-Hans: Legend badge tier is 传奇, not a chart legend
- ku: "removed you" read as "you removed"; removed status is derxistî
- pt: verb buttons (Open, Archive, Save address settings, Paste link / Scan), link vs address in onboarding, accepted/removed %1$s events
- az (iOS): Mark deleted/verified/read, Keep conversation, Forward, Lock after, broken bold
- pt-BR: Monthly badge period, "shown on your profile" caption
- de: Support SimpleX as an action (it is also an alert button)
- cs (iOS): %d day singular, Test relay caption grammar

---------

Co-authored-by: Evgeny <evgeny@poberezkin.com>
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
Co-authored-by: mlanp <github@lang.xyz>
Co-authored-by: Ranakan <ranakan.dev@protonmail.ch>
Co-authored-by: Random <random-r@users.noreply.hosted.weblate.org>
Co-authored-by: Hosted Weblate user 54392 <hamburger2048@users.noreply.hosted.weblate.org>
Co-authored-by: SanctumSaturn <oraculogithub@gmail.com>
Co-authored-by: summoner001 <summoner@disroot.org>
Co-authored-by: Mireli5656 <miraliseyidli5656@gmail.com>
Co-authored-by: Terciman <ter.distant121@passinbox.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: jonnysemon <jonnysemon@users.noreply.hosted.weblate.org>
Co-authored-by: No name <usir.alerts@onionmail.org>
Co-authored-by: zenobit <zenobit@disroot.org>
Co-authored-by: Fábio Pereira (Serzedo) <fpereira-84@users.noreply.hosted.weblate.org>
Co-authored-by: Martin Kozempel <martin1928@users.noreply.hosted.weblate.org>
Co-authored-by: Mireli5656 <mireli5656@users.noreply.hosted.weblate.org>
Co-authored-by: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com>
2026-10-19 12:24:24 +00:00
2ea1ec0d50 ui: reconnect call (#7711)
* Update Call.hs

* Update Internal.hs

* add reconnecting string

* Update WebRTC.kt

* desktop: show reconnecting state, keep call duration

* android keep connection time correct wiith adding reconnecting

* Update CallTypes.swift add reconnecting status on IOS

* Update WebRTC.swift add reconnecting

* add reconnecting and make sure call duration is correct

* Update call.ts

* core: regenerate call.js from call.ts

* Update Call.hs revert call status change

minimization

* Update Internal.hs rever to minimize changes

* Update CallTypes.swift minimize changes

* Update WebRTC.kt minimize changes

* Update CallView.desktop.kt desktop shows reconnecting without sending to core

* Update CallView.android.kt show reconnecting without sending it to the core

* Update ActiveCallView.swift show reconnecting to ui without sending to core

* Update CallView.desktop.kt add reconnecting sound on reconnect

* Update CallView.android.kt add reconnecting sound

* Update ActiveCallView.swift play reconnecting sound when reconnecting

* Update RecAndPlay.desktop.kt

* rebuild

* refactor

* build

* android, desktop: restart ICE to reconnect calls

* ios: restart ICE to reconnect calls

* webrtc: add call reconnection e2e tests

* android, desktop: fix lost call commands

---------

Co-authored-by: GuavaGoat <320862384+GuavaGoat@users.noreply.github.com>
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-19 12:17:16 +01:00
EvgenyandEvgeny @ SimpleX Chat 0563460204 core, ui: support block markdown (#7734)
* plan: support block markdown

* update plans

* core, ui: markdown plans and implementation

* better

* simplify

* markdown tests and fixes

* implement

* fixes

* fix test

* bold

* block markdown rendering

* fix selection and rtl

* fixes

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-18 22:44:33 +01:00
EvgenyandEvgeny @ SimpleX Chat 77f9f4a464 core: add peer type "agent" (#7738)
* add agent peer type

* bot types

* agent app icons

* refactor

* smaller image

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-17 19:23:53 +01:00
spaced4ndy a356512645 Merge branch 'master' into badge-in-app-checkout 2026-10-16 22:07:28 +04:00
spaced4ndy c998eb1fee ios, android, desktop: use the production badge page 2026-10-16 21:30:55 +04:00
spaced4ndy 898c6f1266 ios, android, desktop: choose a badge on the website 2026-10-16 21:07:45 +04:00
sh aaa388e570 desktop: add emoji picker (#7708)
* desktop: add emoji picker data and generator

* desktop: emoji picker in compose field

* desktop: document compose emoji picker
2026-10-16 14:34:04 +01:00
spacedandy-agents-simplex e3324c6828 Merge branch 'master' into badge-in-app-checkout
# Conflicts:
#	simplex-chat.cabal
#	src/Simplex/Chat/Store/Postgres/Migrations.hs
#	src/Simplex/Chat/Store/SQLite/Migrations.hs
#	src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt
#	src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql
2026-10-16 09:40:53 +00:00
Narasimha-sc 23ca3ea42f desktop: hide SimpleX address and chat preferences rows with no profile and no mobile in use (#7717) 2026-10-15 05:37:37 +01:00
Narasimha-sc 000258224c desktop: fix crash in SimpleX address screen when there is no profile (#7679)
* desktop: fix crash in SimpleX address screen when there is no profile

* desktop: close SimpleX address screen when there is no profile

* desktop: rerun address screen self-close when its modal is reused or the stack changes

* desktop: close SimpleX address screen only when it is the top modal

* plans: correct address no-profile crash triggers and fix description

* plans: correct address no-profile crash fix description and verification

* plans: tighten address no-profile crash wording

* plans: add self-destruct trigger to address no-profile crash

* plans: qualify self-destruct trigger on desktop

* plans: drop desktop-only title from address no-profile crash

* plans: no connected mobile, not no mobile

* spec, product: document isLastModal and address screen without profile

* plans, spec, product: plan sections, address row spec, GAP-08 and GAP-09

* spec, product, plans: fix GAP-08/09 wording, table placement, ModalManager line

* spec, product: GAP-08/09 accuracy, gap count, clickable ModalManager location

* product, plans: GAP-09 at the level the code supports; qualify picker auto-open

* spec, product, plans: fix GAP-09 locations, stale line links, wording

* spec, product, plans: update plain-text line numbers; GAP-09 read wording

* plans: name the picker auto-open condition

* spec, plans: wording; security note

* plans: self-destruct did not crash on Android master; not a trigger

* plans: self-destruct path possible but unconfirmed; Android recovers silently

* spec, product, plans: drop GAP-09 and unrelated line refreshes

* plan: Android self-destruct path confirmed in logcat

* desktop: close Chat preferences screen when there is no profile, as the address screen does
2026-10-14 22:14:55 +01:00
spaced4ndy 59c588932e badge-service: verify App Store and Google Play purchases (#7654) 2026-10-13 15:24:07 +00:00
EvgenyandEvgeny @ SimpleX Chat 2f4a443dda ui: markdown viewer (#7702)
* ui: markdown viewer

* simplify

* fixes

* plan

* ios sheet, center modal on desktop

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-13 14:38:37 +01:00
EvgenyandEvgeny @ SimpleX Chat 7d870c6ff5 ui: open file after tap when it is received (#7700)
* ui: open file after tap when it is received

* fix ios

* simplify

* simplify

* better

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-13 11:24:14 +01:00
EvgenyandEvgeny @ SimpleX Chat 1bd7c95006 ui: additional check for plain domains (#7699)
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-13 08:53:04 +01:00
Evgeny d673a6b021 ui: show unicode characters in address as unicode markers (#7698)
* ui: show unicode characters in address as unicode markers

* defence in depth for links in messages (they are non-clickable from parser)

---------

Current code does not have this problem, as markdown parser rejects such links, and they are not clickable - it is needed for new markdown file viewer - this way unicode links in markdown show with unicode sequences instead of look-alike letters.
2026-10-13 08:42:59 +01:00
EvgenyandEvgeny @ SimpleX Chat 07c363849b core, ui: invite member of one group to another group (#7682)
* rfc: invite member of one group to another group

* update

* update

* implement

* version

* update

* do not show error if contact was removed when joining group

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-11 09:50:42 +01:00
Narasimha-sc 7d8a174388 android: recognise passphrase fields as passwords for password managers (#7612)
* android: recognise passphrase fields as passwords for password managers

Passphrase fields used a hand-rolled VisualTransformation lambda, so Compose never
marked them as password fields: the autofill structure carried no hints and no
password inputType, and password managers could not identify them. The raw
passphrase was also exposed through the CopyText/ACTION_COPY accessibility action.

PassphraseField now declares an autofill content type and uses
PasswordVisualTransformation, which sets the password semantics Compose derives
that flag from.

Fields that create a passphrase declare NewPassword. Where no field would carry
plain password (first-time setup, hidden profile password) they declare both, as
managers do not recognise a form whose every field is newPassword. On the change
form the current-passphrase field supplies password, so the new fields declare
only newPassword - adding password there leaves the manager unable to tell which
field holds the new value and suppresses the save prompt.

* android: do not offer to save hidden profile passwords

Hidden profile password fields no longer declare an autofill content type.
Compose commits the autofill session, which shows the password manager's
save prompt, only after the last field with a content type leaves the
screen, so these fields never trigger it. A saved entry would reveal that
the hidden profile exists.

Rewrite the plan to match the code.
2026-10-10 21:57:12 +01:00
Narasimha-scandEvgeny Poberezkin afcaf22100 android, desktop: storage breakdown in developer options (#7603)
* android, desktop: storage breakdown in developer options

Port of the iOS Storage screen (#5529): lists each top-level entry of the app's data, config and temp folders with its recursive size, so it is possible to see what takes space.

* android, desktop: simplify storage view

Use DefaultProgressView, drop the bold total and redundant absoluteFile, and do not follow top-level symlinks (matches iOS; avoids counting the Android lib link).

* android, desktop: storage view: do not crash on names the JVM cannot convert to Path

Under a non-UTF-8 locale on Linux, File.toPath() throws InvalidPathException for a non-ASCII top-level name (e.g. a received file decrypted into tmpDir); log it and show 0 bytes. Also correct plan wording.

* android, desktop: storage view: fold path conversion into treeSize, use produceState

Also correct plan wording (du per-directory overhead, unlistable roots, Windows junctions).

* android, desktop: storage view: open as card screen like other settings screens

* android, desktop: storage view: list top-level entries as Path to keep their exact names

File.listFiles + toPath loses names that are not valid in the JVM file-name encoding (non-ASCII under a C locale, invalid UTF-8), so those entries showed 0 bytes. Files.newDirectoryStream keeps the raw bytes.

* android, desktop: storage view: normalize root paths before dropping nested roots

A root spelled with .. (e.g. XDG_DATA_HOME=/x/data/../tmp) compared as nested in another root and its size was shown nowhere.

* android, desktop: document storage view in spec and product docs

* android, desktop: storage view: single catch when listing a root

* android, desktop: do not log file paths in storage view

The walk's IOException messages contain the full path, which in tmpDir can be a received file's original name.

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2026-10-10 21:55:08 +01:00
Narasimha-scandEvgeny Poberezkin d72f68e6dc android, desktop: free strings returned by the core (#7595)
The core allocates every chat_* response with malloc and passes ownership to
the caller, as iOS does in API.swift. Both JNI bindings copied the bytes into a
Java string and dropped the pointer, so every command, event and file read
leaked its whole response into the C allocator - invisible to both the JVM and
the Haskell heap profiler.

Desktop frees in decode_to_utf8_string, the funnel every entry point already
goes through. Android has no such funnel because NewStringUTF is called inline,
so decode_and_free is added and the call sites routed through it. chatReadFile
frees directly on both.

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2026-10-10 19:08:35 +01:00
Narasimha-sc 74c6b9d930 android: show attachment options above the keyboard (#7570) 2026-10-10 17:02:40 +01:00
spaced4ndy cf3d6c45d0 ios, android: tell the buyer once a run when a swept purchase cannot be handed over (#7674) 2026-10-09 11:59:39 +00:00
spaced4ndy 57ab333a2b Merge branch 'master' into badge-in-app-checkout 2026-10-09 15:00:36 +04:00
spaced4ndy 7c2c7503f2 ui: do not show "No relays" while leaving a channel (#7673) 2026-10-09 10:56:00 +00:00
EvgenyandEvgeny @ SimpleX Chat 9c9c86f9c0 core, ui: fix profiles, add error alerts (#7663)
* core, ui: fix profiles, add error alerts

* simplify

* query plans

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-08 22:53:59 +01:00
EvgenyandEvgeny @ SimpleX Chat 96970373b0 core: add status when switching queue (#7664)
* core: add status when switching queue

* fix

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-08 16:31:29 +01:00
spaced4ndy 75e6fe8f5d ios, android: tell the buyer a badge was added when the store purchase completes off screen (#7662) 2026-10-08 15:29:05 +00:00
shandspaced4ndy efab293609 desktop: deep links on macOS, Windows and Linux (#7605)
* tests: close the walk stream in withTempDir

* desktop: receive app links from args and macOS

* desktop: forward an app link to the running app

* desktop: initialize the desktop platform lazily

* tests: share the temp directory helper

* desktop: register simplexchat scheme in packages

* desktop: register simplexchat scheme at runtime

* ui: end the badge page with a link on desktop

* desktop: raise the window over other apps

* docs: describe desktop deep links in the spec

* docs: plan desktop deep links

* docs: report on desktop deep links

* desktop: open simplex connection links

* docs: describe simplex links on desktop

* desktop: keep a link from opening twice

* desktop: retry taking a signal held open

* desktop: keep the user's AppImage link handler

* desktop: register Windows links through Capabilities

* desktop: add %u to the deb entry only once

* docs: describe the review fixes

* ui: open the badge link screen on the left

* ui: import moko accessors in the badge screens

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2026-10-08 14:48:50 +00:00
EvgenyandEvgeny @ SimpleX Chat 0c1ffa65bc core: group fixes/improvements (#7660)
* core: group fixes/improvements

* Large messages dropped by relays and hosts (the same 15602 limit was applied, without accounting for forwarding header)
* Members below v18 did not receive forwarded messages or history in p2p groups.
* Join confirmations near the size limit could fail.
* SMP servers are limited to 2 host names each.

* simplify

* remove legacy forwarding and history support

* only restrict p2p groups

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-08 15:06:18 +01:00
spaced4ndy b4f1249436 core, ios, android: name the resolved store purchase so the app finishes it without a sweep (#7659) 2026-10-08 13:46:27 +00:00
spaced4ndy c0c5ba8393 Merge branch 'master' into badge-in-app-checkout 2026-10-08 16:49:27 +04:00
sh dd7768e543 android, desktop: upgrade moko-resources to 0.27.1 (#7661) 2026-10-08 12:32:57 +00:00
spaced4ndy 80b7f96a96 merge master into badge-in-app-checkout 2026-10-08 14:31:30 +04:00
spaced4ndy 27d12f230d core, ui: buy a badge with an App Store or Google Play purchase (#7590) 2026-10-07 14:32:48 +00:00
sh 40478c1c45 android: target API 36, AGP 8.10.1 (#7656)
* android: migrate back handling to callbacks

* android: target API 36, AGP 8.10.1

* android: opt out of predictive back app-wide
2026-10-07 10:30:26 +01:00
spaced4ndyandEvgeny Poberezkin 86671a1699 core, ui: confirm before connecting a call answered without e2e encryption (#7647)
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2026-10-05 09:45:57 +01:00
a9322ff32c android: prevent access to chat list when accepting call in locked state (#7627)
* android: prevent access to chat list when accepting call in locked state

* android: request auth on resume during a call

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
Co-authored-by: shum <github.shum@liber.li>
2026-10-04 12:07:39 +01:00
shandNarasimha-sc be05a46628 android: StrongBox for new keystore keys, show key storage level (#7637)
* android: create new keystore keys in StrongBox

* android: show keystore key storage level

* ui: save keystore key before marking it stored

* android: show keystore storage level in the footer text instead of a separate row

* android: return keystore storage label, drop enum

---------

Co-authored-by: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com>
2026-10-04 10:47:46 +01:00
1a969a6cb9 core, ui: remove database backups after key changes (#7628)
* core, ui: remove database backups after key changes

* ui: delete database backups on chat start without delaying encryption marker reset

Keeping encryptionStartedAt set until chat start made DatabaseErrorView show
"The attempt to change database passphrase was not completed" with a Restore
button after every successful passphrase change when the passphrase is not
stored. Restore the marker handling from master and delete backups
unconditionally after chat starts.

* another flag

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
Co-authored-by: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com>
2026-10-03 16:56:58 +01:00
SimpleX Chat 51630d61ef 7.1-beta.6: android 386, desktop 167, ios 362 2026-10-03 13:33:46 +00:00
Evgeny Poberezkin 6b596c0c35 Merge branch 'stable' 2026-10-03 08:05:19 +01:00
EvgenyandNarasimha-sc 53e6d435bc android, desktop: blur media thumbnails in reply quotes and the chat list (#7639)
"Blur media" hid images and videos in a chat but showed the same media
sharp as the thumbnail of a quoted message and as the last message's
image, video or link preview in the chat list.

Small views are now blurred with the same reveal as chat media. They are
resampled relative to the width they are drawn at, so a thumbnail is
blurred as much on screen as media in a chat, and drawn as the centre
crop the thumbnail shows. In-chat media keeps the same blur.

Blurring the chat list also needs: each last message gets its own blur
state, loaded chat-list videos use it and hide their full-screen play
button while blurred, a right-click on a thumbnail no longer leaves it
revealed on desktop, and leaving a chat mid-scroll no longer undoes
reveals in the list on Android.

Co-authored-by: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com>
2026-10-03 07:17:20 +01:00
EvgenyandEvgeny @ SimpleX Chat a1cf69e9a9 desktop: allow only one connection from call page (#7619)
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-02 17:06:48 +01:00
EvgenyandEvgeny @ SimpleX Chat 806943bd62 android, desktop: do not show caller profile in hidden preview mode (#7620)
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-10-02 17:02:24 +01:00
Narasimha-sc 205d17e2fa android, desktop: make media blur much lighter on CPU (#7483)
* ui: blur media by resampling the preview, not a per-frame effect

Modifier.blur put a BlurEffect on a display-sized graphics layer, so the
Gaussian was re-evaluated on every frame the media was drawn. It also
requires RenderEffect, which Android applies only from API 31, so below
Android 12 media was drawn unblurred while the setting read as on.

A blur and a downscale discard the same thing - detail finer than their
radius - so the preview is now resampled to about one pixel per radius and
stretched back. That runs once when the item composes, needs no
RenderEffect, and removes the detail irreversibly rather than convolving
it. The first resampling step bounds both sides, so no image, however
shaped, can produce a large intermediate.

While the blur hides the media the file is also left unread, so an image
scrolled past is no longer read, decoded at its full size and kept in the
image cache only to be hidden again. blurHidesMedia() is the single
definition that both the drawing and the loading decision use, so they
cannot disagree about whether the media is on screen.

* plans: blur media by resampling the preview

* ui: shorten comments in media blur

* ui: smooth the media blur and match its strength to the old one

Stretching the resampled preview straight to the screen showed its pixel grid. Double it back
up until its longest side is at least half the reference width before drawing, so the last
stretch is short and the tents compose into a bell. The reference width moves from 360 to 400:
fitted against Gaussians, 360 blurred 5-75% more than Modifier.blur did, 400 is within 10% at
every setting.

(cherry picked from commit c0344a9a61)
2026-10-02 15:59:38 +01:00
SimpleX Chat 2158f3039a 7.1-beta.5: android 383, desktop 165, ios 360 2026-09-30 15:58:31 +00:00