Links now use the flat accent colour and default avatars the same
semi-transparent warm tint as dates and delivery ticks, instead of
sampling the sunrise gradient by on-screen position.
The sampling machinery did real work on every frame: link colour
recomposed as items scrolled, and each default avatar rendered
through an offscreen compositing layer to mask the gradient onto the
icon. Both are gone — links are a plain span colour, avatars set
their icon tint directly. Bubbles keep the position-sampled gradient
(they can't be flat-tinted: the wallpaper pattern would show through
and hurt text legibility). Non-SIMPLEX themes are unaffected.
Paints the SIMPLEX chat over one screen-spanning "sunrise" gradient:
- bubbles, avatars and links sample the gradient by on-screen position (a shared
20°-tilted axis anchored to the chat viewport);
- small text (dates, delivery checks, names, quoted authors, event notices,
call/voice/deleted secondary text) uses a per-wallpaper semi-transparent warm
tint, so it stays evenly legible over the gradient;
- decryption/integrity-error and deleted/marked-deleted bubbles use the received
gradient instead of a flat grey;
- wallpaper stops and secondary colours resolve from the composition, so per-chat
wallpaper overrides and the wallpaper-picker preview render correctly.
Side effects for all themes (details in the PR): event/feature text follows the
active theme instead of a start-up-frozen colour, and the via-proxy meta icon
matches the meta row on media bubbles.
Each preset wallpaper in the SIMPLEX theme now paints a per-wallpaper colour
gradient behind the chat (the pattern still shows on top) instead of a flat
background — the "sunrise" look the theme was designed around. Other themes
are unchanged. Bubble/text colours and the pattern-image refresh follow in
later PRs.
Opening a video full screen could crash with NoSuchElementException from
VLC native-library discovery. Each MediaPlayerFactory() runs a JDK
ServiceLoader (not thread-safe), and the second preview factory added in
#6924 let the render thread and preview thread construct factories
concurrently. Serialize the two constructions behind a shared lock.
* android, desktop, ios: remove left padding on consecutive received messages in channels
In channels, a received message that does not show an avatar (a consecutive post from the same sender) drops the avatar-sized left padding and sits flush-left. Applies to both owner broadcasts (ChannelRcv) and contributor posts (GroupRcv); the first message of each run still shows the avatar. Gated on ChatInfo.isChannel, so regular groups, business and direct chats, sent messages, and avatar-shown messages are unchanged.
* docs: add plan justifying removing left padding on consecutive received messages in channels
* ios: fix right gap on consecutive received messages in channels
Removing the avatar-sized left padding from no-avatar received messages
(this PR) shifted those bubbles ~44pt left, but maxWidth still reserved
the avatar inset, so consecutive messages stopped ~44pt short of the
first (avatar) message on the right.
Widen maxWidth for no-avatar channel-received items so their right edge
matches the avatar-shown first message. The no-avatar predicate reuses
the exact shouldShowAvatar expression from the render path (lifted to a
file-scope function so the maxWidth site can call it), so the width and
the rendered layout can never disagree.
Android is unaffected: Compose derives content width from padding, so
reducing the start padding already widened the row there.
* ios: increase left padding
* kotlin: increase left gap
---------
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
* android, desktop: fix crash on opening chat with extremely wide image
An image with an extreme aspect ratio (e.g. 4000x1) made the chat
unopenable: the framed item's Box clamped its aspectRatio only on the
low side (coerceAtLeast(1f / 2.33f)), leaving very wide images
unbounded. During an intrinsic measure pass Compose derives
width = height * ratio, which for a 4000:1 image overflows Constraints
and throws IllegalArgumentException on every render.
Add the symmetric upper bound (coerceIn(1f / 2.33f, 2.33f)), matching
the existing tall-image height cap in PriorityLayout
(constraints.maxWidth * 2.33f).
* docs: add plan justifying wide-image chat crash fix
The armv7a-android cross-compiler GHC refuses to disambiguate the bare
record update m {memberRole = role} (the field is shared by many record
types), failing the lib:simplex-chat build with "Record update is
ambiguous, and requires a type signature".
Annotate the updated record as (m :: GroupMember), matching the existing
workaround already used a few lines below in the same function.
* Fix group link use after admin demotion
* fix: group role change
* size limit
* fix
* allow delete
* do not remove link
* query plan
* relay test
* refactor
---------
Co-authored-by: Paul Bottinelli <paul.bottinelli@trailofbits.com>
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
* desktop: fix updater deleting the download before "Open file location"
The in-app updater downloads to a temp UUID file via createTmpFileAndDelete,
then relies on `file.renameTo(newFile)` to move the bytes to the asset name so
they survive that helper's `finally { tmpFile.delete() }`. The rename's return
value was ignored: if it failed, the bytes stayed at the UUID path and the
finally block deleted the only copy, so the "Download completed" dialog appeared
but "Open file location" opened an empty /tmp/simplex.
Use Files.move with REPLACE_EXISTING instead. It performs the same in-place
rename when possible (verified: inode preserved, no copy), falls back to
copy+delete when an atomic rename isn't possible, and throws on genuine failure
- which the existing outer catch handles - instead of silently losing the file.
* docs: plan for updater open-file-location fix
* docs: plan - note Whonix compatibility (updater previously failed there)
* core: block obfuscated simplex links if the group does not allow them
* remove newlines
* remove renames
* name
* more efficient parser
* remove comment
---------
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
* android, desktop, ios: remove right gap on received messages in channels
In channels received messages now use the full row width instead of the chat-bubble right gap, matching the broadcast/feed style. Gated on ChatInfo.isChannel (useRelays), the always-present channel flag used across the channel UI; sent messages and non-channel groups, business and direct chats are unchanged.
* docs: add plan justifying removing right gap on received messages in channels
---------
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
* docs: add channel webpage setup guide
Step-by-step guide for channel owners to set up a web preview page:
enable the webpage in the app, copy the generated embed code, and host
the page. Includes the customizable data-* attributes and troubleshooting.
Linked from the user guide contents.
* docs: reorder channel webpage steps to recommended flow
Set up embedding first to build and test the page from any address,
and set the webpage URL last so the link is only shown to subscribers
once the page works. Also drop the incorrect 'Save and notify channel
subscribers' prompt references (that dialog only appears when leaving
with unsaved changes, not on Save).
* ios: open SimpleX links in chat messages via in-app connect flow
Tapping an inline SimpleX connection link in message text was dispatched
through UIApplication.shared.open. iOS drops an open() of a URL owned by
the same app while it is in the foreground (the simplex: scheme and the
simplex.chat universal links both belong to this app), so the tap was
ignored and never reached the connection flow. Web links (Safari) and
mailto:/tel: (other apps) were unaffected, which is why only SimpleX
links appeared dead.
Route SimpleX links to ChatModel.appOpenUrl instead - the same sink
onOpenURL feeds, leading to connectViaUrl/planAndConnect. This matches
the connection-link card and the multiplatform clients, which connect
in-process rather than via an OS round-trip.
Also fixes the same problem for the "Send questions and ideas" and
"connect to SimpleX Chat developers" buttons, which open simplexTeamURL
(a simplex: link) the same broken way.
* docs: plan - justify iOS in-app dispatch for SimpleX links in messages
Root cause and justification for opening inline SimpleX links via the
in-app connect flow instead of UIApplication.shared.open (undefined
re-entry of the same foreground app for a self-owned simplex: URL).