mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-10-31 16:22:49 +00:00
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:
@@ -19,6 +19,7 @@ dependencies {
|
||||
api(projects.libraries.pushproviders.api)
|
||||
implementation(projects.libraries.designsystem)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
implementation(projects.libraries.preferences.api)
|
||||
implementation(projects.libraries.matrixui)
|
||||
implementation(projects.libraries.workmanager.api)
|
||||
implementation(projects.tests.testutils)
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.test.notifications
|
||||
|
||||
import io.element.android.libraries.preferences.api.store.NotificationSound
|
||||
import io.element.android.libraries.push.api.notifications.NotificationSoundUpdater
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
|
||||
class FakeNotificationSoundUpdater(
|
||||
private val recreateNoisyChannelLambda: (sound: NotificationSound, version: Int) -> Unit = { _, _ -> lambdaError() },
|
||||
private val recreateRingingCallChannelLambda: (sound: NotificationSound, version: Int) -> Unit = { _, _ -> lambdaError() },
|
||||
private val readNoisyChannelSoundLambda: () -> NotificationSound? = { null },
|
||||
private val readRingingCallChannelSoundLambda: () -> NotificationSound? = { null },
|
||||
) : NotificationSoundUpdater {
|
||||
override fun recreateNoisyChannel(sound: NotificationSound, version: Int) {
|
||||
recreateNoisyChannelLambda(sound, version)
|
||||
}
|
||||
|
||||
override fun recreateRingingCallChannel(sound: NotificationSound, version: Int) {
|
||||
recreateRingingCallChannelLambda(sound, version)
|
||||
}
|
||||
|
||||
override suspend fun readNoisyChannelSound(): NotificationSound? = readNoisyChannelSoundLambda()
|
||||
|
||||
override suspend fun readRingingCallChannelSound(): NotificationSound? = readRingingCallChannelSoundLambda()
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.test.notifications
|
||||
|
||||
import io.element.android.libraries.push.api.notifications.SoundDisplayNameResolver
|
||||
|
||||
class FakeSoundDisplayNameResolver(
|
||||
// Default resolves to a non-null sentinel so a default-constructed fake doesn't masquerade
|
||||
// as "every Custom URI is unresolvable" — that would trip mid-session detection paths in
|
||||
// every test that uses default fakes. Tests that need the unavailable case pass `{ null }`.
|
||||
private val resolveLambda: suspend (uri: String) -> String? = { "FakeRingtoneTitle" },
|
||||
) : SoundDisplayNameResolver {
|
||||
override suspend fun resolveCustomSoundTitle(uri: String): String? = resolveLambda(uri)
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.push.test.notifications.sound
|
||||
|
||||
import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier
|
||||
import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier.CopyResult
|
||||
import io.element.android.libraries.push.api.notifications.sound.NotificationSoundCopier.SoundSlot
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
|
||||
class FakeNotificationSoundCopier(
|
||||
private val copyLambda: (String, SoundSlot) -> CopyResult = { _, _ -> lambdaError() },
|
||||
private val deleteStoredSoundForLambda: (SoundSlot) -> Unit = {},
|
||||
) : NotificationSoundCopier {
|
||||
override suspend fun copyToAppFiles(sourceUriString: String, slot: SoundSlot): CopyResult = copyLambda(sourceUriString, slot)
|
||||
|
||||
override suspend fun deleteStoredSoundFor(slot: SoundSlot) {
|
||||
deleteStoredSoundForLambda(slot)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user