Skip to content

Commit 810aabe

Browse files
authored
Send DTD and DevTools URI to widget preview (#8599)
Follow up to #8595 At the moment I don't see consequences to having or not having the DTD connection, but I expect that in the future, the widget preview will respond to theme change updates over DTD. (and potentially other things?) Based on the conversation in #8595 (comment), the DevTools URI also does not have a visible consequence, but it should prevent flutter tools from starting its own DevTools instance when widget-preview is run.
1 parent 883eb82 commit 810aabe

File tree

2 files changed

+65
-15
lines changed

2 files changed

+65
-15
lines changed

src/io/flutter/sdk/FlutterSdk.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,14 +416,20 @@ public FlutterCommand flutterTest(@NotNull PubRoot root, @NotNull VirtualFile fi
416416
}
417417

418418
@NotNull
419-
public FlutterCommand widgetPreview(@NotNull PubRoot root, boolean isVerboseMode) {
419+
public FlutterCommand widgetPreview(@NotNull PubRoot root, boolean isVerboseMode, @Nullable String dtdUri, @Nullable String devToolsUri) {
420420
final List<String> args = new ArrayList<>();
421421
args.add("start");
422422
args.add("--web-server");
423423
args.add("--machine");
424424
if (isVerboseMode) {
425425
args.add("--verbose");
426426
}
427+
if (dtdUri != null) {
428+
args.add("--dtd-url=" + dtdUri);
429+
}
430+
if (devToolsUri != null) {
431+
args.add("--devtools-server-address=" + devToolsUri);
432+
}
427433

428434
return new FlutterCommand(this, root.getRoot(), FlutterCommand.Type.WIDGET_PREVIEW, args.toArray(new String[]{}));
429435
}

src/io/flutter/widgetpreview/WidgetPreviewPanel.java

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,22 @@
77
import com.intellij.openapi.diagnostic.Logger;
88
import com.intellij.openapi.editor.colors.EditorColorsListener;
99
import com.intellij.openapi.editor.colors.EditorColorsManager;
10-
import com.intellij.openapi.editor.colors.EditorColorsScheme;
1110
import com.intellij.openapi.project.Project;
1211
import com.intellij.openapi.ui.SimpleToolWindowPanel;
1312
import com.intellij.openapi.util.Disposer;
1413
import com.intellij.openapi.wm.ToolWindow;
1514
import com.intellij.util.messages.MessageBusConnection;
15+
import com.jetbrains.lang.dart.ide.toolingDaemon.DartToolingDaemonService;
1616
import icons.FlutterIcons;
1717
import io.flutter.FlutterBundle;
1818
import io.flutter.FlutterUtils;
19+
import io.flutter.dart.DtdUtils;
20+
import io.flutter.devtools.DevToolsUrl;
1921
import io.flutter.devtools.DevToolsUtils;
2022
import io.flutter.logging.PluginLogger;
2123
import io.flutter.pub.PubRoot;
24+
import io.flutter.run.daemon.DevToolsInstance;
25+
import io.flutter.run.daemon.DevToolsService;
2226
import io.flutter.sdk.FlutterCommand;
2327
import io.flutter.sdk.FlutterSdk;
2428
import io.flutter.sdk.FlutterSdkVersion;
@@ -27,8 +31,8 @@
2731
import io.flutter.utils.OpenApiUtils;
2832
import io.flutter.view.BrowserUrlProvider;
2933
import io.flutter.view.EmbeddedTab;
30-
import io.flutter.view.WidgetPreviewUrlProvider;
3134
import io.flutter.view.ViewUtils;
35+
import io.flutter.view.WidgetPreviewUrlProvider;
3236
import org.jetbrains.annotations.NotNull;
3337
import org.jetbrains.annotations.Nullable;
3438

@@ -37,6 +41,8 @@
3741
import java.util.List;
3842
import java.util.Optional;
3943
import java.util.concurrent.CompletableFuture;
44+
import java.util.concurrent.TimeUnit;
45+
import java.util.concurrent.TimeoutException;
4046
import java.util.concurrent.atomic.AtomicReference;
4147
import java.util.function.Consumer;
4248

@@ -67,7 +73,7 @@ public WidgetPreviewPanel(@NotNull Project project, @NotNull ToolWindow toolWind
6773
}
6874

6975
private void startWidgetPreview() {
70-
ApplicationManager.getApplication().executeOnPooledThread(() -> {
76+
OpenApiUtils.safeExecuteOnPooledThread(() -> {
7177
try {
7278
// Check versioning of Flutter SDK.
7379
FlutterSdk sdk = FlutterSdk.getFlutterSdk(project);
@@ -102,7 +108,9 @@ private void startWidgetPreview() {
102108
}
103109

104110
boolean isVerboseMode = FlutterSettings.getInstance().isVerboseLogging();
105-
final FlutterCommand command = sdk.widgetPreview(root, isVerboseMode);
111+
final String dtdUri = getDtdUri();
112+
final String devToolsUri = getDevToolsUri();
113+
final FlutterCommand command = sdk.widgetPreview(root, isVerboseMode, dtdUri, devToolsUri);
106114
LOG.info(command.getDisplayCommand());
107115

108116
final ProcessHandler handler = new MostlySilentColoredProcessHandler(command.createGeneralCommandLine(project));
@@ -120,6 +128,43 @@ private void startWidgetPreview() {
120128
});
121129
}
122130

131+
private @Nullable String getDevToolsUri() {
132+
try {
133+
final CompletableFuture<DevToolsInstance> devToolsFuture = DevToolsService.getInstance(project).getDevToolsInstance();
134+
if (devToolsFuture == null) {
135+
LOG.error("DevTools future is null.");
136+
return null;
137+
}
138+
139+
final DevToolsInstance instance = devToolsFuture.get(30, TimeUnit.SECONDS);
140+
if (instance == null) {
141+
LOG.error("DevTools instance is null.");
142+
return null;
143+
}
144+
return new DevToolsUrl.Builder().setDevToolsHost(instance.host()).setDevToolsPort(instance.port()).build().getUrlString();
145+
}
146+
catch (InterruptedException | java.util.concurrent.ExecutionException | TimeoutException e) {
147+
LOG.error("DevTools service failed: ", e);
148+
}
149+
return null;
150+
}
151+
152+
private @Nullable String getDtdUri() {
153+
try {
154+
final DartToolingDaemonService dtd = new DtdUtils().readyDtdService(project).get(30, TimeUnit.SECONDS);
155+
if (dtd == null) {
156+
LOG.error("DTD service is null.");
157+
return null;
158+
}
159+
160+
return dtd.getUri();
161+
}
162+
catch (TimeoutException | java.util.concurrent.ExecutionException | InterruptedException e) {
163+
LOG.error("DTD service is not available after 30 seconds.", e);
164+
}
165+
return null;
166+
}
167+
123168
// This is intended for the first time we load the panel - save the URL and listen for changes.
124169
private void setUrlAndLoad(@NotNull String url) {
125170
this.urlProvider = new WidgetPreviewUrlProvider(url, new DevToolsUtils().getIsBackgroundBright());
@@ -142,19 +187,18 @@ private void loadUrl(@NotNull BrowserUrlProvider urlProvider) {
142187
});
143188
}
144189

190+
// TODO(https://github.com/flutter/flutter/issues/177945): Ideally widget preview would change colors based on theme changes events,
191+
// which we already send for the DevTools panels. If this is implemented then we can remove this listening code.
145192
private void listenForReload() {
146193
MessageBusConnection connection = project.getMessageBus().connect();
147-
connection.subscribe(EditorColorsManager.TOPIC, new EditorColorsListener() {
148-
@Override
149-
public void globalSchemeChange(@Nullable EditorColorsScheme scheme) {
150-
if (urlProvider == null) {
151-
return;
152-
}
194+
connection.subscribe(EditorColorsManager.TOPIC, (EditorColorsListener)scheme -> {
195+
if (urlProvider == null) {
196+
return;
197+
}
153198

154-
final boolean changed = urlProvider.maybeUpdateColor();
155-
if (changed) {
156-
loadUrl(urlProvider);
157-
}
199+
final boolean changed = urlProvider.maybeUpdateColor();
200+
if (changed) {
201+
loadUrl(urlProvider);
158202
}
159203
});
160204
Disposer.register(toolWindow.getDisposable(), connection);

0 commit comments

Comments
 (0)