Skip to content

Commit

Permalink
Merge pull request #1329 from vector-im/feature/bma/advancedSettings
Browse files Browse the repository at this point in the history
New advanced settings screen
  • Loading branch information
bmarty authored Sep 14, 2023
2 parents de835f9 + e058402 commit b1250a4
Show file tree
Hide file tree
Showing 41 changed files with 702 additions and 73 deletions.
2 changes: 2 additions & 0 deletions features/messages/impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ dependencies {
implementation(projects.libraries.mediapickers.api)
implementation(projects.libraries.featureflag.api)
implementation(projects.libraries.mediaupload.api)
implementation(projects.libraries.preferences.api)
implementation(projects.features.networkmonitor.api)
implementation(projects.services.analytics.api)
implementation(libs.coil.compose)
Expand Down Expand Up @@ -76,6 +77,7 @@ dependencies {
testImplementation(projects.libraries.featureflag.test)
testImplementation(projects.libraries.mediaupload.test)
testImplementation(projects.libraries.mediapickers.test)
testImplementation(projects.libraries.preferences.test)
testImplementation(projects.libraries.textcomposer.test)
testImplementation(libs.test.mockk)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.utils.messagesummary.MessageSummaryFormatter
import io.element.android.features.networkmonitor.api.NetworkMonitor
import io.element.android.features.networkmonitor.api.NetworkStatus
import io.element.android.features.preferences.api.store.PreferencesStore
import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
import io.element.android.libraries.architecture.Async
import io.element.android.libraries.architecture.Presenter
Expand All @@ -66,8 +67,6 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.SnackbarMessage
import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsState
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.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
Expand Down Expand Up @@ -97,7 +96,7 @@ class MessagesPresenter @AssistedInject constructor(
private val dispatchers: CoroutineDispatchers,
private val clipboardHelper: ClipboardHelper,
private val analyticsService: AnalyticsService,
private val featureFlagService: FeatureFlagService,
private val preferencesStore: PreferencesStore,
@Assisted private val navigator: MessagesNavigator,
) : Presenter<MessagesState> {

Expand Down Expand Up @@ -146,15 +145,17 @@ class MessagesPresenter @AssistedInject constructor(
timelineState.eventSink(TimelineEvents.SetHighlightedEvent(composerState.mode.relatedEventId))
}

var enableTextFormatting by remember { mutableStateOf(true) }
LaunchedEffect(Unit) {
enableTextFormatting = featureFlagService.isFeatureEnabled(FeatureFlags.RichTextEditor)
}
val enableTextFormatting by preferencesStore.isRichTextEditorEnabledFlow().collectAsState(initial = true)

fun handleEvents(event: MessagesEvents) {
when (event) {
is MessagesEvents.HandleAction -> {
localCoroutineScope.handleTimelineAction(event.action, event.event, composerState)
localCoroutineScope.handleTimelineAction(
action = event.action,
targetEvent = event.event,
composerState = composerState,
enableTextFormatting = enableTextFormatting,
)
}
is MessagesEvents.ToggleReaction -> {
localCoroutineScope.toggleReaction(event.emoji, event.eventId)
Expand Down Expand Up @@ -204,14 +205,15 @@ class MessagesPresenter @AssistedInject constructor(
action: TimelineItemAction,
targetEvent: TimelineItem.Event,
composerState: MessageComposerState,
enableTextFormatting: Boolean,
) = launch {
when (action) {
TimelineItemAction.Copy -> handleCopyContents(targetEvent)
TimelineItemAction.Redact -> handleActionRedact(targetEvent)
TimelineItemAction.Edit -> handleActionEdit(targetEvent, composerState)
TimelineItemAction.Edit -> handleActionEdit(targetEvent, composerState, enableTextFormatting)
TimelineItemAction.Reply,
TimelineItemAction.ReplyInThread -> handleActionReply(targetEvent, composerState)
TimelineItemAction.Developer -> handleShowDebugInfoAction(targetEvent)
TimelineItemAction.ViewSource -> handleShowDebugInfoAction(targetEvent)
TimelineItemAction.Forward -> handleForwardAction(targetEvent)
TimelineItemAction.ReportContent -> handleReportAction(targetEvent)
TimelineItemAction.EndPoll -> handleEndPollAction(targetEvent)
Expand Down Expand Up @@ -260,11 +262,15 @@ class MessagesPresenter @AssistedInject constructor(
}
}

private suspend fun handleActionEdit(targetEvent: TimelineItem.Event, composerState: MessageComposerState) {
private suspend fun handleActionEdit(
targetEvent: TimelineItem.Event,
composerState: MessageComposerState,
enableTextFormatting: Boolean,
) {
val composerMode = MessageComposerMode.Edit(
targetEvent.eventId,
(targetEvent.content as? TimelineItemTextBasedContent)?.let {
if (featureFlagService.isFeatureEnabled(FeatureFlags.RichTextEditor)) {
if (enableTextFormatting) {
it.htmlBody ?: it.body
} else {
it.body
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package io.element.android.features.messages.impl.actionlist

import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
Expand All @@ -30,15 +31,15 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemStateContent
import io.element.android.features.messages.impl.timeline.model.event.canBeCopied
import io.element.android.features.messages.impl.timeline.model.event.canReact
import io.element.android.features.preferences.api.store.PreferencesStore
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.meta.BuildMeta
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import javax.inject.Inject

class ActionListPresenter @Inject constructor(
private val buildMeta: BuildMeta,
private val preferencesStore: PreferencesStore,
) : Presenter<ActionListState> {

@Composable
Expand All @@ -49,6 +50,8 @@ class ActionListPresenter @Inject constructor(
mutableStateOf(ActionListState.Target.None)
}

val isDeveloperModeEnabled by preferencesStore.isDeveloperModeEnabledFlow().collectAsState(initial = false)

val displayEmojiReactions by remember {
derivedStateOf {
val event = (target.value as? ActionListState.Target.Success)?.event
Expand All @@ -63,6 +66,7 @@ class ActionListPresenter @Inject constructor(
timelineItem = event.event,
userCanRedact = event.canRedact,
userCanSendMessage = event.canSendMessage,
isDeveloperModeEnabled = isDeveloperModeEnabled,
target = target,
)
}
Expand All @@ -79,23 +83,24 @@ class ActionListPresenter @Inject constructor(
timelineItem: TimelineItem.Event,
userCanRedact: Boolean,
userCanSendMessage: Boolean,
isDeveloperModeEnabled: Boolean,
target: MutableState<ActionListState.Target>
) = launch {
target.value = ActionListState.Target.Loading(timelineItem)
val actions =
when (timelineItem.content) {
is TimelineItemRedactedContent -> {
if (buildMeta.isDebuggable) {
listOf(TimelineItemAction.Developer)
if (isDeveloperModeEnabled) {
listOf(TimelineItemAction.ViewSource)
} else {
emptyList()
}
}
is TimelineItemStateContent -> {
buildList {
add(TimelineItemAction.Copy)
if (buildMeta.isDebuggable) {
add(TimelineItemAction.Developer)
if (isDeveloperModeEnabled) {
add(TimelineItemAction.ViewSource)
}
}
}
Expand All @@ -115,8 +120,8 @@ class ActionListPresenter @Inject constructor(
if (timelineItem.content.canBeCopied()) {
add(TimelineItemAction.Copy)
}
if (buildMeta.isDebuggable) {
add(TimelineItemAction.Developer)
if (isDeveloperModeEnabled) {
add(TimelineItemAction.ViewSource)
}
if (!timelineItem.isMine) {
add(TimelineItemAction.ReportContent)
Expand Down Expand Up @@ -144,8 +149,8 @@ class ActionListPresenter @Inject constructor(
if (timelineItem.content.canBeCopied()) {
add(TimelineItemAction.Copy)
}
if (buildMeta.isDebuggable) {
add(TimelineItemAction.Developer)
if (isDeveloperModeEnabled) {
add(TimelineItemAction.ViewSource)
}
if (!timelineItem.isMine) {
add(TimelineItemAction.ReportContent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,15 @@ fun aTimelineItemActionList(): ImmutableList<TimelineItemAction> {
TimelineItemAction.Edit,
TimelineItemAction.Redact,
TimelineItemAction.ReportContent,
TimelineItemAction.Developer,
TimelineItemAction.ViewSource,
)
}
fun aTimelineItemPollActionList(): ImmutableList<TimelineItemAction> {
return persistentListOf(
TimelineItemAction.EndPoll,
TimelineItemAction.Reply,
TimelineItemAction.Copy,
TimelineItemAction.Developer,
TimelineItemAction.ViewSource,
TimelineItemAction.ReportContent,
TimelineItemAction.Redact,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ sealed class TimelineItemAction(
data object Reply : TimelineItemAction(CommonStrings.action_reply, VectorIcons.Reply)
data object ReplyInThread : TimelineItemAction(CommonStrings.action_reply_in_thread, VectorIcons.Reply)
data object Edit : TimelineItemAction(CommonStrings.action_edit, VectorIcons.Edit)
data object Developer : TimelineItemAction(CommonStrings.action_view_source, VectorIcons.DeveloperMode)
data object ViewSource : TimelineItemAction(CommonStrings.action_view_source, VectorIcons.DeveloperMode)
data object ReportContent : TimelineItemAction(CommonStrings.action_report_content, VectorIcons.ReportContent, destructive = true)
data object EndPoll : TimelineItemAction(CommonStrings.action_end_poll, VectorIcons.PollEnd)
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.featureflag.test.InMemoryPreferencesStore
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.room.MatrixRoom
import io.element.android.libraries.matrix.api.room.MatrixRoomMembersState
Expand All @@ -64,7 +65,6 @@ import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID_2
import io.element.android.libraries.matrix.test.core.aBuildMeta
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.matrix.test.room.aRoomMember
import io.element.android.libraries.mediapickers.test.FakePickerProvider
Expand Down Expand Up @@ -364,7 +364,7 @@ class MessagesPresenterTest {
presenter.present()
}.test {
val initialState = awaitItem()
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.Developer, aMessageEvent()))
initialState.eventSink.invoke(MessagesEvents.HandleAction(TimelineItemAction.ViewSource, aMessageEvent()))
assertThat(awaitItem().actionListState.target).isEqualTo(ActionListState.Target.None)
assertThat(navigator.onShowEventDebugInfoClickedCount).isEqualTo(1)
}
Expand Down Expand Up @@ -614,20 +614,19 @@ class MessagesPresenterTest {
messageComposerContext = MessageComposerContextImpl(),
richTextEditorStateFactory = TestRichTextEditorStateFactory(),

)
)
val timelinePresenter = TimelinePresenter(
timelineItemsFactory = aTimelineItemsFactory(),
room = matrixRoom,
dispatchers = coroutineDispatchers,
appScope = this,
analyticsService = analyticsService,
)
val buildMeta = aBuildMeta()
val actionListPresenter = ActionListPresenter(buildMeta = buildMeta)
val preferencesStore = InMemoryPreferencesStore(isRichTextEditorEnabled = true)
val actionListPresenter = ActionListPresenter(preferencesStore = preferencesStore)
val customReactionPresenter = CustomReactionPresenter(emojibaseProvider = FakeEmojibaseProvider())
val reactionSummaryPresenter = ReactionSummaryPresenter(room = matrixRoom)
val retrySendMenuPresenter = RetrySendMenuPresenter(room = matrixRoom)
val featureFlagsService = FakeFeatureFlagService(mapOf(FeatureFlags.RichTextEditor.key to true))
return MessagesPresenter(
room = matrixRoom,
composerPresenter = messageComposerPresenter,
Expand All @@ -642,7 +641,7 @@ class MessagesPresenterTest {
navigator = navigator,
clipboardHelper = clipboardHelper,
analyticsService = analyticsService,
featureFlagService = featureFlagsService,
preferencesStore = preferencesStore,
dispatchers = coroutineDispatchers,
)
}
Expand Down
Loading

0 comments on commit b1250a4

Please sign in to comment.