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>
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.
* Make Vulkan a *not required* feature
* Add `DeviceHasVulkanSupport` helper to check this on runtime
* When trying to open a screen with a map in it, check if vulkan is supported and display a new error dialog in that case
* Fix random lint issue
* Update screenshots
---------
Co-authored-by: ElementBot <android@element.io>
* Notification settings: pick custom sounds for messages and call ringtones (#6702)
* Feature: add notification sound settings for messages and calls
* Add sound not available banner, accessibility checks
* Fix build and Konsist convention violations
- libraries:preferences:api now uses io.element.android-compose-library
so NotificationSound's @Immutable annotation can resolve, matching the
pattern in libraries:matrix:api.
- Rename SoundUnavailableBannerStateProvider to
NotificationSoundUnavailableStateProvider so the class name contains
the parameter type as required by KonsistClassNameTest.
* Suppress LargeClass on RoomListPresenterTest
The three new sound-unavailable tests pushed the class past Detekt's
default LargeClass threshold. Matches the suppression pattern already
used on five presenter test classes under features/messages/impl/test.
* NotificationSettingsView: guard ringtone-picker launchers in inspection mode
rememberLauncherForActivityResult requires a LocalActivityResultRegistryOwner,
which Paparazzi-driven preview snapshot tests don't provide, causing
NotificationSettingsViewPreview to throw IllegalStateException for every
preview parameter. Extract the click handlers into a helper that returns a
no-op when LocalInspectionMode.current is true; the runtime path is unchanged.
* Handle unresolved notification sounds mid session
* Quality checks, refactor mid session error ui
* Suppress detekt LargeClass on NotificationSettingsPresenterTest
* Remove notification sound resilience layer, replace with file copy
* Reselect element sound option, code cleanup
* Add element fade notification sound option
* Fix new file headers
* Revert to flowOf(Unit) for announcement service
* Add ringtone picker dialog to match message selector
* Update strings in conjunction with ios
* Update test to reflect new string
* Sync strings.
* Update screenshots
* Fix test
* Remove not properly located translations.
This will be fixed in the next String sync.
* Fix test on CI
---------
Co-authored-by: Jenna Vassar <jenna.vassar@toptal.com>
Co-authored-by: ElementBot <android@element.io>
* Fix message type prefixes formatting inconsistencies
* Use new string for the poll summary prefix instead of the A11y text. Also add tests check for the bold spans.
---------
Co-authored-by: Jorge Martín <jorgem@element.io>
Resolved conflicts:
- libraries/matrix/impl/.../fakes/FakeFfiSpaceRoomList.kt: took upstream's
direct return for rooms() — the simulateLongTask wrapper is for IO-style
operations like paginate/reset, not a quick read.
- libraries/ui-strings/src/main/res/values/temporary.xml: kept the file with
only the live strings (action_mark_as_read, a11y_jump_to_unread_messages).
Dropped common_black (upstream moved theme strings to module-local R.string)
and a11y_jump_to_unread_messages_count (badge count was removed earlier).
- RoomInfo.kt and its fixtures/tests: took upstream's version since both
branches independently added fullyReadEventId via the same SDK bump
(matrix-rust-components-kotlin 26.05.20).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Improve `FetchPushForegroundService`'s reliability
- Don't use DI, we can just create the notification channel. This should speed up the creation of the service and reduce the number of `ForegroundServiceDidNotStartInTimeException` received. Also use `MainScope` instead of the app's coroutine scope.
- Move the wakelock releasing mechanism to `onDestroy` so it's always used. Previously, this would only happen when `stopService` was called, which would only happen when `stopSelf()` is called, but not when the OS or the service manager stops the service.
* Add fallback value for the notification channel title
* Replace the wrong string for the notification/channel title
---------
Co-authored-by: Benoit Marty <benoitm@element.io>
* Sync Strings from Localazy
* Use the previous plurals as plain strings
* Add extra case for 1 vs multiple users
* Update screenshots
---------
Co-authored-by: Jorge Martín <jorgem@element.io>