Skip to content

Commit 5be69be

Browse files
authored
Show option to open widget preview in separate browser in the case of embedded error (#8701)
Fixes #8605 by showing an error panel in the case that the embedded browser cannot be found / loaded. To test, make sure the widget preview can open in the normal case, then replace `FlutterUtils.embeddedBrowser(project)` with `null` to test the error case. I will be making a separate PR to fix another issue where the widget preview panel seems to render multiple times. CC @bkonyi
1 parent fbba4cd commit 5be69be

2 files changed

Lines changed: 40 additions & 11 deletions

File tree

src/io/flutter/view/ViewUtils.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,27 +64,32 @@ public void presentLabels(@NotNull ToolWindow toolWindow, @NotNull List<String>
6464

6565

6666
public void presentClickableLabel(ToolWindow toolWindow, List<LabelInput> labels) {
67+
JPanel center = createClickableLabelPanel(labels);
68+
replacePanelLabel(toolWindow, center);
69+
}
70+
71+
public JPanel createClickableLabelPanel(List<LabelInput> labels) {
6772
final JPanel panel = new JPanel(new GridLayout(0, 1));
6873

6974
for (LabelInput input : labels) {
7075
if (input.listener == null) {
7176
final JLabel descriptionLabel = new JLabel(wrapWithHtml(input.text));
7277
descriptionLabel.setBorder(JBUI.Borders.empty(5));
7378
descriptionLabel.setHorizontalAlignment(SwingConstants.CENTER);
74-
panel.add(descriptionLabel, BorderLayout.NORTH);
79+
panel.add(descriptionLabel);
7580
}
7681
else {
7782
final LinkLabel<String> linkLabel = new LinkLabel<>(wrapWithHtml(input.text), null);
7883
linkLabel.setBorder(JBUI.Borders.empty(5));
7984
linkLabel.setListener(input.listener, null);
8085
linkLabel.setHorizontalAlignment(SwingConstants.CENTER);
81-
panel.add(linkLabel, BorderLayout.SOUTH);
86+
panel.add(linkLabel);
8287
}
8388
}
8489

8590
final JPanel center = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.MIDDLE));
8691
center.add(panel);
87-
replacePanelLabel(toolWindow, center);
92+
return center;
8893
}
8994

