Remove ReadReceipts feature flag.

This commit is contained in:
Benoit Marty 2024-01-10 15:42:03 +01:00 committed by Benoit Marty
parent cd1b80ef18
commit 4dcafb6aa6
15 changed files with 14 additions and 70 deletions

View file

@ -40,8 +40,6 @@ import io.element.android.features.poll.api.actions.EndPollAction
import io.element.android.features.poll.api.actions.SendPollResponseAction import io.element.android.features.poll.api.actions.SendPollResponseAction
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.coroutine.CoroutineDispatchers import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.encryption.BackupState import io.element.android.libraries.matrix.api.encryption.BackupState
import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.EncryptionService
@ -71,7 +69,6 @@ class TimelinePresenter @AssistedInject constructor(
@Assisted private val navigator: MessagesNavigator, @Assisted private val navigator: MessagesNavigator,
private val verificationService: SessionVerificationService, private val verificationService: SessionVerificationService,
private val encryptionService: EncryptionService, private val encryptionService: EncryptionService,
private val featureFlagService: FeatureFlagService,
private val redactedVoiceMessageManager: RedactedVoiceMessageManager, private val redactedVoiceMessageManager: RedactedVoiceMessageManager,
private val sendPollResponseAction: SendPollResponseAction, private val sendPollResponseAction: SendPollResponseAction,
private val endPollAction: EndPollAction, private val endPollAction: EndPollAction,
@ -115,7 +112,6 @@ class TimelinePresenter @AssistedInject constructor(
} }
} }
val readReceiptsEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.ReadReceipts).collectAsState(initial = false)
val membersState by room.membersStateFlow.collectAsState() val membersState by room.membersStateFlow.collectAsState()
fun handleEvents(event: TimelineEvents) { fun handleEvents(event: TimelineEvents) {
@ -159,12 +155,7 @@ class TimelinePresenter @AssistedInject constructor(
.onEach { .onEach {
timelineItemsFactory.replaceWith( timelineItemsFactory.replaceWith(
timelineItems = it, timelineItems = it,
roomMembers = if (readReceiptsEnabled) { roomMembers = membersState.roomMembers().orEmpty()
membersState.roomMembers().orEmpty()
} else {
// Give an empty list to not affect performance
emptyList()
}
) )
} }
.onEach { timelineItems -> .onEach { timelineItems ->
@ -190,7 +181,6 @@ class TimelinePresenter @AssistedInject constructor(
highlightedEventId = highlightedEventId.value, highlightedEventId = highlightedEventId.value,
paginationState = paginationState, paginationState = paginationState,
timelineItems = timelineItems, timelineItems = timelineItems,
showReadReceipts = readReceiptsEnabled,
newEventState = newItemState.value, newEventState = newItemState.value,
sessionState = sessionState, sessionState = sessionState,
eventSink = { handleEvents(it) } eventSink = { handleEvents(it) }

View file

@ -28,7 +28,6 @@ import kotlinx.collections.immutable.ImmutableList
data class TimelineState( data class TimelineState(
val timelineItems: ImmutableList<TimelineItem>, val timelineItems: ImmutableList<TimelineItem>,
val timelineRoomInfo: TimelineRoomInfo, val timelineRoomInfo: TimelineRoomInfo,
val showReadReceipts: Boolean,
val highlightedEventId: EventId?, val highlightedEventId: EventId?,
val paginationState: MatrixTimeline.PaginationState, val paginationState: MatrixTimeline.PaginationState,
val newEventState: NewEventState, val newEventState: NewEventState,

View file

@ -48,7 +48,6 @@ import kotlin.random.Random
fun aTimelineState(timelineItems: ImmutableList<TimelineItem> = persistentListOf()) = TimelineState( fun aTimelineState(timelineItems: ImmutableList<TimelineItem> = persistentListOf()) = TimelineState(
timelineItems = timelineItems, timelineItems = timelineItems,
timelineRoomInfo = aTimelineRoomInfo(), timelineRoomInfo = aTimelineRoomInfo(),
showReadReceipts = false,
paginationState = MatrixTimeline.PaginationState( paginationState = MatrixTimeline.PaginationState(
isBackPaginating = false, isBackPaginating = false,
hasMoreToLoadBackwards = true, hasMoreToLoadBackwards = true,

View file

@ -119,7 +119,6 @@ fun TimelineView(
TimelineItemRow( TimelineItemRow(
timelineItem = timelineItem, timelineItem = timelineItem,
timelineRoomInfo = state.timelineRoomInfo, timelineRoomInfo = state.timelineRoomInfo,
showReadReceipts = state.showReadReceipts,
isLastOutgoingMessage = (timelineItem as? TimelineItem.Event)?.isMine == true && isLastOutgoingMessage = (timelineItem as? TimelineItem.Event)?.isMine == true &&
state.timelineItems.first().identifier() == timelineItem.identifier(), state.timelineItems.first().identifier() == timelineItem.identifier(),
highlightedItem = state.highlightedEventId?.value, highlightedItem = state.highlightedEventId?.value,

View file

@ -26,13 +26,11 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItem
internal fun ATimelineItemEventRow( internal fun ATimelineItemEventRow(
event: TimelineItem.Event, event: TimelineItem.Event,
timelineRoomInfo: TimelineRoomInfo = aTimelineRoomInfo(), timelineRoomInfo: TimelineRoomInfo = aTimelineRoomInfo(),
showReadReceipts: Boolean = false,
isLastOutgoingMessage: Boolean = false, isLastOutgoingMessage: Boolean = false,
isHighlighted: Boolean = false, isHighlighted: Boolean = false,
) = TimelineItemEventRow( ) = TimelineItemEventRow(
event = event, event = event,
timelineRoomInfo = timelineRoomInfo, timelineRoomInfo = timelineRoomInfo,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage, isLastOutgoingMessage = isLastOutgoingMessage,
isHighlighted = isHighlighted, isHighlighted = isHighlighted,
onClick = {}, onClick = {},

View file

@ -114,7 +114,6 @@ import kotlin.math.roundToInt
fun TimelineItemEventRow( fun TimelineItemEventRow(
event: TimelineItem.Event, event: TimelineItem.Event,
timelineRoomInfo: TimelineRoomInfo, timelineRoomInfo: TimelineRoomInfo,
showReadReceipts: Boolean,
isLastOutgoingMessage: Boolean, isLastOutgoingMessage: Boolean,
isHighlighted: Boolean, isHighlighted: Boolean,
onClick: () -> Unit, onClick: () -> Unit,
@ -224,7 +223,6 @@ fun TimelineItemEventRow(
isLastOutgoingMessage = isLastOutgoingMessage, isLastOutgoingMessage = isLastOutgoingMessage,
receipts = event.readReceiptState.receipts, receipts = event.readReceiptState.receipts,
), ),
showReadReceipts = showReadReceipts,
onReadReceiptsClicked = { onReadReceiptClick(event) }, onReadReceiptsClicked = { onReadReceiptClick(event) },
modifier = Modifier.padding(top = 4.dp), modifier = Modifier.padding(top = 4.dp),
) )

View file

@ -47,7 +47,6 @@ internal fun TimelineItemEventRowWithRRPreview(
timelineItemReactions = aTimelineItemReactions(count = 0), timelineItemReactions = aTimelineItemReactions(count = 0),
readReceiptState = TimelineItemReadReceipts(state.receipts), readReceiptState = TimelineItemReadReceipts(state.receipts),
), ),
showReadReceipts = true,
isLastOutgoingMessage = false, isLastOutgoingMessage = false,
) )
// A message from current user // A message from current user
@ -61,7 +60,6 @@ internal fun TimelineItemEventRowWithRRPreview(
timelineItemReactions = aTimelineItemReactions(count = 0), timelineItemReactions = aTimelineItemReactions(count = 0),
readReceiptState = TimelineItemReadReceipts(state.receipts), readReceiptState = TimelineItemReadReceipts(state.receipts),
), ),
showReadReceipts = true,
isLastOutgoingMessage = false, isLastOutgoingMessage = false,
) )
// Another message from current user // Another message from current user
@ -75,7 +73,6 @@ internal fun TimelineItemEventRowWithRRPreview(
timelineItemReactions = aTimelineItemReactions(count = 0), timelineItemReactions = aTimelineItemReactions(count = 0),
readReceiptState = TimelineItemReadReceipts(state.receipts), readReceiptState = TimelineItemReadReceipts(state.receipts),
), ),
showReadReceipts = true,
isLastOutgoingMessage = true, isLastOutgoingMessage = true,
) )
} }

View file

@ -43,7 +43,6 @@ import io.element.android.libraries.matrix.api.core.UserId
fun TimelineItemGroupedEventsRow( fun TimelineItemGroupedEventsRow(
timelineItem: TimelineItem.GroupedEvents, timelineItem: TimelineItem.GroupedEvents,
timelineRoomInfo: TimelineRoomInfo, timelineRoomInfo: TimelineRoomInfo,
showReadReceipts: Boolean,
isLastOutgoingMessage: Boolean, isLastOutgoingMessage: Boolean,
highlightedItem: String?, highlightedItem: String?,
sessionState: SessionState, sessionState: SessionState,
@ -71,7 +70,6 @@ fun TimelineItemGroupedEventsRow(
timelineItem = timelineItem, timelineItem = timelineItem,
timelineRoomInfo = timelineRoomInfo, timelineRoomInfo = timelineRoomInfo,
highlightedItem = highlightedItem, highlightedItem = highlightedItem,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage, isLastOutgoingMessage = isLastOutgoingMessage,
sessionState = sessionState, sessionState = sessionState,
onClick = onClick, onClick = onClick,
@ -95,7 +93,6 @@ private fun TimelineItemGroupedEventsRowContent(
timelineItem: TimelineItem.GroupedEvents, timelineItem: TimelineItem.GroupedEvents,
timelineRoomInfo: TimelineRoomInfo, timelineRoomInfo: TimelineRoomInfo,
highlightedItem: String?, highlightedItem: String?,
showReadReceipts: Boolean,
isLastOutgoingMessage: Boolean, isLastOutgoingMessage: Boolean,
sessionState: SessionState, sessionState: SessionState,
onClick: (TimelineItem.Event) -> Unit, onClick: (TimelineItem.Event) -> Unit,
@ -127,7 +124,6 @@ private fun TimelineItemGroupedEventsRowContent(
TimelineItemRow( TimelineItemRow(
timelineItem = subGroupEvent, timelineItem = subGroupEvent,
timelineRoomInfo = timelineRoomInfo, timelineRoomInfo = timelineRoomInfo,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage, isLastOutgoingMessage = isLastOutgoingMessage,
highlightedItem = highlightedItem, highlightedItem = highlightedItem,
sessionState = sessionState, sessionState = sessionState,
@ -145,14 +141,13 @@ private fun TimelineItemGroupedEventsRowContent(
) )
} }
} }
} else if (showReadReceipts) { } else {
TimelineItemReadReceiptView( TimelineItemReadReceiptView(
state = ReadReceiptViewState( state = ReadReceiptViewState(
sendState = null, sendState = null,
isLastOutgoingMessage = false, isLastOutgoingMessage = false,
receipts = timelineItem.aggregatedReadReceipts, receipts = timelineItem.aggregatedReadReceipts,
), ),
showReadReceipts = true,
onReadReceiptsClicked = onExpandGroupClick onReadReceiptsClicked = onExpandGroupClick
) )
} }
@ -168,7 +163,6 @@ internal fun TimelineItemGroupedEventsRowContentExpandedPreview() = ElementPrevi
timelineItem = aGroupedEvents(), timelineItem = aGroupedEvents(),
timelineRoomInfo = aTimelineRoomInfo(), timelineRoomInfo = aTimelineRoomInfo(),
highlightedItem = null, highlightedItem = null,
showReadReceipts = true,
isLastOutgoingMessage = false, isLastOutgoingMessage = false,
sessionState = aSessionState(), sessionState = aSessionState(),
onClick = {}, onClick = {},
@ -193,7 +187,6 @@ internal fun TimelineItemGroupedEventsRowContentCollapsePreview() = ElementPrevi
timelineItem = aGroupedEvents(), timelineItem = aGroupedEvents(),
timelineRoomInfo = aTimelineRoomInfo(), timelineRoomInfo = aTimelineRoomInfo(),
highlightedItem = null, highlightedItem = null,
showReadReceipts = true,
isLastOutgoingMessage = false, isLastOutgoingMessage = false,
sessionState = aSessionState(), sessionState = aSessionState(),
onClick = {}, onClick = {},

View file

@ -30,7 +30,6 @@ import io.element.android.libraries.matrix.api.core.UserId
internal fun TimelineItemRow( internal fun TimelineItemRow(
timelineItem: TimelineItem, timelineItem: TimelineItem,
timelineRoomInfo: TimelineRoomInfo, timelineRoomInfo: TimelineRoomInfo,
showReadReceipts: Boolean,
isLastOutgoingMessage: Boolean, isLastOutgoingMessage: Boolean,
highlightedItem: String?, highlightedItem: String?,
sessionState: SessionState, sessionState: SessionState,
@ -59,7 +58,6 @@ internal fun TimelineItemRow(
if (timelineItem.content is TimelineItemStateContent) { if (timelineItem.content is TimelineItemStateContent) {
TimelineItemStateEventRow( TimelineItemStateEventRow(
event = timelineItem, event = timelineItem,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage, isLastOutgoingMessage = isLastOutgoingMessage,
isHighlighted = highlightedItem == timelineItem.identifier(), isHighlighted = highlightedItem == timelineItem.identifier(),
onClick = { onClick(timelineItem) }, onClick = { onClick(timelineItem) },
@ -72,7 +70,6 @@ internal fun TimelineItemRow(
TimelineItemEventRow( TimelineItemEventRow(
event = timelineItem, event = timelineItem,
timelineRoomInfo = timelineRoomInfo, timelineRoomInfo = timelineRoomInfo,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage, isLastOutgoingMessage = isLastOutgoingMessage,
isHighlighted = highlightedItem == timelineItem.identifier(), isHighlighted = highlightedItem == timelineItem.identifier(),
onClick = { onClick(timelineItem) }, onClick = { onClick(timelineItem) },
@ -94,7 +91,6 @@ internal fun TimelineItemRow(
TimelineItemGroupedEventsRow( TimelineItemGroupedEventsRow(
timelineItem = timelineItem, timelineItem = timelineItem,
timelineRoomInfo = timelineRoomInfo, timelineRoomInfo = timelineRoomInfo,
showReadReceipts = showReadReceipts,
isLastOutgoingMessage = isLastOutgoingMessage, isLastOutgoingMessage = isLastOutgoingMessage,
highlightedItem = highlightedItem, highlightedItem = highlightedItem,
sessionState = sessionState, sessionState = sessionState,

View file

@ -47,7 +47,6 @@ import kotlinx.collections.immutable.toPersistentList
@Composable @Composable
fun TimelineItemStateEventRow( fun TimelineItemStateEventRow(
event: TimelineItem.Event, event: TimelineItem.Event,
showReadReceipts: Boolean,
isLastOutgoingMessage: Boolean, isLastOutgoingMessage: Boolean,
isHighlighted: Boolean, isHighlighted: Boolean,
onClick: () -> Unit, onClick: () -> Unit,
@ -91,7 +90,6 @@ fun TimelineItemStateEventRow(
isLastOutgoingMessage = isLastOutgoingMessage, isLastOutgoingMessage = isLastOutgoingMessage,
receipts = event.readReceiptState.receipts, receipts = event.readReceiptState.receipts,
), ),
showReadReceipts = showReadReceipts,
onReadReceiptsClicked = { onReadReceiptsClick(event) }, onReadReceiptsClicked = { onReadReceiptsClick(event) },
) )
} }
@ -109,7 +107,6 @@ internal fun TimelineItemStateEventRowPreview() = ElementPreview {
receipts = listOf(aReadReceiptData(0)).toPersistentList(), receipts = listOf(aReadReceiptData(0)).toPersistentList(),
) )
), ),
showReadReceipts = true,
isLastOutgoingMessage = false, isLastOutgoingMessage = false,
isHighlighted = false, isHighlighted = false,
onClick = {}, onClick = {},

View file

@ -58,23 +58,20 @@ import kotlinx.collections.immutable.ImmutableList
@Composable @Composable
fun TimelineItemReadReceiptView( fun TimelineItemReadReceiptView(
state: ReadReceiptViewState, state: ReadReceiptViewState,
showReadReceipts: Boolean,
onReadReceiptsClicked: () -> Unit, onReadReceiptsClicked: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
if (state.receipts.isNotEmpty()) { if (state.receipts.isNotEmpty()) {
if (showReadReceipts) { ReadReceiptsRow(modifier = modifier) {
ReadReceiptsRow(modifier = modifier) { ReadReceiptsAvatars(
ReadReceiptsAvatars( receipts = state.receipts,
receipts = state.receipts, modifier = Modifier
modifier = Modifier .clip(RoundedCornerShape(4.dp))
.clip(RoundedCornerShape(4.dp)) .clickable {
.clickable { onReadReceiptsClicked()
onReadReceiptsClicked() }
} .padding(2.dp)
.padding(2.dp) )
)
}
} }
} else { } else {
when (state.sendState) { when (state.sendState) {
@ -209,7 +206,6 @@ internal fun TimelineItemReactionsViewPreview(
) = ElementPreview { ) = ElementPreview {
TimelineItemReadReceiptView( TimelineItemReadReceiptView(
state = state, state = state,
showReadReceipts = true,
onReadReceiptsClicked = {}, onReadReceiptsClicked = {},
) )
} }

View file

@ -685,7 +685,6 @@ class MessagesPresenterTest {
navigator = navigator, navigator = navigator,
encryptionService = FakeEncryptionService(), encryptionService = FakeEncryptionService(),
verificationService = FakeSessionVerificationService(), verificationService = FakeSessionVerificationService(),
featureFlagService = FakeFeatureFlagService(),
redactedVoiceMessageManager = FakeRedactedVoiceMessageManager(), redactedVoiceMessageManager = FakeRedactedVoiceMessageManager(),
endPollAction = FakeEndPollAction(), endPollAction = FakeEndPollAction(),
sendPollResponseAction = FakeSendPollResponseAction(), sendPollResponseAction = FakeSendPollResponseAction(),

View file

@ -35,7 +35,6 @@ import io.element.android.features.poll.api.actions.SendPollResponseAction
import io.element.android.features.poll.test.actions.FakeEndPollAction import io.element.android.features.poll.test.actions.FakeEndPollAction
import io.element.android.features.poll.test.actions.FakeSendPollResponseAction import io.element.android.features.poll.test.actions.FakeSendPollResponseAction
import io.element.android.libraries.featureflag.api.FeatureFlags import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
import io.element.android.libraries.matrix.api.timeline.item.event.EventReaction import io.element.android.libraries.matrix.api.timeline.item.event.EventReaction
@ -89,7 +88,7 @@ class TimelinePresenterTest {
moleculeFlow(RecompositionMode.Immediate) { moleculeFlow(RecompositionMode.Immediate) {
presenter.present() presenter.present()
}.test { }.test {
val initialState = awaitFirstItem() val initialState = awaitItem()
assertThat(initialState.paginationState.hasMoreToLoadBackwards).isTrue() assertThat(initialState.paginationState.hasMoreToLoadBackwards).isTrue()
assertThat(initialState.paginationState.isBackPaginating).isFalse() assertThat(initialState.paginationState.isBackPaginating).isFalse()
initialState.eventSink.invoke(TimelineEvents.LoadMore) initialState.eventSink.invoke(TimelineEvents.LoadMore)
@ -133,8 +132,6 @@ class TimelinePresenterTest {
}.test { }.test {
assertThat(timeline.sendReadReceiptCount).isEqualTo(0) assertThat(timeline.sendReadReceiptCount).isEqualTo(0)
val initialState = awaitFirstItem() val initialState = awaitFirstItem()
// Wait for timeline items to be populated
skipItems(1)
awaitWithLatch { latch -> awaitWithLatch { latch ->
timeline.sendReadReceiptLatch = latch timeline.sendReadReceiptLatch = latch
initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(0)) initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(0))
@ -157,8 +154,6 @@ class TimelinePresenterTest {
}.test { }.test {
assertThat(timeline.sendReadReceiptCount).isEqualTo(0) assertThat(timeline.sendReadReceiptCount).isEqualTo(0)
val initialState = awaitFirstItem() val initialState = awaitFirstItem()
// Wait for timeline items to be populated
skipItems(1)
awaitWithLatch { latch -> awaitWithLatch { latch ->
timeline.sendReadReceiptLatch = latch timeline.sendReadReceiptLatch = latch
initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(1)) initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(1))
@ -181,8 +176,6 @@ class TimelinePresenterTest {
}.test { }.test {
assertThat(timeline.sendReadReceiptCount).isEqualTo(0) assertThat(timeline.sendReadReceiptCount).isEqualTo(0)
val initialState = awaitFirstItem() val initialState = awaitFirstItem()
// Wait for timeline items to be populated
skipItems(1)
awaitWithLatch { latch -> awaitWithLatch { latch ->
timeline.sendReadReceiptLatch = latch timeline.sendReadReceiptLatch = latch
initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(0)) initialState.eventSink.invoke(TimelineEvents.OnScrollFinished(0))
@ -354,8 +347,7 @@ class TimelinePresenterTest {
presenter.present() presenter.present()
}.test { }.test {
assertThat(redactedVoiceMessageManager.invocations.size).isEqualTo(0) assertThat(redactedVoiceMessageManager.invocations.size).isEqualTo(0)
awaitFirstItem() awaitFirstItem().let {
awaitItem().let {
assertThat(it.timelineItems).isNotEmpty() assertThat(it.timelineItems).isNotEmpty()
} }
assertThat(redactedVoiceMessageManager.invocations.size).isEqualTo(1) assertThat(redactedVoiceMessageManager.invocations.size).isEqualTo(1)
@ -386,7 +378,6 @@ class TimelinePresenterTest {
navigator = messagesNavigator, navigator = messagesNavigator,
encryptionService = FakeEncryptionService(), encryptionService = FakeEncryptionService(),
verificationService = FakeSessionVerificationService(), verificationService = FakeSessionVerificationService(),
featureFlagService = FakeFeatureFlagService(),
redactedVoiceMessageManager = redactedVoiceMessageManager, redactedVoiceMessageManager = redactedVoiceMessageManager,
endPollAction = endPollAction, endPollAction = endPollAction,
sendPollResponseAction = sendPollResponseAction, sendPollResponseAction = sendPollResponseAction,

View file

@ -75,11 +75,4 @@ enum class FeatureFlags(
defaultValue = true, defaultValue = true,
isFinished = false, isFinished = false,
), ),
ReadReceipts(
key = "feature.readreceipts",
title = "Show read receipts",
description = null,
defaultValue = true,
isFinished = false,
),
} }

View file

@ -41,7 +41,6 @@ class StaticFeatureFlagProvider @Inject constructor() :
FeatureFlags.PinUnlock -> true FeatureFlags.PinUnlock -> true
FeatureFlags.Mentions -> true FeatureFlags.Mentions -> true
FeatureFlags.SecureStorage -> true FeatureFlags.SecureStorage -> true
FeatureFlags.ReadReceipts -> true
} }
} else { } else {
false false