* core: round down time of sent messages to prevent replies showing above if they are within one second
* fix item timestamps
* query plans
---------
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
* ci: fix mac library build to sign and notarize library
* script
* sign and notarize to test
* remove test build
---------
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
Add Painter.mirrorIfRtl() for icons drawn by shared helpers that take a
Painter, and use it for the delivery receipts "Don't enable" chevron and
the "Show message status" arrow. Mirror the forwarded delivery status
chevron. Place the rows of framed messages (e.g. image captions), the
group member name row and the supporter banner image relative to the
layout direction.
Update the plan: these are no longer deferred, and correct its
descriptions of the dropdown, the chat list header and the tail side.
Surgical refinements on top of the initial RTL fix, plus a design doc
in plans/.
- chatItemShape (ChatItemView.kt): extract `val tailOnRight = ...` so
the predicate names what the conditional does. Comment trimmed to
the single load-bearing invariant ("default path draws tail at
bottom-left") since the rest is implied by the variable name.
- SubscriptionStatusIcon.kt: hoist `val iconModifier =
modifier.mirrorIfRtl()` once at the top of the composable and reuse
it at all five Icon call sites. Calling mirrorIfRtl five times or
once produces the same Modifier within one composition.
- GoToItemInnerButton (ChatItemView.kt): add `mirror: Boolean = false`
parameter and pass `mirror = true` at the directional call site
(ic_arrow_forward, "go to forwarded source"). The other call site
(ic_search) keeps the default and is unchanged.
- Modifiers.kt, FramedItemView.kt: drop two explanatory comments that
restated framework-primitive behavior (mirrorIfRtl's own name, and
the documented behavior of placeRelative).
plans/2026-05-13-rtl-layout-issues.md documents the three independent
mechanisms behind the fix (bubble shape, app-bar slot placement,
asymmetric drawables), the bubble-tail XOR predicate, and four
considered-and-rejected alternatives.
Fixes https://github.com/simplex-chat/simplex-chat/issues/5448
The original report documents four user-visible regressions under an RTL
locale (Arabic, Persian, Hebrew): chat bubble tails on the wrong side,
chat header call/menu buttons not mirrored, settings back arrow pointing
the wrong way, and the chat list profile avatar laid out in its LTR
position. This commit addresses all of them and a handful
of related directional-icon mirroring sites discovered during the audit.
- Chat bubble tail direction: chatItemShape now reads layoutDirection
from the GenericShape lambda and conditions the matrix mirror on
sent != isRtl, so sent-bubble tails are on the outer (end) edge and
received-bubble tails point toward the contact's profile under both
LTR and RTL. The bubble-tail paddings in FramedItemView and ChatView
already use direction-aware start/end and now align with the
mirrored shape automatically.
- App-bar slot mirroring: CenteredRowLayout in FramedItemView switches
from place(...) to placeRelative(...) so the navigation icon and the
action buttons swap visual sides under RTL. Both the chat header
(call/menu buttons) and the chat list header (profile avatar) flow
through this layout, so one fix covers both.
- Asymmetric directional drawables: add Modifier.mirrorIfRtl()
(Modifier.scale(-1f, 1f) when LocalLayoutDirection.current is Rtl)
and apply it to the back arrow in NavigationButtonBack, every variant
of the SubscriptionStatusIcon waves, the WhatsNewView pagination
arrows, the back arrow and submenu chevron in CommandsMenuView, the
back arrow in OnboardingCards and ImageFullScreenView.desktop, the
share-profile chevron in NewChatView, and the sent-via-proxy arrow
in CIMetaView and ChatItemInfoView.
DropdownMenu offsets in ChatView (DpOffset(-width, ...)) are left
unchanged: DropdownMenuPositionProvider already negates the content
offset under RTL, and the menus hang from their own anchor boxes.
* 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
* ci: use default registries for empty variables
* ci: drop package publish tags
* ci: record releases in simplex-chat-libs
* ci: skip recorded versions in publish plan
* nodejs: raise default test timeout for migrations
* nodejs: print download progress without console.error
* nodejs: use the default timeout in migrating core tests
* badge-service: accept a list of Apple roots
* badge-service: document root_certificates
---------
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
* ci: drop dlltool from nodejs libs release
* nodejs: download libsimplex into the user cache
* nodejs: load libsimplex at runtime per backend
* support bot: select db backend with --db
* python: match backend switch error text
* nodejs: download prebuilt add-on at runtime
* ci: build nodejs add-on for libs release
* calculator bot: load libs and add-on in image
* support bot: document add-on override
* nodejs: keep worker test output free of colors
* nodejs: verify sha-256 of downloaded assets
* python: pin core libs release with sha-256
* ci: add packages release script
* ci: release nodejs add-on and open release PR
* ci: publish packages after release PR
* nodejs: keep npm from building the add-on
* calculator bot: build the add-on in the image
* ci: merge package release workflows
* ci: open release PR when publishing fails
* ci: build the add-on with node-addon-api only
* ci: skip publishing in a called packages workflow
* ci: update package release actions to Node 24
* nodejs: fix receive test timeout
* ci: test packages on pull requests
* nodejs: reuse the database in the close stress test
* ci: keep failed package tests from hanging
* ci: skip preset server tests
* ci: plan package builds from the changes
* ci: test packages with a given libsimplex
* ci: test packages with libsimplex of core changes