From 5ce86532d3915456a14c25b4e268dff83c5d25e7 Mon Sep 17 00:00:00 2001 From: Ivan Semenov Date: Mon, 10 Jun 2024 15:06:51 +0200 Subject: [PATCH] [collab/gitlab/github] prefer plugin project scope over orphan scope GitOrigin-RevId: cfb4559bd6b8f27a872a65a4fc33ebedcc143eaa --- .../api-dump-unreviewed.txt | 4 ++ .../async/PluginScopeProviderBase.kt | 30 ++++++++ .../auth/ui/login/TokenLoginDialog.kt | 24 +++++-- .../github/authentication/GHAccountsUtil.kt | 68 +++++++++++++------ .../github/authentication/ui/GHLoginDialog.kt | 16 +++-- .../github/ui/GithubSettingsConfigurable.kt | 9 ++- .../ui/util/GHPluginProjectScopeProvider.kt | 9 +++ .../gitlab/GitLabSettingsConfigurable.kt | 9 ++- .../gitlab/authentication/GitLabLoginUtil.kt | 20 +++--- .../util/GitLabPluginProjectScopeProvider.kt | 9 +++ 10 files changed, 148 insertions(+), 50 deletions(-) create mode 100644 platform/collaboration-tools/src/com/intellij/collaboration/async/PluginScopeProviderBase.kt create mode 100644 plugins/github/src/org/jetbrains/plugins/github/ui/util/GHPluginProjectScopeProvider.kt create mode 100644 plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/util/GitLabPluginProjectScopeProvider.kt diff --git a/platform/collaboration-tools/api-dump-unreviewed.txt b/platform/collaboration-tools/api-dump-unreviewed.txt index 92cbf82b4403..1f8ab66663c7 100644 --- a/platform/collaboration-tools/api-dump-unreviewed.txt +++ b/platform/collaboration-tools/api-dump-unreviewed.txt @@ -491,6 +491,10 @@ a:com.intellij.collaboration.auth.ServerAccount - (com.intellij.openapi.project.Project,java.awt.Component,com.intellij.collaboration.auth.ui.login.LoginModel,java.lang.String,kotlinx.coroutines.flow.Flow,kotlin.jvm.functions.Function1):V - b:(com.intellij.openapi.project.Project,java.awt.Component,com.intellij.collaboration.auth.ui.login.LoginModel,java.lang.String,kotlinx.coroutines.flow.Flow,kotlin.jvm.functions.Function1,I,kotlin.jvm.internal.DefaultConstructorMarker):V - (com.intellij.openapi.project.Project,java.awt.Component,com.intellij.collaboration.auth.ui.login.LoginModel,kotlin.jvm.functions.Function1):V +- (com.intellij.openapi.project.Project,kotlinx.coroutines.CoroutineScope,java.awt.Component,com.intellij.collaboration.auth.ui.login.LoginModel,java.lang.String,kotlin.jvm.functions.Function1):V +- (com.intellij.openapi.project.Project,kotlinx.coroutines.CoroutineScope,java.awt.Component,com.intellij.collaboration.auth.ui.login.LoginModel,java.lang.String,kotlinx.coroutines.flow.Flow,kotlin.jvm.functions.Function1):V +- b:(com.intellij.openapi.project.Project,kotlinx.coroutines.CoroutineScope,java.awt.Component,com.intellij.collaboration.auth.ui.login.LoginModel,java.lang.String,kotlinx.coroutines.flow.Flow,kotlin.jvm.functions.Function1,I,kotlin.jvm.internal.DefaultConstructorMarker):V +- (com.intellij.openapi.project.Project,kotlinx.coroutines.CoroutineScope,java.awt.Component,com.intellij.collaboration.auth.ui.login.LoginModel,kotlin.jvm.functions.Function1):V *f:com.intellij.collaboration.auth.ui.login.TokenLoginInputPanelFactory - *sf:Companion:com.intellij.collaboration.auth.ui.login.TokenLoginInputPanelFactory$Companion - (com.intellij.collaboration.auth.ui.login.TokenLoginPanelModel):V diff --git a/platform/collaboration-tools/src/com/intellij/collaboration/async/PluginScopeProviderBase.kt b/platform/collaboration-tools/src/com/intellij/collaboration/async/PluginScopeProviderBase.kt new file mode 100644 index 000000000000..1971e24fc14c --- /dev/null +++ b/platform/collaboration-tools/src/com/intellij/collaboration/async/PluginScopeProviderBase.kt @@ -0,0 +1,30 @@ +// 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.async + +import com.intellij.openapi.Disposable +import com.intellij.openapi.ui.DialogWrapper +import com.intellij.platform.util.coroutines.childScope +import kotlinx.coroutines.CoroutineScope +import org.jetbrains.annotations.ApiStatus +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext + +/** + * A base class for a plugin service which can supply a coroutine scope to places where structured concurrency is not possible + * Can be subclassed and registered as a light service + */ +@ApiStatus.Internal +open class PluginScopeProviderBase(private val parentCs: CoroutineScope) { + fun createDisposedScope(name: String, disposable: Disposable, context: CoroutineContext = EmptyCoroutineContext): CoroutineScope { + return parentCs.childScope(name, context).apply { + cancelledWith(disposable) + } + } + + fun constructDialog(name: String, constructor: CoroutineScope.() -> D): D { + val cs = parentCs.childScope(name) + return cs.constructor().also { + cs.cancelledWith(it.disposable) + } + } +} \ No newline at end of file diff --git a/platform/collaboration-tools/src/com/intellij/collaboration/auth/ui/login/TokenLoginDialog.kt b/platform/collaboration-tools/src/com/intellij/collaboration/auth/ui/login/TokenLoginDialog.kt index cb168bc6f088..9f44787323ef 100644 --- a/platform/collaboration-tools/src/com/intellij/collaboration/auth/ui/login/TokenLoginDialog.kt +++ b/platform/collaboration-tools/src/com/intellij/collaboration/auth/ui/login/TokenLoginDialog.kt @@ -1,31 +1,41 @@ // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.collaboration.auth.ui.login -import com.intellij.collaboration.async.DisposingMainScope import com.intellij.collaboration.messages.CollaborationToolsBundle +import com.intellij.openapi.application.EDT import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.asContextElement import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogPanel import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.util.NlsContexts -import kotlinx.coroutines.CoroutineScope +import com.intellij.platform.util.coroutines.childScope +import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.launch -import kotlinx.coroutines.plus import java.awt.Component import javax.swing.JComponent class TokenLoginDialog @JvmOverloads constructor( - project: Project?, parent: Component?, + project: Project?, parentCs: CoroutineScope, parent: Component?, private val model: LoginModel, - @NlsContexts.DialogTitle title: String = CollaborationToolsBundle.message("login.dialog.title"), + title: @NlsContexts.DialogTitle String = CollaborationToolsBundle.message("login.dialog.title"), private val userCustomExitSignal: Flow? = null, private val centerPanelSupplier: CoroutineScope.() -> DialogPanel ) : DialogWrapper(project, parent, false, IdeModalityType.IDE) { - private val uiScope = DisposingMainScope(disposable) + ModalityState.stateForComponent(rootPane).asContextElement() + @Deprecated("A proper coroutine scope should be provided") + @OptIn(DelicateCoroutinesApi::class) + @JvmOverloads + constructor( + project: Project?, parent: Component?, + model: LoginModel, + title: @NlsContexts.DialogTitle String = CollaborationToolsBundle.message("login.dialog.title"), + userCustomExitSignal: Flow? = null, + centerPanelSupplier: CoroutineScope.() -> DialogPanel + ) : this(project, GlobalScope, parent, model, title, userCustomExitSignal, centerPanelSupplier) + + private val uiScope = parentCs.childScope(javaClass.name, Dispatchers.EDT + ModalityState.stateForComponent(rootPane).asContextElement()) init { setOKButtonText(CollaborationToolsBundle.message("login.button")) diff --git a/plugins/github/src/org/jetbrains/plugins/github/authentication/GHAccountsUtil.kt b/plugins/github/src/org/jetbrains/plugins/github/authentication/GHAccountsUtil.kt index 42eae28c46b8..ce308e780013 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/authentication/GHAccountsUtil.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/authentication/GHAccountsUtil.kt @@ -1,6 +1,7 @@ // Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.plugins.github.authentication +import com.intellij.collaboration.async.cancelledWith import com.intellij.collaboration.messages.CollaborationToolsBundle import com.intellij.ide.DataManager import com.intellij.ide.passwordSafe.PasswordSafe @@ -16,13 +17,13 @@ import com.intellij.openapi.ui.popup.JBPopupFactory import com.intellij.openapi.util.NlsContexts import com.intellij.openapi.util.text.HtmlBuilder import com.intellij.openapi.util.text.HtmlChunk +import com.intellij.platform.util.coroutines.childScope import com.intellij.ui.CollectionComboBoxModel import com.intellij.ui.components.DropDownLink import com.intellij.util.AuthData import com.intellij.util.concurrency.annotations.RequiresEdt import git4idea.DialogManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import org.jetbrains.plugins.github.api.GithubServerPath import org.jetbrains.plugins.github.authentication.accounts.GHAccountManager import org.jetbrains.plugins.github.authentication.accounts.GithubAccount @@ -30,6 +31,7 @@ import org.jetbrains.plugins.github.authentication.accounts.GithubProjectDefault import org.jetbrains.plugins.github.authentication.ui.GHLoginDialog import org.jetbrains.plugins.github.authentication.ui.GHLoginModel import org.jetbrains.plugins.github.i18n.GithubBundle +import org.jetbrains.plugins.github.ui.util.GHPluginProjectScopeProvider import java.awt.Component import javax.swing.JButton import javax.swing.JComponent @@ -81,20 +83,22 @@ object GHAccountsUtil { val group = DefaultActionGroup() group.add( DumbAwareAction.create(GithubBundle.message("action.Github.Accounts.AddGHAccount.text")) { - GHLoginDialog.OAuth(model, project, parentComponent).apply { - setServer(GithubServerPath.DEFAULT_HOST, false) - showAndGet() - } + scopedDialog(project) { + GHLoginDialog.OAuth(model, project, this, parentComponent).apply { + setServer(GithubServerPath.DEFAULT_HOST, false) + } + }.showAndGet() }) group.add( DumbAwareAction.create(GithubBundle.message("action.Github.Accounts.AddGHAccountWithToken.text")) { - GHLoginDialog.Token(model, project, parentComponent).apply { - title = GithubBundle.message("dialog.title.add.github.account") - setLoginButtonText(GithubBundle.message("accounts.add.button")) - setServer(GithubServerPath.DEFAULT_HOST, false) - showAndGet() - } + scopedDialog(project) { + GHLoginDialog.Token(model, project, this, parentComponent).apply { + title = GithubBundle.message("dialog.title.add.github.account") + setLoginButtonText(GithubBundle.message("accounts.add.button")) + setServer(GithubServerPath.DEFAULT_HOST, false) + } + }.showAndGet() } ) @@ -102,12 +106,13 @@ object GHAccountsUtil { group.add( DumbAwareAction.create(GithubBundle.message("action.Github.Accounts.AddGHEAccount.text")) { - GHLoginDialog.Token(model, project, parentComponent).apply { - title = GithubBundle.message("dialog.title.add.github.account") - setServer("", true) - setLoginButtonText(GithubBundle.message("accounts.add.button")) - showAndGet() - } + scopedDialog(project) { + GHLoginDialog.Token(model, project, this, parentComponent).apply { + title = GithubBundle.message("dialog.title.add.github.account") + setServer("", true) + setLoginButtonText(GithubBundle.message("accounts.add.button")) + } + }.showAndGet() } ) return group @@ -205,15 +210,34 @@ private fun GHLoginRequest.configure(dialog: GHLoginDialog) { login?.let { dialog.setLogin(it, isLoginEditable) } } +@OptIn(DelicateCoroutinesApi::class) +private fun scopedDialog(project: Project?, dialogConstructor: CoroutineScope.() -> D): D { + if (project != null) { + return project.service().constructDialog("GitHub login dialog", dialogConstructor) + } + else { + val cs = GlobalScope.childScope(GHLoginDialog::class.java.name) + val dialog = cs.dialogConstructor() + cs.cancelledWith(dialog.disposable) + return dialog + } +} + private fun GHLoginRequest.loginWithToken(model: GHLoginModel, project: Project?, parentComponent: Component?) { - val dialog = GHLoginDialog.Token(model, project, parentComponent) - configure(dialog) + val dialog = scopedDialog(project) { + GHLoginDialog.Token(model, project, this, parentComponent).also { + configure(it) + } + } DialogManager.show(dialog) } private fun GHLoginRequest.loginWithOAuth(model: GHLoginModel, project: Project?, parentComponent: Component?) { - val dialog = GHLoginDialog.OAuth(model, project, parentComponent) - configure(dialog) + val dialog = scopedDialog(project) { + GHLoginDialog.OAuth(model, project, this, parentComponent).also { + configure(it) + } + } DialogManager.show(dialog) } diff --git a/plugins/github/src/org/jetbrains/plugins/github/authentication/ui/GHLoginDialog.kt b/plugins/github/src/org/jetbrains/plugins/github/authentication/ui/GHLoginDialog.kt index bcdf9429264f..4ece67d7948d 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/authentication/ui/GHLoginDialog.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/authentication/ui/GHLoginDialog.kt @@ -1,7 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.github.authentication.ui -import com.intellij.collaboration.async.DisposingMainScope +import com.intellij.openapi.application.EDT import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.asContextElement import com.intellij.openapi.project.Project @@ -9,13 +9,14 @@ import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.ui.DialogWrapper.IS_VISUAL_PADDING_COMPENSATED_ON_COMPONENT_LEVEL_KEY import com.intellij.openapi.ui.ValidationInfo import com.intellij.openapi.util.NlsContexts +import com.intellij.platform.util.coroutines.childScope import com.intellij.util.ui.JBUI import com.intellij.util.ui.update.UiNotifyConnector import git4idea.i18n.GitBundle import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import kotlinx.coroutines.plus import org.jetbrains.plugins.github.api.GithubApiRequestExecutor import org.jetbrains.plugins.github.api.GithubServerPath import org.jetbrains.plugins.github.i18n.GithubBundle @@ -29,10 +30,11 @@ internal fun JComponent.setPaddingCompensated(): JComponent = internal sealed class GHLoginDialog( private val model: GHLoginModel, project: Project?, + parentCs: CoroutineScope, parent: Component? ) : DialogWrapper(project, parent, false, IdeModalityType.IDE) { - private val cs = DisposingMainScope(disposable) + ModalityState.stateForComponent(window).asContextElement() + private val cs = parentCs.childScope(javaClass.name, Dispatchers.EDT + ModalityState.stateForComponent(window).asContextElement()) protected val loginPanel = GithubLoginPanel(cs, GithubApiRequestExecutor.Factory.getInstance()) { login, server -> model.isAccountUnique(server, login) @@ -69,8 +71,8 @@ internal sealed class GHLoginDialog( } - class Token(model: GHLoginModel, project: Project?, parent: Component?) : - GHLoginDialog(model, project, parent) { + class Token(model: GHLoginModel, project: Project?, parentCs: CoroutineScope, parent: Component?) : + GHLoginDialog(model, project, parentCs, parent) { init { title = GithubBundle.message("login.to.github") @@ -85,8 +87,8 @@ internal sealed class GHLoginDialog( override fun createCenterPanel(): JComponent = loginPanel.setPaddingCompensated() } - class OAuth(model: GHLoginModel, project: Project?, parent: Component?) : - GHLoginDialog(model, project, parent) { + class OAuth(model: GHLoginModel, project: Project?, parentCs: CoroutineScope, parent: Component?) : + GHLoginDialog(model, project, parentCs, parent) { init { title = GithubBundle.message("login.to.github") diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsConfigurable.kt b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsConfigurable.kt index b4f38fe61bf1..d9d9356321f3 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsConfigurable.kt +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsConfigurable.kt @@ -1,9 +1,9 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.github.ui -import com.intellij.collaboration.async.DisposingMainScope import com.intellij.collaboration.auth.ui.AccountsPanelFactory import com.intellij.collaboration.auth.ui.AccountsPanelFactory.Companion.addWarningForMemoryOnlyPasswordSafeAndGet +import com.intellij.openapi.application.EDT import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.asContextElement import com.intellij.openapi.components.service @@ -11,13 +11,14 @@ import com.intellij.openapi.options.BoundConfigurable import com.intellij.openapi.project.Project import com.intellij.openapi.ui.DialogPanel import com.intellij.ui.dsl.builder.* -import kotlinx.coroutines.plus +import kotlinx.coroutines.Dispatchers import org.jetbrains.plugins.github.authentication.accounts.GHAccountManager import org.jetbrains.plugins.github.authentication.accounts.GithubProjectDefaultAccountHolder import org.jetbrains.plugins.github.authentication.ui.GHAccountsDetailsProvider import org.jetbrains.plugins.github.authentication.ui.GHAccountsListModel import org.jetbrains.plugins.github.authentication.ui.GHAccountsPanelActionsController import org.jetbrains.plugins.github.i18n.GithubBundle.message +import org.jetbrains.plugins.github.ui.util.GHPluginProjectScopeProvider import org.jetbrains.plugins.github.util.GithubSettings import org.jetbrains.plugins.github.util.GithubUtil @@ -25,11 +26,13 @@ internal class GithubSettingsConfigurable internal constructor( private val project: Project ) : BoundConfigurable(GithubUtil.SERVICE_DISPLAY_NAME, "settings.github") { override fun createPanel(): DialogPanel { + val scopeProvider = project.service() val defaultAccountHolder = project.service() val accountManager = service() val ghSettings = GithubSettings.getInstance() - val scope = DisposingMainScope(disposable!!) + ModalityState.any().asContextElement() + val scope = scopeProvider.createDisposedScope(javaClass.name, disposable!!, + Dispatchers.EDT + ModalityState.any().asContextElement()) val accountsModel = GHAccountsListModel() val detailsProvider = GHAccountsDetailsProvider(scope, accountManager, accountsModel) diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/util/GHPluginProjectScopeProvider.kt b/plugins/github/src/org/jetbrains/plugins/github/ui/util/GHPluginProjectScopeProvider.kt new file mode 100644 index 000000000000..7025a9f63fa8 --- /dev/null +++ b/plugins/github/src/org/jetbrains/plugins/github/ui/util/GHPluginProjectScopeProvider.kt @@ -0,0 +1,9 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.plugins.github.ui.util + +import com.intellij.collaboration.async.PluginScopeProviderBase +import com.intellij.openapi.components.Service +import kotlinx.coroutines.CoroutineScope + +@Service(Service.Level.PROJECT) +internal class GHPluginProjectScopeProvider(parentCs: CoroutineScope) : PluginScopeProviderBase(parentCs) \ No newline at end of file diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/GitLabSettingsConfigurable.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/GitLabSettingsConfigurable.kt index 014827352965..53238e1b6113 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/GitLabSettingsConfigurable.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/GitLabSettingsConfigurable.kt @@ -1,10 +1,10 @@ // 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 -import com.intellij.collaboration.async.DisposingMainScope import com.intellij.collaboration.auth.ui.AccountsPanelFactory import com.intellij.collaboration.auth.ui.AccountsPanelFactory.Companion.addWarningForMemoryOnlyPasswordSafeAndGet import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.EDT import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.asContextElement import com.intellij.openapi.components.* @@ -15,7 +15,7 @@ import com.intellij.ui.dsl.builder.Align import com.intellij.ui.dsl.builder.AlignX import com.intellij.ui.dsl.builder.bindSelected import com.intellij.ui.dsl.builder.panel -import kotlinx.coroutines.plus +import kotlinx.coroutines.Dispatchers import kotlinx.serialization.Serializable import org.jetbrains.plugins.gitlab.api.GitLabApiManager import org.jetbrains.plugins.gitlab.authentication.accounts.GitLabAccountManager @@ -23,16 +23,19 @@ import org.jetbrains.plugins.gitlab.authentication.accounts.GitLabProjectDefault import org.jetbrains.plugins.gitlab.authentication.ui.GitLabAccountsDetailsProvider import org.jetbrains.plugins.gitlab.authentication.ui.GitLabAccountsListModel import org.jetbrains.plugins.gitlab.authentication.ui.GitLabAccountsPanelActionsController +import org.jetbrains.plugins.gitlab.ui.util.GitLabPluginProjectScopeProvider import org.jetbrains.plugins.gitlab.util.GitLabBundle.message import org.jetbrains.plugins.gitlab.util.GitLabUtil internal class GitLabSettingsConfigurable(private val project: Project) : BoundConfigurable(GitLabUtil.SERVICE_DISPLAY_NAME, "settings.gitlab") { override fun createPanel(): DialogPanel { + val scopeProvider = project.service() val accountManager = service() val defaultAccountHolder = project.service() - val scope = DisposingMainScope(disposable!!) + ModalityState.any().asContextElement() + val scope = scopeProvider.createDisposedScope(javaClass.name, disposable!!, + Dispatchers.EDT + ModalityState.any().asContextElement()) val accountsModel = GitLabAccountsListModel() val detailsProvider = GitLabAccountsDetailsProvider(scope, accountsModel) { account -> accountsModel.newCredentials.getOrElse(account) { diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/authentication/GitLabLoginUtil.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/authentication/GitLabLoginUtil.kt index 30374301fdf8..822b471d07b0 100644 --- a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/authentication/GitLabLoginUtil.kt +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/authentication/GitLabLoginUtil.kt @@ -18,6 +18,7 @@ import org.jetbrains.plugins.gitlab.authentication.accounts.GitLabAccount import org.jetbrains.plugins.gitlab.authentication.accounts.GitLabProjectDefaultAccountHolder import org.jetbrains.plugins.gitlab.authentication.ui.GitLabChooseAccountDialog import org.jetbrains.plugins.gitlab.authentication.ui.GitLabTokenLoginPanelModel +import org.jetbrains.plugins.gitlab.ui.util.GitLabPluginProjectScopeProvider import org.jetbrains.plugins.gitlab.util.GitLabBundle import java.awt.Component import javax.swing.JComponent @@ -95,14 +96,17 @@ object GitLabLoginUtil { title: @NlsContexts.DialogTitle String, serverFieldDisabled: Boolean ): Int { - val dialog = TokenLoginDialog(project, parentComponent, model, title, model.tryGitAuthorizationSignal) { - val cs = this - TokenLoginInputPanelFactory(model).createIn( - cs, - serverFieldDisabled, - tokenNote = CollaborationToolsBundle.message("clone.dialog.insufficient.scopes", GitLabSecurityUtil.MASTER_SCOPES), - errorPresenter = GitLabLoginErrorStatusPresenter(cs, model) - ) + val scopeProvider = project.service() + val dialog = scopeProvider.constructDialog("GitLab token login dialog") { + TokenLoginDialog(project, this, parentComponent, model, title, model.tryGitAuthorizationSignal) { + val cs = this + TokenLoginInputPanelFactory(model).createIn( + cs, + serverFieldDisabled, + tokenNote = CollaborationToolsBundle.message("clone.dialog.insufficient.scopes", GitLabSecurityUtil.MASTER_SCOPES), + errorPresenter = GitLabLoginErrorStatusPresenter(cs, model) + ) + } } dialog.showAndGet() diff --git a/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/util/GitLabPluginProjectScopeProvider.kt b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/util/GitLabPluginProjectScopeProvider.kt new file mode 100644 index 000000000000..136081ee7db7 --- /dev/null +++ b/plugins/gitlab/src/org/jetbrains/plugins/gitlab/ui/util/GitLabPluginProjectScopeProvider.kt @@ -0,0 +1,9 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.plugins.gitlab.ui.util + +import com.intellij.collaboration.async.PluginScopeProviderBase +import com.intellij.openapi.components.Service +import kotlinx.coroutines.CoroutineScope + +@Service(Service.Level.PROJECT) +internal class GitLabPluginProjectScopeProvider(parentCs: CoroutineScope) : PluginScopeProviderBase(parentCs) \ No newline at end of file