feat: improve evolution screen feedback states
This commit is contained in:
@@ -17,6 +17,8 @@ public class MasterAgentEvolutionActivity extends BossScreenActivity {
|
||||
private long lastRealtimeReloadAt;
|
||||
private boolean contentLoaded;
|
||||
private @Nullable String currentMode;
|
||||
private @Nullable String statusMessage;
|
||||
private boolean statusIsError;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -57,12 +59,16 @@ public class MasterAgentEvolutionActivity extends BossScreenActivity {
|
||||
if (!response.ok()) {
|
||||
throw new IllegalStateException(response.message());
|
||||
}
|
||||
runOnUiThread(() -> renderDashboard(response.json));
|
||||
runOnUiThread(() -> {
|
||||
clearStatusMessage();
|
||||
renderDashboard(response.json);
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> {
|
||||
setRefreshing(false);
|
||||
contentLoaded = false;
|
||||
replaceContent(BossUi.buildEmptyCard(this, "自动进化加载失败:" + error.getMessage()));
|
||||
showStatusMessage("自动进化加载失败:" + error.getMessage(), true);
|
||||
renderLoadErrorState(error.getMessage());
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -119,6 +125,7 @@ public class MasterAgentEvolutionActivity extends BossScreenActivity {
|
||||
"autonomous".equals(currentMode) ? "完全自我进化" : "受控自动进化",
|
||||
autoApplyLowRiskRules ? "低风险提案会自动采纳。" : "所有提案都需要人工确认。"
|
||||
));
|
||||
maybeRenderStatusBanner();
|
||||
|
||||
Button controlledButton = BossUi.buildMiniActionButton(this, "切到受控模式", false);
|
||||
controlledButton.setEnabled(!"controlled".equals(currentMode));
|
||||
@@ -181,7 +188,7 @@ public class MasterAgentEvolutionActivity extends BossScreenActivity {
|
||||
proposal.optString("summary", "暂无摘要"),
|
||||
proposal.optString("proposalType", "-")
|
||||
+ " · " + proposal.optString("riskLevel", "-")
|
||||
+ " · " + proposal.optString("createdAt", "-"),
|
||||
+ " · " + formatTime(proposal.optString("createdAt", "-")),
|
||||
null,
|
||||
null
|
||||
));
|
||||
@@ -208,7 +215,7 @@ public class MasterAgentEvolutionActivity extends BossScreenActivity {
|
||||
this,
|
||||
signal.optString("kind", "signal"),
|
||||
signal.optString("requestText", ""),
|
||||
signal.optString("createdAt", "-"),
|
||||
formatTime(signal.optString("createdAt", "-")),
|
||||
null,
|
||||
null
|
||||
));
|
||||
@@ -227,7 +234,7 @@ public class MasterAgentEvolutionActivity extends BossScreenActivity {
|
||||
this,
|
||||
rule.optString("ruleType", "rule"),
|
||||
rule.optString("sourceProposalId", "直接创建"),
|
||||
rule.optString("createdAt", "-"),
|
||||
formatTime(rule.optString("createdAt", "-")),
|
||||
null,
|
||||
null
|
||||
));
|
||||
@@ -261,14 +268,14 @@ public class MasterAgentEvolutionActivity extends BossScreenActivity {
|
||||
throw new IllegalStateException(response.message());
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
showMessage("已切到 " + ("autonomous".equals(mode) ? "完全自我进化" : "受控自动进化"));
|
||||
showStatusMessage("已切到 " + ("autonomous".equals(mode) ? "完全自我进化" : "受控自动进化"), false);
|
||||
setResult(RESULT_OK);
|
||||
reload();
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> {
|
||||
setRefreshing(false);
|
||||
showMessage("切换失败:" + error.getMessage());
|
||||
showStatusMessage("切换失败:" + error.getMessage(), true);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -289,16 +296,73 @@ public class MasterAgentEvolutionActivity extends BossScreenActivity {
|
||||
throw new IllegalStateException(response.message());
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
showMessage(approve ? "提案已批准" : "提案已拒绝");
|
||||
showStatusMessage(approve ? "提案已批准" : "提案已拒绝", false);
|
||||
setResult(RESULT_OK);
|
||||
reload();
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> {
|
||||
setRefreshing(false);
|
||||
showMessage((approve ? "批准失败:" : "拒绝失败:") + error.getMessage());
|
||||
showStatusMessage((approve ? "批准失败:" : "拒绝失败:") + error.getMessage(), true);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void maybeRenderStatusBanner() {
|
||||
if (statusMessage == null || statusMessage.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
contentRoot.addView(BossUi.buildSoftPanel(
|
||||
this,
|
||||
statusIsError ? "最近状态" : "最近操作",
|
||||
statusMessage,
|
||||
statusIsError ? "你可以直接点顶部刷新重试,或继续切换模式/审批提案。" : "本页已经同步到最新自动进化状态。"
|
||||
));
|
||||
}
|
||||
|
||||
private void renderLoadErrorState(String message) {
|
||||
replaceContent(contentRoot);
|
||||
contentRoot.removeAllViews();
|
||||
contentRoot.addView(BossUi.buildSimpleProfileHeader(
|
||||
this,
|
||||
"主 Agent 自动进化",
|
||||
"信号、提案与生效规则",
|
||||
"当前加载失败,保留在这个页面直接重试即可。"
|
||||
));
|
||||
maybeRenderStatusBanner();
|
||||
Button retryButton = BossUi.buildMiniActionButton(this, "重新加载", true);
|
||||
retryButton.setOnClickListener(v -> reload());
|
||||
contentRoot.addView(BossUi.buildInlineActionRow(this, retryButton));
|
||||
contentRoot.addView(BossUi.buildEmptyCard(this, "自动进化中心暂时不可用:" + message));
|
||||
}
|
||||
|
||||
private void showStatusMessage(String message, boolean isError) {
|
||||
statusMessage = message;
|
||||
statusIsError = isError;
|
||||
showMessage(message);
|
||||
}
|
||||
|
||||
private void clearStatusMessage() {
|
||||
if (!statusIsError) {
|
||||
statusMessage = null;
|
||||
}
|
||||
statusIsError = false;
|
||||
}
|
||||
|
||||
private String formatTime(String value) {
|
||||
if (value == null || value.isEmpty() || "-".equals(value)) {
|
||||
return "-";
|
||||
}
|
||||
String normalized = value.replace('T', ' ');
|
||||
int plusIndex = normalized.indexOf('+');
|
||||
if (plusIndex > 0) {
|
||||
return normalized.substring(0, plusIndex);
|
||||
}
|
||||
int zIndex = normalized.indexOf('Z');
|
||||
if (zIndex > 0) {
|
||||
return normalized.substring(0, zIndex);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,68 @@ public class MasterAgentEvolutionActivityTest {
|
||||
assertEquals(1, activity.reloadCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renderDashboardShowsStatusBannerAndFormattedTimes() throws Exception {
|
||||
TestMasterAgentEvolutionActivity activity = Robolectric
|
||||
.buildActivity(TestMasterAgentEvolutionActivity.class, new Intent())
|
||||
.setup()
|
||||
.get();
|
||||
|
||||
ReflectionHelpers.setField(activity, "statusMessage", "提案已批准");
|
||||
ReflectionHelpers.setField(activity, "statusIsError", false);
|
||||
|
||||
JSONObject payload = new JSONObject()
|
||||
.put("config", new JSONObject()
|
||||
.put("mode", "controlled")
|
||||
.put("autoApplyLowRiskRules", false))
|
||||
.put("signals", new JSONArray()
|
||||
.put(new JSONObject()
|
||||
.put("signalId", "signal-1")
|
||||
.put("kind", "backend_fallback")
|
||||
.put("requestText", "主节点暂时不可用")
|
||||
.put("createdAt", "2026-04-16T12:00:00+08:00")))
|
||||
.put("proposals", new JSONArray())
|
||||
.put("rules", new JSONArray()
|
||||
.put(new JSONObject()
|
||||
.put("ruleId", "rule-1")
|
||||
.put("ruleType", "fast_path_rule")
|
||||
.put("createdAt", "2026-04-16T12:02:00+08:00")));
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"renderDashboard",
|
||||
ReflectionHelpers.ClassParameter.from(JSONObject.class, payload)
|
||||
);
|
||||
|
||||
View content = activity.findViewById(R.id.screen_content);
|
||||
assertTrue(viewTreeContainsText(content, "最近操作"));
|
||||
assertTrue(viewTreeContainsText(content, "提案已批准"));
|
||||
assertTrue(viewTreeContainsText(content, "2026-04-16 12:00:00"));
|
||||
assertTrue(viewTreeContainsText(content, "2026-04-16 12:02:00"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void renderLoadErrorStateKeepsRetryEntryVisible() throws Exception {
|
||||
TestMasterAgentEvolutionActivity activity = Robolectric
|
||||
.buildActivity(TestMasterAgentEvolutionActivity.class, new Intent())
|
||||
.setup()
|
||||
.get();
|
||||
|
||||
ReflectionHelpers.setField(activity, "statusMessage", "自动进化加载失败:network down");
|
||||
ReflectionHelpers.setField(activity, "statusIsError", true);
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"renderLoadErrorState",
|
||||
ReflectionHelpers.ClassParameter.from(String.class, "network down")
|
||||
);
|
||||
|
||||
View content = activity.findViewById(R.id.screen_content);
|
||||
assertTrue(viewTreeContainsText(content, "当前加载失败,保留在这个页面直接重试即可。"));
|
||||
assertTrue(viewTreeContainsText(content, "重新加载"));
|
||||
assertTrue(viewTreeContainsText(content, "自动进化中心暂时不可用:network down"));
|
||||
assertTrue(viewTreeContainsText(content, "最近状态"));
|
||||
}
|
||||
|
||||
private static boolean viewTreeContainsText(View root, String expectedText) {
|
||||
if (root instanceof TextView) {
|
||||
CharSequence text = ((TextView) root).getText();
|
||||
|
||||
Reference in New Issue
Block a user