Skip to content

Commit 8f94b4c

Browse files
authored
Merge pull request #4845 from element-hq/feature/bma/batteryOptimization
Add a banner to ask the user to disable battery optimization when Event cannot be resolved from Push
2 parents 23efebe + 751f7e7 commit 8f94b4c

File tree

39 files changed

+776
-36
lines changed

39 files changed

+776
-36
lines changed

features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/notifications/NotificationSettingsView.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import io.element.android.libraries.designsystem.theme.components.IconSource
3838
import io.element.android.libraries.designsystem.theme.components.ListItem
3939
import io.element.android.libraries.designsystem.theme.components.Text
4040
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
41+
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsEvents
4142
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
4243
import io.element.android.libraries.ui.strings.CommonStrings
4344
import kotlinx.collections.immutable.toImmutableList
@@ -149,7 +150,7 @@ private fun NotificationSettingsContentView(
149150
Text(stringResource(R.string.full_screen_intent_banner_message))
150151
},
151152
onClick = {
152-
state.fullScreenIntentPermissionsState.openFullScreenIntentSettings()
153+
state.fullScreenIntentPermissionsState.eventSink(FullScreenIntentPermissionsEvents.OpenSettings)
153154
}
154155
)
155156
}

features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListContentStateProvider.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
1212
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
1313
import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState
1414
import io.element.android.libraries.matrix.api.core.RoomId
15+
import io.element.android.libraries.push.api.battery.BatteryOptimizationState
16+
import io.element.android.libraries.push.api.battery.aBatteryOptimizationState
1517
import kotlinx.collections.immutable.ImmutableList
1618
import kotlinx.collections.immutable.persistentListOf
1719
import kotlinx.collections.immutable.toPersistentSet
@@ -31,10 +33,12 @@ internal fun aRoomsContentState(
3133
securityBannerState: SecurityBannerState = SecurityBannerState.None,
3234
summaries: ImmutableList<RoomListRoomSummary> = aRoomListRoomSummaryList(),
3335
fullScreenIntentPermissionsState: FullScreenIntentPermissionsState = aFullScreenIntentPermissionsState(),
36+
batteryOptimizationState: BatteryOptimizationState = aBatteryOptimizationState(),
3437
seenRoomInvites: Set<RoomId> = emptySet(),
3538
) = RoomListContentState.Rooms(
3639
securityBannerState = securityBannerState,
3740
fullScreenIntentPermissionsState = fullScreenIntentPermissionsState,
41+
batteryOptimizationState = batteryOptimizationState,
3842
summaries = summaries,
3943
seenRoomInvites = seenRoomInvites.toPersistentSet(),
4044
)

