feat: surface thread status summary in conversation info

This commit is contained in:
kris
2026-04-05 03:32:12 +08:00
parent 5a53b60f13
commit 2a34c19cc9
2 changed files with 128 additions and 9 deletions

View File

@@ -43,16 +43,20 @@ public class ConversationInfoActivityTest {
activity,
"renderConversation",
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildDetailPayload()),
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildParticipantsPayload())
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildParticipantsPayload()),
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildThreadStatusPayload())
);
LinearLayout content = activity.findViewById(R.id.screen_content);
assertTrue(viewTreeContainsText(content.getChildAt(0), "北区试产线回归"));
assertTrue(viewTreeContainsText(content.getChildAt(0), "单线程会话"));
assertTrue(viewTreeContainsText(content.getChildAt(1), "发起群聊"));
assertTrue(viewTreeContainsText(content.getChildAt(1), "选择其他线程加入新群"));
assertTrue(viewTreeContainsText(content.getChildAt(2), "线程详情"));
assertTrue(viewTreeContainsText(content.getChildAt(2), "查看当前线程聊天与项目"));
assertTrue(viewTreeContainsText(content.getChildAt(1), "线程状态摘要"));
assertTrue(viewTreeContainsTextFragment(content.getChildAt(1), "当前进度:已经记录最近 2 条进展"));
assertTrue(viewTreeContainsTextFragment(content.getChildAt(1), "建议下一步:继续同步 Android 只读页"));
assertTrue(viewTreeContainsText(content.getChildAt(2), "发起群聊"));
assertTrue(viewTreeContainsText(content.getChildAt(2), "选择其他线程加入新群"));
assertTrue(viewTreeContainsText(content.getChildAt(3), "线程详情"));
assertTrue(viewTreeContainsText(content.getChildAt(3), "查看当前线程聊天与项目"));
assertTrue(viewTreeContainsText(content, "参与线程"));
assertTrue(viewTreeContainsText(content, "硬件审计协作"));
assertFalse(viewTreeContainsText(content, "从当前会话选择其他线程,创建新的独立群聊"));
@@ -73,7 +77,8 @@ public class ConversationInfoActivityTest {
activity,
"renderConversation",
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildDetailPayload()),
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildParticipantsPayload())
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildParticipantsPayload()),
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildThreadStatusPayload())
);
View threadDetailRow = findClickableViewContainingText(
@@ -114,7 +119,8 @@ public class ConversationInfoActivityTest {
activity,
"renderConversation",
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildDetailPayload()),
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildParticipantsPayload())
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildParticipantsPayload()),
ReflectionHelpers.ClassParameter.from(JSONObject.class, buildThreadStatusPayload())
);
View threadStatusRow = findClickableViewContainingText(
@@ -188,6 +194,19 @@ public class ConversationInfoActivityTest {
return new JSONObject().put("participants", participants);
}
private static JSONObject buildThreadStatusPayload() throws Exception {
return new JSONObject()
.put("threadStatusDocument", new JSONObject()
.put("projectGoal", "完成线程状态回归")
.put("currentProgress", "已经记录最近 2 条进展")
.put("currentBlockers", "暂无阻塞")
.put("recommendedNextStep", "继续同步 Android 只读页")
.put("updatedAt", "2026-04-04T18:00:00+08:00"))
.put("recentProgressEvents", new JSONArray()
.put(new JSONObject().put("summary", "事件 2"))
.put(new JSONObject().put("summary", "事件 1")));
}
private static boolean viewTreeContainsText(View root, String expectedText) {
if (root instanceof TextView) {
CharSequence text = ((TextView) root).getText();
@@ -207,6 +226,25 @@ public class ConversationInfoActivityTest {
return false;
}
private static boolean viewTreeContainsTextFragment(View root, String expectedText) {
if (root instanceof TextView) {
CharSequence text = ((TextView) root).getText();
if (text != null && text.toString().contains(expectedText)) {
return true;
}
}
if (!(root instanceof ViewGroup)) {
return false;
}
ViewGroup group = (ViewGroup) root;
for (int index = 0; index < group.getChildCount(); index += 1) {
if (viewTreeContainsTextFragment(group.getChildAt(index), expectedText)) {
return true;
}
}
return false;
}
private static View findClickableViewContainingText(View root, String expectedText) {
if (root == null) {
return null;