mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[collab/gitlab/github] persist review changes grouping preferences
GitOrigin-RevId: 828169e0ac2190b734a35f14a5a62338d55a25ce
This commit is contained in:
committed by
intellij-monorepo-bot
parent
16d9271f23
commit
37aa331340
+21
-4
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.collaboration.ui.codereview.changes
|
||||
|
||||
import com.intellij.collaboration.async.launchNow
|
||||
import com.intellij.collaboration.ui.codereview.CodeReviewProgressTreeModel
|
||||
import com.intellij.collaboration.ui.codereview.details.model.CodeReviewChangeListViewModel
|
||||
import com.intellij.collaboration.ui.codereview.setupCodeReviewProgressModel
|
||||
@@ -11,7 +12,6 @@ import com.intellij.collaboration.util.fileStatus
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.actionSystem.DataKey
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vcs.FilePath
|
||||
import com.intellij.openapi.vcs.changes.ChangesUtil
|
||||
import com.intellij.openapi.vcs.changes.ui.*
|
||||
@@ -38,7 +38,7 @@ object CodeReviewChangeListComponentFactory {
|
||||
progressModel: CodeReviewProgressTreeModel<*>?,
|
||||
emptyTextText: @Nls String): AsyncChangesTree {
|
||||
val treeModel = createTreeModel(vm)
|
||||
val tree = createTree(vm.project, treeModel).apply {
|
||||
val tree = cs.createTree(vm, treeModel).apply {
|
||||
emptyText.text = emptyTextText
|
||||
}.also { tree ->
|
||||
ClientProperty.put(tree, ExpandableItemsHandler.IGNORE_ITEM_SELECTION, true)
|
||||
@@ -89,8 +89,8 @@ object CodeReviewChangeListComponentFactory {
|
||||
return tree
|
||||
}
|
||||
|
||||
private fun createTree(project: Project, treeModel: AsyncChangesTreeModel) =
|
||||
object : AsyncChangesTree(project, false, false) {
|
||||
private fun CoroutineScope.createTree(vm: CodeReviewChangeListViewModel, treeModel: AsyncChangesTreeModel) =
|
||||
object : AsyncChangesTree(vm.project, false, false) {
|
||||
override val changesTreeModel: AsyncChangesTreeModel = treeModel
|
||||
|
||||
override fun getData(dataId: String): Any? {
|
||||
@@ -108,6 +108,23 @@ object CodeReviewChangeListComponentFactory {
|
||||
|
||||
private fun getSelectedFiles(): List<VirtualFile> =
|
||||
getSelectedChanges().mapNotNull { it.filePath.virtualFile }
|
||||
|
||||
override fun installGroupingSupport(): ChangesGroupingSupport =
|
||||
if (vm is CodeReviewChangeListViewModel.WithGrouping) {
|
||||
ChangesGroupingSupport(vm.project, this, false).also { gs ->
|
||||
installGroupingSupport(this, gs, vm.grouping::value, vm::setGrouping)
|
||||
launchNow {
|
||||
vm.grouping.collect {
|
||||
if(gs.groupingKeys != it) {
|
||||
gs.setGroupingKeysOrSkip(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
super.installGroupingSupport()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
@@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
interface CodeReviewChangeListViewModel {
|
||||
val project: Project
|
||||
@@ -50,6 +51,16 @@ interface CodeReviewChangeListViewModel {
|
||||
val detailsByChange: StateFlow<Map<RefComparisonChange, CodeReviewChangeDetails>>
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
interface WithGrouping : CodeReviewChangeListViewModel {
|
||||
/**
|
||||
* A set of enabled grouping policies
|
||||
*/
|
||||
val grouping: StateFlow<Set<String>>
|
||||
|
||||
fun setGrouping(grouping: Collection<String>)
|
||||
}
|
||||
|
||||
sealed interface SelectionRequest {
|
||||
data object All : SelectionRequest
|
||||
data class OneChange(val change: RefComparisonChange) : SelectionRequest
|
||||
@@ -63,6 +74,7 @@ interface CodeReviewChangeListViewModel {
|
||||
fun CodeReviewChangeListViewModel.WithDetails.isViewedStateForAllChanges(changes: Iterable<RefComparisonChange>, viewed: Boolean): Boolean =
|
||||
changes.all { detailsByChange.value[it]?.isRead == viewed }
|
||||
|
||||
@ApiStatus.Internal
|
||||
abstract class CodeReviewChangeListViewModelBase(
|
||||
parentCs: CoroutineScope,
|
||||
protected val changeList: CodeReviewChangeList
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@ abstract class CollectableSerializablePersistentStateComponent<T : Any>(defaultS
|
||||
}
|
||||
|
||||
|
||||
protected fun updateStateAndEmit(updateFunction: (currentState: T) -> T): T {
|
||||
protected fun updateStateAndEmit(updateFunction: (currentState: T) -> T) {
|
||||
updateState(updateFunction)
|
||||
stateFlow.update(updateFunction)
|
||||
return updateState(updateFunction)
|
||||
}
|
||||
}
|
||||
+22
-22
@@ -2,9 +2,10 @@
|
||||
package org.jetbrains.plugins.github.pullrequest.config
|
||||
|
||||
import com.intellij.collaboration.async.mapState
|
||||
import com.intellij.collaboration.util.CollectableSerializablePersistentStateComponent
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.project.Project
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import com.intellij.openapi.vcs.changes.ui.ChangesGroupingSupport
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jetbrains.plugins.github.api.GHRepositoryCoordinates
|
||||
@@ -16,10 +17,8 @@ import org.jetbrains.plugins.github.authentication.accounts.GithubAccount
|
||||
|
||||
@Service(Service.Level.PROJECT)
|
||||
@State(name = "GithubPullRequestsUISettings", storages = [Storage(StoragePathMacros.WORKSPACE_FILE)], reportStatistic = false)
|
||||
class GithubPullRequestsProjectUISettings(private val project: Project)
|
||||
: SerializablePersistentStateComponent<GithubPullRequestsProjectUISettings.SettingsState>(SettingsState()) {
|
||||
|
||||
private val stateOfState = MutableStateFlow(SettingsState())
|
||||
internal class GithubPullRequestsProjectUISettings(private val project: Project)
|
||||
: CollectableSerializablePersistentStateComponent<GithubPullRequestsProjectUISettings.SettingsState>(SettingsState()) {
|
||||
|
||||
@Serializable
|
||||
data class SettingsState(
|
||||
@@ -27,7 +26,8 @@ class GithubPullRequestsProjectUISettings(private val project: Project)
|
||||
val recentNewPullRequestHead: RepoCoordinatesHolder? = null,
|
||||
val reviewCommentPreferred: Boolean = true,
|
||||
val editorReviewEnabled: Boolean = true,
|
||||
val highlightDiffLinesInEditor: Boolean = false
|
||||
val highlightDiffLinesInEditor: Boolean = false,
|
||||
val changesGrouping: Set<String> = setOf(ChangesGroupingSupport.DIRECTORY_GROUPING, ChangesGroupingSupport.MODULE_GROUPING)
|
||||
)
|
||||
|
||||
var selectedUrlAndAccount: Pair<String, GithubAccount>?
|
||||
@@ -36,7 +36,7 @@ class GithubPullRequestsProjectUISettings(private val project: Project)
|
||||
val account = GHAccountSerializer.deserialize(accountId) ?: return null
|
||||
return url to account
|
||||
}
|
||||
set(value) = updateAndSetState {
|
||||
set(value) = updateStateAndEmit {
|
||||
it.copy(selectedUrlAndAccountId = value?.let { (repo, account) ->
|
||||
UrlAndAccount(repo, GHAccountSerializer.serialize(account))
|
||||
})
|
||||
@@ -44,40 +44,40 @@ class GithubPullRequestsProjectUISettings(private val project: Project)
|
||||
|
||||
var recentNewPullRequestHead: GHRepositoryCoordinates?
|
||||
get() = state.recentNewPullRequestHead?.let { GHRepositoryCoordinates(it.server, GHRepositoryPath(it.owner, it.repository)) }
|
||||
set(value) = updateAndSetState {
|
||||
set(value) = updateStateAndEmit {
|
||||
it.copy(recentNewPullRequestHead = value?.let { RepoCoordinatesHolder(it) })
|
||||
}
|
||||
|
||||
var reviewCommentsPreferred: Boolean
|
||||
get() = state.reviewCommentPreferred
|
||||
set(value) = updateAndSetState {
|
||||
set(value) = updateStateAndEmit {
|
||||
it.copy(reviewCommentPreferred = value)
|
||||
}
|
||||
|
||||
var editorReviewEnabled: Boolean
|
||||
get() = state.editorReviewEnabled
|
||||
set(value) = updateAndSetState {
|
||||
set(value) = updateStateAndEmit {
|
||||
it.copy(editorReviewEnabled = value)
|
||||
}
|
||||
|
||||
var highlightDiffLinesInEditor: Boolean
|
||||
get() = state.highlightDiffLinesInEditor
|
||||
set(value) = updateAndSetState {
|
||||
set(value) = updateStateAndEmit {
|
||||
it.copy(highlightDiffLinesInEditor = value)
|
||||
}
|
||||
|
||||
val reviewCommentsPreferredState: StateFlow<Boolean> = stateOfState.mapState { it.reviewCommentPreferred }
|
||||
val editorReviewEnabledState: StateFlow<Boolean> = stateOfState.mapState { it.editorReviewEnabled }
|
||||
val highlightDiffLinesInEditorState: StateFlow<Boolean> = stateOfState.mapState { it.highlightDiffLinesInEditor }
|
||||
var changesGrouping: Set<String>
|
||||
get() = state.changesGrouping
|
||||
set(value) {
|
||||
updateStateAndEmit {
|
||||
it.copy(changesGrouping = value)
|
||||
}
|
||||
}
|
||||
val changesGroupingState: StateFlow<Set<String>> = stateFlow.mapState { it.changesGrouping }
|
||||
|
||||
override fun loadState(state: SettingsState) {
|
||||
super.loadState(state)
|
||||
stateOfState.value = state
|
||||
}
|
||||
|
||||
private inline fun updateAndSetState(updateFunction: (currentState: SettingsState) -> SettingsState) {
|
||||
stateOfState.value = updateState(updateFunction)
|
||||
}
|
||||
val reviewCommentsPreferredState: StateFlow<Boolean> = stateFlow.mapState { it.reviewCommentPreferred }
|
||||
val editorReviewEnabledState: StateFlow<Boolean> = stateFlow.mapState { it.editorReviewEnabled }
|
||||
val highlightDiffLinesInEditorState: StateFlow<Boolean> = stateFlow.mapState { it.highlightDiffLinesInEditor }
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
|
||||
+9
-1
@@ -14,13 +14,14 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.plugins.github.api.data.pullrequest.isViewed
|
||||
import org.jetbrains.plugins.github.pullrequest.config.GithubPullRequestsProjectUISettings
|
||||
import org.jetbrains.plugins.github.pullrequest.data.GHPRDataContext
|
||||
import org.jetbrains.plugins.github.pullrequest.data.provider.GHPRDataProvider
|
||||
import org.jetbrains.plugins.github.pullrequest.data.provider.createThreadsRequestsFlow
|
||||
import org.jetbrains.plugins.github.pullrequest.data.provider.createViewedStateRequestsFlow
|
||||
|
||||
@ApiStatus.Experimental
|
||||
interface GHPRChangeListViewModel : CodeReviewChangeListViewModel.WithDetails {
|
||||
interface GHPRChangeListViewModel : CodeReviewChangeListViewModel.WithDetails, CodeReviewChangeListViewModel.WithGrouping {
|
||||
val isUpdating: StateFlow<Boolean>
|
||||
val isOnLatest: Boolean
|
||||
|
||||
@@ -40,6 +41,7 @@ internal class GHPRChangeListViewModelImpl(
|
||||
changes: CodeReviewChangesContainer,
|
||||
changeList: CodeReviewChangeList
|
||||
) : GHPRChangeListViewModel, CodeReviewChangeListViewModelBase(parentCs, changeList) {
|
||||
private val preferences = GithubPullRequestsProjectUISettings.getInstance(project)
|
||||
private val repository: GitRepository get() = dataContext.repositoryDataService.remoteCoordinates.repository
|
||||
|
||||
private val _isUpdating = MutableStateFlow(false)
|
||||
@@ -57,6 +59,8 @@ internal class GHPRChangeListViewModelImpl(
|
||||
MutableStateFlow(emptyMap())
|
||||
}
|
||||
|
||||
override val grouping: StateFlow<Set<String>> = preferences.changesGroupingState
|
||||
|
||||
fun setUpdating(updating: Boolean) {
|
||||
_isUpdating.value = updating
|
||||
}
|
||||
@@ -85,6 +89,10 @@ internal class GHPRChangeListViewModelImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun setGrouping(grouping: Collection<String>) {
|
||||
preferences.changesGrouping = grouping.toSet()
|
||||
}
|
||||
|
||||
private fun createDetailsByChangeFlow(): Flow<Map<RefComparisonChange, CodeReviewChangeDetails>> {
|
||||
val threadsFlow = dataProvider.reviewData.createThreadsRequestsFlow().values()
|
||||
val viewedStateFlow = viewedStateData.createViewedStateRequestsFlow().values()
|
||||
|
||||
+12
-1
@@ -5,6 +5,7 @@ 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.openapi.vcs.changes.ui.ChangesGroupingSupport
|
||||
import git4idea.remote.hosting.knownRepositories
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -24,7 +25,8 @@ internal class GitLabMergeRequestsPreferences(private val project: Project)
|
||||
val showEventsInTimeline: Boolean = true,
|
||||
val highlightDiffLinesInEditor: Boolean = true,
|
||||
val usedAsDraftSubmitActionLast: Boolean = true,
|
||||
val editorReviewEnabled: Boolean = true
|
||||
val editorReviewEnabled: Boolean = true,
|
||||
val changesGrouping: Set<String> = setOf(ChangesGroupingSupport.DIRECTORY_GROUPING, ChangesGroupingSupport.MODULE_GROUPING)
|
||||
)
|
||||
|
||||
var selectedRepoAndAccount: Pair<GitLabProjectMapping, GitLabAccount>?
|
||||
@@ -78,4 +80,13 @@ internal class GitLabMergeRequestsPreferences(private val project: Project)
|
||||
it.copy(editorReviewEnabled = value)
|
||||
}
|
||||
}
|
||||
|
||||
var changesGrouping: Set<String>
|
||||
get() = state.changesGrouping
|
||||
set(value) {
|
||||
updateStateAndEmit {
|
||||
it.copy(changesGrouping = value)
|
||||
}
|
||||
}
|
||||
val changesGroupingState: StateFlow<Set<String>> = stateFlow.mapState { it.changesGrouping }
|
||||
}
|
||||
+11
-1
@@ -15,10 +15,13 @@ import git4idea.changes.GitBranchComparisonResult
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import org.jetbrains.plugins.gitlab.api.GitLabId
|
||||
import org.jetbrains.plugins.gitlab.mergerequest.GitLabMergeRequestsPreferences
|
||||
import org.jetbrains.plugins.gitlab.mergerequest.data.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
interface GitLabMergeRequestChangeListViewModel : CodeReviewChangeListViewModel.WithDetails {
|
||||
interface GitLabMergeRequestChangeListViewModel
|
||||
: CodeReviewChangeListViewModel.WithDetails,
|
||||
CodeReviewChangeListViewModel.WithGrouping {
|
||||
val isOnLatest: Boolean
|
||||
|
||||
fun setViewedState(changes: Iterable<RefComparisonChange>, viewed: Boolean)
|
||||
@@ -33,6 +36,7 @@ internal class GitLabMergeRequestChangeListViewModelImpl(
|
||||
) : CodeReviewChangeListViewModelBase(parentCs, changeList),
|
||||
GitLabMergeRequestChangeListViewModel {
|
||||
private val persistentChangesViewedState = project.service<GitLabPersistentMergeRequestChangesViewedState>()
|
||||
private val preferences = project.service<GitLabMergeRequestsPreferences>()
|
||||
|
||||
private val _showDiffRequests = MutableSharedFlow<Unit>()
|
||||
val showDiffRequests: Flow<Unit> = _showDiffRequests.asSharedFlow()
|
||||
@@ -67,6 +71,8 @@ internal class GitLabMergeRequestChangeListViewModelImpl(
|
||||
}
|
||||
}.stateIn(cs, SharingStarted.Eagerly, emptyMap())
|
||||
|
||||
override val grouping: StateFlow<Set<String>> = preferences.changesGroupingState
|
||||
|
||||
override fun showDiffPreview() {
|
||||
cs.launch {
|
||||
_showDiffRequests.emit(Unit)
|
||||
@@ -90,6 +96,10 @@ internal class GitLabMergeRequestChangeListViewModelImpl(
|
||||
viewed
|
||||
)
|
||||
}
|
||||
|
||||
override fun setGrouping(grouping: Collection<String>) {
|
||||
preferences.changesGrouping = grouping.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
||||
Reference in New Issue
Block a user