Remove FeatureFlag.PinnedEvents

This commit is contained in:
Benoit Marty 2025-08-12 15:03:25 +02:00 committed by Benoit Marty
parent be9861bea9
commit 4f0535714e
13 changed files with 92 additions and 230 deletions

View file

@ -1,15 +0,0 @@
/*
* Copyright 2024 New Vector 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.features.messages.api.pinned
import androidx.compose.runtime.Composable
fun interface IsPinnedMessagesFeatureEnabled {
@Composable
operator fun invoke(): Boolean
}

View file

@ -18,7 +18,6 @@ import com.squareup.anvil.annotations.ContributesBinding
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEnabled
import io.element.android.features.messages.impl.UserEventPermissions
import io.element.android.features.messages.impl.actionlist.model.TimelineItemAction
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionComparator
@ -62,7 +61,6 @@ class DefaultActionListPresenter @AssistedInject constructor(
@Assisted
private val postProcessor: TimelineItemActionPostProcessor,
private val appPreferencesStore: AppPreferencesStore,
private val isPinnedMessagesFeatureEnabled: IsPinnedMessagesFeatureEnabled,
private val room: BaseRoom,
private val userSendFailureFactory: VerifiedUserSendFailureFactory,
private val featureFlagService: FeatureFlagService,
@ -87,7 +85,6 @@ class DefaultActionListPresenter @AssistedInject constructor(
val isDeveloperModeEnabled by remember {
appPreferencesStore.isDeveloperModeEnabledFlow()
}.collectAsState(initial = false)
val isPinnedEventsEnabled = isPinnedMessagesFeatureEnabled()
val pinnedEventIds by remember {
room.roomInfoFlow.map { it.pinnedEventIds }
}.collectAsState(initial = persistentListOf())
@ -99,7 +96,6 @@ class DefaultActionListPresenter @AssistedInject constructor(
timelineItem = event.event,
usersEventPermissions = event.userEventPermissions,
isDeveloperModeEnabled = isDeveloperModeEnabled,
isPinnedEventsEnabled = isPinnedEventsEnabled,
pinnedEventIds = pinnedEventIds,
target = target,
)
@ -116,7 +112,6 @@ class DefaultActionListPresenter @AssistedInject constructor(
timelineItem: TimelineItem.Event,
usersEventPermissions: UserEventPermissions,
isDeveloperModeEnabled: Boolean,
isPinnedEventsEnabled: Boolean,
pinnedEventIds: ImmutableList<EventId>,
target: MutableState<ActionListState.Target>
) = launch {
@ -126,7 +121,6 @@ class DefaultActionListPresenter @AssistedInject constructor(
timelineItem = timelineItem,
usersEventPermissions = usersEventPermissions,
isDeveloperModeEnabled = isDeveloperModeEnabled,
isPinnedEventsEnabled = isPinnedEventsEnabled,
isEventPinned = pinnedEventIds.contains(timelineItem.eventId),
)
@ -154,7 +148,6 @@ class DefaultActionListPresenter @AssistedInject constructor(
timelineItem: TimelineItem.Event,
usersEventPermissions: UserEventPermissions,
isDeveloperModeEnabled: Boolean,
isPinnedEventsEnabled: Boolean,
isEventPinned: Boolean,
): List<TimelineItemAction> {
val canRedact = timelineItem.isMine && usersEventPermissions.canRedactOwn || !timelineItem.isMine && usersEventPermissions.canRedactOther
@ -189,7 +182,7 @@ class DefaultActionListPresenter @AssistedInject constructor(
if (canRedact && timelineItem.content is TimelineItemPollContent && !timelineItem.content.isEnded) {
add(TimelineItemAction.EndPoll)
}
val canPinUnpin = isPinnedEventsEnabled && usersEventPermissions.canPinUnpin && timelineItem.isRemote
val canPinUnpin = usersEventPermissions.canPinUnpin && timelineItem.isRemote
if (canPinUnpin) {
if (isEventPinned) {
add(TimelineItemAction.Unpin)

View file

@ -1,41 +0,0 @@
/*
* Copyright 2024 New Vector 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.features.messages.impl.pinned
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEnabled
import io.element.android.libraries.di.AppScope
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject
@ContributesBinding(AppScope::class)
class DefaultIsPinnedMessagesFeatureEnabled @Inject constructor(
private val featureFlagService: FeatureFlagService,
) : IsPinnedMessagesFeatureEnabled {
@Composable
override operator fun invoke(): Boolean {
var isFeatureEnabled by rememberSaveable {
mutableStateOf(false)
}
LaunchedEffect(Unit) {
featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents)
.onEach { isFeatureEnabled = it }
.launchIn(this)
}
return isFeatureEnabled
}
}

View file

@ -12,8 +12,6 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.coroutine.mapState
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.room.CreateTimelineParams
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.sync.SyncService
@ -23,7 +21,6 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
@ -35,7 +32,6 @@ import javax.inject.Inject
class PinnedEventsTimelineProvider @Inject constructor(
private val room: JoinedRoom,
private val syncService: SyncService,
private val featureFlagService: FeatureFlagService,
private val dispatchers: CoroutineDispatchers,
) : TimelineProvider {
private val _timelineStateFlow: MutableStateFlow<AsyncData<Timeline>> =
@ -66,20 +62,10 @@ class PinnedEventsTimelineProvider @Inject constructor(
}
private suspend fun onActive() = coroutineScope {
combine(
featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents),
syncService.syncState,
) { isEnabled, _ ->
syncService.syncState.onEach {
// do not use syncState here as data can be loaded from cache, it's just to trigger retry if needed
isEnabled
loadTimelineIfNeeded()
}
.onEach { isFeatureEnabled ->
if (isFeatureEnabled) {
loadTimelineIfNeeded()
} else {
resetTimeline()
}
}
.launchIn(this)
}

View file

@ -52,7 +52,7 @@ class ActionListPresenterTest {
@Test
fun `present - initial state`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -63,7 +63,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for message from me redacted`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -100,7 +100,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for message from others redacted`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -141,7 +141,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for others message`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -188,7 +188,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for others message in a thread`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
presenter.test {
val initialState = awaitItem()
val messageEvent = aMessageEvent(
@ -234,7 +234,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for others message cannot sent message`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -280,7 +280,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for others message and can redact`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -328,7 +328,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for others message and cannot send reaction`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -376,7 +376,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for my message`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -423,7 +423,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for my message in a thread`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
presenter.test {
val initialState = awaitItem()
val messageEvent = aMessageEvent(
@ -469,7 +469,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for my message cannot redact`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -515,7 +515,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for my message no permission`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -558,7 +558,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for a media item`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -607,7 +607,6 @@ class ActionListPresenterTest {
fun `present - compute for a media item - caption disabled`() = runTest {
val presenter = createActionListPresenter(
isDeveloperModeEnabled = true,
isPinFeatureEnabled = true,
allowCaption = false,
)
moleculeFlow(RecompositionMode.Immediate) {
@ -657,7 +656,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for a media with caption item`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -708,7 +707,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for a media with caption item - other user event`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -757,7 +756,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for a state item in debug build`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -797,7 +796,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for a state item in non-debuggable build`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -824,7 +823,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute message in non-debuggable build`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -870,7 +869,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute message when user can't pin`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -921,7 +920,6 @@ class ActionListPresenterTest {
}
val presenter = createActionListPresenter(
isDeveloperModeEnabled = true,
isPinFeatureEnabled = true,
room = room
)
moleculeFlow(RecompositionMode.Immediate) {
@ -970,7 +968,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute message with no actions`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -1017,7 +1015,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute not sent message`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -1061,7 +1059,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for editable poll message`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -1105,7 +1103,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for non-editable poll message`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -1148,7 +1146,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for ended poll message`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -1190,7 +1188,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for voice message`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -1235,7 +1233,7 @@ class ActionListPresenterTest {
@Test
fun `present - compute for call notify`() = runTest {
val presenter = createActionListPresenter(isDeveloperModeEnabled = true, isPinFeatureEnabled = true)
val presenter = createActionListPresenter(isDeveloperModeEnabled = true)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -1275,7 +1273,7 @@ class ActionListPresenterTest {
val room = FakeBaseRoom(
userDisplayNameResult = { Result.success("Alice") }
)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, isPinFeatureEnabled = false, room = room)
val presenter = createActionListPresenter(isDeveloperModeEnabled = false, room = room)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
@ -1299,7 +1297,6 @@ class ActionListPresenterTest {
private fun createActionListPresenter(
isDeveloperModeEnabled: Boolean,
isPinFeatureEnabled: Boolean,
room: BaseRoom = FakeBaseRoom(),
allowCaption: Boolean = true,
): ActionListPresenter {
@ -1307,7 +1304,6 @@ private fun createActionListPresenter(
return DefaultActionListPresenter(
postProcessor = TimelineItemActionPostProcessor.Default,
appPreferencesStore = preferencesStore,
isPinnedMessagesFeatureEnabled = { isPinFeatureEnabled },
room = room,
userSendFailureFactory = VerifiedUserSendFailureFactory(room),
featureFlagService = FakeFeatureFlagService(

View file

@ -10,8 +10,6 @@ package io.element.android.features.messages.impl.pinned.banner
import com.google.common.truth.Truth.assertThat
import io.element.android.features.messages.impl.pinned.PinnedEventsTimelineProvider
import io.element.android.libraries.eventformatter.test.FakePinnedMessagesBannerFormatter
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.sync.SyncService
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
@ -35,7 +33,7 @@ import org.junit.Test
class PinnedMessagesBannerPresenterTest {
@Test
fun `present - initial state`() = runTest {
val presenter = createPinnedMessagesBannerPresenter(isFeatureEnabled = true)
val presenter = createPinnedMessagesBannerPresenter()
presenter.test {
val initialState = awaitItem()
assertThat(initialState).isEqualTo(PinnedMessagesBannerState.Hidden)
@ -43,15 +41,6 @@ class PinnedMessagesBannerPresenterTest {
}
}
@Test
fun `present - feature disabled`() = runTest {
val presenter = createPinnedMessagesBannerPresenter(isFeatureEnabled = false)
presenter.test {
val initialState = awaitItem()
assertThat(initialState).isEqualTo(PinnedMessagesBannerState.Hidden)
}
}
@Test
fun `present - loading state`() = runTest {
val room = FakeJoinedRoom(
@ -188,14 +177,10 @@ class PinnedMessagesBannerPresenterTest {
)
),
syncService: SyncService = FakeSyncService(),
isFeatureEnabled: Boolean = true,
): PinnedMessagesBannerPresenter {
val timelineProvider = PinnedEventsTimelineProvider(
room = room,
syncService = syncService,
featureFlagService = FakeFeatureFlagService(
initialState = mapOf(FeatureFlags.PinnedEvents.key to isFeatureEnabled)
),
dispatchers = testCoroutineDispatchers(),
)
timelineProvider.launchIn(backgroundScope)

View file

@ -17,8 +17,6 @@ import io.element.android.features.messages.impl.pinned.PinnedEventsTimelineProv
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.protection.aTimelineProtectionState
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.room.JoinedRoom
import io.element.android.libraries.matrix.api.sync.SyncService
@ -51,34 +49,17 @@ import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class PinnedMessagesListPresenterTest {
@Test
fun `present - initial state feature disabled`() = runTest {
fun `present - initial state`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
)
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = false)
presenter.test {
val initialState = awaitItem()
assertThat(initialState).isEqualTo(PinnedMessagesListState.Loading)
cancelAndIgnoreRemainingEvents()
}
}
@Test
fun `present - initial state feature enabled`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
}
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
val presenter = createPinnedMessagesListPresenter(room = room)
presenter.test {
val initialState = awaitItem()
assertThat(initialState).isEqualTo(PinnedMessagesListState.Loading)
@ -90,15 +71,15 @@ class PinnedMessagesListPresenterTest {
fun `present - timeline failure state`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
createTimelineResult = { Result.failure(RuntimeException()) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
val presenter = createPinnedMessagesListPresenter(room = room)
presenter.test {
skipItems(3)
val failureState = awaitItem()
@ -111,15 +92,15 @@ class PinnedMessagesListPresenterTest {
fun `present - empty state`() = runTest {
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf()))
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf()))
},
createTimelineResult = { Result.success(FakeTimeline()) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
val presenter = createPinnedMessagesListPresenter(room = room)
presenter.test {
skipItems(3)
val emptyState = awaitItem()
@ -133,15 +114,15 @@ class PinnedMessagesListPresenterTest {
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true)
val presenter = createPinnedMessagesListPresenter(room = room)
presenter.test {
skipItems(3)
val filledState = awaitItem() as PinnedMessagesListState.Filled
@ -162,15 +143,15 @@ class PinnedMessagesListPresenterTest {
val analyticsService = FakeAnalyticsService()
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, isFeatureEnabled = true, analyticsService = analyticsService)
val presenter = createPinnedMessagesListPresenter(room = room, analyticsService = analyticsService)
presenter.test {
skipItems(3)
val filledState = awaitItem() as PinnedMessagesListState.Filled
@ -210,15 +191,15 @@ class PinnedMessagesListPresenterTest {
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator)
presenter.test {
skipItems(3)
val filledState = awaitItem() as PinnedMessagesListState.Filled
@ -241,15 +222,15 @@ class PinnedMessagesListPresenterTest {
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator)
presenter.test {
skipItems(3)
val filledState = awaitItem() as PinnedMessagesListState.Filled
@ -272,15 +253,15 @@ class PinnedMessagesListPresenterTest {
val pinnedEventsTimeline = createPinnedMessagesTimeline()
val room = FakeJoinedRoom(
baseRoom = FakeBaseRoom(
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
canRedactOwnResult = { Result.success(true) },
canRedactOtherResult = { Result.success(true) },
canUserPinUnpinResult = { Result.success(true) },
).apply {
givenRoomInfo(aRoomInfo(pinnedEventIds = listOf(AN_EVENT_ID)))
},
createTimelineResult = { Result.success(pinnedEventsTimeline) },
)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator, isFeatureEnabled = true)
val presenter = createPinnedMessagesListPresenter(room = room, navigator = navigator)
presenter.test {
skipItems(3)
val filledState = awaitItem() as PinnedMessagesListState.Filled
@ -315,15 +296,11 @@ class PinnedMessagesListPresenterTest {
navigator: PinnedMessagesListNavigator = FakePinnedMessagesListNavigator(),
room: JoinedRoom = FakeJoinedRoom(),
syncService: SyncService = FakeSyncService(),
isFeatureEnabled: Boolean = true,
analyticsService: AnalyticsService = FakeAnalyticsService(),
): PinnedMessagesListPresenter {
val timelineProvider = PinnedEventsTimelineProvider(
room = room,
syncService = syncService,
featureFlagService = FakeFeatureFlagService(
initialState = mapOf(FeatureFlags.PinnedEvents.key to isFeatureEnabled)
),
dispatchers = testCoroutineDispatchers(),
)
timelineProvider.launchIn(backgroundScope)

View file

@ -18,7 +18,6 @@ import androidx.compose.runtime.rememberCoroutineScope
import im.vector.app.features.analytics.plan.Interaction
import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.messages.api.pinned.IsPinnedMessagesFeatureEnabled
import io.element.android.features.roomcall.api.RoomCallState
import io.element.android.features.roomdetails.impl.members.details.RoomMemberDetailsPresenter
import io.element.android.features.roomdetails.impl.securityandprivacy.permissions.securityAndPrivacyPermissionsAsState
@ -68,7 +67,6 @@ class RoomDetailsPresenter @Inject constructor(
private val roomCallStatePresenter: Presenter<RoomCallState>,
private val dispatchers: CoroutineDispatchers,
private val analyticsService: AnalyticsService,
private val isPinnedMessagesFeatureEnabled: IsPinnedMessagesFeatureEnabled,
private val clipboardHelper: ClipboardHelper,
private val appPreferencesStore: AppPreferencesStore,
) : Presenter<RoomDetailsState> {
@ -86,7 +84,6 @@ class RoomDetailsPresenter @Inject constructor(
val isFavorite by remember { derivedStateOf { roomInfo.isFavorite } }
val joinRule by remember { derivedStateOf { roomInfo.joinRule } }
val canShowPinnedMessages = isPinnedMessagesFeatureEnabled()
val pinnedMessagesCount by remember { derivedStateOf { roomInfo.pinnedEventIds.size } }
val canShowMediaGallery by remember {
@ -201,7 +198,6 @@ class RoomDetailsPresenter @Inject constructor(
displayRolesAndPermissionsSettings = !isDm && isUserAdmin,
isPublic = joinRule == JoinRule.Public,
heroes = roomInfo.heroes.toPersistentList(),
canShowPinnedMessages = canShowPinnedMessages,
canShowMediaGallery = canShowMediaGallery,
pinnedMessagesCount = pinnedMessagesCount,
snackbarMessage = snackbarMessage,

View file

@ -39,7 +39,6 @@ data class RoomDetailsState(
val displayRolesAndPermissionsSettings: Boolean,
val isPublic: Boolean,
val heroes: ImmutableList<MatrixUser>,
val canShowPinnedMessages: Boolean,
val canShowMediaGallery: Boolean,
val pinnedMessagesCount: Int?,
val snackbarMessage: SnackbarMessage?,

View file

@ -109,7 +109,6 @@ fun aRoomDetailsState(
displayAdminSettings: Boolean = false,
isPublic: Boolean = true,
heroes: List<MatrixUser> = emptyList(),
canShowPinnedMessages: Boolean = true,
canShowMediaGallery: Boolean = true,
pinnedMessagesCount: Int? = null,
snackbarMessage: SnackbarMessage? = null,
@ -140,7 +139,6 @@ fun aRoomDetailsState(
displayRolesAndPermissionsSettings = displayAdminSettings,
isPublic = isPublic,
heroes = heroes.toPersistentList(),
canShowPinnedMessages = canShowPinnedMessages,
canShowMediaGallery = canShowMediaGallery,
pinnedMessagesCount = pinnedMessagesCount,
snackbarMessage = snackbarMessage,

View file

@ -237,12 +237,10 @@ fun RoomDetailsView(
}
PreferenceCategory {
if (state.canShowPinnedMessages) {
PinnedMessagesItem(
pinnedMessagesCount = state.pinnedMessagesCount,
onPinnedMessagesClick = onPinnedMessagesClick
)
}
PinnedMessagesItem(
pinnedMessagesCount = state.pinnedMessagesCount,
onPinnedMessagesClick = onPinnedMessagesClick
)
PollsItem(
openPollHistory = openPollHistory
)

View file

@ -82,7 +82,6 @@ class RoomDetailsPresenterTest {
FeatureFlags.Knock.key to false,
)
),
isPinnedMessagesFeatureEnabled: Boolean = true,
encryptionService: FakeEncryptionService = FakeEncryptionService(),
clipboardHelper: ClipboardHelper = FakeClipboardHelper(),
appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore()
@ -110,7 +109,6 @@ class RoomDetailsPresenterTest {
leaveRoomPresenter = { leaveRoomState },
roomCallStatePresenter = { aStandByCallState() },
dispatchers = dispatchers,
isPinnedMessagesFeatureEnabled = { isPinnedMessagesFeatureEnabled },
analyticsService = analyticsService,
clipboardHelper = clipboardHelper,
appPreferencesStore = appPreferencesStore,
@ -132,7 +130,6 @@ class RoomDetailsPresenterTest {
assertThat(initialState.roomAvatarUrl).isEqualTo(room.info().avatarUrl)
assertThat(initialState.roomTopic).isEqualTo(RoomTopicState.ExistingTopic(room.info().topic!!))
assertThat(initialState.memberCount).isEqualTo(room.info().joinedMembersCount)
assertThat(initialState.canShowPinnedMessages).isTrue()
assertThat(initialState.pinnedMessagesCount).isEqualTo(0)
assertThat(initialState.canShowSecurityAndPrivacy).isFalse()
assertThat(initialState.showDebugInfo).isFalse()

View file

@ -34,13 +34,6 @@ enum class FeatureFlags(
defaultValue = { false },
isFinished = false,
),
PinnedEvents(
key = "feature.pinnedEvents",
title = "Pinned Events",
description = "Allow user to pin events in a room",
defaultValue = { true },
isFinished = false,
),
SyncOnPush(
key = "feature.syncOnPush",
title = "Sync on push",