Skip to content

Commit af45605

Browse files
NmurtasDevclaude
andcommitted
Make device info always visible and fix API detection
- Show device information ALWAYS visible (no need to click) - Extract API level from config.ini (image.sysdir.1) for reliable detection - Display layout: Name (bold) → Android version → Device type (gray) → Status - Simplify UI: removed click-to-expand complexity - Fix: version now correctly extracted from AVD system image path - Use centered text alignment for all info labels - Smaller font sizes for secondary info (11pt for version, 10pt for device/status) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 3c15dfe commit af45605

1 file changed

Lines changed: 54 additions & 27 deletions

File tree

src/main/java/net/nicolamurtas/android/emulator/AndroidEmulatorManager.java

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -280,38 +280,43 @@ private JPanel createDeviceCard(EmulatorService.AvdInfo avd) {
280280
BorderFactory.createEmptyBorder(10, 10, 10, 10)
281281
));
282282
card.setPreferredSize(new Dimension(180, 200));
283-
card.setCursor(new Cursor(Cursor.HAND_CURSOR));
284283

285-
// Device name at top
284+
// Top panel with name and info
285+
JPanel topPanel = new JPanel(new BorderLayout(3, 3));
286+
287+
// Device name
286288
JLabel nameLabel = new JLabel(avd.name(), SwingConstants.CENTER);
287289
nameLabel.setFont(nameLabel.getFont().deriveFont(Font.BOLD, 14f));
288-
card.add(nameLabel, BorderLayout.NORTH);
290+
topPanel.add(nameLabel, BorderLayout.NORTH);
289291

290-
// Details panel (initially hidden, toggled on click)
291-
JPanel detailsPanel = new JPanel(new GridLayout(0, 1, 2, 2));
292-
detailsPanel.setVisible(false);
292+
// Info panel with version and device type (ALWAYS VISIBLE)
293+
JPanel infoPanel = new JPanel(new GridLayout(0, 1, 2, 2));
293294

294-
// Extract API level and convert to Android version name
295-
String apiLevel = extractApiLevel(avd.target());
295+
// Extract API level from config.ini (more reliable than target string)
296+
String apiLevel = extractApiLevelFromPath(avd.path());
296297
String androidVersion = getAndroidVersionName(apiLevel);
297-
JLabel versionLabel = new JLabel("📱 " + androidVersion);
298-
versionLabel.setFont(versionLabel.getFont().deriveFont(Font.BOLD));
299-
detailsPanel.add(versionLabel);
298+
JLabel versionLabel = new JLabel(androidVersion, SwingConstants.CENTER);
299+
versionLabel.setFont(versionLabel.getFont().deriveFont(Font.PLAIN, 11f));
300+
infoPanel.add(versionLabel);
300301

301-
// Show device type from path (e.g., pixel_7)
302+
// Show device type
302303
String deviceType = extractDeviceType(avd.path());
303304
if (deviceType != null && !deviceType.isEmpty()) {
304-
detailsPanel.add(new JLabel("📐 Device: " + deviceType));
305+
JLabel deviceLabel = new JLabel(deviceType, SwingConstants.CENTER);
306+
deviceLabel.setFont(deviceLabel.getFont().deriveFont(Font.PLAIN, 10f));
307+
deviceLabel.setForeground(Color.GRAY);
308+
infoPanel.add(deviceLabel);
305309
}
306310

307311
// Check if running
308312
boolean isRunning = emulatorService != null && emulatorService.isEmulatorRunning(avd.name());
309-
JLabel statusLabel = new JLabel(isRunning ? "🟢 Running" : " Stopped");
310-
statusLabel.setFont(statusLabel.getFont().deriveFont(Font.BOLD));
313+
JLabel statusLabel = new JLabel(isRunning ? " Running" : " Stopped", SwingConstants.CENTER);
314+
statusLabel.setFont(statusLabel.getFont().deriveFont(Font.BOLD, 10f));
311315
statusLabel.setForeground(isRunning ? new Color(76, 175, 80) : Color.GRAY);
312-
detailsPanel.add(statusLabel);
316+
infoPanel.add(statusLabel);
313317

314-
card.add(detailsPanel, BorderLayout.CENTER);
318+
topPanel.add(infoPanel, BorderLayout.CENTER);
319+
card.add(topPanel, BorderLayout.NORTH);
315320

316321
// Action buttons panel
317322
JPanel actionsPanel = new JPanel(new GridLayout(2, 2, 5, 5));
@@ -345,21 +350,43 @@ private JPanel createDeviceCard(EmulatorService.AvdInfo avd) {
345350

346351
card.add(actionsPanel, BorderLayout.SOUTH);
347352

348-
// Toggle details on card click
349-
card.addMouseListener(new java.awt.event.MouseAdapter() {
350-
@Override
351-
public void mouseClicked(java.awt.event.MouseEvent e) {
352-
detailsPanel.setVisible(!detailsPanel.isVisible());
353-
card.revalidate();
354-
card.repaint();
353+
return card;
354+
}
355+
356+
/**
357+
* Extracts API level from AVD config.ini file.
358+
* This is more reliable than parsing the target string.
359+
*/
360+
private String extractApiLevelFromPath(String avdPath) {
361+
if (avdPath == null) return "Unknown";
362+
363+
try {
364+
Path configIni = Path.of(avdPath).resolve("config.ini");
365+
if (Files.exists(configIni)) {
366+
String content = Files.readString(configIni);
367+
// Look for image.sysdir.1=system-images/android-35/google_apis/x86_64/
368+
for (String line : content.split("\n")) {
369+
if (line.startsWith("image.sysdir.1=")) {
370+
String sysdir = line.substring(15).trim();
371+
// Extract API number from: system-images/android-35/google_apis/x86_64/
372+
String[] parts = sysdir.split("/");
373+
for (String part : parts) {
374+
if (part.startsWith("android-")) {
375+
return part.substring(8); // Remove "android-" prefix
376+
}
377+
}
378+
}
379+
}
355380
}
356-
});
381+
} catch (Exception e) {
382+
logger.debug("Could not extract API level from path: {}", avdPath);
383+
}
357384

358-
return card;
385+
return "Unknown";
359386
}
360387

361388
/**
362-
* Extracts API level from target string.
389+
* Extracts API level from target string (fallback method).
363390
*/
364391
private String extractApiLevel(String target) {
365392
if (target == null) return "Unknown";

0 commit comments

Comments
 (0)