feat: explain task phase in android progress cards
This commit is contained in:
@@ -1339,6 +1339,19 @@ public final class BossUi {
|
||||
titleRow.addView(pin);
|
||||
card.addView(titleRow);
|
||||
|
||||
String phase = progress == null ? "" : progress.optString("phase", "").trim();
|
||||
if (!TextUtils.isEmpty(phase)) {
|
||||
TextView phaseView = secondaryText(context, "当前状态:" + executionPhaseLabel(phase));
|
||||
phaseView.setPadding(0, dp(context, 8), 0, 0);
|
||||
card.addView(phaseView);
|
||||
}
|
||||
String lastProgressAt = progress == null ? "" : progress.optString("lastProgressAt", "").trim();
|
||||
if (!TextUtils.isEmpty(lastProgressAt)) {
|
||||
TextView lastProgressView = secondaryText(context, "最后更新:" + lastProgressAt);
|
||||
lastProgressView.setPadding(0, dp(context, 4), 0, 0);
|
||||
card.addView(lastProgressView);
|
||||
}
|
||||
|
||||
JSONArray steps = progress == null ? null : progress.optJSONArray("steps");
|
||||
if (steps == null || steps.length() == 0) {
|
||||
card.addView(progressLine(context, "等待执行进度回写", "running"));
|
||||
@@ -1931,6 +1944,37 @@ public final class BossUi {
|
||||
return card;
|
||||
}
|
||||
|
||||
private static String executionPhaseLabel(String phase) {
|
||||
switch (phase) {
|
||||
case "queued":
|
||||
return "等待设备接收";
|
||||
case "claimed":
|
||||
return "设备已接收";
|
||||
case "executor_starting":
|
||||
return "正在启动执行器";
|
||||
case "turn_started":
|
||||
return "已写入目标线程";
|
||||
case "awaiting_reply":
|
||||
return "等待线程回复";
|
||||
case "completing":
|
||||
return "正在回写结果";
|
||||
case "completed":
|
||||
return "已完成";
|
||||
case "recoverable_failed":
|
||||
return "可恢复失败";
|
||||
case "terminal_failed":
|
||||
return "执行失败";
|
||||
case "timed_out":
|
||||
return "执行超时";
|
||||
case "canceled":
|
||||
return "已取消";
|
||||
case "needs_user_action":
|
||||
return "需要用户处理";
|
||||
default:
|
||||
return phase;
|
||||
}
|
||||
}
|
||||
|
||||
private static View progressLine(Context context, String text, String status) {
|
||||
LinearLayout row = new LinearLayout(context);
|
||||
row.setOrientation(LinearLayout.HORIZONTAL);
|
||||
|
||||
@@ -948,6 +948,42 @@ public class ProjectDetailActivityUiTest {
|
||||
assertTrue(viewTreeContainsText(messageView, "Mendel(explorer)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executionProgressMessageRendersPhaseExplanation() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
.putExtra(ProjectDetailActivity.EXTRA_PROJECT_ID, "thread-phase")
|
||||
.putExtra(ProjectDetailActivity.EXTRA_PROJECT_NAME, "Boss开发主线程");
|
||||
TestProjectDetailActivity activity = Robolectric
|
||||
.buildActivity(TestProjectDetailActivity.class, intent)
|
||||
.setup()
|
||||
.get();
|
||||
|
||||
JSONObject message = new JSONObject()
|
||||
.put("id", "progress-phase-1")
|
||||
.put("sender", "master")
|
||||
.put("senderLabel", "主 Agent")
|
||||
.put("body", "执行进度")
|
||||
.put("kind", "execution_progress")
|
||||
.put("sentAt", "2026-06-06T10:16:00+08:00")
|
||||
.put("executionProgress", new JSONObject()
|
||||
.put("status", "running")
|
||||
.put("phase", "awaiting_reply")
|
||||
.put("lastProgressAt", "2026-06-06T10:15:30+08:00")
|
||||
.put("steps", new JSONArray()
|
||||
.put(new JSONObject()
|
||||
.put("text", "等待目标线程回复")
|
||||
.put("status", "running"))));
|
||||
|
||||
View messageView = ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"buildMessageView",
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, message)
|
||||
);
|
||||
|
||||
assertTrue(viewTreeContainsText(messageView, "当前状态:等待线程回复"));
|
||||
assertTrue(viewTreeContainsText(messageView, "最后更新:2026-06-06T10:15:30+08:00"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void executionProgressMessageRendersCodexApprovalAndFileChangeSections() throws Exception {
|
||||
Intent intent = new Intent()
|
||||
|
||||
Reference in New Issue
Block a user