From 16d9271f235ab6267870038e5294568f83cf37a2 Mon Sep 17 00:00:00 2001 From: Ivan Semenov Date: Wed, 27 Mar 2024 15:50:47 +0100 Subject: [PATCH] [collab/gitlab] rework MR settings to use flow instead of listener and extract a utility base class GitOrigin-RevId: 551d76f91a0a9aad4a8d03bf593c4158e7c34985 --- ...bleSerializablePersistentStateComponent.kt | 24 ++++++++++++++++++ .../GitLabMergeRequestsPreferences.kt | 25 ++++++------------- .../GitLabMergeRequestEditorReviewUIModel.kt | 12 ++++----- .../GitLabMergeRequestTimelineViewModel.kt | 2 +- .../ui/comment/GitLabNoteEditingViewModel.kt | 14 +++-------- 5 files changed, 42 insertions(+), 35 deletions(-) create mode 100644 platform/collaboration-tools/src/com/intellij/collaboration/util/CollectableSerializablePersistentStateComponent.kt diff --git a/platform/collaboration-tools/src/com/intellij/collaboration/util/CollectableSerializablePersistentStateComponent.kt b/platform/collaboration-tools/src/com/intellij/collaboration/util/CollectableSerializablePersistentStateComponent.kt new file mode 100644 index 000000000000..348f262e0231 --- /dev/null +++ b/platform/collaboration-tools/src/com/intellij/collaboration/util/CollectableSerializablePersistentStateComponent.kt @@ -0,0 +1,24 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.collaboration.util + +import com.intellij.openapi.components.SerializablePersistentStateComponent +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.update +import org.jetbrains.annotations.ApiStatus + +@ApiStatus.Experimental +abstract class CollectableSerializablePersistentStateComponent(defaultState: T) + : SerializablePersistentStateComponent(defaultState) { + protected val stateFlow: MutableStateFlow = MutableStateFlow(defaultState) + + override fun loadState(state: T) { + super.loadState(state) + stateFlow.value = state + } + + + protected fun updateStateAndEmit(updateFunction: (currentState: T) -> T): T { + stateFlow.update(updateFunction) + return updateState(updateFunction) + } +} \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/GitLabMergeRequestsPreferences.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/GitLabMergeRequestsPreferences.kt index f13c525e2ed0..90674d4b98d7 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/GitLabMergeRequestsPreferences.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/GitLabMergeRequestsPreferences.kt @@ -1,24 +1,22 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.plugins.gitlab.mergerequest -import com.intellij.openapi.Disposable +import com.intellij.collaboration.async.mapState +import com.intellij.collaboration.util.CollectableSerializablePersistentStateComponent import com.intellij.openapi.components.* import com.intellij.openapi.project.Project -import com.intellij.util.EventDispatcher import git4idea.remote.hosting.knownRepositories +import kotlinx.coroutines.flow.StateFlow import kotlinx.serialization.Serializable import org.jetbrains.plugins.gitlab.GitLabProjectsManager import org.jetbrains.plugins.gitlab.authentication.accounts.GitLabAccount import org.jetbrains.plugins.gitlab.authentication.accounts.GitLabAccountManager import org.jetbrains.plugins.gitlab.util.GitLabProjectMapping -import java.util.* @Service(Service.Level.PROJECT) @State(name = "GitLabMergeRequestsSettings", storages = [Storage(StoragePathMacros.WORKSPACE_FILE)], reportStatistic = false) -class GitLabMergeRequestsPreferences(private val project: Project) - : SerializablePersistentStateComponent(SettingsState()) { - - private val listeners = EventDispatcher.create(Listener::class.java) +internal class GitLabMergeRequestsPreferences(private val project: Project) + : CollectableSerializablePersistentStateComponent(SettingsState()) { @Serializable data class SettingsState( @@ -62,6 +60,7 @@ class GitLabMergeRequestsPreferences(private val project: Project) it.copy(highlightDiffLinesInEditor = value) } } + val highlightDiffLinesInEditorState: StateFlow = stateFlow.mapState { it.highlightDiffLinesInEditor } var usedAsDraftSubmitActionLast: Boolean get() = state.usedAsDraftSubmitActionLast @@ -70,6 +69,7 @@ class GitLabMergeRequestsPreferences(private val project: Project) it.copy(usedAsDraftSubmitActionLast = value) } } + val usedAsDraftSubmitActionLastState: StateFlow = stateFlow.mapState { it.usedAsDraftSubmitActionLast } var editorReviewEnabled: Boolean get() = state.editorReviewEnabled @@ -78,15 +78,4 @@ class GitLabMergeRequestsPreferences(private val project: Project) it.copy(editorReviewEnabled = value) } } - - private inline fun updateStateAndEmit(updateFunction: (currentState: SettingsState) -> SettingsState) { - val state = super.updateState(updateFunction) - listeners.multicaster.onSettingsChange(state) - } - - fun addListener(disposable: Disposable, listener: Listener) = listeners.addListener(listener, disposable) - - fun interface Listener : EventListener { - fun onSettingsChange(settings: SettingsState) - } } \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewUIModel.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewUIModel.kt index cfdb56f5111c..2139fa92c1a1 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewUIModel.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewUIModel.kt @@ -2,6 +2,7 @@ package org.jetbrains.plugins.gitlab.mergerequest.ui.editor import com.intellij.collaboration.async.combineState +import com.intellij.collaboration.async.launchNow import com.intellij.collaboration.async.mapModelsToViewModels import com.intellij.collaboration.async.stateInNow import com.intellij.collaboration.ui.codereview.editor.* @@ -16,6 +17,7 @@ import com.intellij.openapi.editor.Document import com.intellij.openapi.util.Key import com.intellij.openapi.vcs.ex.LineStatusMarkerRangesSource import com.intellij.openapi.vcs.ex.LstRange +import com.intellij.util.cancelOnDispose import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.* import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO @@ -25,7 +27,7 @@ import org.jetbrains.plugins.gitlab.mergerequest.GitLabMergeRequestsPreferences * A wrapper over [GitLabMergeRequestEditorReviewFileViewModel] to encapsulate LST integration */ internal class GitLabMergeRequestEditorReviewUIModel internal constructor( - cs: CoroutineScope, + private val cs: CoroutineScope, private val preferences: GitLabMergeRequestsPreferences, private val fileVm: GitLabMergeRequestEditorReviewFileViewModel, document: Document @@ -96,13 +98,11 @@ internal class GitLabMergeRequestEditorReviewUIModel internal constructor( } override fun addDiffHighlightListener(disposable: Disposable, listener: () -> Unit) { - var lastKnown = preferences.highlightDiffLinesInEditor - preferences.addListener(disposable) { - if (lastKnown != it.highlightDiffLinesInEditor) { + cs.launchNow { + preferences.highlightDiffLinesInEditorState.collect { listener() } - lastKnown = it.highlightDiffLinesInEditor - } + }.cancelOnDispose(disposable, false) } private fun StateFlow.shiftLine(): StateFlow = diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineViewModel.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineViewModel.kt index 7b932166d962..bc123b51baed 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineViewModel.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineViewModel.kt @@ -36,7 +36,7 @@ interface GitLabMergeRequestTimelineViewModel : GitLabMergeRequestViewModel { private val LOG = logger() -class LoadAllGitLabMergeRequestTimelineViewModel( +internal class LoadAllGitLabMergeRequestTimelineViewModel( private val project: Project, parentCs: CoroutineScope, private val projectData: GitLabProject, diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabNoteEditingViewModel.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabNoteEditingViewModel.kt index 4abf54f4521c..21ff12b791ed 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabNoteEditingViewModel.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabNoteEditingViewModel.kt @@ -9,10 +9,10 @@ import com.intellij.collaboration.ui.codereview.comment.CodeReviewTextEditingVie import com.intellij.collaboration.ui.codereview.comment.submitActionIn import com.intellij.openapi.components.service import com.intellij.openapi.project.Project -import com.intellij.openapi.util.Disposer import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch import org.jetbrains.annotations.Nls import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO @@ -105,13 +105,7 @@ private abstract class NewGitLabNoteViewModelBase( ) : AbstractGitLabNoteEditingViewModel(project, parentCs, initialText), NewGitLabNoteViewModel { private val preferences = project.service() - override val usedAsDraftSubmitActionLast: StateFlow = channelFlow { - val disposable = Disposer.newDisposable() - preferences.addListener(disposable) { - trySend(it.usedAsDraftSubmitActionLast) - } - awaitClose { Disposer.dispose(disposable) } - }.stateIn(cs, SharingStarted.Lazily, preferences.usedAsDraftSubmitActionLast) + override val usedAsDraftSubmitActionLast: StateFlow = preferences.usedAsDraftSubmitActionLastState override fun submit() { submit {