Notification settings: pick custom sounds for messages and call ringtones (#6897)

* 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>
This commit is contained in:
Benoit Marty
2026-05-28 16:54:12 +02:00
committed by GitHub
parent bdedf41f99
commit c88edc9621
79 changed files with 3135 additions and 139 deletions
@@ -245,19 +245,25 @@ private fun RoomsViewList(
)
}
}
SecurityBannerState.None -> if (state.fullScreenIntentPermissionsState.shouldDisplayBanner) {
item {
FullScreenIntentPermissionBanner(state = state.fullScreenIntentPermissionsState)
// Banner precedence (top-to-bottom): full-screen-intent > battery-optimization >
// new-notification-sound > sound-unavailable. At most one renders at a time.
SecurityBannerState.None -> when {
state.fullScreenIntentPermissionsState.shouldDisplayBanner -> {
item {
FullScreenIntentPermissionBanner(state = state.fullScreenIntentPermissionsState)
}
}
} else if (state.batteryOptimizationState.shouldDisplayBanner) {
item {
BatteryOptimizationBanner(state = state.batteryOptimizationState)
state.batteryOptimizationState.shouldDisplayBanner -> {
item {
BatteryOptimizationBanner(state = state.batteryOptimizationState)
}
}
} else if (state.showNewNotificationSoundBanner) {
item {
NewNotificationSoundBanner(
onDismissClick = { eventSink(RoomListEvent.DismissNewNotificationSoundBanner) },
)
state.showNewNotificationSoundBanner -> {
item {
NewNotificationSoundBanner(
onDismissClick = { eventSink(RoomListEvent.DismissNewNotificationSoundBanner) },
)
}
}
}
}
@@ -89,6 +89,7 @@ import org.junit.Rule
import org.junit.Test
import kotlin.time.Duration.Companion.seconds
@Suppress("LargeClass")
class RoomListPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()