[collab/gitlab] rework MR settings to use flow instead of listener and extract a utility base class

GitOrigin-RevId: 551d76f91a0a9aad4a8d03bf593c4158e7c34985
This commit is contained in:
Ivan Semenov
2024-04-02 14:23:53 +00:00
committed by intellij-monorepo-bot
parent d0a981b512
commit 16d9271f23
5 changed files with 42 additions and 35 deletions
@@ -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<T : Any>(defaultState: T)
: SerializablePersistentStateComponent<T>(defaultState) {
protected val stateFlow: MutableStateFlow<T> = 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)
}
}
@@ -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<GitLabMergeRequestsPreferences.SettingsState>(SettingsState()) {
private val listeners = EventDispatcher.create(Listener::class.java)
internal class GitLabMergeRequestsPreferences(private val project: Project)
: CollectableSerializablePersistentStateComponent<GitLabMergeRequestsPreferences.SettingsState>(SettingsState()) {
@Serializable
data class SettingsState(
@@ -62,6 +60,7 @@ class GitLabMergeRequestsPreferences(private val project: Project)
it.copy(highlightDiffLinesInEditor = value)
}
}
val highlightDiffLinesInEditorState: StateFlow<Boolean> = 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<Boolean> = 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)
}
}
@@ -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<Int?>.shiftLine(): StateFlow<Int?> =
@@ -36,7 +36,7 @@ interface GitLabMergeRequestTimelineViewModel : GitLabMergeRequestViewModel {
private val LOG = logger<GitLabMergeRequestTimelineViewModel>()
class LoadAllGitLabMergeRequestTimelineViewModel(
internal class LoadAllGitLabMergeRequestTimelineViewModel(
private val project: Project,
parentCs: CoroutineScope,
private val projectData: GitLabProject,
@@ -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<GitLabMergeRequestsPreferences>()
override val usedAsDraftSubmitActionLast: StateFlow<Boolean> = 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<Boolean> = preferences.usedAsDraftSubmitActionLastState
override fun submit() {
submit {