Rail: desktop parity (element-web rootSpaces) — spaces nested inside another
joined space no longer get a rail entry; their rooms stay reachable through
the parent space. Nested set persisted for clean cold starts.
Updater: new libraries/blapupdate module checks the git.utn.lol release feed
(6h throttle), offers a banner at the top of the chat list, downloads the
ABI-matched APK and hands it to the system installer. Per-version dismissal.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Space rail: selecting a space while another is selected kept serving the old
filter (unkeyed remember in SpaceFiltersPresenter) — key it on the space id.
Home: track child lists of all spaces (not just the selected one) and hide
space-owned rooms at Home, Discord-style. Filter chips still search everything;
the owned set is persisted so Home is clean on cold start. Voice rooms now
classify in every space without visiting it first.
ntfy: reconnect immediately when the default network returns instead of
waiting out up to 5 minutes of backoff, and surface the socket state
(Connected/Reconnecting) in the foreground-service notification.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Login/onboarding: Element swirl logo replaced with the purple five-dot mark,
onboarding + migration backgrounds regenerated as purple gradients
- Space rail: Discord-style animated selection pill on the left edge, corner
morph + accent ring on the selected item (there was no visible cue before)
- DM rows: bridged DMs (Discord/Telegram/WhatsApp/Signal/Slack/IRC/XMPP,
detected from the ghost user's mxid prefix) get a colored network badge
on the avatar
- Room list: section order now matches desktop everywhere — Text, Voice,
DMs last (the DMs-first-at-Home special case is gone)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Everything from port rounds 1-5 plus today's fixes, on top of upstream develop:
- Branding: Blap name/id (lol.utn.blap), purple #7c66e0 accent (both colorGreen*
and colorAlphaGreen* Compound ramps remapped), Hanken Grotesk, squircle
avatars, five-dot notification icon, de-branded strings across all locales
- Push: new libraries/pushproviders/ntfy module — FGS websocket to an ntfy
server's Matrix gateway, no Google. Includes base64 payload decode, restart
on boot/update/app-open, background-FGS-start crash guard, and a proactive
battery-optimization banner (Doze kills the socket without the exemption)
- Spoilers (MSC2010, interops with Blap desktop 1.0.3): render + tap-to-reveal,
Discord ||text|| send syntax, SPOILER_ filename convention for media both ways
- Home: Discord-style space rail, client-side room-list sections, DM-first sort
- Calls: embedded Element Call fork 0.20.3 assets (camera-off joins, bottom strip)
- Threads on by default; RTC ping timeline items hidden; reply-quote restyle
- URLs now point at git.utn.lol/enki/blap (was codeberg); version 26.07.2
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Announce expanded/collapsed state on the timeline group header
GroupHeaderView (the accordion-style header used for grouped state
events in the timeline) uses toggleable() combined with
clearAndSetSemantics { contentDescription = text }. The
clearAndSetSemantics block discards the state information that
toggleable() would otherwise expose, so TalkBack never announces
whether the group is currently expanded or collapsed.
Add an explicit stateDescription (two new a11y_state_expanded /
a11y_state_collapsed strings in temporary.xml) alongside the existing
contentDescription so the expanded/collapsed state is communicated to
assistive technology.
Internal note: this single-file/single-root-cause fix addresses three
separate BITV findings raised in the same accessibility audit against
this component's toggle semantics.
* Update screenshots
---------
Co-authored-by: ElementBot <android@element.io>
* Add content scanner support to media gallery and viewer
* Improve UI and previews
* Remove default content validation state in media content views
* Disable click for invalid media items in the gallery events
* Update screenshots
---------
Co-authored-by: ElementBot <android@element.io>
* Simplify how event content with captions are displayed
The caption component will now be added in `TimelineItemEventContentView` instead of separately in each `TimelineItem__View` component
* Make sure `CoilMediaFetcher` methods to fetch media throw errors
We need to catch them later to check if the content scanner marked some thumbnails or medias as invalid/unsafe in `AsyncImage` instances
* Add a `ContentScannerService` that allows us to manually scan a list of medias in an event and then update and store the results
The results take the form of `ContentValidationValue`, stored in a `ContentValidationState` instance tied to the event
* Create `EventContentValidationCache` to keep the `ContentValidationStates` for events in a room
* Expose `EventContentValidationCache` to Compose using `LocalEventContentValidationState`
Also add a couple of helper functions to avoid having to manually remember the states
* Use the new components to display invalid content in the timeline items
* Add `blurhash` to most media items so we can use it while validating the thumbnails/medias
* Fix custom layout issues with screenshot and UI tests
* Also check the validation state for replied-to events in the composer
* Fix and add tests
* Handle unrecoverable content validation errors too: display a 'not found' UI
* Improve the performance of `EqualWidthColumn` for the single item case
* Update screenshots
---------
Co-authored-by: ElementBot <android@element.io>
FormattingOption used clearAndSetSemantics with only a contentDescription,
so the Bold/Italic/Underline toggle buttons never exposed whether they
were currently active to TalkBack. Add a stateDescription reflecting the
selected/unselected state alongside the existing contentDescription.
New a11y_active / a11y_inactive strings added to temporary.xml for
Localazy import.
This can only happen when the app was killed by the OS and then you received some notification.
This notification action creates a new `DefaultSessionPreferencesStore` when trying to fetch `isSendPublicReadReceiptsEnabled`, which would contain a different session coroutine scope than the one created when instantiating the navigation graph (`@SessionCoroutineScope`), resulting in flows that never emit any items and close automatically as 'completed'.
This in turn prevented the timeline items subscription in `TimelinePresenter` from progressing, since we're also checking `isRenderReadReceiptsEnabled` there, which is closed and in turn closes the timeline items flow.
* Allow HS to disable encryption in Element Pro
Add `force_disable_e2ee` support in the Element well known retriever and cache to allow a homeserver to disable encrypted room creation and enabling encryption in an existing room in Element Pro clients
* Bump enterprise repo back to `main` branch
Picking an attachment reset the composer to Normal, which dropped an
in-progress edit: the attachment went out as a new message and the
leftover edit text then created another one instead of editing the
original.
Route every attach path through a single resetComposerModeAfterAttaching()
helper that clears Reply/Normal but keeps an edit pending, so the typed
text still edits the original on the next send. This also covers the
multi-item gallery picker added in #6519, which reset the mode
unconditionally.
Reply is still cleared (the attachment becomes the reply).
Fixes#7083.
* Create a `ContentScanner` component:
- Add `:features:contentscanner:api` module with the interface.
- Implement the concrete component using the Rust SDK in `:libraries:matrix:impl`.
This can be used to both set up the content scanner media fetching in the SDK Client and manually scanning media sources from the Android side
* Create `ContentScannerUrlProvider` in a new `:features:contentscaner:api` module as a noop implementation
Use it as a placeholder for the code to instantiate a `RustContentScanner` with the fetched URL and set it as part of the SDK client.
* Expose the optional `ContentScanner` in the `@SessionScope`
* Split the storage part of the Element well-known retriever so it can be reused for the non-session bound retriever.
Also add the new `content_scanner_url` field to it.
This will be used by the enterprise code to fetch the actual content scanner url.
* Bump enterprise commit to have access to the actual content scanner url provider implementation
* Fix tests and lint issues
* Use the right namespace for `:features:contentscanner:api`, also use the right namespace for `impl`
---------
Co-authored-by: Benoit Marty <benoitm@element.io>