diff --git a/plugins/devkit/devkit-core/gen/com/intellij/devkit/core/icons/DevkitCoreIcons.java b/plugins/devkit/devkit-core/gen/com/intellij/devkit/core/icons/DevkitCoreIcons.java
index 4f31fcdc5426..d5861c858ceb 100644
--- a/plugins/devkit/devkit-core/gen/com/intellij/devkit/core/icons/DevkitCoreIcons.java
+++ b/plugins/devkit/devkit-core/gen/com/intellij/devkit/core/icons/DevkitCoreIcons.java
@@ -18,7 +18,6 @@ public final class DevkitCoreIcons {
return IconManager.getInstance().loadRasterizedIcon(path, expUIPath, DevkitCoreIcons.class.getClassLoader(), cacheKey, flags);
}
/** 16x16 */ public static final @NotNull Icon Add_sdk = load("icons/expui/addSDK.svg", "icons/add_sdk.svg", 641117830, 2);
- /** 16x16 */ public static final @NotNull Icon ComposeToolWindow = load("icons/expui/composeToolWindow.svg", 542147654, 2);
public static final class Gutter {
/** 12x12 */ public static final @NotNull Icon DescriptionFile = load("icons/expui/gutter/descriptionFile@14x14.svg", "icons/gutter/descriptionFile.svg", 1318760137, 2);
diff --git a/plugins/devkit/devkit-core/gen/org/jetbrains/idea/devkit/DevKitIcons.java b/plugins/devkit/devkit-core/gen/org/jetbrains/idea/devkit/DevKitIcons.java
deleted file mode 100644
index 0358325aee5e..000000000000
--- a/plugins/devkit/devkit-core/gen/org/jetbrains/idea/devkit/DevKitIcons.java
+++ /dev/null
@@ -1,89 +0,0 @@
-// 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.idea.devkit;
-
-import com.intellij.devkit.core.icons.DevkitCoreIcons;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-
-/**
- * @deprecated Use {@link DevkitCoreIcons} instead.
- */
-@Deprecated(forRemoval = true)
-public final class DevKitIcons {
- private DevKitIcons() {
- }
-
- /** @deprecated Use {@link DevkitCoreIcons#Add_sdk} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon Add_sdk = DevkitCoreIcons.Add_sdk;
-
- /** @deprecated Use {@link DevkitCoreIcons#ComposeToolWindow} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon ComposeToolWindow = DevkitCoreIcons.ComposeToolWindow;
-
- /**
- * @deprecated Use {@link DevkitCoreIcons.Gutter} instead.
- */
- @Deprecated(forRemoval = true)
- public static final class Gutter {
- private Gutter() {
- }
-
- /** @deprecated Use {@link DevkitCoreIcons.Gutter#DescriptionFile} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon DescriptionFile = DevkitCoreIcons.Gutter.DescriptionFile;
-
- /** @deprecated Use {@link DevkitCoreIcons.Gutter#Diff} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon Diff = DevkitCoreIcons.Gutter.Diff;
-
- /** @deprecated Use {@link DevkitCoreIcons.Gutter#Plugin} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon Plugin = DevkitCoreIcons.Gutter.Plugin;
-
- /** @deprecated Use {@link DevkitCoreIcons.Gutter#Properties} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon Properties = DevkitCoreIcons.Gutter.Properties;
- }
-
- /** @deprecated Use {@link DevkitCoreIcons#Items} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon Items = DevkitCoreIcons.Items;
-
- /** @deprecated Use {@link DevkitCoreIcons#LegacyPluginModule} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon LegacyPluginModule = DevkitCoreIcons.LegacyPluginModule;
-
- /** @deprecated Use {@link DevkitCoreIcons#PluginModule} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon PluginModule = DevkitCoreIcons.PluginModule;
-
- /** @deprecated Use {@link DevkitCoreIcons#PluginV2} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon PluginV2 = DevkitCoreIcons.PluginV2;
-
- /** @deprecated Use {@link DevkitCoreIcons#ProjectService} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon ProjectService = DevkitCoreIcons.ProjectService;
-
- /** @deprecated Use {@link DevkitCoreIcons#ProjectState} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon ProjectState = DevkitCoreIcons.ProjectState;
-
- /** @deprecated Use {@link DevkitCoreIcons#RemoteMapping} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon RemoteMapping = DevkitCoreIcons.RemoteMapping;
-
- /** @deprecated Use {@link DevkitCoreIcons#Sdk_closed} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon Sdk_closed = DevkitCoreIcons.Sdk_closed;
-
- /** @deprecated Use {@link DevkitCoreIcons#Service} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon Service = DevkitCoreIcons.Service;
-
- /** @deprecated Use {@link DevkitCoreIcons#State} */
- @Deprecated(forRemoval = true)
- public static final @NotNull Icon State = DevkitCoreIcons.State;
-}
diff --git a/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml b/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml
index e9801887e07d..4db5cea2edd6 100644
--- a/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml
+++ b/plugins/devkit/devkit-core/resources/intellij.devkit.core.xml
@@ -778,10 +778,6 @@
language="JAVA"
implementationClass="org.jetbrains.idea.devkit.threadingModelHelper.java.JavaLockReqPsiOps"/>
-
-
-
diff --git a/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties b/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties
index 2b444a2848bd..0576d027177a 100644
--- a/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties
+++ b/plugins/devkit/devkit-core/resources/messages/DevKitBundle.properties
@@ -803,9 +803,6 @@ inspection.content.module.namespace.missing.fix.add.name=Add ''{0}'' namespace
line.marker.descriptors.including.content.module.name=Descriptors including this content module
line.marker.descriptors.including.content.module.tooltip=''{0}'' content module is included in {1} plugin XML descriptors
line.marker.descriptors.including.content.module.popup.title=Descriptors Including This Content Module
-compose.hot.reload.failed.to.download.compose.hot.reload.agent=Failed to download 'Compose Hot Reload' agent
-compose.hot.reload.restart.your.run.configuration=Compose Hot Reload agent is being downloaded to ''{0}''. Restart your run configuration after it gets completed.
-compose.hot.reload.hot.reload.agent.has.been.saved=Restart your run configuration. Compose Hot Reload agent has been saved to ''{0}''.
usage.type.module.in.content=In content
usage.type.module.in.dependencies=In dependencies
diff --git a/plugins/devkit/intellij.devkit.compose/BUILD.bazel b/plugins/devkit/intellij.devkit.compose/BUILD.bazel
index a256c833f8cf..08b8cdb2f4cf 100644
--- a/plugins/devkit/intellij.devkit.compose/BUILD.bazel
+++ b/plugins/devkit/intellij.devkit.compose/BUILD.bazel
@@ -21,7 +21,7 @@ jvm_library(
name = "compose",
module_name = "intellij.devkit.compose",
visibility = ["//visibility:public"],
- srcs = glob(["src/**/*.kt", "src/**/*.java", "src/**/*.form"], allow_empty = True),
+ srcs = glob(["src/**/*.kt", "src/**/*.java", "src/**/*.form", "gen/**/*.kt", "gen/**/*.java"], allow_empty = True),
resources = [":compose_resources"],
kotlinc_opts = ":custom_compose",
deps = [
@@ -57,6 +57,7 @@ jvm_library(
"//platform/execution",
"//platform/platform-util-io:ide-util-io",
"//platform/execution-impl",
+ "//platform/util/jdom",
],
plugins = ["@lib//:compose-plugin"]
)
diff --git a/plugins/devkit/intellij.devkit.compose/gen/com/intellij/devkit/compose/icons/DevkitComposeIcons.java b/plugins/devkit/intellij.devkit.compose/gen/com/intellij/devkit/compose/icons/DevkitComposeIcons.java
new file mode 100644
index 000000000000..d8f5d4543949
--- /dev/null
+++ b/plugins/devkit/intellij.devkit.compose/gen/com/intellij/devkit/compose/icons/DevkitComposeIcons.java
@@ -0,0 +1,22 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.intellij.devkit.compose.icons;
+
+import com.intellij.ui.IconManager;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * NOTE THIS FILE IS AUTO-GENERATED
+ * DO NOT EDIT IT BY HAND, run "Generate icon classes" configuration instead
+ */
+public final class DevkitComposeIcons {
+ private static @NotNull Icon load(@NotNull String path, int cacheKey, int flags) {
+ return IconManager.getInstance().loadRasterizedIcon(path, DevkitComposeIcons.class.getClassLoader(), cacheKey, flags);
+ }
+ /** 16x16 */ public static final @NotNull Icon ComposeHotReload = load("icons/composeHotReload.svg", 618232810, 2);
+ /** 16x16 */ public static final @NotNull Icon ComposeToolWindow = load("icons/composeToolWindow.svg", 542147654, 2);
+ /** 16x16 */ public static final @NotNull Icon Github = load("icons/github.svg", 2052536327, 2);
+ /** 16x16 */ public static final @NotNull Icon JewelToolWindow = load("icons/jewelToolWindow.svg", -219486260, 2);
+ /** 16x16 */ public static final @NotNull Icon LockReqs = load("icons/lock-reqs.svg", 1816243125, 2);
+}
diff --git a/plugins/devkit/intellij.devkit.compose/intellij.devkit.compose.iml b/plugins/devkit/intellij.devkit.compose/intellij.devkit.compose.iml
index 3bc3861526bc..3e2659b7f6a2 100644
--- a/plugins/devkit/intellij.devkit.compose/intellij.devkit.compose.iml
+++ b/plugins/devkit/intellij.devkit.compose/intellij.devkit.compose.iml
@@ -26,6 +26,7 @@
+
@@ -61,5 +62,6 @@
+
\ No newline at end of file
diff --git a/plugins/devkit/intellij.devkit.compose/resources/icon-robots.txt b/plugins/devkit/intellij.devkit.compose/resources/android-releases/icon-robots.txt
similarity index 100%
rename from plugins/devkit/intellij.devkit.compose/resources/icon-robots.txt
rename to plugins/devkit/intellij.devkit.compose/resources/android-releases/icon-robots.txt
diff --git a/plugins/devkit/intellij.devkit.compose/resources/icons/composeHotReload.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/composeHotReload.svg
new file mode 100644
index 000000000000..09799002b540
--- /dev/null
+++ b/plugins/devkit/intellij.devkit.compose/resources/icons/composeHotReload.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/plugins/devkit/intellij.devkit.compose/resources/icons/composeHotReload_dark.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/composeHotReload_dark.svg
new file mode 100644
index 000000000000..a171a7f34fce
--- /dev/null
+++ b/plugins/devkit/intellij.devkit.compose/resources/icons/composeHotReload_dark.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/plugins/devkit/devkit-core/resources/icons/expui/composeToolWindow.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/composeToolWindow.svg
similarity index 100%
rename from plugins/devkit/devkit-core/resources/icons/expui/composeToolWindow.svg
rename to plugins/devkit/intellij.devkit.compose/resources/icons/composeToolWindow.svg
diff --git a/plugins/devkit/devkit-core/resources/icons/expui/composeToolWindow@20x20.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/composeToolWindow@20x20.svg
similarity index 100%
rename from plugins/devkit/devkit-core/resources/icons/expui/composeToolWindow@20x20.svg
rename to plugins/devkit/intellij.devkit.compose/resources/icons/composeToolWindow@20x20.svg
diff --git a/plugins/devkit/devkit-core/resources/icons/expui/composeToolWindow@20x20_dark.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/composeToolWindow@20x20_dark.svg
similarity index 100%
rename from plugins/devkit/devkit-core/resources/icons/expui/composeToolWindow@20x20_dark.svg
rename to plugins/devkit/intellij.devkit.compose/resources/icons/composeToolWindow@20x20_dark.svg
diff --git a/plugins/devkit/devkit-core/resources/icons/expui/composeToolWindow_dark.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/composeToolWindow_dark.svg
similarity index 100%
rename from plugins/devkit/devkit-core/resources/icons/expui/composeToolWindow_dark.svg
rename to plugins/devkit/intellij.devkit.compose/resources/icons/composeToolWindow_dark.svg
diff --git a/plugins/devkit/intellij.devkit.compose/resources/icons/icon-robots.txt b/plugins/devkit/intellij.devkit.compose/resources/icons/icon-robots.txt
new file mode 100644
index 000000000000..e6724694521a
--- /dev/null
+++ b/plugins/devkit/intellij.devkit.compose/resources/icons/icon-robots.txt
@@ -0,0 +1 @@
+skip: *20x20.svg
\ No newline at end of file
diff --git a/plugins/devkit/intellij.devkit.compose/resources/icons/jewel-tool-window@20x20.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/jewel-tool-window@20x20.svg
deleted file mode 100644
index 236467bfe6ac..000000000000
--- a/plugins/devkit/intellij.devkit.compose/resources/icons/jewel-tool-window@20x20.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/plugins/devkit/intellij.devkit.compose/resources/icons/jewel-tool-window@20x20_dark.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/jewel-tool-window@20x20_dark.svg
deleted file mode 100644
index 04e8f0a6df39..000000000000
--- a/plugins/devkit/intellij.devkit.compose/resources/icons/jewel-tool-window@20x20_dark.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/plugins/devkit/intellij.devkit.compose/resources/icons/jewel-tool-window.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/jewelToolWindow.svg
similarity index 100%
rename from plugins/devkit/intellij.devkit.compose/resources/icons/jewel-tool-window.svg
rename to plugins/devkit/intellij.devkit.compose/resources/icons/jewelToolWindow.svg
diff --git a/plugins/devkit/intellij.devkit.compose/resources/intui/icons/jewel-tool-window@20x20.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/jewelToolWindow@20x20.svg
similarity index 100%
rename from plugins/devkit/intellij.devkit.compose/resources/intui/icons/jewel-tool-window@20x20.svg
rename to plugins/devkit/intellij.devkit.compose/resources/icons/jewelToolWindow@20x20.svg
diff --git a/plugins/devkit/intellij.devkit.compose/resources/intui/icons/jewel-tool-window@20x20_dark.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/jewelToolWindow@20x20_dark.svg
similarity index 100%
rename from plugins/devkit/intellij.devkit.compose/resources/intui/icons/jewel-tool-window@20x20_dark.svg
rename to plugins/devkit/intellij.devkit.compose/resources/icons/jewelToolWindow@20x20_dark.svg
diff --git a/plugins/devkit/intellij.devkit.compose/resources/icons/jewel-tool-window_dark.svg b/plugins/devkit/intellij.devkit.compose/resources/icons/jewelToolWindow_dark.svg
similarity index 100%
rename from plugins/devkit/intellij.devkit.compose/resources/icons/jewel-tool-window_dark.svg
rename to plugins/devkit/intellij.devkit.compose/resources/icons/jewelToolWindow_dark.svg
diff --git a/plugins/devkit/intellij.devkit.compose/resources/intellij.devkit.compose.xml b/plugins/devkit/intellij.devkit.compose/resources/intellij.devkit.compose.xml
index d4f8f26a1bf0..04bfe603263c 100644
--- a/plugins/devkit/intellij.devkit.compose/resources/intellij.devkit.compose.xml
+++ b/plugins/devkit/intellij.devkit.compose/resources/intellij.devkit.compose.xml
@@ -27,27 +27,28 @@
-
-
+
+
-
-
+
+
+
+ icon="com.intellij.devkit.compose.icons.DevkitComposeIcons.ComposeToolWindow"/>
diff --git a/plugins/devkit/intellij.devkit.compose/resources/intui/icons/jewel-tool-window.svg b/plugins/devkit/intellij.devkit.compose/resources/intui/icons/jewel-tool-window.svg
deleted file mode 100644
index 4782437da8d9..000000000000
--- a/plugins/devkit/intellij.devkit.compose/resources/intui/icons/jewel-tool-window.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/plugins/devkit/intellij.devkit.compose/resources/intui/icons/jewel-tool-window_dark.svg b/plugins/devkit/intellij.devkit.compose/resources/intui/icons/jewel-tool-window_dark.svg
deleted file mode 100644
index ef0e5b3f87fc..000000000000
--- a/plugins/devkit/intellij.devkit.compose/resources/intui/icons/jewel-tool-window_dark.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/plugins/devkit/intellij.devkit.compose/resources/messages/DevkitComposeBundle.properties b/plugins/devkit/intellij.devkit.compose/resources/messages/DevkitComposeBundle.properties
index e6c11abf47c9..2d1b60cce698 100644
--- a/plugins/devkit/intellij.devkit.compose/resources/messages/DevkitComposeBundle.properties
+++ b/plugins/devkit/intellij.devkit.compose/resources/messages/DevkitComposeBundle.properties
@@ -48,9 +48,8 @@ jewel.swing.text.areas=Text areas:
compose.sandbox=Compose Sandbox
compose.sandbox.show.automatically.on.project.open=Show automatically on project open
configurable.name.settings.page.on.compose=Settings Page on Compose
-label.compose.hot.reload.available.banner=Compose Hot Reload is available. Enjoy!
-link.label.enable.hot.reload=Enable Hot Reload
-link.label.dismiss=Dismiss
+label.compose.hot.reload.available.banner=Hot Reload is available. Use the 'Run with Compose Hot Reload' run action.
+link.label.dismiss=Got it!
toolwindow.stripe.ComposeUIPreview=Compose UI Preview
compose.preview.empty.text.top=Preview will appear here \u1F300.
@@ -71,4 +70,10 @@ action.ComposePreviewRefreshAuto.description=Toggles automatic refresh on change
action.LockReqAnalysis.text=Analyze Lock Requirements
progress.title.analyzing.lock.requirements=Analyzing lock requirements
tab.title.locking.requirements=Locking Requirements
+
+action.DevkitComposeHotReloadExecutorAction.text=Run with Compose Hot Reload
+action.DevkitComposeHotReloadExecutorAction.description=Run with Compose Hot Reload
+action.DevkitComposeHotReloadExecutorAction.text.0=Run ''{0}'' with Compose Hot Reload
action.JewelCustomPopupRenderer.text=Use Jewel Custom Popup Renderer
+
+compose.hot.reload.failed.to.download.compose.hot.reload.agent=Failed to download 'Compose Hot Reload' agent
\ No newline at end of file
diff --git a/plugins/devkit/intellij.devkit.compose/resources/studio-splash-screens/icon-robots.txt b/plugins/devkit/intellij.devkit.compose/resources/studio-splash-screens/icon-robots.txt
new file mode 100644
index 000000000000..1313ad9016c8
--- /dev/null
+++ b/plugins/devkit/intellij.devkit.compose/resources/studio-splash-screens/icon-robots.txt
@@ -0,0 +1 @@
+skip: *
diff --git a/plugins/devkit/intellij.devkit.compose/src/demo/IdeSampleIconKeys.kt b/plugins/devkit/intellij.devkit.compose/src/demo/IdeSampleIconKeys.kt
index 16880facd9a7..07cfcdac507c 100644
--- a/plugins/devkit/intellij.devkit.compose/src/demo/IdeSampleIconKeys.kt
+++ b/plugins/devkit/intellij.devkit.compose/src/demo/IdeSampleIconKeys.kt
@@ -4,5 +4,5 @@ import org.jetbrains.jewel.ui.icon.PathIconKey
internal object IdeSampleIconKeys {
val gitHub = PathIconKey("icons/github.svg", IdeSampleIconKeys::class.java)
- val jewelToolWindow = PathIconKey("icons/jewel-tool-window.svg", IdeSampleIconKeys::class.java)
+ val jewelToolWindow = PathIconKey("icons/jewelToolWindow.svg", IdeSampleIconKeys::class.java)
}
diff --git a/plugins/devkit/intellij.devkit.compose/src/demo/JewelIcons.kt b/plugins/devkit/intellij.devkit.compose/src/demo/JewelIcons.kt
deleted file mode 100644
index a78ca3bb55b7..000000000000
--- a/plugins/devkit/intellij.devkit.compose/src/demo/JewelIcons.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.intellij.devkit.compose.demo
-
-import com.intellij.openapi.util.IconLoader
-
-internal object JewelIcons {
- @JvmField
- val ToolWindowIcon = IconLoader.getIcon("/icons/jewel-tool-window.svg", javaClass)
-}
diff --git a/plugins/devkit/intellij.devkit.compose/src/demo/SwingComparisonTabPanel.kt b/plugins/devkit/intellij.devkit.compose/src/demo/SwingComparisonTabPanel.kt
index 3fef75eca573..a4efdbfe21ae 100644
--- a/plugins/devkit/intellij.devkit.compose/src/demo/SwingComparisonTabPanel.kt
+++ b/plugins/devkit/intellij.devkit.compose/src/demo/SwingComparisonTabPanel.kt
@@ -12,6 +12,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import com.intellij.devkit.compose.DevkitComposeBundle
+import com.intellij.devkit.compose.icons.DevkitComposeIcons
import com.intellij.icons.AllIcons
import com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI
import com.intellij.openapi.editor.colors.EditorFontType
@@ -212,7 +213,7 @@ internal class SwingComparisonTabPanel : BorderLayoutPanel() {
private fun Panel.iconsRow() {
row(DevkitComposeBundle.message("jewel.swing.icons")) {
- cell(JBLabel(JewelIcons.ToolWindowIcon).apply { border = JBUI.Borders.customLine(JBColor.RED) })
+ cell(JBLabel(DevkitComposeIcons.JewelToolWindow).apply { border = JBUI.Borders.customLine(JBColor.RED) })
.align(AlignY.CENTER)
compose {
diff --git a/plugins/devkit/intellij.devkit.compose/src/demo/dialog/JewelToolwindowAction.kt b/plugins/devkit/intellij.devkit.compose/src/demo/dialog/JewelToolwindowAction.kt
index c7f5335fa703..5a18a3268fff 100644
--- a/plugins/devkit/intellij.devkit.compose/src/demo/dialog/JewelToolwindowAction.kt
+++ b/plugins/devkit/intellij.devkit.compose/src/demo/dialog/JewelToolwindowAction.kt
@@ -2,7 +2,7 @@
package com.intellij.devkit.compose.demo.dialog
import com.intellij.devkit.compose.DevkitComposeBundle
-import com.intellij.devkit.core.icons.DevkitCoreIcons
+import com.intellij.devkit.compose.icons.DevkitComposeIcons
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.project.DumbAwareAction
@@ -41,7 +41,7 @@ internal class JewelToolwindowAction : DumbAwareAction() {
id = TOOLWINDOW_ID,
anchor = ToolWindowAnchor.BOTTOM,
component = null,
- icon = DevkitCoreIcons.ComposeToolWindow,
+ icon = DevkitComposeIcons.ComposeToolWindow,
contentFactory = com.intellij.devkit.compose.demo.JewelDemoToolWindowFactory(),
stripeTitle = DevkitComposeBundle.messagePointer("jewel.toolwindow.title"),
)
diff --git a/plugins/devkit/intellij.devkit.compose/src/demo/releasessample/ReleasesSampleCompose.kt b/plugins/devkit/intellij.devkit.compose/src/demo/releasessample/ReleasesSampleCompose.kt
index f450719738d7..e1bed8e69738 100644
--- a/plugins/devkit/intellij.devkit.compose/src/demo/releasessample/ReleasesSampleCompose.kt
+++ b/plugins/devkit/intellij.devkit.compose/src/demo/releasessample/ReleasesSampleCompose.kt
@@ -28,7 +28,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
-import com.intellij.devkit.compose.demo.JewelIcons
+import com.intellij.devkit.compose.icons.DevkitComposeIcons
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project
import com.intellij.util.ui.JBUI
@@ -332,7 +332,7 @@ private fun RightColumn(selectedItem: ContentItem?, modifier: Modifier = Modifie
@Composable
private fun ReleaseImage(imagePath: String) {
- val painterProvider = rememberResourcePainterProvider(imagePath, JewelIcons::class.java)
+ val painterProvider = rememberResourcePainterProvider(imagePath, DevkitComposeIcons::class.java)
val painter by painterProvider.getPainter()
val controller = rememberFoilInteractionController()
diff --git a/plugins/devkit/intellij.devkit.compose/src/hotreload/ComposeHotReloadCommandLinePatcher.kt b/plugins/devkit/intellij.devkit.compose/src/hotreload/ComposeHotReloadCommandLinePatcher.kt
deleted file mode 100644
index 43053a9bca81..000000000000
--- a/plugins/devkit/intellij.devkit.compose/src/hotreload/ComposeHotReloadCommandLinePatcher.kt
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
-package com.intellij.devkit.compose.hotreload
-
-import com.intellij.execution.JavaRunConfigurationBase
-import com.intellij.execution.RunConfigurationExtension
-import com.intellij.execution.application.ApplicationConfiguration
-import com.intellij.execution.configurations.JavaParameters
-import com.intellij.execution.configurations.RunConfigurationBase
-import com.intellij.execution.configurations.RunnerSettings
-import com.intellij.notification.Notification
-import com.intellij.notification.NotificationType
-import com.intellij.openapi.application.PathManager
-import com.intellij.openapi.components.Service
-import com.intellij.openapi.components.service
-import com.intellij.openapi.diagnostic.logger
-import com.intellij.openapi.diagnostic.trace
-import com.intellij.openapi.project.IntelliJProjectUtil
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.project.ProjectManager
-import com.intellij.openapi.util.registry.Registry
-import com.intellij.openapi.util.registry.RegistryValue
-import com.intellij.openapi.util.registry.RegistryValueListener
-import com.intellij.openapi.wm.IdeFocusManager
-import com.intellij.util.download.DownloadableFileService
-import kotlinx.coroutines.*
-import kotlinx.coroutines.future.await
-import org.jetbrains.idea.devkit.DevKitBundle
-import java.nio.file.Files
-import java.nio.file.Path
-import java.util.*
-import java.util.concurrent.atomic.AtomicReference
-import kotlin.io.path.*
-
-private val logger = logger()
-
-private const val COMPOSE_HOT_RELOAD_AGENT_DEFAULT_VERSION = "1.1.0-alpha03"
-private const val COMPOSE_HOT_RELOAD_AGENT_FILE_PREFIX = "compose-hot-reload-agent"
-private const val HOT_RELOAD_ENABLED_REGISTRY_KEY = "devkit.compose.hot.reload.enabled"
-private const val HOT_RELOAD_AGENT_VERSION_REGISTRY_KEY = "devkit.compose.hot.reload.agent.version"
-
-private val COMPOSE_HOT_RELOAD_AGENT_VERSION: String get() {
- val versionFromRegistry = try {
- Registry.stringValue(HOT_RELOAD_AGENT_VERSION_REGISTRY_KEY)
- }
- catch (_: MissingResourceException) {
- ""
- }
- return versionFromRegistry.ifEmpty { COMPOSE_HOT_RELOAD_AGENT_DEFAULT_VERSION }
-}
-//https://repo1.maven.org/maven2/org/jetbrains/compose/hot-reload/hot-reload-agent/1.0.0-beta04/hot-reload-agent-1.0.0-beta04-standalone.jar
-private val COMPOSE_HOT_RELOAD_AGENT_URL get() = "https://repo1.maven.org/maven2/org/jetbrains/compose/hot-reload/hot-reload-agent/$COMPOSE_HOT_RELOAD_AGENT_VERSION/hot-reload-agent-$COMPOSE_HOT_RELOAD_AGENT_VERSION-standalone.jar"
-private val COMPOSE_HOT_RELOAD_AGENT_FILE_NAME get() = "$COMPOSE_HOT_RELOAD_AGENT_FILE_PREFIX-$COMPOSE_HOT_RELOAD_AGENT_VERSION.jar"
-
-internal class ComposeHotReloadCommandLinePatcher : RunConfigurationExtension() {
-
- class ComposeHotReloadRegistryListener : RegistryValueListener {
- override fun afterValueChanged(value: RegistryValue) {
- if (value.key == HOT_RELOAD_ENABLED_REGISTRY_KEY && value.asBoolean()) {
- val project = IdeFocusManager.getGlobalInstance().lastFocusedFrame?.project ?: ProjectManager.getInstance().openProjects.firstOrNull()
- service().triggerDownload(project)
- }
- }
- }
-
- @Service(Service.Level.APP)
- private class ComposeHotReloadAgentHolder(val cs: CoroutineScope) {
- private val downloadJob: AtomicReference = AtomicReference(null)
- val agentFilePath: Path get() = Path(PathManager.getTempPath(), COMPOSE_HOT_RELOAD_AGENT_FILE_NAME)
-
- fun triggerDownload(project: Project?) {
- val currentAgentFilePath = agentFilePath
- if (!currentAgentFilePath.exists()) {
- logger.info("Compose Hot Reload agent not found at '$currentAgentFilePath'. Downloading it from '$COMPOSE_HOT_RELOAD_AGENT_URL'...")
-
- val job = cs.launch(Dispatchers.IO, start = CoroutineStart.LAZY) {
- try {
- downloadAgent(project)
- }
- catch (t: Throwable) {
- logger.error("Failed to download Compose Hot Reload agent", t)
- Notification("Debugger", DevKitBundle.message("compose.hot.reload.failed.to.download.compose.hot.reload.agent"), NotificationType.ERROR).notify(project)
- }
- finally {
- downloadJob.compareAndSet(coroutineContext.job, null)
- }
- }
- val prevValue = downloadJob.compareAndExchange(null, job)
- if (prevValue == null) {
- job.start()
- logger.info("Compose Hot Reload agent download job has been started")
- }
- else {
- job.cancel()
- logger.info("Compose Hot Reload agent download already in progress")
- }
- }
- else {
- logger.trace { "Compose Hot Reload agent already downloaded to '$currentAgentFilePath'" }
- }
- }
-
- private suspend fun downloadAgent(project: Project?) {
- val downloadingNotification = Notification("Debugger", DevKitBundle.message("compose.hot.reload.restart.your.run.configuration", agentFilePath), NotificationType.INFORMATION)
- downloadingNotification.notify(project)
-
- val tempFile = Files.createTempFile(Path(PathManager.getTempPath()), COMPOSE_HOT_RELOAD_AGENT_FILE_NAME, ".tmp").apply {
- // we need only the name
- deleteIfExists()
- }
-
- val fileService = DownloadableFileService.getInstance()
- val fileDescription = fileService.createFileDescription(COMPOSE_HOT_RELOAD_AGENT_URL, tempFile.fileName.pathString)
- val downloader = fileService.createDownloader(listOf(fileDescription), "Compose Hot Reload Agent")
- val downloadedFilesFuture = downloader.downloadWithBackgroundProgress(PathManager.getTempPath(), project)
- cleanOldAgents()
- val agentTempFile = downloadedFilesFuture.await()?.firstOrNull() ?: throw IllegalStateException("Failed to download Compose Hot Reload agent")
- val agentTempFilePath = Path(agentTempFile.first.path)
- try {
- agentTempFilePath.moveTo(agentFilePath, overwrite = true)
- }
- catch (_: Throwable) {
- agentTempFilePath.deleteIfExists()
- throw IllegalStateException("Failed to move Compose Hot Reload agent from '$agentTempFilePath' to '$agentFilePath'")
- }
- downloadingNotification.expire()
- Notification("Debugger", DevKitBundle.message("compose.hot.reload.hot.reload.agent.has.been.saved", agentFilePath), NotificationType.INFORMATION).notify(project)
- }
- }
-
- override fun ?> updateJavaParameters(configuration: T & Any, params: JavaParameters, runnerSettings: RunnerSettings?) {
- if (!IntelliJProjectUtil.isIntelliJPlatformProject(configuration.project)) return
- if (configuration !is JavaRunConfigurationBase) return
-
- if (params.mainClass != "org.jetbrains.intellij.build.devServer.DevMainKt"
- && params.mainClass != "com.intellij.idea.Main") {
- // only IDE build configurations supported here so far
- return
- }
-
- val module = configuration.configurationModule.module ?: return
- val jdk = JavaParameters.getJdkToRunModule(module, true) ?: return
- val versionString = jdk.versionString ?: ""
- if (!versionString.contains("JetBrains Runtime")) {
- // we may only expect -XX:+AllowEnhancedClassRedefinition on JBR
- return
- }
-
- val project = configuration.project
- val agentHolder = service()
-
- val agentFilePath = agentHolder.agentFilePath
- if (!agentFilePath.exists()) {
- agentHolder.triggerDownload(project)
- return
- }
-
- val vmParametersList = params.vmParametersList
- vmParametersList.add("-javaagent:${agentFilePath.pathString}")
- vmParametersList.add("-Dcompose.reload.devToolsEnabled=false")
- vmParametersList.add("-Dcompose.reload.staticsReinitializeMode=AllDirty")
- vmParametersList.add("-XX:+AllowEnhancedClassRedefinition")
- vmParametersList.add("-Didea.dev.additional.classpath=${agentFilePath.pathString}")
- }
-
- override fun isApplicableFor(configuration: RunConfigurationBase<*>): Boolean {
- return Registry.`is`(HOT_RELOAD_ENABLED_REGISTRY_KEY, false) && (configuration is ApplicationConfiguration //use this instead of 'is KotlinRunConfiguration' to avoid having dependency on Kotlin plugin here
- || configuration.factory?.id == "JetRunConfigurationType")
- }
-}
-
-private fun cleanOldAgents() {
- try {
- for (it in Path(PathManager.getTempPath()).listDirectoryEntries("$COMPOSE_HOT_RELOAD_AGENT_FILE_PREFIX-*.jar")) {
- if (it.fileName.toString() == COMPOSE_HOT_RELOAD_AGENT_FILE_NAME) continue // skip the actual version
- try {
- it.toFile().delete()
- }
- catch (_: Throwable) {
- // ignore
- }
- }
- }
- catch (_ : Throwable) {
- // ignore
- }
-}
diff --git a/plugins/devkit/intellij.devkit.compose/src/hotreload/DevkitHotReloadCommandLinePatcher.kt b/plugins/devkit/intellij.devkit.compose/src/hotreload/DevkitHotReloadCommandLinePatcher.kt
new file mode 100644
index 000000000000..8a875a26b73b
--- /dev/null
+++ b/plugins/devkit/intellij.devkit.compose/src/hotreload/DevkitHotReloadCommandLinePatcher.kt
@@ -0,0 +1,208 @@
+// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.intellij.devkit.compose.hotreload
+
+import com.intellij.debugger.impl.GenericDebuggerRunner
+import com.intellij.devkit.compose.DevkitComposeBundle
+import com.intellij.devkit.compose.icons.DevkitComposeIcons
+import com.intellij.execution.ExecutionException
+import com.intellij.execution.Executor
+import com.intellij.execution.JavaRunConfigurationBase
+import com.intellij.execution.RunConfigurationExtension
+import com.intellij.execution.application.ApplicationConfiguration
+import com.intellij.execution.configurations.JavaParameters
+import com.intellij.execution.configurations.RunConfigurationBase
+import com.intellij.execution.configurations.RunProfile
+import com.intellij.execution.configurations.RunnerSettings
+import com.intellij.execution.runners.ExecutionEnvironment
+import com.intellij.openapi.application.PathManager
+import com.intellij.openapi.diagnostic.logger
+import com.intellij.openapi.project.IntelliJProjectUtil.isIntelliJPlatformProject
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.NlsActions.ActionDescription
+import com.intellij.openapi.util.NlsActions.ActionText
+import com.intellij.openapi.util.NlsSafe
+import com.intellij.openapi.util.registry.Registry
+import com.intellij.openapi.wm.ToolWindowId
+import com.intellij.util.download.DownloadableFileService
+import org.jetbrains.annotations.Nls
+import org.jetbrains.annotations.NonNls
+import java.nio.file.Files
+import java.nio.file.Path
+import javax.swing.Icon
+import kotlin.io.path.absolutePathString
+import kotlin.io.path.exists
+import kotlin.io.path.listDirectoryEntries
+import kotlin.io.path.pathString
+
+private const val COMPOSE_HOT_RELOAD_AGENT_DEFAULT_VERSION = "1.1.0-alpha03"
+private const val COMPOSE_HOT_RELOAD_AGENT_FILE_PREFIX = "agent"
+private const val HOT_RELOAD_AGENT_VERSION_REGISTRY_KEY = "devkit.compose.hot.reload.agent.version"
+
+private val LOG = logger()
+
+private val COMPOSE_HOT_RELOAD_AGENT_VERSION: String
+ get() {
+ val versionFromRegistry = Registry.stringValue(HOT_RELOAD_AGENT_VERSION_REGISTRY_KEY)
+ return versionFromRegistry.ifEmpty { COMPOSE_HOT_RELOAD_AGENT_DEFAULT_VERSION }
+ }
+
+private val COMPOSE_HOT_RELOAD_AGENT_URL: String
+ get() = "https://repo1.maven.org/maven2/org/jetbrains/compose/hot-reload/hot-reload-agent/$COMPOSE_HOT_RELOAD_AGENT_VERSION/hot-reload-agent-$COMPOSE_HOT_RELOAD_AGENT_VERSION-standalone.jar"
+private val COMPOSE_HOT_RELOAD_AGENT_FILE_NAME: String
+ get() = "$COMPOSE_HOT_RELOAD_AGENT_FILE_PREFIX-$COMPOSE_HOT_RELOAD_AGENT_VERSION.jar"
+private val agentFilePath: Path
+ get() = getAgentTempPath().resolve(COMPOSE_HOT_RELOAD_AGENT_FILE_NAME)
+
+@Throws(ExecutionException::class)
+internal fun ensureAgentDownloaded(project: Project?) {
+ val currentAgentFilePath = agentFilePath
+ if (!currentAgentFilePath.exists()) {
+ LOG.info("Compose Hot Reload agent not found at '$currentAgentFilePath'. Downloading it from '$COMPOSE_HOT_RELOAD_AGENT_URL'...")
+
+ try {
+ downloadAgentFile(project)
+ }
+ catch (t: Throwable) {
+ throw ExecutionException(DevkitComposeBundle.message("compose.hot.reload.failed.to.download.compose.hot.reload.agent"), t)
+ }
+ }
+ else {
+ LOG.debug("Compose Hot Reload agent already downloaded to '$currentAgentFilePath'")
+ }
+}
+
+private fun downloadAgentFile(project: Project?): Path? {
+ val fileService = DownloadableFileService.getInstance()
+ val fileDescription = fileService.createFileDescription(COMPOSE_HOT_RELOAD_AGENT_URL, COMPOSE_HOT_RELOAD_AGENT_FILE_NAME)
+ val downloader = fileService.createDownloader(listOf(fileDescription), "Compose Hot Reload Agent")
+
+ Files.createDirectories(getAgentTempPath())
+ downloader.downloadFilesWithProgress(getAgentTempPath().absolutePathString(), project, null)
+
+ cleanOldAgents()
+
+ return getAgentTempPath().resolve(COMPOSE_HOT_RELOAD_AGENT_FILE_NAME)
+ .takeIf { it.exists() }
+}
+
+private const val DEVKIT_HOT_RELOAD_EXECUTOR_ID = "DevkitComposeHotReloadExecutor"
+
+internal class DevkitHotReloadExecutor : Executor() {
+ override fun getId(): @NonNls String = DEVKIT_HOT_RELOAD_EXECUTOR_ID
+ override fun getContextActionId(): @NonNls String = id
+ override fun getToolWindowId(): String = ToolWindowId.DEBUG
+
+ override fun getToolWindowIcon(): Icon = DevkitComposeIcons.ComposeHotReload
+ override fun getIcon(): Icon = DevkitComposeIcons.ComposeHotReload
+ override fun getDisabledIcon(): Icon? = null
+
+ @Suppress("DialogTitleCapitalization")
+ override fun getDescription(): @ActionDescription String = DevkitComposeBundle.message("action.DevkitComposeHotReloadExecutorAction.description")
+ override fun getActionName(): @ActionText String = DevkitComposeBundle.message("action.DevkitComposeHotReloadExecutorAction.text")
+
+ override fun getStartActionText(): @Nls(capitalization = Nls.Capitalization.Title) String {
+ return DevkitComposeBundle.message("action.DevkitComposeHotReloadExecutorAction.text")
+ }
+
+ override fun getStartActionText(configurationName: @NlsSafe String): @Nls(capitalization = Nls.Capitalization.Title) String {
+ if (configurationName.isEmpty()) return startActionText
+ val configName = shortenNameIfNeeded(configurationName)
+ return DevkitComposeBundle.message("action.DevkitComposeHotReloadExecutorAction.text.0", configName)
+ }
+
+ override fun getHelpId(): @NonNls String? = null
+
+ override fun isApplicable(project: Project): Boolean {
+ return isIntelliJPlatformProject(project)
+ }
+}
+
+internal class DevkitHotReloadRunner : GenericDebuggerRunner() {
+ override fun getRunnerId(): String = "DevkitHotReloadRunner"
+
+ override fun canRun(executorId: String, profile: RunProfile): Boolean {
+ return executorId == DEVKIT_HOT_RELOAD_EXECUTOR_ID
+ }
+
+ @Throws(ExecutionException::class)
+ override fun execute(environment: ExecutionEnvironment) {
+ ensureAgentDownloaded(environment.project)
+
+ super.execute(environment)
+ }
+}
+
+internal class DevkitHotReloadCommandLinePatcher : RunConfigurationExtension() {
+
+ override fun ?> updateJavaParameters(
+ configuration: T & Any,
+ params: JavaParameters,
+ runnerSettings: RunnerSettings?,
+ ) {
+ // only update parameters for our executor, here we don't know it
+ }
+
+ override fun ?> updateJavaParameters(
+ configuration: T & Any,
+ params: JavaParameters,
+ runnerSettings: RunnerSettings?,
+ executor: Executor
+ ) {
+ if (executor.id != DEVKIT_HOT_RELOAD_EXECUTOR_ID) return
+ if (!isIntelliJPlatformProject(configuration.project)) return
+ if (configuration !is JavaRunConfigurationBase) return
+
+ if (params.mainClass != "org.jetbrains.intellij.build.devServer.DevMainKt"
+ && params.mainClass != "com.intellij.idea.Main") {
+ // only IDE build configurations supported here so far
+ return
+ }
+
+ val module = configuration.configurationModule.module ?: return
+ val jdk = JavaParameters.getJdkToRunModule(module, true) ?: return
+ val versionString = jdk.versionString ?: ""
+ if (!versionString.contains("JetBrains Runtime")) {
+ // we may only expect -XX:+AllowEnhancedClassRedefinition on JBR
+ return
+ }
+
+ val vmParametersList = params.vmParametersList
+ vmParametersList.add("-javaagent:${agentFilePath.pathString}")
+ vmParametersList.add("-Dcompose.reload.devToolsEnabled=false")
+ vmParametersList.add("-Dcompose.reload.staticsReinitializeMode=AllDirty")
+ vmParametersList.add("-XX:+AllowEnhancedClassRedefinition")
+ vmParametersList.add("-Didea.dev.additional.classpath=${agentFilePath.pathString}")
+ }
+
+ override fun isApplicableFor(configuration: RunConfigurationBase<*>): Boolean {
+ //use this instead of 'is KotlinRunConfiguration' to avoid having dependency on Kotlin plugin here
+ return configuration is ApplicationConfiguration
+ || configuration.factory?.id == "JetRunConfigurationType"
+ }
+}
+
+private fun getAgentTempPath(): Path {
+ return PathManager.getTempDir().resolve("devkit-hot-reload")
+}
+
+private fun cleanOldAgents() {
+ val agentTempPath = getAgentTempPath()
+ if (!agentTempPath.exists()) return
+
+ try {
+ for (it in agentTempPath.listDirectoryEntries("$COMPOSE_HOT_RELOAD_AGENT_FILE_PREFIX-*.jar")) {
+ if (it.fileName.toString() == COMPOSE_HOT_RELOAD_AGENT_FILE_NAME) continue // skip the actual version
+
+ try {
+ Files.delete(it)
+ }
+ catch (t: Throwable) {
+ // ignore
+ LOG.warn("Failed to delete old Compose Hot Reload agent file", t)
+ }
+ }
+ }
+ catch (_: Throwable) {
+ // ignore
+ }
+}
diff --git a/plugins/devkit/intellij.devkit.compose/src/hotreload/ComposeHotReloadSuggester.kt b/plugins/devkit/intellij.devkit.compose/src/hotreload/DevkitHotReloadSuggester.kt
similarity index 67%
rename from plugins/devkit/intellij.devkit.compose/src/hotreload/ComposeHotReloadSuggester.kt
rename to plugins/devkit/intellij.devkit.compose/src/hotreload/DevkitHotReloadSuggester.kt
index e4b720f0df0f..124b2c14cd2d 100644
--- a/plugins/devkit/intellij.devkit.compose/src/hotreload/ComposeHotReloadSuggester.kt
+++ b/plugins/devkit/intellij.devkit.compose/src/hotreload/DevkitHotReloadSuggester.kt
@@ -3,15 +3,14 @@ package com.intellij.devkit.compose.hotreload
import com.intellij.devkit.compose.DevkitComposeBundle
import com.intellij.devkit.compose.hasCompose
+import com.intellij.devkit.compose.icons.DevkitComposeIcons
import com.intellij.facet.FacetManager
-import com.intellij.icons.AllIcons
+import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.DumbAware
+import com.intellij.openapi.project.IntelliJProjectUtil.isIntelliJPlatformProject
import com.intellij.openapi.project.Project
-import com.intellij.openapi.util.Key
-import com.intellij.openapi.util.registry.Registry
-import com.intellij.openapi.util.registry.RegistryManager
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiManager
import com.intellij.ui.EditorNotificationPanel
@@ -24,23 +23,26 @@ import java.util.function.Function
import javax.swing.JComponent
private const val COMPOSE_HOT_RELOAD_ENABLED_MARKER = "plugin:androidx.compose.compiler.plugins.kotlin:generateFunctionKeyMetaAnnotations"
-private const val REGISTRY_KEY = "devkit.compose.hot.reload.enabled"
-internal class ComposeHotReloadSuggester : EditorNotificationProvider, DumbAware {
- private val SUGGESTION_DISMISSED_KEY = Key.create("HOT_RELOAD_SUGGESTION_DISMISSED")
+internal class DevkitHotReloadSuggester : EditorNotificationProvider, DumbAware {
+ private val SUGGESTION_DISMISSED_KEY = "COMPOSE_HOT_RELOAD_GOT_IT"
override fun collectNotificationData(project: Project, file: VirtualFile): Function? {
- if (Registry.`is`(REGISTRY_KEY)) return null
+ if (!isIntelliJPlatformProject(project)) return null
if (!hasCompose(project)) return null
- if (isSuggestionDismissed(file)) return null
+ if (isSuggestionDismissed(project)) return null
if (!isComposeUiFile(project, file)) return null
- return Function { editor -> Banner(project, editor.file) }
+ return Function { _ -> Banner(project) }
}
- private fun isSuggestionDismissed(file: VirtualFile): Boolean {
- return file.getUserData(SUGGESTION_DISMISSED_KEY) != null
+ private fun isSuggestionDismissed(project: Project): Boolean {
+ return PropertiesComponent.getInstance(project).getBoolean(SUGGESTION_DISMISSED_KEY)
+ }
+
+ private fun dismissSuggestion(project: Project) {
+ PropertiesComponent.getInstance(project).setValue(SUGGESTION_DISMISSED_KEY, true)
}
private fun isComposeUiFile(project: Project, file: VirtualFile): Boolean {
@@ -67,21 +69,13 @@ internal class ComposeHotReloadSuggester : EditorNotificationProvider, DumbAware
&& segments[2].identifier == "runtime"
}
- private inner class Banner(val project: Project, val file: VirtualFile) : EditorNotificationPanel(Status.Success) {
+ private inner class Banner(val project: Project) : EditorNotificationPanel(Status.Success) {
init {
- @Suppress("DialogTitleCapitalization")
text = DevkitComposeBundle.message("label.compose.hot.reload.available.banner")
- icon(AllIcons.Debugger.DebuggerSync)
-
- @Suppress("DialogTitleCapitalization")
- createActionLabel(DevkitComposeBundle.message("link.label.enable.hot.reload")) {
- RegistryManager.getInstance().get(REGISTRY_KEY).setValue(true)
-
- EditorNotifications.getInstance(project).updateAllNotifications()
- }
+ icon(DevkitComposeIcons.ComposeHotReload)
createActionLabel(DevkitComposeBundle.message("link.label.dismiss")) {
- file.putCopyableUserData(SUGGESTION_DISMISSED_KEY, true)
+ dismissSuggestion(project)
EditorNotifications.getInstance(project).updateAllNotifications()
}
diff --git a/plugins/devkit/intellij.devkit.compose/src/hotreload/ComposeHotReloadTips.kt b/plugins/devkit/intellij.devkit.compose/src/hotreload/DevkitHotReloadTips.kt
similarity index 97%
rename from plugins/devkit/intellij.devkit.compose/src/hotreload/ComposeHotReloadTips.kt
rename to plugins/devkit/intellij.devkit.compose/src/hotreload/DevkitHotReloadTips.kt
index e6fa44475e7b..2150b47ccc1c 100644
--- a/plugins/devkit/intellij.devkit.compose/src/hotreload/ComposeHotReloadTips.kt
+++ b/plugins/devkit/intellij.devkit.compose/src/hotreload/DevkitHotReloadTips.kt
@@ -16,7 +16,7 @@ import java.util.function.Consumer
private const val tipPrefix: String = "//TIP"
private const val MAGIC_SANDBOX_FILENAME = "ComposeSandbox.kt"
-internal class ComposeHotReloadTips : com.intellij.lang.documentation.DocumentationProvider {
+internal class DevkitHotReloadTips : com.intellij.lang.documentation.DocumentationProvider {
private val commentTokenType: IElementType = KtTokens.EOL_COMMENT