Merge branch 'develop' into feature/bma/scroll-to-unread-messages

This commit is contained in:
Benoit Marty
2026-06-08 17:30:11 +02:00
278 changed files with 2880 additions and 1792 deletions
@@ -279,6 +279,7 @@ private fun RoomsViewList(
hideInviteAvatars = hideInvitesAvatars,
isInviteSeen = room.displayType == RoomSummaryDisplayType.INVITE &&
state.seenRoomInvites.contains(room.roomId),
showUnreadCount = state.showUnreadCount,
onClick = onRoomClick,
eventSink = eventSink,
)
@@ -76,8 +76,9 @@ internal fun RoomSummaryRow(
hideInviteAvatars: Boolean,
isInviteSeen: Boolean,
onClick: (RoomListRoomSummary) -> Unit,
eventSink: (RoomListEvent) -> Unit,
modifier: Modifier = Modifier,
showUnreadCount: Boolean = false,
eventSink: (RoomListEvent) -> Unit,
) {
Box(modifier = modifier) {
when (room.displayType) {
@@ -127,7 +128,7 @@ internal fun RoomSummaryRow(
timestamp = room.timestamp,
isHighlighted = room.isHighlighted
)
MessagePreviewAndIndicatorRow(room = room)
MessagePreviewAndIndicatorRow(room = room, showUnreadCount = showUnreadCount)
}
}
RoomSummaryDisplayType.KNOCKED -> {
@@ -273,6 +274,7 @@ private fun InviteSubtitle(
@Composable
private fun MessagePreviewAndIndicatorRow(
room: RoomListRoomSummary,
showUnreadCount: Boolean,
modifier: Modifier = Modifier,
) {
Row(
@@ -360,8 +362,18 @@ private fun MessagePreviewAndIndicatorRow(
}
if (room.hasNewContent) {
val contentDescription = stringResource(CommonStrings.a11y_notifications_new_messages)
val count = if (showUnreadCount) {
if (room.userDefinedNotificationMode == RoomNotificationMode.MUTE) {
room.numberOfUnreadMessages
} else {
room.numberOfUnreadNotifications
}
} else {
null
}
UnreadIndicatorAtom(
color = tint,
count = count,
contentDescription = contentDescription,
)
}
@@ -36,6 +36,7 @@ open class RoomListContentStateProvider : PreviewParameterProvider<RoomListConte
internal fun aRoomsContentState(
securityBannerState: SecurityBannerState = SecurityBannerState.None,
showNewNotificationSoundBanner: Boolean = false,
showUnreadCount: Boolean = false,
summaries: ImmutableList<RoomListRoomSummary> = aRoomListRoomSummaryList(),
fullScreenIntentPermissionsState: FullScreenIntentPermissionsState = aFullScreenIntentPermissionsState(),
batteryOptimizationState: BatteryOptimizationState = aBatteryOptimizationState(),
@@ -43,6 +44,7 @@ internal fun aRoomsContentState(
) = RoomListContentState.Rooms(
securityBannerState = securityBannerState,
showNewNotificationSoundBanner = showNewNotificationSoundBanner,
showUnreadCount = showUnreadCount,
fullScreenIntentPermissionsState = fullScreenIntentPermissionsState,
batteryOptimizationState = batteryOptimizationState,
summaries = summaries,
@@ -44,6 +44,8 @@ import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.libraries.architecture.AsyncData
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
@@ -90,6 +92,7 @@ class RoomListPresenter(
private val announcementService: AnnouncementService,
private val coldStartWatcher: AnalyticsColdStartWatcher,
private val spaceFiltersPresenter: Presenter<SpaceFiltersState>,
private val featureFlagService: FeatureFlagService,
) : Presenter<RoomListState> {
private val encryptionService = client.encryptionService
@@ -165,13 +168,17 @@ class RoomListPresenter(
roomListDataSource.updateFilter(allFilters)
}
val canReportRoom by produceState(false) { value = client.canReportRoom() }
val showUnreadCount by produceState(false) {
value = featureFlagService.isFeatureEnabled(FeatureFlags.UnreadIndicatorCount)
}
val contentState = roomListContentState(
securityBannerDismissed,
showNewNotificationSoundBanner,
showUnreadCount,
)
val canReportRoom by produceState(false) { value = client.canReportRoom() }
return RoomListState(
contextMenu = contextMenu.value,
declineInviteMenu = declineInviteMenu.value,
@@ -226,6 +233,7 @@ class RoomListPresenter(
private fun roomListContentState(
securityBannerDismissed: Boolean,
showNewNotificationSoundBanner: Boolean,
showUnreadCount: Boolean,
): RoomListContentState {
val roomSummaries by produceState(initialValue = AsyncData.Loading()) {
roomListDataSource.roomSummariesFlow.collect { value = AsyncData.Success(it) }
@@ -254,6 +262,7 @@ class RoomListPresenter(
RoomListContentState.Rooms(
securityBannerState = securityBannerState,
showNewNotificationSoundBanner = showNewNotificationSoundBanner,
showUnreadCount = showUnreadCount,
fullScreenIntentPermissionsState = fullScreenIntentPermissionsPresenter.present(),
batteryOptimizationState = batteryOptimizationPresenter.present(),
summaries = roomSummaries.dataOrNull().orEmpty().toImmutableList(),
@@ -72,6 +72,7 @@ sealed interface RoomListContentState {
val fullScreenIntentPermissionsState: FullScreenIntentPermissionsState,
val batteryOptimizationState: BatteryOptimizationState,
val showNewNotificationSoundBanner: Boolean,
val showUnreadCount: Boolean,
val summaries: ImmutableList<RoomListRoomSummary>,
val seenRoomInvites: ImmutableSet<RoomId>,
) : RoomListContentState
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="banner_battery_optimization_content_android">"すべての通知を確実に受信するために、このアプリのバッテリー最適化を無効にしてください。"</string>
<string name="banner_battery_optimization_submit_android">"最適化を無効にする"</string>
<string name="banner_battery_optimization_submit_android">"無効にする"</string>
<string name="banner_battery_optimization_title_android">"通知が届いていませんか?"</string>
<string name="banner_new_sound_message">"通知音が更新され、より明確で速く、そして邪魔にならなくなりました。"</string>
<string name="banner_new_sound_title">"サウンドを刷新しました"</string>
@@ -38,7 +38,7 @@
<string name="screen_roomlist_filter_low_priority_empty_state_title">"低い優先度のチャットはまだありません"</string>
<string name="screen_roomlist_filter_mixed_empty_state_subtitle">"フィルターを解除して他のチャットを表示できます"</string>
<string name="screen_roomlist_filter_mixed_empty_state_title">"この選択中にチャットがありません"</string>
<string name="screen_roomlist_filter_people">"人々"</string>
<string name="screen_roomlist_filter_people">"ユーザー"</string>
<string name="screen_roomlist_filter_people_empty_state_title">"まだダイレクトメッセージは届いていません"</string>
<string name="screen_roomlist_filter_rooms">"ルーム"</string>
<string name="screen_roomlist_filter_rooms_empty_state_title">"まだルームに参加していません"</string>
@@ -6,7 +6,7 @@
<string name="banner_new_sound_message">"Vaše oznámenia boli aktualizované – sú prehľadnejšie, rýchlejšie a menej rušivé."</string>
<string name="banner_new_sound_title">"Obnovili sme vaše zvuky"</string>
<string name="banner_set_up_recovery_content">"Vytvorte nový kľúč na obnovenie, ktorý môžete použiť na obnovenie vašej histórie šifrovaných správ v prípade straty prístupu k vašim zariadeniam."</string>
<string name="banner_set_up_recovery_submit">"Nastaviť obnovenie"</string>
<string name="banner_set_up_recovery_submit">"Získať kľúč na obnovenie"</string>
<string name="banner_set_up_recovery_title">"Nastaviť obnovenie"</string>
<string name="confirm_recovery_key_banner_message">"Potvrďte svoj kľúč na obnovenie, aby ste zachovali prístup k úložisku kľúčov a histórii správ."</string>
<string name="confirm_recovery_key_banner_primary_button_title">"Zadajte kľúč na obnovenie"</string>
@@ -36,6 +36,8 @@ import io.element.android.libraries.dateformatter.api.DateFormatter
import io.element.android.libraries.dateformatter.test.FakeDateFormatter
import io.element.android.libraries.eventformatter.api.RoomLatestEventFormatter
import io.element.android.libraries.eventformatter.test.FakeRoomLatestEventFormatter
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
@@ -669,6 +671,7 @@ class RoomListPresenterTest {
appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(),
seenInvitesStore: SeenInvitesStore = InMemorySeenInvitesStore(),
announcementService: AnnouncementService = FakeAnnouncementService(),
featureFlagService: FeatureFlagService = FakeFeatureFlagService(),
) = RoomListPresenter(
client = client,
leaveRoomPresenter = { leaveRoomState },
@@ -697,5 +700,6 @@ class RoomListPresenterTest {
seenInvitesStore = seenInvitesStore,
announcementService = announcementService,
coldStartWatcher = FakeAnalyticsColdStartWatcher(),
featureFlagService = featureFlagService,
)
}