features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import io.element.android.libraries.matrix.api.sync.SyncService
5252
import io.element.android.libraries.matrix.api.timeline.ReceiptType
5353
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
5454
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
55+
import io.element.android.libraries.push.api.battery.BatteryOptimizationState
5556
import io.element.android.libraries.push.api.notifications.NotificationCleaner
5657
import io.element.android.services.analytics.api.AnalyticsService
5758
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
@@ -88,6 +89,7 @@ class RoomListPresenter @Inject constructor(
8889
private val analyticsService: AnalyticsService,
8990
private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
9091
private val fullScreenIntentPermissionsPresenter: Presenter<FullScreenIntentPermissionsState>,
92+
private val batteryOptimizationPresenter: Presenter<BatteryOptimizationState>,
9193
private val notificationCleaner: NotificationCleaner,
9294
private val logoutPresenter: Presenter<DirectLogoutState>,
9395
private val appPreferencesStore: AppPreferencesStore,
@@ -248,6 +250,7 @@ class RoomListPresenter @Inject constructor(
248250
RoomListContentState.Rooms(
249251
securityBannerState = securityBannerState,
250252
fullScreenIntentPermissionsState = fullScreenIntentPermissionsPresenter.present(),
253+
batteryOptimizationState = batteryOptimizationPresenter.present(),
251254
summaries = roomSummaries.dataOrNull().orEmpty().toPersistentList(),
252255
seenRoomInvites = seenRoomInvites.toPersistentSet(),
253256
)

features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListState.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
1818
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
1919
import io.element.android.libraries.matrix.api.core.RoomId
2020
import io.element.android.libraries.matrix.api.user.MatrixUser
21+
import io.element.android.libraries.push.api.battery.BatteryOptimizationState
2122
import kotlinx.collections.immutable.ImmutableList
2223
import kotlinx.collections.immutable.ImmutableSet
2324

@@ -78,6 +79,7 @@ sealed interface RoomListContentState {
7879
data class Rooms(
7980
val securityBannerState: SecurityBannerState,
8081
val fullScreenIntentPermissionsState: FullScreenIntentPermissionsState,
82+
val batteryOptimizationState: BatteryOptimizationState,
8183
val summaries: ImmutableList<RoomListRoomSummary>,
8284
val seenRoomInvites: ImmutableSet<RoomId>,
8385
) : RoomListContentState

features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListStateProvider.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
2727
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
2828
import io.element.android.libraries.matrix.api.core.UserId
2929
import io.element.android.libraries.matrix.api.user.MatrixUser
30+
import io.element.android.libraries.push.api.battery.aBatteryOptimizationState
3031
import io.element.android.libraries.ui.strings.CommonStrings
3132
import kotlinx.collections.immutable.ImmutableList
3233
import kotlinx.collections.immutable.persistentListOf
@@ -45,6 +46,7 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
4546
aRoomListState(contentState = aSkeletonContentState()),
4647
aRoomListState(searchState = aRoomListSearchState(isSearchActive = true, query = "Test")),
4748
aRoomListState(contentState = aRoomsContentState(securityBannerState = SecurityBannerState.SetUpRecovery)),
49+
aRoomListState(contentState = aRoomsContentState(batteryOptimizationState = aBatteryOptimizationState(shouldDisplayBanner = true))),
4850
)
4951
}
5052

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.features.roomlist.impl.components
9+
10+
import androidx.compose.runtime.Composable
11+
import androidx.compose.ui.Modifier
12+
import androidx.compose.ui.res.stringResource
13+
import io.element.android.features.roomlist.impl.R
14+
import io.element.android.libraries.designsystem.components.Announcement
15+
import io.element.android.libraries.designsystem.components.AnnouncementType
16+
import io.element.android.libraries.designsystem.preview.ElementPreview
17+
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
18+
import io.element.android.libraries.push.api.battery.BatteryOptimizationEvents
19+
import io.element.android.libraries.push.api.battery.BatteryOptimizationState
20+
import io.element.android.libraries.push.api.battery.aBatteryOptimizationState
21+
22+
@Composable
23+
internal fun BatteryOptimizationBanner(
24+
state: BatteryOptimizationState,
25+
modifier: Modifier = Modifier,
26+
) {
27+
Announcement(
28+
modifier = modifier.roomListBannerPadding(),
29+
title = stringResource(R.string.banner_battery_optimization_title_android),
30+
description = stringResource(R.string.banner_battery_optimization_content_android),
31+
type = AnnouncementType.Actionable(
32+
actionText = stringResource(R.string.banner_battery_optimization_submit_android),
33+
onActionClick = { state.eventSink(BatteryOptimizationEvents.RequestDisableOptimizations) },
34+
onDismissClick = { state.eventSink(BatteryOptimizationEvents.Dismiss) },
35+
),
36+
)
37+
}
38+
39+
@PreviewsDayNight
40+
@Composable
41+
internal fun BatteryOptimizationBannerPreview() = ElementPreview {
42+
BatteryOptimizationBanner(
43+
state = aBatteryOptimizationState(),
44+
)
45+
}

features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/FullScreenIntentPermissionBanner.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import io.element.android.libraries.designsystem.components.Announcement
1515
import io.element.android.libraries.designsystem.components.AnnouncementType
1616
import io.element.android.libraries.designsystem.preview.ElementPreview
1717
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
18+
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsEvents
1819
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
1920
import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState
2021
import io.element.android.libraries.ui.strings.CommonStrings
@@ -29,8 +30,8 @@ fun FullScreenIntentPermissionBanner(
2930
description = stringResource(R.string.full_screen_intent_banner_message),
3031
type = AnnouncementType.Actionable(
3132
actionText = stringResource(CommonStrings.action_continue),
32-
onDismissClick = state.dismissFullScreenIntentBanner,
33-
onActionClick = state.openFullScreenIntentSettings,
33+
onDismissClick = { state.eventSink(FullScreenIntentPermissionsEvents.Dismiss) },
34+
onActionClick = { state.eventSink(FullScreenIntentPermissionsEvents.OpenSettings) },
3435
),
3536
modifier = modifier.roomListBannerPadding(),
3637
)

features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/components/RoomListContentView.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ private fun EmptyView(
149149
onDismissClick = { eventSink(RoomListEvents.DismissBanner) },
150150
)
151151
}
152-
else -> Unit
152+
SecurityBannerState.None -> Unit
153153
}
154154
}
155155
}
@@ -234,6 +234,10 @@ private fun RoomsViewList(
234234
item {
235235
FullScreenIntentPermissionBanner(state = state.fullScreenIntentPermissionsState)
236236
}
237+
} else if (state.batteryOptimizationState.shouldDisplayBanner) {
238+
item {
239+
BatteryOptimizationBanner(state = state.batteryOptimizationState)
240+
}
237241
}
238242
}
239243

features/roomlist/impl/src/main/res/values/localazy.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
3+
<string name="banner_battery_optimization_content_android">"Disable battery optimization for this app, to make sure all notifications are received."</string>
4+
<string name="banner_battery_optimization_submit_android">"Disable optimization"</string>
5+
<string name="banner_battery_optimization_title_android">"Notifications not arriving?"</string>
36
<string name="banner_set_up_recovery_content">"Recover your cryptographic identity and message history with a recovery key if you have lost all your existing devices."</string>
47
<string name="banner_set_up_recovery_submit">"Set up recovery"</string>
58
<string name="banner_set_up_recovery_title">"Set up recovery to protect your account"</string>

features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import io.element.android.libraries.preferences.api.store.AppPreferencesStore
7575
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
7676
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
7777
import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore
78+
import io.element.android.libraries.push.api.battery.aBatteryOptimizationState
7879
import io.element.android.libraries.push.api.notifications.NotificationCleaner
7980
import io.element.android.libraries.push.test.notifications.FakeNotificationCleaner
8081
import io.element.android.services.analytics.api.AnalyticsService
@@ -712,6 +713,7 @@ class RoomListPresenterTest {
712713
analyticsService = analyticsService,
713714
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter,
714715
fullScreenIntentPermissionsPresenter = { aFullScreenIntentPermissionsState() },
716+
batteryOptimizationPresenter = { aBatteryOptimizationState() },
715717
notificationCleaner = notificationCleaner,
716718
logoutPresenter = { aDirectLogoutState() },
717719
appPreferencesStore = appPreferencesStore,

0 commit comments

Comments
 (0)