113 lines
6.3 KiB
Markdown
113 lines
6.3 KiB
Markdown
# Android Chat Status Row Implementation Plan
|
|
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
**Goal:** Render `conversationTasks` and `executionWarnings` as a compact inline status row beneath each message on the Android chat page, dedupe grouped warnings per message, and keep realtime patches scoped to the affected message.
|
|
|
|
**Architecture:** Add a reusable status-row builder in `BossUi` and wire `ProjectDetailActivity.buildMessageView` to compute grouped tasks/warnings, append the status row under each bubble, and compare a fingerprint during realtime patches so only impacted views re-render.
|
|
|
|
**Tech Stack:** Android/Java UI (`ProjectDetailActivity.java`, `BossUi.java`) and Node-powered source-verification tests (`tests/android-chat-incremental-realtime-append.test.ts`, `tests/android-chat-local-realtime-patch.test.ts`).
|
|
|
|
---
|
|
|
|
### Task 1: Fail on missing inline status row in realtime append test
|
|
|
|
**Files:**
|
|
- Modify: `tests/android-chat-incremental-realtime-append.test.ts`
|
|
- Test: `npm test tests/android-chat-incremental-realtime-append.test.ts`
|
|
|
|
- [ ] **Step 1: Write the failing test**
|
|
```ts
|
|
assert.match(
|
|
source,
|
|
/wrapper\.addView\(BossUi\.buildMessageStatusRow\(/,
|
|
"expected every message bubble to append BossUi.buildMessageStatusRow",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/List<JSONObject> messageWarnings = collectMessageWarnings\(projectMessagesPayload, messageId\);/,
|
|
"expected the new status row builder to source grouped warnings per message",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/String statusFingerprint = buildStatusFingerprint\(messageId, projectMessagesPayload\);/,
|
|
"expected realtime patches to compute a fingerprint before replacing a message view",
|
|
);
|
|
```
|
|
- [ ] **Step 2: Run it to prove failure**
|
|
Run: `npm test tests/android-chat-incremental-realtime-append.test.ts`
|
|
Expected: FAIL because `BossUi.buildMessageStatusRow` and the new helper functions do not yet exist.
|
|
- [ ] **Step 3: Re-run after implementation to confirm success**
|
|
Run: `npm test tests/android-chat-incremental-realtime-append.test.ts`
|
|
Expected: PASS.
|
|
|
|
### Task 2: Fail on missing helper signatures in realtime patch test
|
|
|
|
**Files:**
|
|
- Modify: `tests/android-chat-local-realtime-patch.test.ts`
|
|
- Test: `npm test tests/android-chat-local-realtime-patch.test.ts`
|
|
|
|
- [ ] **Step 1: Write the failing test**
|
|
```ts
|
|
assert.match(
|
|
source,
|
|
/LinearLayout statusRow = buildMessageStatusRow\(this, message, conversationTask, messageWarnings\);/,
|
|
"expected buildMessageStatusRow to be invoked when each message is rendered",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/List<JSONObject> buildMessageWarnings\(JSONObject payload, String messageId\);/,
|
|
"expected a helper that returns grouped warnings keyed by message id",
|
|
);
|
|
assert.match(
|
|
source,
|
|
/if \(!TextUtils\.equals\(currentFingerprint, nextFingerprint\)\) \{ replaceMessageViewById\(/,
|
|
"expected realtime patch to compare status fingerprint before rerendering",
|
|
);
|
|
```
|
|
- [ ] **Step 2: Run it to prove failure**
|
|
Run: `npm test tests/android-chat-local-realtime-patch.test.ts`
|
|
Expected: FAIL because helper signatures and fingerprint comparisons are missing.
|
|
- [ ] **Step 3: Re-run after implementation to confirm success**
|
|
Run: `npm test tests/android-chat-local-realtime-patch.test.ts`
|
|
Expected: PASS.
|
|
|
|
### Task 3: Add BossUi helper for compact status row
|
|
|
|
**Files:**
|
|
- Modify: `android/app/src/main/java/com/hyzq/boss/BossUi.java`
|
|
- Test: `npm test tests/android-chat-incremental-realtime-append.test.ts`
|
|
- Test: `npm test tests/android-chat-local-realtime-patch.test.ts`
|
|
|
|
- [ ] **Step 1: Implement `buildMessageStatusRow`**
|
|
Add a method that accepts `(Context context, String statusLabel, String detailText, boolean outgoing)` and returns a horizontal `LinearLayout` with spaced pills and body text, using rounded background colors and `TextView` ellipsizing. Keep it compact (max height) and re-usable for both warnings and conversation task summaries.
|
|
- [ ] **Step 2: Run targeted tests**
|
|
Run: `npm test tests/android-chat-incremental-realtime-append.test.ts tests/android-chat-local-realtime-patch.test.ts`
|
|
Expected: PASS after the helper is referenced by `ProjectDetailActivity`.
|
|
|
|
### Task 4: Wire ProjectDetailActivity to the new status row
|
|
|
|
**Files:**
|
|
- Modify: `android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java`
|
|
- Test: `npm test tests/android-chat-incremental-realtime-append.test.ts`
|
|
- Test: `npm test tests/android-chat-local-realtime-patch.test.ts`
|
|
|
|
- [ ] **Step 1: Add helper methods for grouped warnings/tasks and fingerprinting**
|
|
Implement `List<JSONObject> collectMessageWarnings(JSONObject payload, String messageId)`, `@Nullable JSONObject findConversationTask(String messageId)`, and `private String buildStatusFingerprint(String messageId, JSONObject payload)` that concatenates task/w warning summaries so the realtime patch can detect status changes without re-rendering unchanged rows.
|
|
- [ ] **Step 2: Update `buildMessageView` to append a status row**
|
|
Inside `buildMessageView`, compute `List<JSONObject> messageWarnings` and `JSONObject messageTask`, then call `BossUi.buildMessageStatusRow(this, description, detail, outgoing)` and add it directly beneath the bubble instead of the previous warning card logic. Use the grouped data to deduplicate identical warnings (e.g., map by `warningId` or `title+summary`).
|
|
- [ ] **Step 3: Update realtime patch logic**
|
|
In `tryPatchRealtimeExecutionWarnings`, compute `String currentFingerprint = buildStatusFingerprint(messageId, currentRenderedProjectPayload)` and `String nextFingerprint = buildStatusFingerprint(messageId, projectMessagesPayload)`; only call `replaceMessageViewById` when they differ. Ensure `currentRenderedProjectPayload` is updated once per patch and that `renderNearBottom`/`setRefreshing` behavior stays the same.
|
|
- [ ] **Step 4: Run regression tests**
|
|
Run: `npm test tests/android-chat-incremental-realtime-append.test.ts tests/android-chat-local-realtime-patch.test.ts`
|
|
Expected: PASS.
|
|
|
|
### Task 5: Final verification
|
|
|
|
**Files:**
|
|
- Test: all above tests
|
|
|
|
- [ ] **Step 1: Run the two test files together**
|
|
Run: `npm test tests/android-chat-incremental-realtime-append.test.ts tests/android-chat-local-realtime-patch.test.ts`
|
|
Expected: PASS with no additional failures.
|