diff --git a/flutter-idea/src/io/flutter/actions/RefreshToolWindowAction.java b/flutter-idea/src/io/flutter/actions/RefreshToolWindowAction.java new file mode 100644 index 0000000000..e171e9a838 --- /dev/null +++ b/flutter-idea/src/io/flutter/actions/RefreshToolWindowAction.java @@ -0,0 +1,39 @@ +/* + * Copyright 2024 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +package io.flutter.actions; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import io.flutter.FlutterUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class RefreshToolWindowAction extends DumbAwareAction { + private String toolWindowId; + + public RefreshToolWindowAction() { + super(AllIcons.Actions.Refresh); + } + + public RefreshToolWindowAction(@NotNull String toolWindowId) { + super(AllIcons.Actions.Refresh); + this.toolWindowId = toolWindowId; + } + @Override + public void actionPerformed(@NotNull AnActionEvent event) { + final Project project = event.getProject(); + if (project == null) { + return; + } + + Optional.ofNullable( + FlutterUtils.embeddedBrowser(project)) + .ifPresent(embeddedBrowser -> embeddedBrowser.refresh(toolWindowId)); + } +} diff --git a/flutter-idea/src/io/flutter/deeplinks/DeepLinksViewFactory.java b/flutter-idea/src/io/flutter/deeplinks/DeepLinksViewFactory.java index 753b4042f2..93ec442c83 100644 --- a/flutter-idea/src/io/flutter/deeplinks/DeepLinksViewFactory.java +++ b/flutter-idea/src/io/flutter/deeplinks/DeepLinksViewFactory.java @@ -5,32 +5,27 @@ */ package io.flutter.deeplinks; -import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; -import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.ui.content.ContentManager; -import icons.FlutterIcons; import io.flutter.FlutterUtils; +import io.flutter.actions.RefreshToolWindowAction; import io.flutter.bazel.WorkspaceCache; import io.flutter.devtools.DevToolsIdeFeature; import io.flutter.devtools.DevToolsUrl; -import io.flutter.performance.FlutterPerformanceView; import io.flutter.run.daemon.DevToolsService; import io.flutter.sdk.FlutterSdk; import io.flutter.sdk.FlutterSdkVersion; import io.flutter.utils.AsyncUtils; -import io.flutter.utils.UIUtils; -import io.flutter.view.FlutterViewMessages; import kotlin.coroutines.Continuation; import org.jetbrains.annotations.NotNull; +import java.util.List; import java.util.Optional; public class DeepLinksViewFactory implements ToolWindowFactory { - private static String TOOL_WINDOW_ID = "Flutter Deep Links"; + @NotNull private static String TOOL_WINDOW_ID = "Flutter Deep Links"; @Override public Object isApplicableAsync(@NotNull Project project, @NotNull Continuation $completion) { @@ -41,7 +36,6 @@ public Object isApplicableAsync(@NotNull Project project, @NotNull Continuation< @Override public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) { - final ContentManager contentManager = toolWindow.getContentManager(); FlutterSdk sdk = FlutterSdk.getFlutterSdk(project); FlutterSdkVersion sdkVersion = sdk == null ? null : sdk.getVersion(); @@ -78,5 +72,9 @@ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindo }); } ); + + // TODO(helin24): It may be better to add this to the gear actions or to attach as a mouse event on individual tabs within a tool + // window, but I wasn't able to get either working immediately. + toolWindow.setTitleActions(List.of(new RefreshToolWindowAction(TOOL_WINDOW_ID))); } } diff --git a/flutter-idea/src/io/flutter/devtools/DevToolsExtensionsViewFactory.java b/flutter-idea/src/io/flutter/devtools/DevToolsExtensionsViewFactory.java index 62fc544e4b..1141ac91a1 100644 --- a/flutter-idea/src/io/flutter/devtools/DevToolsExtensionsViewFactory.java +++ b/flutter-idea/src/io/flutter/devtools/DevToolsExtensionsViewFactory.java @@ -13,6 +13,7 @@ import com.intellij.ui.content.ContentManager; import icons.FlutterIcons; import io.flutter.FlutterUtils; +import io.flutter.actions.RefreshToolWindowAction; import io.flutter.bazel.WorkspaceCache; import io.flutter.run.daemon.DevToolsService; import io.flutter.sdk.FlutterSdk; @@ -24,9 +25,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.Optional; public class DevToolsExtensionsViewFactory implements ToolWindowFactory { + @NotNull private static String TOOL_WINDOW_ID = "Flutter DevTools Extensions"; + public static void init(Project project) { project.getMessageBus().connect().subscribe( FlutterViewMessages.FLUTTER_DEBUG_TOPIC, (FlutterViewMessages.FlutterDebugNotifier)event -> initView(project, event) @@ -84,6 +88,8 @@ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindo }); } ); + + window.setTitleActions(List.of(new RefreshToolWindowAction(TOOL_WINDOW_ID))); } @Nullable diff --git a/flutter-idea/src/io/flutter/devtools/RemainingDevToolsViewFactory.java b/flutter-idea/src/io/flutter/devtools/RemainingDevToolsViewFactory.java index b98c7e94f7..a89e6ebf27 100644 --- a/flutter-idea/src/io/flutter/devtools/RemainingDevToolsViewFactory.java +++ b/flutter-idea/src/io/flutter/devtools/RemainingDevToolsViewFactory.java @@ -9,25 +9,24 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; -import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.content.ContentManager; -import icons.FlutterIcons; import io.flutter.FlutterUtils; +import io.flutter.actions.RefreshToolWindowAction; import io.flutter.bazel.WorkspaceCache; import io.flutter.run.daemon.DevToolsService; import io.flutter.sdk.FlutterSdk; import io.flutter.sdk.FlutterSdkVersion; import io.flutter.utils.AsyncUtils; -import io.flutter.utils.UIUtils; import io.flutter.view.FlutterViewMessages; import kotlin.coroutines.Continuation; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.Optional; public class RemainingDevToolsViewFactory implements ToolWindowFactory { - private static String TOOL_WINDOW_ID = "Flutter DevTools"; + @NotNull private static String TOOL_WINDOW_ID = "Flutter DevTools"; public static void init(Project project) { project.getMessageBus().connect().subscribe( FlutterViewMessages.FLUTTER_DEBUG_TOPIC, (FlutterViewMessages.FlutterDebugNotifier)event -> initView(project, event) @@ -86,6 +85,8 @@ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindo }); } ); + + window.setTitleActions(List.of(new RefreshToolWindowAction(TOOL_WINDOW_ID))); } @Nullable diff --git a/flutter-idea/src/io/flutter/view/EmbeddedBrowser.java b/flutter-idea/src/io/flutter/view/EmbeddedBrowser.java index 762ac716fe..b6a23e989f 100644 --- a/flutter-idea/src/io/flutter/view/EmbeddedBrowser.java +++ b/flutter-idea/src/io/flutter/view/EmbeddedBrowser.java @@ -22,8 +22,8 @@ import io.flutter.analytics.Analytics; import io.flutter.devtools.DevToolsUrl; import io.flutter.utils.AsyncUtils; -import org.jetbrains.annotations.NotNull; import io.flutter.utils.LabelInput; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -270,6 +270,25 @@ public void updateVmServiceUri(@NotNull String newVmServiceUri) { }); } + // This will refresh all the browser tabs within a tool window (e.g. if there are multiple apps running and the inspector tool window is + // refreshed, an inspector tab will refresh for each app.) + // TODO(helin24): Consider allowing refresh for single browser tabs within tool windows. + public void refresh(String toolWindowId) { + Map tabs = windows.get(toolWindowId); + + if (tabs == null) { + return; + } + + tabs.forEach((tabName, tab) -> { + if (tab == null || tab.devToolsUrlFuture == null) return; + tab.devToolsUrlFuture.thenAccept(devToolsUrl -> { + if (devToolsUrl == null) return; + tab.embeddedTab.loadUrl(devToolsUrl.getUrlString()); + }); + }); + } + private void updateUrlAndReload(Function newDevToolsUrlFn) { this.windows.forEach((window, tabs) -> { tabs.forEach((tabName, tab) -> { diff --git a/flutter-idea/src/io/flutter/view/FlutterView.java b/flutter-idea/src/io/flutter/view/FlutterView.java index 414cf7ce0c..7ea471fcb0 100644 --- a/flutter-idea/src/io/flutter/view/FlutterView.java +++ b/flutter-idea/src/io/flutter/view/FlutterView.java @@ -6,7 +6,6 @@ package io.flutter.view; import com.google.common.annotations.VisibleForTesting; -import com.intellij.execution.runners.ExecutionUtil; import com.intellij.ide.browsers.BrowserLauncher; import com.intellij.ide.ui.UISettingsListener; import com.intellij.openapi.Disposable; @@ -17,7 +16,6 @@ import com.intellij.openapi.editor.colors.EditorColorsListener; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.progress.EmptyProgressIndicator; -import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.VerticalFlowLayout; @@ -35,10 +33,10 @@ import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import com.intellij.xdebugger.XSourcePosition; -import icons.FlutterIcons; import io.flutter.FlutterBundle; import io.flutter.FlutterInitializer; import io.flutter.FlutterUtils; +import io.flutter.actions.RefreshToolWindowAction; import io.flutter.bazel.WorkspaceCache; import io.flutter.devtools.DevToolsIdeFeature; import io.flutter.devtools.DevToolsUrl; @@ -46,7 +44,10 @@ import io.flutter.inspector.InspectorGroupManagerService; import io.flutter.inspector.InspectorService; import io.flutter.inspector.InspectorSourceLocation; -import io.flutter.jxbrowser.*; +import io.flutter.jxbrowser.FailureType; +import io.flutter.jxbrowser.InstallationFailedReason; +import io.flutter.jxbrowser.JxBrowserManager; +import io.flutter.jxbrowser.JxBrowserStatus; import io.flutter.run.FlutterDevice; import io.flutter.run.daemon.DevToolsInstance; import io.flutter.run.daemon.DevToolsService; @@ -64,10 +65,12 @@ import javax.swing.*; import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import java.util.*; -import java.util.concurrent.atomic.AtomicReference; +import java.util.Optional; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; @com.intellij.openapi.components.State( name = "FlutterView", @@ -244,6 +247,8 @@ private void addBrowserInspectorViewContent(FlutterApp app, ); busSubscribed = true; } + + toolWindow.setTitleActions(List.of(new RefreshToolWindowAction(TOOL_WINDOW_ID))); } else { BrowserLauncher.getInstance().browse( new DevToolsUrl.Builder() diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index d3e35ce2fe..bc0cd4a351 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -546,6 +546,10 @@ text="Open Flutter DevTools" description="Open Flutter DevTools" icon="FlutterIcons.Dart_16"> + + +