77import com .intellij .openapi .diagnostic .Logger ;
88import com .intellij .openapi .editor .colors .EditorColorsListener ;
99import com .intellij .openapi .editor .colors .EditorColorsManager ;
10- import com .intellij .openapi .editor .colors .EditorColorsScheme ;
1110import com .intellij .openapi .project .Project ;
1211import com .intellij .openapi .ui .SimpleToolWindowPanel ;
1312import com .intellij .openapi .util .Disposer ;
1413import com .intellij .openapi .wm .ToolWindow ;
1514import com .intellij .util .messages .MessageBusConnection ;
15+ import com .jetbrains .lang .dart .ide .toolingDaemon .DartToolingDaemonService ;
1616import icons .FlutterIcons ;
1717import io .flutter .FlutterBundle ;
1818import io .flutter .FlutterUtils ;
19+ import io .flutter .dart .DtdUtils ;
20+ import io .flutter .devtools .DevToolsUrl ;
1921import io .flutter .devtools .DevToolsUtils ;
2022import io .flutter .logging .PluginLogger ;
2123import io .flutter .pub .PubRoot ;
24+ import io .flutter .run .daemon .DevToolsInstance ;
25+ import io .flutter .run .daemon .DevToolsService ;
2226import io .flutter .sdk .FlutterCommand ;
2327import io .flutter .sdk .FlutterSdk ;
2428import io .flutter .sdk .FlutterSdkVersion ;
2731import io .flutter .utils .OpenApiUtils ;
2832import io .flutter .view .BrowserUrlProvider ;
2933import io .flutter .view .EmbeddedTab ;
30- import io .flutter .view .WidgetPreviewUrlProvider ;
3134import io .flutter .view .ViewUtils ;
35+ import io .flutter .view .WidgetPreviewUrlProvider ;
3236import org .jetbrains .annotations .NotNull ;
3337import org .jetbrains .annotations .Nullable ;
3438
3741import java .util .List ;
3842import java .util .Optional ;
3943import java .util .concurrent .CompletableFuture ;
44+ import java .util .concurrent .TimeUnit ;
45+ import java .util .concurrent .TimeoutException ;
4046import java .util .concurrent .atomic .AtomicReference ;
4147import 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