android: preserve device detail summary context

This commit is contained in:
kris
2026-03-27 13:28:15 +08:00
parent ff56617fdb
commit 9e0b5b223f
3 changed files with 108 additions and 23 deletions

View File

@@ -57,11 +57,12 @@ public class DeviceDetailActivity extends BossScreenActivity {
deviceName = device.optString("name", deviceId);
configureScreen(deviceName, device.optString("endpoint", "设备详情"));
WechatSurfaceMapper.DeviceDetailSummary summary = WechatSurfaceMapper.toDeviceDetailSummary(device);
appendContent(BossUi.buildListRow(
this,
device.optString("name", "设备"),
buildDeviceSubtitle(device),
buildDeviceMeta(device),
summary.title.isEmpty() ? "设备" : summary.title,
summary.subtitle,
summary.meta,
null,
null
));
@@ -71,26 +72,6 @@ public class DeviceDetailActivity extends BossScreenActivity {
setRefreshing(false);
}
private String buildDeviceSubtitle(JSONObject device) {
String note = device.optString("note", "");
if (!note.isEmpty()) {
return note;
}
return "状态 " + device.optString("status", "unknown") + " · 账号 " + device.optString("account", "-");
}
private @Nullable String buildDeviceMeta(JSONObject device) {
String endpoint = device.optString("endpoint", "");
if (!endpoint.isEmpty()) {
return endpoint;
}
JSONArray projects = device.optJSONArray("projects");
if (projects == null || projects.length() == 0) {
return null;
}
return "项目 " + joinArray(projects);
}
private void openSkills() {
Intent intent = new Intent(this, SkillInventoryActivity.class);
intent.putExtra(SkillInventoryActivity.EXTRA_DEVICE_ID, deviceId);

View File

@@ -1,6 +1,7 @@
package com.hyzq.boss;
import org.json.JSONObject;
import org.json.JSONArray;
import java.util.Arrays;
import java.util.List;
@@ -52,6 +53,15 @@ public final class WechatSurfaceMapper {
);
}
public static DeviceDetailSummary toDeviceDetailSummary(JSONObject item) {
JSONObject source = item == null ? new JSONObject() : item;
return new DeviceDetailSummary(
source.optString("title", source.optString("name", "")),
buildSubtitle(source),
buildDetailMeta(source)
);
}
public static String[] rootTabLabels() {
return ROOT_TAB_LABELS.toArray(new String[0]);
}
@@ -89,6 +99,38 @@ public final class WechatSurfaceMapper {
return status + " · " + account;
}
private static String buildDetailMeta(JSONObject source) {
StringBuilder builder = new StringBuilder();
appendSegment(builder, source.optString("note", ""));
appendSegment(builder, source.optString("endpoint", ""));
JSONArray projects = source.optJSONArray("projects");
if (projects != null && projects.length() > 0) {
StringBuilder projectBuilder = new StringBuilder();
for (int i = 0; i < projects.length(); i++) {
String project = projects.optString(i);
if (project.isEmpty()) continue;
if (projectBuilder.length() > 0) {
projectBuilder.append(", ");
}
projectBuilder.append(project);
}
if (projectBuilder.length() > 0) {
appendSegment(builder, "项目 " + projectBuilder);
}
}
return builder.length() == 0 ? null : builder.toString();
}
private static void appendSegment(StringBuilder builder, String value) {
if (value == null || value.isEmpty()) {
return;
}
if (builder.length() > 0) {
builder.append(" · ");
}
builder.append(value);
}
public static final class ConversationRow {
public final String title;
public final String preview;
@@ -112,4 +154,16 @@ public final class WechatSurfaceMapper {
this.subtitle = subtitle;
}
}
public static final class DeviceDetailSummary {
public final String title;
public final String subtitle;
public final String meta;
public DeviceDetailSummary(String title, String subtitle, String meta) {
this.title = title;
this.subtitle = subtitle;
this.meta = meta;
}
}
}

View File

@@ -53,6 +53,23 @@ public class WechatSurfaceMapperTest {
assertEquals("异常 · 17600003315", row.subtitle);
}
@Test
public void deviceDetailSummary_keepsEssentialContextAlongsideNoteEndpointAndProjects() throws Exception {
JSONObject item = new StubJSONObject()
.withString("name", "Mac Studio")
.withString("status", "online")
.withString("account", "17600003315")
.withString("note", "书房主机")
.withString("endpoint", "https://boss.hyzq.net/device/mac-studio")
.withArray("projects", "master-agent", "android-app");
WechatSurfaceMapper.DeviceDetailSummary summary = WechatSurfaceMapper.toDeviceDetailSummary(item);
assertEquals("Mac Studio", summary.title);
assertEquals("在线 · 17600003315", summary.subtitle);
assertEquals("书房主机 · https://boss.hyzq.net/device/mac-studio · 项目 master-agent, android-app", summary.meta);
}
@Test
public void rootMeMenuTitles_matchApprovedSimpleMenu() throws Exception {
assertArrayEquals(
@@ -116,6 +133,11 @@ public class WechatSurfaceMapperTest {
return this;
}
StubJSONObject withArray(String key, String... entries) {
values.put(key, new StubJSONArray(entries));
return this;
}
@Override
public String optString(String key, String defaultValue) {
Object value = values.get(key);
@@ -133,5 +155,33 @@ public class WechatSurfaceMapperTest {
Object value = values.get(key);
return value instanceof Boolean ? (Boolean) value : defaultValue;
}
@Override
public org.json.JSONArray optJSONArray(String key) {
Object value = values.get(key);
return value instanceof org.json.JSONArray ? (org.json.JSONArray) value : null;
}
}
private static final class StubJSONArray extends org.json.JSONArray {
private final String[] entries;
StubJSONArray(String... entries) {
this.entries = entries == null ? new String[0] : entries;
}
@Override
public int length() {
return entries.length;
}
@Override
public String optString(int index) {
if (index < 0 || index >= entries.length) {
return "";
}
String value = entries[index];
return value == null ? "" : value;
}
}
}