9095
public void replacePanelLabel(ToolWindow toolWindow, JComponent label) {

src/io/flutter/widgetpreview/WidgetPreviewPanel.java

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.intellij.execution.ExecutionException;
44
import com.intellij.execution.process.ProcessHandler;
5+
import com.intellij.ide.browsers.BrowserLauncher;
56
import com.intellij.openapi.Disposable;
67
import com.intellij.openapi.application.ApplicationManager;
78
import com.intellij.openapi.diagnostic.Logger;
@@ -30,6 +31,7 @@
3031
import io.flutter.utils.MostlySilentColoredProcessHandler;
3132
import io.flutter.utils.OpenApiUtils;
3233
import io.flutter.view.BrowserUrlProvider;
34+
import io.flutter.view.EmbeddedBrowser;
3335
import io.flutter.view.EmbeddedTab;
3436
import io.flutter.view.ViewUtils;
3537
import io.flutter.view.WidgetPreviewUrlProvider;
@@ -84,6 +86,7 @@ private void startWidgetPreview() {
8486
}
8587

8688
if (sdk.getVersion().fullVersion().equals(FlutterSdkVersion.UNKNOWN_VERSION)) {
89+
LOG.warn("Flutter SDK version is unknown or incomplete.");
8790
viewUtils.presentLabels(toolWindow, List.of("A Flutter SDK was found at the location",
8891
"specified in the settings, however the directory",
8992
"is in an incomplete state. To fix, shut down the IDE,",
@@ -93,6 +96,7 @@ private void startWidgetPreview() {
9396
}
9497

9598
if (!sdk.getVersion().canUseWidgetPreview()) {
99+
LOG.info("Flutter SDK version is too old for widget preview: " + sdk.getVersion().fullVersion());
96100
showInfoMessage(FlutterBundle.message("widget.preview.sdk.too.old"));
97101
return;
98102
}
@@ -103,6 +107,7 @@ private void startWidgetPreview() {
103107

104108
final PubRoot root = PubRoot.forFile(project.getProjectFile());
105109
if (root == null) {
110+
LOG.warn("Pub root not found for project: " + project.getName());
106111
showInfoMessage("Pub root could not be found to start widget preview.");
107112
return;
108113
}
@@ -116,13 +121,15 @@ private void startWidgetPreview() {
116121
final ProcessHandler handler = new MostlySilentColoredProcessHandler(command.createGeneralCommandLine(project));
117122
flutterProcessRef.set(handler);
118123
Consumer<String> onError = (message) -> {
124+
LOG.warn("Widget preview process error: " + message);
119125
showInfoMessage(FlutterBundle.message("widget.preview.error", message != null ? message : ""));
120126
};
121127
Consumer<@NotNull String> onSuccess = this::setUrlAndLoad;
122128
handler.addProcessListener(new WidgetPreviewListener(urlFuture, isVerboseMode, onError, onSuccess));
123129
handler.startNotify();
124130
}
125131
catch (ExecutionException e) {
132+
LOG.error("Failed to execute widget preview command", e);
126133
throw new RuntimeException(e);
127134
}
128135
});
@@ -167,23 +174,40 @@ private void startWidgetPreview() {
167174

168175
// This is intended for the first time we load the panel - save the URL and listen for changes.
169176
private void setUrlAndLoad(@NotNull String url) {
177+
LOG.info("Widget preview URL received: " + url);
170178
this.urlProvider = new WidgetPreviewUrlProvider(url, new DevToolsUtils().getIsBackgroundBright());
171179
loadUrl(urlProvider);
172180
listenForReload();
173181
}
174182

175183
private void loadUrl(@NotNull BrowserUrlProvider urlProvider) {
184+
LOG.info("Embedded browser is available: " + (FlutterUtils.embeddedBrowser(project) != null));
176185
showInfoMessage(FlutterBundle.message("widget.preview.loading", urlProvider.getBrowserUrl()));
177186

178187
OpenApiUtils.safeInvokeLater(() -> {
179-
Optional.ofNullable(
180-
FlutterUtils.embeddedBrowser(project))
181-
.ifPresent(embeddedBrowser ->
182-
{
183-
embeddedBrowser.openPanel(toolWindow, "Widget Preview", FlutterIcons.Flutter, urlProvider,
184-
System.out::println,
185-
null);
186-
});
188+
final Consumer<EmbeddedBrowser> onBrowserAvailable = embeddedBrowser -> {
189+
embeddedBrowser.openPanel(toolWindow, "Widget Preview", FlutterIcons.Flutter, urlProvider,
190+
System.out::println,
191+
null);
192+
};
193+
194+
final Runnable onBrowserUnavailable = () -> {
195+
final List<io.flutter.utils.LabelInput> inputs = List.of(
196+
new io.flutter.utils.LabelInput("Embedded browser is not available."),
197+
new io.flutter.utils.LabelInput("Open in external browser", (label, data) -> {
198+
BrowserLauncher.getInstance().browse(urlProvider.getBrowserUrl(), null);
199+
}));
200+
final JPanel panel = viewUtils.createClickableLabelPanel(inputs);
201+
ApplicationManager.getApplication().invokeLater(() -> {
202+
contentPanel.removeAll();
203+
contentPanel.add(panel, BorderLayout.CENTER);
204+
contentPanel.revalidate();
205+
contentPanel.repaint();
206+
});
207+
};
208+
209+
Optional.<EmbeddedBrowser>ofNullable(FlutterUtils.embeddedBrowser(project))
210+
.ifPresentOrElse(onBrowserAvailable, onBrowserUnavailable);
187211
});
188212
}
189213

0 commit comments

Comments
 (0)