13
13
import com .intellij .openapi .application .Application ;
14
14
import com .intellij .openapi .application .ApplicationManager ;
15
15
import com .intellij .openapi .application .ModalityState ;
16
+ import com .intellij .openapi .diagnostic .Logger ;
16
17
import com .intellij .openapi .project .DumbAware ;
17
18
import com .intellij .openapi .project .Project ;
18
19
import com .intellij .openapi .project .ProjectManager ;
28
29
import com .intellij .util .ui .JBUI ;
29
30
import icons .FlutterIcons ;
30
31
import io .flutter .FlutterBundle ;
32
+ import io .flutter .logging .PluginLogger ;
31
33
import io .flutter .run .FlutterDevice ;
32
34
import io .flutter .run .daemon .DeviceService ;
33
35
import io .flutter .sdk .AndroidEmulatorManager ;
43
45
import java .util .List ;
44
46
45
47
public class DeviceSelectorAction extends AnAction implements CustomComponentAction , DumbAware {
48
+ private static final @ NotNull Logger LOG = PluginLogger .createLogger (DeviceSelectorAction .class );
49
+
46
50
private static final Key <JButton > CUSTOM_COMPONENT_KEY = Key .create ("customComponent" );
47
51
private static final Key <JBLabel > ICON_LABEL_KEY = Key .create ("iconLabel" );
48
52
private static final Key <JBLabel > TEXT_LABEL_KEY = Key .create ("textLabel" );
49
53
private static final Key <JBLabel > ARROW_LABEL_KEY = Key .create ("arrowLabel" );
50
54
private static final @ NotNull Icon DEFAULT_DEVICE_ICON = FlutterIcons .Mobile ;
51
55
private static final @ NotNull Icon DEFAULT_ARROW_ICON = IconUtil .scale (AllIcons .General .ChevronDown , null , 1.2f );
52
56
53
- private final List <AnAction > actions = new ArrayList <>();
57
+ private volatile @ NotNull List <AnAction > actions = new ArrayList <>();
54
58
private final List <Project > knownProjects = Collections .synchronizedList (new ArrayList <>());
55
59
56
60
private @ Nullable SelectDeviceAction selectedDeviceAction ;
@@ -386,7 +390,11 @@ private static boolean isSelectorVisible(@Nullable Project project) {
386
390
}
387
391
388
392
private void updateActions (@ NotNull Project project , @ NotNull Presentation presentation ) {
389
- actions .clear ();
393
+ final String projectName = project .getName ();
394
+ LOG .debug ("[" + projectName + "] Building device selector actions" );
395
+
396
+ // Create a new list instead of modifying the existing one
397
+ final List <AnAction > newActions = new ArrayList <>();
390
398
391
399
final DeviceService deviceService = DeviceService .getInstance (project );
392
400
@@ -399,7 +407,8 @@ private void updateActions(@NotNull Project project, @NotNull Presentation prese
399
407
if (device == null ) continue ;
400
408
401
409
final SelectDeviceAction deviceAction = new SelectDeviceAction (device , devices );
402
- actions .add (deviceAction );
410
+ newActions .add (deviceAction );
411
+ LOG .debug ("[" + projectName + "] Device action added for " + device );
403
412
404
413
if (Objects .equals (device , selectedDevice )) {
405
414
selectedDeviceAction = deviceAction ;
@@ -411,37 +420,42 @@ private void updateActions(@NotNull Project project, @NotNull Presentation prese
411
420
// Show the 'Open iOS Simulator' action.
412
421
if (SystemInfo .isMac ) {
413
422
boolean simulatorOpen = false ;
414
- for (AnAction action : actions ) {
423
+ for (AnAction action : newActions ) {
415
424
if (action instanceof SelectDeviceAction deviceAction ) {
416
425
final FlutterDevice device = deviceAction .device ;
417
426
if (device .isIOS () && device .emulator ()) {
418
427
simulatorOpen = true ;
428
+ break ;
419
429
}
420
430
}
421
431
}
422
-
423
- actions .add (new Separator ( ));
424
- actions . add ( new OpenSimulatorAction (! simulatorOpen ) );
432
+ newActions . add ( new Separator ());
433
+ newActions .add (new OpenSimulatorAction (! simulatorOpen ));
434
+ LOG . debug ( "[" + projectName + "] 'Open iOS Simulator' action added" );
425
435
}
426
436
427
437
// Add Open Android emulators actions.
428
438
final List <OpenEmulatorAction > emulatorActions = OpenEmulatorAction .getEmulatorActions (project );
429
439
if (emulatorActions != null && !emulatorActions .isEmpty ()) {
430
- actions .add (new Separator ());
431
- actions .addAll (emulatorActions );
440
+ newActions .add (new Separator ());
441
+ newActions .addAll (emulatorActions );
442
+ LOG .debug ("[" + projectName + "] Emulator action added: " + emulatorActions );
432
443
}
433
444
if (!FlutterModuleUtils .hasInternalDartSdkPath (project )) {
434
- actions .add (new Separator ());
435
- actions .add (RestartFlutterDaemonAction .forDeviceSelector ());
445
+ newActions .add (new Separator ());
446
+ newActions .add (RestartFlutterDaemonAction .forDeviceSelector ());
436
447
}
437
448
449
+ // Atomically replace the action list
450
+ LOG .debug ("[" + projectName + "] Replacing device selector actions" );
451
+ this .actions = newActions ;
452
+
438
453
var tracker = ActivityTracker .getInstance ();
439
454
if (tracker != null ) {
440
455
tracker .inc ();
441
456
}
442
457
}
443
458
444
-
445
459
private static class SelectDeviceAction extends AnAction {
446
460
@ NotNull private final FlutterDevice device ;
447
461
0 commit comments