From f9495fe71810f4df5c5302973ada75962831af2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Wouts?= Date: Thu, 26 Oct 2023 01:05:24 +1100 Subject: [PATCH] chore(intellij): migrate away from internal API for status bar widget (#2154) --- integrations/intellij/gradle.properties | 6 +- .../plugin/services/ProjectService.kt | 26 +++++---- .../statusbar/OpenMenuStatusBarWidget.kt | 8 +-- .../OpenMenuStatusBarWidgetFactory.kt | 56 +++++++++++++++++++ .../src/main/resources/META-INF/plugin.xml | 1 + 5 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/statusbar/OpenMenuStatusBarWidgetFactory.kt diff --git a/integrations/intellij/gradle.properties b/integrations/intellij/gradle.properties index 0361c0ec3d5..8db9a619bed 100644 --- a/integrations/intellij/gradle.properties +++ b/integrations/intellij/gradle.properties @@ -7,14 +7,14 @@ pluginVersion = 1.25.3 # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html # for insight into build numbers and IntelliJ Platform versions. -pluginSinceBuild = 223 +pluginSinceBuild = 231 # Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl # See https://jb.gg/intellij-platform-builds-list for available build versions. -pluginVerifierIdeVersions = 2022.3,2023.1 +pluginVerifierIdeVersions = 2023.1,2023.2 platformType = IC -platformVersion = 2022.3 +platformVersion = 2023.1 platformDownloadSources = true # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html diff --git a/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/services/ProjectService.kt b/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/services/ProjectService.kt index d83cbe5b8a7..2c13bf55e4e 100644 --- a/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/services/ProjectService.kt +++ b/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/services/ProjectService.kt @@ -22,11 +22,12 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.newvfs.BulkFileListener import com.intellij.openapi.vfs.newvfs.events.VFileEvent +import com.intellij.openapi.wm.StatusBarWidgetFactory import com.intellij.openapi.wm.ToolWindow import com.intellij.openapi.wm.ToolWindowAnchor import com.intellij.openapi.wm.ToolWindowManager -import com.intellij.openapi.wm.WindowManager import com.intellij.openapi.wm.ex.ToolWindowManagerListener +import com.intellij.openapi.wm.impl.status.widget.StatusBarWidgetsManager import com.intellij.psi.PsiFile import com.intellij.ui.content.ContentFactory import com.intellij.ui.jcef.JBCefBrowser @@ -37,7 +38,7 @@ import com.previewjs.intellij.plugin.api.Previewable import com.previewjs.intellij.plugin.api.StartPreviewRequest import com.previewjs.intellij.plugin.api.StopPreviewRequest import com.previewjs.intellij.plugin.api.UpdatePendingFileRequest -import com.previewjs.intellij.plugin.statusbar.OpenMenuStatusBarWidget +import com.previewjs.intellij.plugin.statusbar.OpenMenuStatusBarWidgetFactory import org.apache.commons.lang.StringUtils import org.cef.browser.CefBrowser import org.cef.browser.CefFrame @@ -55,11 +56,11 @@ class ProjectService(private val project: Project) : Disposable { } private val app = ApplicationManager.getApplication() - private val statusBar = WindowManager.getInstance().getStatusBar(project) private val smallLogo = IconLoader.getIcon("/logo.svg", javaClass) private val service = app.getService(PreviewJsSharedService::class.java) private var consoleView: ConsoleView? = null private var consoleToolWindow: ToolWindow? = null + private var previewBaseUrl: String? = null private var previewBrowser: JBCefBrowser? = null private var previewToolWindow: ToolWindow? = null private var previewToolWindowActive = false @@ -174,6 +175,8 @@ class ProjectService(private val project: Project) : Disposable { }) } + fun getPreviewBaseUrl(): String? = this.previewBaseUrl + fun printToConsole(text: String) { app.invokeLater { if (project.isDisposed) { @@ -315,11 +318,7 @@ class ProjectService(private val project: Project) : Disposable { currentPreviewWorkspaceId = workspaceId val startPreviewResponse = api.startPreview(StartPreviewRequest(workspaceId)) val previewBaseUrl = startPreviewResponse.url - OpenMenuStatusBarWidget( - url = previewBaseUrl, - onStop = { closePreview() }, - onOpenBrowser = { BrowserUtil.open(previewBaseUrl) } - ).install(statusBar) + this@ProjectService.previewBaseUrl = previewBaseUrl val previewUrl = "$previewBaseUrl?p=${URLEncoder.encode(previewableId, "utf-8")}" app.invokeLater { var browser = previewBrowser @@ -378,6 +377,7 @@ class ProjectService(private val project: Project) : Disposable { browser.loadURL("$previewUrl#panel") } previewToolWindow?.show() + updateStatusBarWidget() } }, { "Warning: unable to open preview for $previewableId" @@ -385,8 +385,6 @@ class ProjectService(private val project: Project) : Disposable { } fun closePreview(processKilled: Boolean = false) { - @Suppress("UnstableApiUsage") - statusBar.removeWidget(OpenMenuStatusBarWidget.ID) previewToolWindow?.remove() previewToolWindow = null previewBrowser?.let { @@ -404,6 +402,14 @@ class ProjectService(private val project: Project) : Disposable { }) } currentPreviewWorkspaceId = null + previewBaseUrl = null + updateStatusBarWidget() + } + + private fun updateStatusBarWidget() { + StatusBarWidgetFactory.EP_NAME.findExtension(OpenMenuStatusBarWidgetFactory::class.java)?.let { + project.getService(StatusBarWidgetsManager::class.java).updateWidget(it) + } } override fun dispose() { diff --git a/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/statusbar/OpenMenuStatusBarWidget.kt b/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/statusbar/OpenMenuStatusBarWidget.kt index 20196423229..4eaf226b8a2 100644 --- a/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/statusbar/OpenMenuStatusBarWidget.kt +++ b/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/statusbar/OpenMenuStatusBarWidget.kt @@ -10,8 +10,6 @@ class OpenMenuStatusBarWidget(private val url: String, private val onStop: () -> const val ID = "previewjs.open-menu" } - private var installed = false - override fun ID(): String = ID override fun getPresentation(): StatusBarWidget.WidgetPresentation { @@ -47,11 +45,7 @@ class OpenMenuStatusBarWidget(private val url: String, private val onStop: () -> } override fun install(statusBar: StatusBar) { - if (installed) { - return - } - installed = true - statusBar.addWidget(this) + // Nothing to do. } override fun dispose() { diff --git a/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/statusbar/OpenMenuStatusBarWidgetFactory.kt b/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/statusbar/OpenMenuStatusBarWidgetFactory.kt new file mode 100644 index 00000000000..b630feefa1b --- /dev/null +++ b/integrations/intellij/src/main/kotlin/com/previewjs/intellij/plugin/statusbar/OpenMenuStatusBarWidgetFactory.kt @@ -0,0 +1,56 @@ +package com.previewjs.intellij.plugin.statusbar + +import com.intellij.ide.BrowserUtil +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.NlsContexts.ConfigurableName +import com.intellij.openapi.wm.StatusBar +import com.intellij.openapi.wm.StatusBarWidget +import com.intellij.openapi.wm.StatusBarWidgetFactory +import com.previewjs.intellij.plugin.services.ProjectService +import org.jetbrains.annotations.NonNls + +class OpenMenuStatusBarWidgetFactory : StatusBarWidgetFactory { + companion object { + private var EMPTY_WIDGET = object : StatusBarWidget { + override fun ID(): String = OpenMenuStatusBarWidget.ID + + override fun install(statusBar: StatusBar) { + // Do nothing. + } + + override fun dispose() { + // Do nothing. + } + } + } + + override fun getId(): @NonNls String { + return OpenMenuStatusBarWidget.ID + } + + override fun getDisplayName(): @ConfigurableName String { + return "Preview.js Status" + } + + override fun createWidget(project: Project): StatusBarWidget { + val projectService = project.getService(ProjectService::class.java) + val previewBaseUrl = projectService.getPreviewBaseUrl() ?: return EMPTY_WIDGET + return OpenMenuStatusBarWidget( + url = previewBaseUrl, + onStop = { projectService.closePreview() }, + onOpenBrowser = { BrowserUtil.open(previewBaseUrl) } + ) + } + + override fun disposeWidget(widget: StatusBarWidget) { + widget.dispose() + } + + override fun canBeEnabledOn(statusBar: StatusBar): Boolean { + return true + } + + override fun isAvailable(project: Project): Boolean { + return project.getService(ProjectService::class.java).getPreviewBaseUrl() != null + } +} diff --git a/integrations/intellij/src/main/resources/META-INF/plugin.xml b/integrations/intellij/src/main/resources/META-INF/plugin.xml index 17f1754f0c6..0238fa5dbd9 100644 --- a/integrations/intellij/src/main/resources/META-INF/plugin.xml +++ b/integrations/intellij/src/main/resources/META-INF/plugin.xml @@ -21,6 +21,7 @@ +