* core, ui: plan per-server roles for self-hosted servers
* core: add per-server roles field to UserServer
* core: add nullable role columns to protocol_servers
* core: persist per-server roles
* core: validate server coverage using per-server roles
* test: cover per-server roles resolution and coverage
* multiplatform: per-server role toggles for self-hosted servers
* ios: per-server role toggles for self-hosted servers
* core: per-server role overrides with per-role defaults
* test: cover three-state per-server role resolution
* fix: derive Eq for ServerRolesOverride
* multiplatform: three-state role dropdowns on saved servers
* ios: three-state role pickers on saved servers
* test: per-server roles independent across two servers
* test: enable names role in name-resolution tests
* style: trim comments in per-server roles code
* chore: rename server_roles migration to 20260716 (last)
* core: per-server roles override operator roles, inherit when unset
* multiplatform: per-server role default inherits from operator
* ios: per-server role default inherits from operator
* refactor(servers): tidy per-server roles per review
- dedup no-operator default into ServerRoles.noOperatorDefault (Kotlin/Swift)
- iOS: move roles-section control flow to the call site via a named gate,
and parse the server address once instead of up to three times
- Kotlin: collapse redundant derivedState; revert defaultOn->default rename
for cross-platform parity
- drop unused Hashable conformance on Swift ServerRoles
- add agentServerCfgs test for names inheritance from an operator
- remove no-op enableNamesRole calls from dormant DirectoryTests
- fix ChatClient import ordering
* chore(migration): date server_roles migration 20260720
* only show roles when server is enabled, move section above QR code
---------
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
On an incoming call the desktop window blinked continuously (FileNotFoundException
from SoundPlayer.start writing into a missing ...\Temp\simplex).
Root cause: Files.desktop top-level val initializers run in any process that
touches the facade class, including a transient second instance (which reaches
acquireSingleInstance -> dataDir). Two of them deleted shared state used by the
running primary:
- tmpDir had .also { deleteOnExit() } - the second instance's normal exit deleted
...\Temp\simplex, so the primary then failed to write call sounds/recordings.
- preferencesTmpDir had .also { deleteRecursively() } - the second instance's
<clinit> wiped configPath\tmp (same anti-pattern, firing even earlier).
Make both declarations pure and do the destructive cleanup in Main, past the
single-instance check, so only the owning instance performs it (preferencesTmpDir
kept early, before any settings write). The remaining val-initializer side effects
are idempotent creations (mkdirs) that destroy nothing and are left in place.
Wide images size their preview box with a fixed width of DEFAULT_MAX_IMAGE_WIDTH
(500dp). #7125 switched the box from .aspectRatio() to a fixed .height() computed
from that nominal width; on screens narrower than 500dp, .width(500dp) is clamped
to the available width but the fixed height is not, so the top-aligned FillWidth
image is shorter than its box, leaving an empty strip below.
Compute the height from the width actually granted via a small Modifier.layout so
it tracks the clamped width, restoring the self-correcting behaviour .aspectRatio()
had. coerceAtMost(w) keeps the box within its nominal width (and bounds the
unbounded intrinsic-measurement pass), and coerceAtLeast(0) mirrors what
Modifier.width()'s SizeNode does for a negative w on a tiny window - so both
dimensions stay in range and the #7123 Constraints overflow crash cannot recur.
* ui: what's new in 7.0 (#7265)
* docs: add Hosting your own Chat Relay guide (#7263)
* docs: add Hosting your own Chat Relay guide
* cli: run headless relay without a terminal
--headless (no -e) now runs via simplexChatCore instead of the terminal
UI, so the relay runs as a systemd service without a TTY (withTerminal
requires one). Drains the event queue logging only errors, and sets
stdout to line-buffering so logs reach the journal.
* docs/chat-relay: debounce service
* Apply suggestions from code review
Co-authored-by: Evgeny <evgeny@poberezkin.com>
---------
Co-authored-by: Evgeny <evgeny@poberezkin.com>
* Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 47.9% (179 of 373 strings)
Translation: SimpleX Chat/SimpleX Chat website
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/zh_Hant/
* Translated using Weblate (Turkish)
Currently translated at 63.0% (235 of 373 strings)
Translation: SimpleX Chat/SimpleX Chat website
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/tr/
* Translated using Weblate (Indonesian)
Currently translated at 95.7% (357 of 373 strings)
Translation: SimpleX Chat/SimpleX Chat website
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/website/id/
---------
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
Co-authored-by: Evgeny <evgeny@poberezkin.com>
Co-authored-by: HUGOALH <hugoalh@users.noreply.hosted.weblate.org>
Co-authored-by: Omer <abulomer2001@gmail.com>
Co-authored-by: Rafi <rafimuhmad90@protonmail.com>
* docs: add Hosting your own Chat Relay guide
* cli: run headless relay without a terminal
--headless (no -e) now runs via simplexChatCore instead of the terminal
UI, so the relay runs as a systemd service without a TTY (withTerminal
requires one). Drains the event queue logging only errors, and sets
stdout to line-buffering so logs reach the journal.
* docs/chat-relay: debounce service
* Apply suggestions from code review
Co-authored-by: Evgeny <evgeny@poberezkin.com>
---------
Co-authored-by: Evgeny <evgeny@poberezkin.com>
getLoadedImage subsampled with an OR cap on the larger side, so tall
images (e.g. phone screenshots) were reduced far below the display size
and rendered blurry. Mirror Android's calculateInSampleSize (keep the
smaller side at the target) so previews stay sharp, and add a decoded-
pixel ceiling so extreme aspect ratios can't blow up decode memory.
* desktop: show startup errors in a copyable window instead of bare "Failed to launch JVM"
When any exception escapes main() before the app window appears - a missing
DLL, a failed migration, broken AWT init - the jpackage launcher shows only
"Failed to launch JVM" and the cause is recorded nowhere: the launcher runs
without a console, so stderr is lost. Every report in #4146 stalled on this.
Catch the error and show it in a native Win32 window laid out like a message
box: an error icon and message, two clickable report links (the GitHub issue
tracker and the support email) above a read-only selectable box with the stack
trace, and an OK button. The links are SS_NOTIFY statics opened with
ShellExecute (browser for the URL, mail client for the email). Native, not
Swing, because broken AWT initialization is one of the failure causes. On
Windows the process then exits cleanly so the launcher does not also show its
own box; on other systems the error is rethrown to stderr.
* docs: plan justifying desktop startup error window (#4146)
* desktop: bundle jdk.accessibility to fix "Failed to launch JVM" when assistive technologies are enabled (#4146)
The jlinked runtime shipped in desktop packages did not include the
jdk.accessibility module. On Windows, when Java Access Bridge is enabled
(jabswitch -enable, "Enable Java Access Bridge" in Ease of Access, or a
screen reader creating %USERPROFILE%\.accessibility.properties), AWT
throws AWTError "Assistive Technology not found:
com.sun.java.accessibility.AccessBridge" during Toolkit init, before any
window or log output, and the jpackage launcher reports "Failed to
launch JVM".
* docs: plan justifying jdk.accessibility fix for Windows JVM launch (#4146)
* desktop: bundle jdk.accessibility only when building the Windows package