From 87b24a838a05ad37e438fa086ca0dc7f2c5de3e2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 28 Aug 2025 02:14:41 +0000 Subject: [PATCH 1/4] Initial plan From 64ec3d314e302f32bb97962836dcadba6e53a3eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 28 Aug 2025 02:22:20 +0000 Subject: [PATCH 2/4] Fix NoSuchElementException in DeviceSelectorAction by adding defensive sizing Co-authored-by: AlexV525 <15884415+AlexV525@users.noreply.github.com> --- .../flutter/actions/DeviceSelectorAction.java | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/io/flutter/actions/DeviceSelectorAction.java b/src/io/flutter/actions/DeviceSelectorAction.java index c2c23728b..353c43159 100644 --- a/src/io/flutter/actions/DeviceSelectorAction.java +++ b/src/io/flutter/actions/DeviceSelectorAction.java @@ -115,21 +115,48 @@ public Dimension getPreferredSize() { int width = 0; int height = JBUI.scale(22); + // Provide fallback values if client properties are not yet set if (iconLabel instanceof JBLabel label && label.getIcon() instanceof Icon icon) { width += icon.getIconWidth(); height = Math.max(height, icon.getIconHeight()); } + else if (iconLabel == null) { + // Fallback: use default mobile icon size when component is not fully initialized + Icon defaultIcon = FlutterIcons.Mobile; + if (defaultIcon != null) { + width += defaultIcon.getIconWidth(); + height = Math.max(height, defaultIcon.getIconHeight()); + } + } if (textLabel instanceof JBLabel label && label.getText() instanceof String text && !text.isEmpty()) { final FontMetrics fm = label.getFontMetrics(label.getFont()); - width += Objects.requireNonNull(fm).stringWidth(text); - height = Math.max(height, fm.getHeight()); + if (fm != null) { + width += fm.stringWidth(text); + height = Math.max(height, fm.getHeight()); + } + } + else if (textLabel == null) { + // Fallback: estimate width for typical device name length + final FontMetrics fm = getFontMetrics(getFont()); + if (fm != null) { + width += fm.stringWidth("No device selected"); + height = Math.max(height, fm.getHeight()); + } } if (arrowLabel instanceof JBLabel label && label.getIcon() instanceof Icon icon) { width += icon.getIconWidth(); height = Math.max(height, icon.getIconHeight()); } + else if (arrowLabel == null) { + // Fallback: use default chevron down icon size + Icon defaultArrow = IconUtil.scale(AllIcons.General.ChevronDown, null, 1.2f); + if (defaultArrow != null) { + width += defaultArrow.getIconWidth(); + height = Math.max(height, defaultArrow.getIconHeight()); + } + } width += JBUI.scale(24); height += JBUI.scale(8); From 0b4968a781427f01ac47aa105f9156fd147e41a3 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Thu, 28 Aug 2025 10:40:04 +0800 Subject: [PATCH 3/4] Extract messages --- src/io/flutter/FlutterBundle.properties | 2 ++ src/io/flutter/actions/DeviceSelectorAction.java | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/io/flutter/FlutterBundle.properties b/src/io/flutter/FlutterBundle.properties index 5eb641da6..d5ecbb1a5 100644 --- a/src/io/flutter/FlutterBundle.properties +++ b/src/io/flutter/FlutterBundle.properties @@ -74,6 +74,8 @@ flutter.io.gettingStarted.IDE.url=https://docs.flutter.dev/tools/android-studio flutter.io.runAndDebug.url=https://docs.flutter.dev/tools/android-studio#running-and-debugging devicelist.loading=Loading... +devicelist.noDevices= +devicelist.noDeviceSelected= flutter.pop.frame.action.text=Drop Frame (Flutter) flutter.pop.frame.action.description=Pop the current frame off the stack diff --git a/src/io/flutter/actions/DeviceSelectorAction.java b/src/io/flutter/actions/DeviceSelectorAction.java index 353c43159..63977d963 100644 --- a/src/io/flutter/actions/DeviceSelectorAction.java +++ b/src/io/flutter/actions/DeviceSelectorAction.java @@ -140,7 +140,7 @@ else if (textLabel == null) { // Fallback: estimate width for typical device name length final FontMetrics fm = getFontMetrics(getFont()); if (fm != null) { - width += fm.stringWidth("No device selected"); + width += fm.stringWidth(FlutterBundle.message("devicelist.noDeviceSelected")); height = Math.max(height, fm.getHeight()); } } @@ -313,11 +313,11 @@ public void projectClosing(@NotNull Project project) { text = FlutterBundle.message("devicelist.loading"); } else { - text = ""; + text = FlutterBundle.message("devicelist.noDevices"); } } else if (selectedDevice == null) { - text = ""; + text = FlutterBundle.message("devicelist.noDeviceSelected"); } else { text = selectedDevice.presentationName(); From 98e1775e367a3e6e5981e645389c1a8c548f5592 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Thu, 28 Aug 2025 10:41:06 +0800 Subject: [PATCH 4/4] Remove redundant checks --- src/io/flutter/actions/DeviceSelectorAction.java | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/io/flutter/actions/DeviceSelectorAction.java b/src/io/flutter/actions/DeviceSelectorAction.java index 63977d963..570b1d82f 100644 --- a/src/io/flutter/actions/DeviceSelectorAction.java +++ b/src/io/flutter/actions/DeviceSelectorAction.java @@ -121,12 +121,10 @@ public Dimension getPreferredSize() { height = Math.max(height, icon.getIconHeight()); } else if (iconLabel == null) { - // Fallback: use default mobile icon size when component is not fully initialized + // Fallback: use the default mobile icon size when the component is not fully initialized Icon defaultIcon = FlutterIcons.Mobile; - if (defaultIcon != null) { - width += defaultIcon.getIconWidth(); - height = Math.max(height, defaultIcon.getIconHeight()); - } + width += defaultIcon.getIconWidth(); + height = Math.max(height, defaultIcon.getIconHeight()); } if (textLabel instanceof JBLabel label && label.getText() instanceof String text && !text.isEmpty()) { @@ -150,12 +148,10 @@ else if (textLabel == null) { height = Math.max(height, icon.getIconHeight()); } else if (arrowLabel == null) { - // Fallback: use default chevron down icon size + // Fallback: use the default chevron down icon size Icon defaultArrow = IconUtil.scale(AllIcons.General.ChevronDown, null, 1.2f); - if (defaultArrow != null) { - width += defaultArrow.getIconWidth(); - height = Math.max(height, defaultArrow.getIconHeight()); - } + width += defaultArrow.getIconWidth(); + height = Math.max(height, defaultArrow.getIconHeight()); } width += JBUI.scale(24);