diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/api/GitLabProjectConnection.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/api/GitLabProjectConnection.kt index fb4b697546b7..85de935a91d1 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/api/GitLabProjectConnection.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/api/GitLabProjectConnection.kt @@ -36,8 +36,9 @@ class GitLabProjectConnection( val tokenRefreshFlow: Flow = tokenState.drop(1).map { } - val projectData: GitLabProject = GitLabLazyProject(project, scope, apiClient, glMetadata, repo, glProject, currentUser, tokenRefreshFlow) - val imageLoader: GitLabImageLoader = GitLabImageLoader(apiClient, repo.repository.serverPath) + val imageLoader: GitLabImageLoader = GitLabImageLoader(apiClient, repo.repository) + + val projectData: GitLabProject = GitLabLazyProject(project, scope, apiClient, glMetadata, repo, glProject, currentUser, tokenRefreshFlow, imageLoader) val serverVersion: GitLabVersion? = glMetadata?.version diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/api/request/GitLabUsersApi.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/api/request/GitLabUsersApi.kt index adb894cd7915..46f3d2ae9e06 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/api/request/GitLabUsersApi.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/api/request/GitLabUsersApi.kt @@ -9,6 +9,7 @@ import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.api.dto.GitLabUserRestDTO import org.jetbrains.plugins.gitlab.util.GitLabApiRequestName import java.awt.Image +import java.net.URI import java.net.http.HttpResponse @SinceGitLab("7.0", note = "No exact version") @@ -33,3 +34,8 @@ suspend fun GitLabApi.loadImage(uri: String): Image { val request = request(uri).GET().build() return loadImage(request).body() } + +suspend fun GitLabApi.loadImage(uri: URI): Image { + val request = request(uri).GET().build() + return loadImage(request).body() +} diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/data/GitLabImageLoader.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/data/GitLabImageLoader.kt index b48b14be93a6..66fa7e089830 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/data/GitLabImageLoader.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/data/GitLabImageLoader.kt @@ -2,15 +2,20 @@ package org.jetbrains.plugins.gitlab.data import com.intellij.collaboration.ui.icon.AsyncImageIconsProvider +import com.intellij.collaboration.ui.html.AsyncHtmlImageLoader +import com.intellij.collaboration.util.resolveRelative import com.intellij.openapi.diagnostic.logger import com.intellij.util.IconUtil import com.intellij.util.ui.ImageUtil import icons.CollaborationToolsIcons import org.jetbrains.plugins.gitlab.api.GitLabApi -import org.jetbrains.plugins.gitlab.api.GitLabServerPath +import org.jetbrains.plugins.gitlab.api.GitLabProjectCoordinates import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.api.request.loadImage +import org.jetbrains.plugins.gitlab.api.restApiUri import java.awt.Image +import java.net.URI +import java.net.URL import javax.swing.Icon import kotlin.coroutines.cancellation.CancellationException @@ -20,25 +25,34 @@ private const val LOADED_GRAVATAR_SIZE: Int = 80 class GitLabImageLoader( private val apiClient: GitLabApi, - private val server: GitLabServerPath -) : AsyncImageIconsProvider.AsyncImageLoader { + private val gitLabProjectCoordinates: GitLabProjectCoordinates +) : AsyncImageIconsProvider.AsyncImageLoader, AsyncHtmlImageLoader { override suspend fun load(key: GitLabUserDTO): Image? { return key.avatarUrl?.let { avatarUrl -> val actualUri = when { avatarUrl.startsWith("http") -> avatarUrl avatarUrl.startsWith("/avatar") -> "https://secure.gravatar.com$avatarUrl?s=$LOADED_GRAVATAR_SIZE&d=identicon" - else -> server.uri + avatarUrl + else -> gitLabProjectCoordinates.serverPath.uri + avatarUrl } - try { - apiClient.loadImage(actualUri) - } - catch (ce: CancellationException) { - throw ce - } - catch (e: Exception) { - LOG.warn("Failed to load the avatar image from avatarUrl $avatarUrl with actual URI $actualUri", e) - throw e + load(null, actualUri) + } + } + + override suspend fun load(baseUrl: URL?, src: String): Image? { + try { + if (src.startsWith("/uploads/")) { + val uriString = gitLabProjectCoordinates.restApiUri.resolveRelative(src.trimStart('/')).toString() + return apiClient.loadImage(uriString) } + val uri = URI.create(src) + return apiClient.loadImage(uri) + } + catch (ce: CancellationException) { + throw ce + } + catch (e: Exception) { + LOG.warn("Failed to load the image from src $src", e) + throw e } } @@ -49,4 +63,4 @@ class GitLabImageLoader( override suspend fun postProcess(image: Image): Image { return ImageUtil.createCircleImage(ImageUtil.toBufferedImage(image)) } -} \ No newline at end of file +} diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabProject.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabProject.kt index 6ac6031d3cd7..66349540ad1f 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabProject.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/data/GitLabProject.kt @@ -17,6 +17,7 @@ import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.api.dto.GitLabWorkItemDTO.GitLabWidgetDTO.WorkItemWidgetAssignees import org.jetbrains.plugins.gitlab.api.dto.GitLabWorkItemDTO.WorkItemType import org.jetbrains.plugins.gitlab.api.request.* +import org.jetbrains.plugins.gitlab.data.GitLabImageLoader import org.jetbrains.plugins.gitlab.mergerequest.api.dto.GitLabMergeRequestDTO import org.jetbrains.plugins.gitlab.mergerequest.api.request.loadMergeRequest import org.jetbrains.plugins.gitlab.mergerequest.api.request.mergeRequestSetReviewers @@ -67,6 +68,7 @@ class GitLabLazyProject( private val initialData: GitLabProjectDTO, private val currentUser: GitLabUserDTO, private val tokenRefreshFlow: Flow, + imageLoader: GitLabImageLoader ) : GitLabProject { private val cs = parentCs.childScope(javaClass.name) @@ -84,9 +86,9 @@ class GitLabLazyProject( } override val gitLabProjectId: GitLabId = initialData.id - val uploadFileUrlBase: String = projectMapping.repository.serverPath.toString() + "/-/project/" + gitLabProjectId.guessRestId() + "/uploads/" + private val uploadFileUrlBase: String = projectMapping.repository.serverPath.toString() + "/-/project/" + gitLabProjectId.guessRestId() + "/uploads/" - override val contextDataLoader: GitLabContextDataLoader = GitLabContextDataLoader(uploadFileUrlBase) + override val contextDataLoader: GitLabContextDataLoader = GitLabContextDataLoader(imageLoader, uploadFileUrlBase) override val mergeRequests by lazy { CachingGitLabProjectMergeRequestsStore(project, cs, api, glMetadata, projectMapping, currentUser, tokenRefreshFlow) diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffExtension.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffExtension.kt index c41ca9abc61c..8ffba501d10b 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffExtension.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffExtension.kt @@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.withContext import org.jetbrains.plugins.gitlab.GitLabSettings import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.mergerequest.ui.diff.GitLabMergeRequestDiffDiscussionViewModel import org.jetbrains.plugins.gitlab.mergerequest.ui.diff.GitLabMergeRequestDiffDraftNoteViewModel import org.jetbrains.plugins.gitlab.mergerequest.ui.diff.GitLabMergeRequestDiffNewDiscussionViewModel @@ -84,7 +85,7 @@ class GitLabMergeRequestDiffExtension : DiffExtension() { UnifiedCodeReviewItemPosition(change, leftLine, rightLine) } }, - rendererFactory = { createRenderer(it, changeVm.avatarIconsProvider) } + rendererFactory = { createRenderer(it, changeVm.avatarIconsProvider, changeVm.contextDataLoader) } ) } } @@ -94,13 +95,14 @@ class GitLabMergeRequestDiffExtension : DiffExtension() { private fun CoroutineScope.createRenderer( model: GitLabMergeRequestEditorMappedComponentModel, avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader, ): CodeReviewComponentInlayRenderer = when (model) { is GitLabMergeRequestEditorMappedComponentModel.Discussion<*> -> - GitLabMergeRequestDiscussionInlayRenderer(this, project, model.vm, avatarIconsProvider, + GitLabMergeRequestDiscussionInlayRenderer(this, project, model.vm, avatarIconsProvider, contextDataLoader, GitLabStatistics.MergeRequestNoteActionPlace.DIFF) is GitLabMergeRequestEditorMappedComponentModel.DraftNote<*> -> - GitLabMergeRequestDraftNoteInlayRenderer(this, project, model.vm, avatarIconsProvider, + GitLabMergeRequestDraftNoteInlayRenderer(this, project, model.vm, avatarIconsProvider, contextDataLoader, GitLabStatistics.MergeRequestNoteActionPlace.DIFF) is GitLabMergeRequestEditorMappedComponentModel.NewDiscussion<*> -> GitLabMergeRequestNewDiscussionInlayRenderer(this, project, model.vm, avatarIconsProvider, diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffViewModel.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffViewModel.kt index 5eed48f04075..d649c9c623e5 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffViewModel.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/diff/GitLabMergeRequestDiffViewModel.kt @@ -28,6 +28,7 @@ import org.jetbrains.plugins.gitlab.mergerequest.GitLabMergeRequestsPreferences import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequest import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequestChanges import org.jetbrains.plugins.gitlab.mergerequest.data.loadRevisionsAndParseChanges +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.mergerequest.ui.createDiffDataFlow import org.jetbrains.plugins.gitlab.mergerequest.ui.diff.* import org.jetbrains.plugins.gitlab.mergerequest.ui.review.GitLabMergeRequestDiscussionsViewModels @@ -71,6 +72,7 @@ internal class GitLabMergeRequestDiffProcessorViewModelImpl( private val mergeRequest: GitLabMergeRequest, private val discussionsContainer: GitLabMergeRequestDiscussionsViewModels, private val avatarIconsProvider: IconsProvider, + private val contextDataLoader: GitLabContextDataLoader, ) : GitLabMergeRequestDiffViewModel, GitLabMergeRequestReviewViewModelBase( parentCs.childScope("GitLab Merge Request Diff Review VM"), currentUser, mergeRequest, @@ -194,7 +196,8 @@ internal class GitLabMergeRequestDiffProcessorViewModelImpl( project, this, mergeRequest, diffData, change, this@GitLabMergeRequestDiffProcessorViewModelImpl, - discussionsContainer, discussionsViewOption, avatarIconsProvider + discussionsContainer, discussionsViewOption, avatarIconsProvider, + contextDataLoader ) override fun findNextComment(currentThreadId: String, additionalIsVisible: (String) -> Boolean): String? = diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/file/GitLabMergeRequestTimelineFileEditor.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/file/GitLabMergeRequestTimelineFileEditor.kt index 5fa17305a481..4f39873c4904 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/file/GitLabMergeRequestTimelineFileEditor.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/file/GitLabMergeRequestTimelineFileEditor.kt @@ -111,7 +111,9 @@ class GitLabMergeRequestTimelineEditorFactory(private val project: Project, pare withContext(Dispatchers.Main.immediate) { timelineVmResult.fold( onSuccess = { - val timeline = GitLabMergeRequestTimelineComponentFactory.create(project, this, it, projectVm.avatarIconProvider) + val timeline = GitLabMergeRequestTimelineComponentFactory.create(project, this, it, + projectVm.avatarIconProvider, + projectVm.contextDataLoader) wrapper.setContent(timeline) wrapper.repaint() }, diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabConnectedProjectViewModel.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabConnectedProjectViewModel.kt index 37edea0f3d43..b5a2b594d950 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabConnectedProjectViewModel.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabConnectedProjectViewModel.kt @@ -48,6 +48,7 @@ interface GitLabConnectedProjectViewModel { val accountVm: GitLabAccountViewModel val listVm: GitLabMergeRequestsListViewModel val currentMergeRequestReviewVm: Flow + val contextDataLoader: GitLabContextDataLoader fun findMergeRequestDetails(mrIid: String): GitLabMergeRequestDetails? fun reloadMergeRequestDetails(mergeRequestId: String) fun getDiffViewModel(mrIid: String): Flow> @@ -77,6 +78,8 @@ abstract class GitLabConnectedProjectViewModelBase( override val avatarIconProvider: IconsProvider = CachingIconsProvider(AsyncImageIconsProvider(cs, connection.imageLoader)) + override val contextDataLoader: GitLabContextDataLoader = connection.projectData.contextDataLoader + private val projectName: @Nls String = connection.repo.repository.projectPath.name override val listVm: GitLabMergeRequestsListViewModel = run { @@ -103,7 +106,8 @@ abstract class GitLabConnectedProjectViewModelBase( connection.projectData.mergeRequests.getShared(iid) .transformConsecutiveSuccesses { mapScoped { - GitLabMergeRequestViewModels(project, this, connection.projectData, avatarIconProvider, it, connection.currentUser, + GitLabMergeRequestViewModels(project, this, connection.projectData, avatarIconProvider, + it, connection.currentUser, ::openMergeRequestDetails, ::openMergeRequestTimeline, ::openMergeRequestDiff) } } diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabContextDataLoader.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabContextDataLoader.kt index 036ef1729d96..72d513e4c334 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabContextDataLoader.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabContextDataLoader.kt @@ -1,6 +1,7 @@ // Copyright 2000-2025 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.ui +import com.intellij.collaboration.ui.html.AsyncHtmlImageLoader import org.jetbrains.annotations.ApiStatus /** @@ -8,5 +9,6 @@ import org.jetbrains.annotations.ApiStatus */ @ApiStatus.Internal class GitLabContextDataLoader( + val imageLoader: AsyncHtmlImageLoader, val uploadFileUrlBase: String ) \ No newline at end of file diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabMergeRequestViewModels.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabMergeRequestViewModels.kt index ca63ee4e4783..d39e26fb34b4 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabMergeRequestViewModels.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/GitLabMergeRequestViewModels.kt @@ -66,7 +66,8 @@ internal class GitLabMergeRequestViewModels( } private val _diffVm by lazy { - GitLabMergeRequestDiffProcessorViewModelImpl(project, cs, currentUser, mergeRequest, discussionsVms, avatarIconProvider).apply { + GitLabMergeRequestDiffProcessorViewModelImpl(project, cs, currentUser, mergeRequest, discussionsVms, + avatarIconProvider, projectData.contextDataLoader).apply { setup() } } @@ -74,7 +75,8 @@ internal class GitLabMergeRequestViewModels( val editorReviewVm: GitLabMergeRequestEditorReviewViewModel by lazy { GitLabMergeRequestEditorReviewViewModel(cs, project, projectData.projectMapping, currentUser, mergeRequest, - discussionsVms, avatarIconProvider, openMergeRequestDetails, openMergeRequestDiff).apply { + discussionsVms, avatarIconProvider, projectData.contextDataLoader, + openMergeRequestDetails, openMergeRequestDiff).apply { setup() } } diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/diff/GitLabMergeRequestDiffInlayComponentsFactory.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/diff/GitLabMergeRequestDiffInlayComponentsFactory.kt index eeb227b3d3e0..c90f3169bd03 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/diff/GitLabMergeRequestDiffInlayComponentsFactory.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/diff/GitLabMergeRequestDiffInlayComponentsFactory.kt @@ -18,6 +18,7 @@ import com.intellij.util.ui.launchOnShow import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.ui.comment.* import org.jetbrains.plugins.gitlab.util.GitLabBundle import org.jetbrains.plugins.gitlab.util.GitLabStatistics @@ -32,10 +33,11 @@ internal object GitLabMergeRequestDiffInlayComponentsFactory { project: Project, cs: CoroutineScope, avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader, vm: GitLabMergeRequestDiscussionViewModel, place: GitLabStatistics.MergeRequestNoteActionPlace, ): JComponent = - GitLabDiscussionComponentFactory.create(project, cs, avatarIconsProvider, vm, place).apply { + GitLabDiscussionComponentFactory.create(project, cs, avatarIconsProvider, contextDataLoader, vm, place).apply { border = JBUI.Borders.empty(CodeReviewCommentUIUtil.getInlayPadding(CodeReviewChatItemUIUtil.ComponentType.COMPACT)) }.apply { isFocusable = true @@ -57,10 +59,12 @@ internal object GitLabMergeRequestDiffInlayComponentsFactory { project: Project, cs: CoroutineScope, avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader, vm: GitLabNoteViewModel, place: GitLabStatistics.MergeRequestNoteActionPlace, ): JComponent = - GitLabNoteComponentFactory.create(CodeReviewChatItemUIUtil.ComponentType.COMPACT, project, cs, avatarIconsProvider, vm, place).apply { + GitLabNoteComponentFactory.create(CodeReviewChatItemUIUtil.ComponentType.COMPACT, project, cs, avatarIconsProvider, + contextDataLoader, vm, place).apply { border = JBUI.Borders.empty(CodeReviewCommentUIUtil.getInlayPadding(CodeReviewChatItemUIUtil.ComponentType.COMPACT)) }.apply { isFocusable = true diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/diff/GitLabMergeRequestDiffReviewViewModel.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/diff/GitLabMergeRequestDiffReviewViewModel.kt index 724156d6f8e2..f1576c10823a 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/diff/GitLabMergeRequestDiffReviewViewModel.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/diff/GitLabMergeRequestDiffReviewViewModel.kt @@ -24,6 +24,7 @@ import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequest import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequestNewDiscussionPosition import org.jetbrains.plugins.gitlab.mergerequest.data.mapToLocation import org.jetbrains.plugins.gitlab.mergerequest.diff.GitLabMergeRequestDiffViewModel +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.mergerequest.ui.details.model.GitLabPersistentMergeRequestChangesViewedState import org.jetbrains.plugins.gitlab.mergerequest.ui.filterInFile import org.jetbrains.plugins.gitlab.mergerequest.ui.review.GitLabMergeRequestDiscussionsViewModels @@ -42,6 +43,7 @@ interface GitLabMergeRequestDiffReviewViewModel { val locationsWithNewDiscussions: StateFlow> val avatarIconsProvider: IconsProvider + val contextDataLoader: GitLabContextDataLoader fun nextComment(focused: String, additionalIsVisible: (String) -> Boolean): String? fun nextComment(cursorLocation: UnifiedCodeReviewItemPosition, additionalIsVisible: (String) -> Boolean): String? @@ -66,6 +68,7 @@ internal class GitLabMergeRequestDiffReviewViewModelImpl( private val discussionsContainer: GitLabMergeRequestDiscussionsViewModels, discussionsViewOption: StateFlow, override val avatarIconsProvider: IconsProvider, + override val contextDataLoader: GitLabContextDataLoader ) : GitLabMergeRequestDiffReviewViewModel { private val cs = parentCs.childScope(javaClass.name) diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewController.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewController.kt index ffc72b7201e2..5964720f99ae 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewController.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewController.kt @@ -27,6 +27,7 @@ import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.mergerequest.GitLabMergeRequestsPreferences +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabProjectViewModel import org.jetbrains.plugins.gitlab.util.GitLabStatistics @@ -103,7 +104,7 @@ internal class GitLabMergeRequestEditorReviewController(private val project: Pro } launchNow { editor.renderInlays(model.inlays, HashingUtil.mappingStrategy(GitLabMergeRequestEditorMappedComponentModel::key)) { - createRenderer(it, fileVm.avatarIconsProvider) + createRenderer(it, fileVm.avatarIconsProvider, fileVm.contextDataLoader) } } @@ -122,13 +123,16 @@ internal class GitLabMergeRequestEditorReviewController(private val project: Pro private fun CoroutineScope.createRenderer( inlayModel: GitLabMergeRequestEditorMappedComponentModel, avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader ) = when (inlayModel) { is GitLabMergeRequestEditorMappedComponentModel.Discussion<*> -> GitLabMergeRequestDiscussionInlayRenderer(this, project, inlayModel.vm, avatarIconsProvider, + contextDataLoader, GitLabStatistics.MergeRequestNoteActionPlace.EDITOR) is GitLabMergeRequestEditorMappedComponentModel.DraftNote<*> -> GitLabMergeRequestDraftNoteInlayRenderer(this, project, inlayModel.vm, avatarIconsProvider, + contextDataLoader, GitLabStatistics.MergeRequestNoteActionPlace.EDITOR) is GitLabMergeRequestEditorMappedComponentModel.NewDiscussion<*> -> GitLabMergeRequestNewDiscussionInlayRenderer(this, project, inlayModel.vm, avatarIconsProvider, diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewFileViewModel.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewFileViewModel.kt index aec5c7a5dc26..19c0038744a2 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewFileViewModel.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewFileViewModel.kt @@ -29,6 +29,7 @@ import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequest import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequestNewDiscussionPosition import org.jetbrains.plugins.gitlab.mergerequest.data.mapToLocation +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.mergerequest.ui.filterInFile import org.jetbrains.plugins.gitlab.mergerequest.ui.review.GitLabMergeRequestDiscussionsViewModels import org.jetbrains.plugins.gitlab.mergerequest.ui.review.mapToLocation @@ -54,6 +55,7 @@ interface GitLabMergeRequestEditorReviewFileViewModel { val newDiscussions: StateFlow> val avatarIconsProvider: IconsProvider + val contextDataLoader: GitLabContextDataLoader fun lookupNextComment(line: Int, additionalIsVisible: (String) -> Boolean): String? fun lookupNextComment(noteTrackingId: String, additionalIsVisible: (String) -> Boolean): String? @@ -79,6 +81,7 @@ internal class GitLabMergeRequestEditorReviewFileViewModelImpl( private val reviewVm: GitLabMergeRequestEditorReviewViewModel, discussionsViewOption: StateFlow, override val avatarIconsProvider: IconsProvider, + override val contextDataLoader: GitLabContextDataLoader ) : GitLabMergeRequestEditorReviewFileViewModel { private val cs = parentCs.childScope(javaClass.name, Dispatchers.Default) diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewViewModel.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewViewModel.kt index fdbe6cf56977..59966e37529f 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewViewModel.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/GitLabMergeRequestEditorReviewViewModel.kt @@ -33,6 +33,7 @@ import org.jetbrains.annotations.ApiStatus import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.mergerequest.GitLabMergeRequestsPreferences import org.jetbrains.plugins.gitlab.mergerequest.data.GitLabMergeRequest +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.mergerequest.ui.createDiffDataFlow import org.jetbrains.plugins.gitlab.mergerequest.ui.review.GitLabMergeRequestDiscussionsViewModels import org.jetbrains.plugins.gitlab.mergerequest.ui.review.GitLabMergeRequestReviewViewModelBase @@ -52,6 +53,7 @@ class GitLabMergeRequestEditorReviewViewModel internal constructor( private val mergeRequest: GitLabMergeRequest, private val discussionsVms: GitLabMergeRequestDiscussionsViewModels, private val avatarIconsProvider: IconsProvider, + private val contextDataLoader: GitLabContextDataLoader, private val openMergeRequestDetails: (String, GitLabStatistics.ToolWindowOpenTabActionPlace, Boolean) -> Unit, private val openMergeRequestDiff: (String, Boolean) -> Unit, ) : GitLabMergeRequestReviewViewModelBase( @@ -251,7 +253,7 @@ class GitLabMergeRequestEditorReviewViewModel internal constructor( GitLabMergeRequestEditorReviewFileViewModelImpl( this, project, mergeRequest, changes.selectedItem!!, diffData, discussionsVms, this@GitLabMergeRequestEditorReviewViewModel, - discussionsViewOption, avatarIconsProvider + discussionsViewOption, avatarIconsProvider, contextDataLoader ).also { vm -> launchNow { vm.showDiffRequests.collect { line -> diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/editorInlayRenderers.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/editorInlayRenderers.kt index 0e5affead695..ec195f7ce719 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/editorInlayRenderers.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/editor/editorInlayRenderers.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.project.Project import kotlinx.coroutines.CoroutineScope import org.jetbrains.annotations.ApiStatus import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.mergerequest.ui.diff.GitLabMergeRequestDiffInlayComponentsFactory import org.jetbrains.plugins.gitlab.ui.comment.GitLabMergeRequestDiscussionViewModel import org.jetbrains.plugins.gitlab.ui.comment.GitLabNoteViewModel @@ -18,9 +19,11 @@ class GitLabMergeRequestDiscussionInlayRenderer internal constructor(cs: Corouti project: Project, vm: GitLabMergeRequestDiscussionViewModel, avatarIconsProvider: IconsProvider, - place: GitLabStatistics.MergeRequestNoteActionPlace) + contextDataLoader: GitLabContextDataLoader, + place: GitLabStatistics.MergeRequestNoteActionPlace, +) : CodeReviewComponentInlayRenderer( - GitLabMergeRequestDiffInlayComponentsFactory.createDiscussion(project, cs, avatarIconsProvider, vm, place) + GitLabMergeRequestDiffInlayComponentsFactory.createDiscussion(project, cs, avatarIconsProvider, contextDataLoader, vm, place) ) @ApiStatus.Internal @@ -28,9 +31,11 @@ class GitLabMergeRequestDraftNoteInlayRenderer internal constructor(cs: Coroutin project: Project, vm: GitLabNoteViewModel, avatarIconsProvider: IconsProvider, - place: GitLabStatistics.MergeRequestNoteActionPlace) + contextDataLoader: GitLabContextDataLoader, + place: GitLabStatistics.MergeRequestNoteActionPlace, +) : CodeReviewComponentInlayRenderer( - GitLabMergeRequestDiffInlayComponentsFactory.createDraftNote(project, cs, avatarIconsProvider, vm, place) + GitLabMergeRequestDiffInlayComponentsFactory.createDraftNote(project, cs, avatarIconsProvider, contextDataLoader, vm, place) ) @ApiStatus.Internal diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineComponentFactory.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineComponentFactory.kt index bf1257c35212..6966aff6d668 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineComponentFactory.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineComponentFactory.kt @@ -20,7 +20,6 @@ import com.intellij.ide.DataManager import com.intellij.openapi.actionSystem.ActionGroup import com.intellij.openapi.actionSystem.ActionManager import com.intellij.openapi.actionSystem.ActionPlaces -import com.intellij.openapi.application.EDT import com.intellij.openapi.diagnostic.thisLogger import com.intellij.openapi.editor.colors.EditorColorsManager import com.intellij.openapi.project.Project @@ -32,17 +31,16 @@ import com.intellij.ui.PopupHandler import com.intellij.ui.ScrollPaneFactory import com.intellij.ui.components.panels.ListLayout import com.intellij.ui.components.panels.Wrapper -import com.intellij.util.ui.JBUI import com.intellij.util.ui.JBUI.Borders import com.intellij.util.ui.StyleSheetUtil import com.intellij.util.ui.launchOnShow import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import org.jetbrains.annotations.Nls import org.jetbrains.plugins.gitlab.api.dto.* +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.mergerequest.ui.details.GitLabMergeRequestViewModel import org.jetbrains.plugins.gitlab.mergerequest.util.addGitLabHyperlinkListener import org.jetbrains.plugins.gitlab.ui.comment.* @@ -55,7 +53,8 @@ internal object GitLabMergeRequestTimelineComponentFactory { fun create(project: Project, cs: CoroutineScope, timelineVm: GitLabMergeRequestTimelineViewModel, - avatarIconsProvider: IconsProvider + avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader ): JComponent { val titleComponent = GitLabMergeRequestTimelineTitleComponent.create(project, cs, timelineVm).let { CollaborationToolsUIUtil.wrapWithLimitedSize(it, CodeReviewChatItemUIUtil.TEXT_CONTENT_WIDTH) @@ -63,10 +62,10 @@ internal object GitLabMergeRequestTimelineComponentFactory { border = Borders.empty(CodeReviewTimelineUIUtil.HEADER_VERT_PADDING, CodeReviewTimelineUIUtil.ITEM_HOR_PADDING) } val descriptionComponent = GitLabMergeRequestTimelineDescriptionComponent - .createComponent(project, cs, timelineVm, avatarIconsProvider) + .createComponent(project, cs, timelineVm, avatarIconsProvider, contextDataLoader) val timelinePanel = VerticalListPanel(0) - val errorOrTimelineComponent = createErrorOrTimelineComponent(cs, project, avatarIconsProvider, timelineVm, timelinePanel) + val errorOrTimelineComponent = createErrorOrTimelineComponent(cs, project, avatarIconsProvider, contextDataLoader, timelineVm, timelinePanel) val newNoteField = timelineVm.newNoteVm?.let { cs.createNewNoteField(project, avatarIconsProvider, it) @@ -138,6 +137,7 @@ internal object GitLabMergeRequestTimelineComponentFactory { private fun createErrorOrTimelineComponent(cs: CoroutineScope, project: Project, avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader, timelineVm: GitLabMergeRequestTimelineViewModel, timelinePanel: JComponent): JComponent { val actionManager = ActionManager.getInstance() @@ -148,7 +148,7 @@ internal object GitLabMergeRequestTimelineComponentFactory { val timelineItems = MutableStateFlow>(listOf()) val timelineItemContent = ComponentListPanelFactory.createVertical(cs, timelineItems) { item -> - createItemComponent(project, avatarIconsProvider, item) + createItemComponent(project, avatarIconsProvider, contextDataLoader, item) } val timelineItemsAndLoadingLabel = VerticalListPanel(gap = 0).apply { val panel = this @@ -196,6 +196,7 @@ internal object GitLabMergeRequestTimelineComponentFactory { private fun CoroutineScope.createItemComponent(project: Project, avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader, item: GitLabMergeRequestTimelineItemViewModel): JComponent = when (item) { is GitLabMergeRequestTimelineItemViewModel.Immutable -> { @@ -208,10 +209,10 @@ internal object GitLabMergeRequestTimelineComponentFactory { } } is GitLabMergeRequestTimelineItemViewModel.Discussion -> { - GitLabMergeRequestTimelineDiscussionComponentFactory.createIn(project, this, item, avatarIconsProvider) + GitLabMergeRequestTimelineDiscussionComponentFactory.createIn(project, this, item, avatarIconsProvider, contextDataLoader) } is GitLabMergeRequestTimelineItemViewModel.DraftNote -> { - GitLabMergeRequestTimelineDiscussionComponentFactory.createIn(project, this, item, avatarIconsProvider) + GitLabMergeRequestTimelineDiscussionComponentFactory.createIn(project, this, item, avatarIconsProvider, contextDataLoader) } } @@ -223,8 +224,10 @@ internal object GitLabMergeRequestTimelineComponentFactory { is GitLabMergeRequestTimelineItemViewModel.StateEvent -> createStateChangeContent(item) } - private fun createSystemDiscussionContent(project: Project, - item: GitLabMergeRequestTimelineItemViewModel.SystemNote): JComponent { + private fun createSystemDiscussionContent( + project: Project, + item: GitLabMergeRequestTimelineItemViewModel.SystemNote + ): JComponent { val content = item.content if (content.contains("Compare with previous version")) { try { @@ -253,10 +256,11 @@ internal object GitLabMergeRequestTimelineComponentFactory { StyleSheetUtil.loadStyleSheet("""ul {margin: 0}""") } - private fun createCommitsListPane(project: Project, commits: @NlsSafe String) = SimpleHtmlPane(noUlGapsStyleSheet, addBrowserListener = false).apply { - setHtmlBody(commits) - addGitLabHyperlinkListener(project) - } + private fun createCommitsListPane(project: Project, commits: @NlsSafe String) = + SimpleHtmlPane(noUlGapsStyleSheet, addBrowserListener = false).apply { + setHtmlBody(commits) + addGitLabHyperlinkListener(project) + } private fun createLabeledEventContent(item: GitLabMergeRequestTimelineItemViewModel.LabelEvent): JComponent { val text = when (item.event.actionEnum) { diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineDescriptionComponent.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineDescriptionComponent.kt index 1fe0f8bce2fc..2cbd0237fb06 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineDescriptionComponent.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineDescriptionComponent.kt @@ -13,6 +13,7 @@ import com.intellij.util.ui.UIUtil import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.map import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.ui.comment.GitLabNoteComponentFactory.createTextPanel import org.jetbrains.plugins.gitlab.util.GitLabBundle import javax.swing.JComponent @@ -32,10 +33,11 @@ internal object GitLabMergeRequestTimelineDescriptionComponent { cs: CoroutineScope, vm: GitLabMergeRequestTimelineViewModel, avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader, ): JComponent { val titlePanel = CodeReviewTimelineUIUtil.createTitleTextPane(vm.author.name, vm.author.webUrl, date = null) val descriptionTextComponent = createTextPanel(project, cs, vm.descriptionHtml.map { it.ifBlank { noDescriptionHtmlText } }, - vm.serverUrl) + vm.serverUrl, contextDataLoader) return CodeReviewChatItemUIUtil.buildDynamic(CodeReviewChatItemUIUtil.ComponentType.FULL, diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineDiscussionComponentFactory.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineDiscussionComponentFactory.kt index 5fe564531aa1..ac83ea8c2da9 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineDiscussionComponentFactory.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/mergerequest/ui/timeline/GitLabMergeRequestTimelineDiscussionComponentFactory.kt @@ -33,6 +33,7 @@ import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO import org.jetbrains.plugins.gitlab.mergerequest.data.filePath +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.mergerequest.ui.emoji.GitLabReactionsComponentFactory import org.jetbrains.plugins.gitlab.mergerequest.util.localizedMessageOrClassName import org.jetbrains.plugins.gitlab.ui.comment.GitLabDiscussionComponentFactory @@ -53,18 +54,20 @@ internal object GitLabMergeRequestTimelineDiscussionComponentFactory { fun createIn(project: Project, cs: CoroutineScope, vm: GitLabMergeRequestTimelineDiscussionViewModel, - avatarIconsProvider: IconsProvider): JComponent = + avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader): JComponent = VerticalListPanel().apply { name = "GitLab Discussion Panel ${vm.id}" - add(createDiscussionItemIn(project, cs, vm, avatarIconsProvider)) - add(createRepliesPanelIn(project, cs, vm, avatarIconsProvider)) + add(createDiscussionItemIn(project, cs, vm, avatarIconsProvider, contextDataLoader)) + add(createRepliesPanelIn(project, cs, vm, avatarIconsProvider, contextDataLoader)) } fun createIn(project: Project, cs: CoroutineScope, vm: GitLabMergeRequestTimelineItemViewModel.DraftNote, - avatarIconsProvider: IconsProvider): JComponent { - val contentPanel = createContentIn(project, cs, vm) + avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader): JComponent { + val contentPanel = createContentIn(project, cs, vm, contextDataLoader) val mainItem = CodeReviewChatItemUIUtil.build(ComponentType.FULL, { avatarIconsProvider.getIcon(vm.author, it) }, contentPanel) { @@ -82,8 +85,9 @@ internal object GitLabMergeRequestTimelineDiscussionComponentFactory { private fun createDiscussionItemIn(project: Project, cs: CoroutineScope, vm: GitLabMergeRequestTimelineDiscussionViewModel, - avatarIconsProvider: IconsProvider): JComponent { - val contentPanel = createContentIn(project, cs, vm, avatarIconsProvider) + avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader): JComponent { + val contentPanel = createContentIn(project, cs, vm, avatarIconsProvider, contextDataLoader) val mainItem = CodeReviewChatItemUIUtil.buildDynamic(ComponentType.FULL, { vm.author.createIconValue(cs, avatarIconsProvider, it) }, contentPanel) { @@ -104,13 +108,14 @@ internal object GitLabMergeRequestTimelineDiscussionComponentFactory { private fun createContentIn(project: Project, cs: CoroutineScope, vm: GitLabMergeRequestTimelineDiscussionViewModel, - avatarIconsProvider: IconsProvider): JPanel { + avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader): JPanel { val mainNoteVm = vm.mainNote val repliesActionsPanel = createRepliesActionsPanel(cs, avatarIconsProvider, vm).apply { border = JBUI.Borders.empty(Replies.ActionsFolded.VERTICAL_PADDING, 0) bindVisibilityIn(cs, vm.repliesFolded) } - val textPanel = createDiscussionTextPane(project, cs, vm) + val textPanel = createDiscussionTextPane(project, cs, vm, contextDataLoader) val editVmFlow = mainNoteVm.flatMapLatest { it.actionsVm?.editVm ?: flowOf(null) } val textContentPanel = EditableComponentFactory.wrapTextComponent(cs, textPanel, editVmFlow) { @@ -162,8 +167,10 @@ internal object GitLabMergeRequestTimelineDiscussionComponentFactory { private fun createContentIn(project: Project, cs: CoroutineScope, - vm: GitLabMergeRequestTimelineItemViewModel.DraftNote): JPanel { - val textPanel = GitLabNoteComponentFactory.createTextPanel(project, cs, vm.bodyHtml, vm.serverUrl) + vm: GitLabMergeRequestTimelineItemViewModel.DraftNote, + contextDataLoader: GitLabContextDataLoader): JPanel { + val textPanel = GitLabNoteComponentFactory.createTextPanel(project, cs, vm.bodyHtml, vm.serverUrl, + contextDataLoader) val textContentPanel = EditableComponentFactory.wrapTextComponent(cs, textPanel, vm.actionsVm?.editVm ?: flowOf(null)) { GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.UPDATE_NOTE, @@ -270,7 +277,10 @@ internal object GitLabMergeRequestTimelineDiscussionComponentFactory { ) } - private fun createDiscussionTextPane(project: Project, cs: CoroutineScope, vm: GitLabMergeRequestTimelineDiscussionViewModel): JComponent { + private fun createDiscussionTextPane( + project: Project, cs: CoroutineScope, vm: GitLabMergeRequestTimelineDiscussionViewModel, + contextDataLoader: GitLabContextDataLoader + ): JComponent { val collapsedFlow = combine(vm.collapsible, vm.collapsed) { collapsible, collapsed -> collapsible && collapsed } @@ -279,7 +289,7 @@ internal object GitLabMergeRequestTimelineDiscussionComponentFactory { if (collapsed) mainNote.body else mainNote.bodyHtml }.flatMapLatest { it } - val textPane = GitLabNoteComponentFactory.createTextPanel(project, cs, textFlow, vm.serverUrl) + val textPane = GitLabNoteComponentFactory.createTextPanel(project, cs, textFlow, vm.serverUrl, contextDataLoader) val layout = SizeRestrictedSingleComponentLayout() return JPanel(layout).apply { name = "Text pane wrapper" @@ -306,10 +316,14 @@ internal object GitLabMergeRequestTimelineDiscussionComponentFactory { private fun createRepliesPanelIn(project: Project, cs: CoroutineScope, vm: GitLabMergeRequestTimelineDiscussionViewModel, - avatarIconsProvider: IconsProvider): JPanel { + avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader + ): JPanel { val repliesListPanel = ComponentListPanelFactory.createVertical(cs, vm.replies) { noteVm -> - GitLabNoteComponentFactory.create(ComponentType.FULL_SECONDARY, project, this, avatarIconsProvider, noteVm, - ACTION_PLACE) + GitLabNoteComponentFactory.create( + ComponentType.FULL_SECONDARY, project, this, avatarIconsProvider, contextDataLoader, noteVm, + ACTION_PLACE + ) } val repliesPanel = VerticalListPanel().apply { diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabDiscussionComponentFactory.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabDiscussionComponentFactory.kt index 652dbf389a8e..2f305a79cae0 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabDiscussionComponentFactory.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabDiscussionComponentFactory.kt @@ -32,6 +32,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.ui.comment.GitLabMergeRequestDiscussionViewModel.NoteItem import org.jetbrains.plugins.gitlab.util.GitLabBundle import org.jetbrains.plugins.gitlab.util.GitLabStatistics @@ -39,10 +40,12 @@ import javax.swing.Action import javax.swing.JComponent internal object GitLabDiscussionComponentFactory { + fun create( project: Project, cs: CoroutineScope, avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader, vm: GitLabMergeRequestDiscussionViewModel, place: GitLabStatistics.MergeRequestNoteActionPlace, ): JComponent { @@ -57,7 +60,8 @@ internal object GitLabDiscussionComponentFactory { TimelineThreadCommentsPanel.UNFOLD_BUTTON_VERTICAL_GAP, 0) } - is NoteItem.Note -> GitLabNoteComponentFactory.create(ComponentType.COMPACT, project, itemCs, avatarIconsProvider, item.vm, place) + is NoteItem.Note -> GitLabNoteComponentFactory.create(ComponentType.COMPACT, project, itemCs, avatarIconsProvider, contextDataLoader, + item.vm, place) } } diff --git a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabNoteComponentFactory.kt b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabNoteComponentFactory.kt index bdced9461bd0..1fa867e4aa61 100644 --- a/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabNoteComponentFactory.kt +++ b/plugins/gitlab/gitlab-core/src/org/jetbrains/plugins/gitlab/ui/comment/GitLabNoteComponentFactory.kt @@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.launch import org.jetbrains.annotations.Nls import org.jetbrains.plugins.gitlab.api.dto.GitLabUserDTO +import org.jetbrains.plugins.gitlab.mergerequest.ui.GitLabContextDataLoader import org.jetbrains.plugins.gitlab.mergerequest.ui.emoji.GitLabReactionsComponentFactory import org.jetbrains.plugins.gitlab.mergerequest.ui.emoji.GitLabReactionsPickerComponentFactory import org.jetbrains.plugins.gitlab.mergerequest.ui.emoji.GitLabReactionsViewModel @@ -37,15 +38,17 @@ import java.net.URL import javax.swing.JComponent internal object GitLabNoteComponentFactory { + fun create( componentType: ComponentType, project: Project, cs: CoroutineScope, avatarIconsProvider: IconsProvider, + contextDataLoader: GitLabContextDataLoader, vm: GitLabNoteViewModel, place: GitLabStatistics.MergeRequestNoteActionPlace, ): JComponent { - val textPanel = createTextPanel(project, cs, vm.bodyHtml, vm.serverUrl).let { panel -> + val textPanel = createTextPanel(project, cs, vm.bodyHtml, vm.serverUrl, contextDataLoader).let { panel -> val actionsVm = vm.actionsVm ?: return@let panel EditableComponentFactory.wrapTextComponent(cs, panel, actionsVm.editVm) { GitLabStatistics.logMrActionExecuted(project, GitLabStatistics.MergeRequestAction.UPDATE_NOTE, place) @@ -173,8 +176,11 @@ internal object GitLabNoteComponentFactory { return button } - fun createTextPanel(project: Project, cs: CoroutineScope, textFlow: Flow<@Nls String>, baseUrl: URL): JComponent = - SimpleHtmlPane(baseUrl = baseUrl, addBrowserListener = false).apply { + fun createTextPanel( + project: Project, cs: CoroutineScope, textFlow: Flow<@Nls String>, baseUrl: URL, + contextDataLoader: GitLabContextDataLoader + ): JComponent = + SimpleHtmlPane(baseUrl = baseUrl, addBrowserListener = false, customImageLoader = contextDataLoader.imageLoader).apply { bindTextIn(cs, textFlow) addGitLabHyperlinkListener(project) }