Unify the log across mobile and tablet #34

Open
opened 2026-07-30 07:54:03 +00:00 by aiko · 3 comments
Owner

The same log renders two different ways depending on viewport, because two issues built it independently.

The B2 integration merged #12 (mobile chrome) and #16 (tablet landscape) into one viewport-dispatched component, and kept both sides' behaviour deliberately — except here. Today:

  • Mobile reaches the log through 記録 LOG, which opens an overlay rendering the upstream chatscope ChatHistoryPanel — real messages, pre-Denpa styling.
  • Tablet landscape (1c) renders LogRail, the 受信記録 design with relay rows.

So rotating a tablet across the breakpoint changes what the log looks like, not just where it sits.

Why it was left

Unifying needs LogRail's hard-coded 320px width parameterised, and the overlay presentation is § 4a/5c work rather than integration work. The integrating agent recorded it in .denpa-work/QUESTIONS.md rather than resolving it by fiat, which was the right call — picking a side would have silently dropped one design.

What is needed

One log presentation, driven by the chrome plan the way every other band already is. LogRail becomes width-parameterised so the overlay can host it at mobile widths, and the upstream ChatHistoryPanel stops being the mobile log.

#17 (受信記録) has since landed and owns the relay-row design — build on it rather than beside it.

Acceptance

  • Mobile overlay and tablet rail render the same rows from the same component.
  • Rotating across the 900px landscape breakpoint does not change the log's appearance beyond its placement and width.
  • The upstream ChatHistoryPanel is no longer the log on any surface; if it becomes unreferenced, delete it.
  • Silence and not-yet-loaded stay visually distinct at both sizes.
The same log renders two different ways depending on viewport, because two issues built it independently. The B2 integration merged `#12` (mobile chrome) and `#16` (tablet landscape) into one viewport-dispatched component, and kept both sides' behaviour deliberately — except here. Today: - **Mobile** reaches the log through 記録 LOG, which opens an overlay rendering the upstream chatscope `ChatHistoryPanel` — real messages, pre-Denpa styling. - **Tablet landscape (1c)** renders `LogRail`, the 受信記録 design with relay rows. So rotating a tablet across the breakpoint changes what the log looks like, not just where it sits. ## Why it was left Unifying needs `LogRail`'s hard-coded `320px` width parameterised, and the overlay presentation is § 4a/5c work rather than integration work. The integrating agent recorded it in `.denpa-work/QUESTIONS.md` rather than resolving it by fiat, which was the right call — picking a side would have silently dropped one design. ## What is needed One log presentation, driven by the chrome plan the way every other band already is. `LogRail` becomes width-parameterised so the overlay can host it at mobile widths, and the upstream `ChatHistoryPanel` stops being the mobile log. `#17` (受信記録) has since landed and owns the relay-row design — build on it rather than beside it. ## Acceptance - Mobile overlay and tablet rail render the same rows from the same component. - Rotating across the 900px landscape breakpoint does not change the log's appearance beyond its placement and width. - The upstream `ChatHistoryPanel` is no longer the log on any surface; if it becomes unreferenced, delete it. - Silence and not-yet-loaded stay visually distinct at both sizes.
Author
Owner

Rescoped — most of this is already built, and this issue's description is stale.

Established while resolving #46. This issue says mobile reaches the log through an overlay rendering the upstream chatscope ChatHistoryPanel, and that the unification needs LogRail's hard-coded 320px parameterised. Both have since happened:

  • src/renderer/src/components/receiver/receiver-chrome.tsx:259-263 renders LogOverlay with LogRail at width: '100%' — the overlay already hosts the rail.
  • src/renderer/src/components/receiver/log-rail.tsx:326 takes width = LOG_RAIL_WIDTH as a prop accepting a number or a string, so 320px is a default rather than a hard-code. log-rail.tsx:34 records the intent: "The 1c rail is a 320px column; the 1a overlay is the same log filling the stage. One component."
  • ChatHistoryPanel is no longer the log on any surface. It is reachable only from components/sidebar/sidebar.tsx, which nothing renders — chrome-is-mounted.test.ts:24 asserts App does not mount <Sidebar>.

The design question is also now answered. #46 rendered the real LogRail at 484, 800 and 320 px and the human verdict was that all three read correctly. The relay row's density is intentional at every width — no wide-variant row, no width-specific treatment. The overlay's extra header and close key are accepted as a legitimate difference from the rail, which needs no dismissal.

What is actually left

  1. Delete the dead log path. ChatHistoryPanel, and sidebar.tsx with it if nothing else survives there. This issue's own acceptance already asks for it: "if it becomes unreferenced, delete it."
  2. Verify rotation on a real device. Both target devices are now attached (see #48) — Pixel 7 Pro and OnePlus Pad. Rotating across the landscape breakpoint must change only placement and width. Currently reasoned from chrome-plan, not observed.
  3. Verify silence and not-yet-loaded stay visually distinct at both sizes. Never checked at either.

Note that reaching the log on a device is currently blocked by onboarding — see #49, which renders as a fixed 292x600 card and has to be got past first.

**Rescoped — most of this is already built, and this issue's description is stale.** Established while resolving [#46](https://git.aiko.works/aiko/denpa/issues/46). This issue says mobile reaches the log through an overlay rendering the upstream chatscope `ChatHistoryPanel`, and that the unification needs `LogRail`'s hard-coded `320px` parameterised. Both have since happened: - `src/renderer/src/components/receiver/receiver-chrome.tsx:259-263` renders `LogOverlay` with `LogRail` at `width: '100%'` — the overlay already hosts the rail. - `src/renderer/src/components/receiver/log-rail.tsx:326` takes `width = LOG_RAIL_WIDTH` as a prop accepting a number or a string, so `320px` is a default rather than a hard-code. `log-rail.tsx:34` records the intent: *"The 1c rail is a 320px column; the 1a overlay is the same log filling the stage. One component."* - `ChatHistoryPanel` is no longer the log on any surface. It is reachable only from `components/sidebar/sidebar.tsx`, which nothing renders — `chrome-is-mounted.test.ts:24` asserts `App` does not mount `<Sidebar>`. **The design question is also now answered.** `#46` rendered the real `LogRail` at 484, 800 and 320 px and the human verdict was that all three read correctly. The relay row's density is intentional at every width — no wide-variant row, no width-specific treatment. The overlay's extra header and close key are accepted as a legitimate difference from the rail, which needs no dismissal. ## What is actually left 1. **Delete the dead log path.** `ChatHistoryPanel`, and `sidebar.tsx` with it if nothing else survives there. This issue's own acceptance already asks for it: *"if it becomes unreferenced, delete it."* 2. **Verify rotation on a real device.** Both target devices are now attached (see [#48](https://git.aiko.works/aiko/denpa/issues/48)) — Pixel 7 Pro and OnePlus Pad. Rotating across the landscape breakpoint must change only placement and width. Currently reasoned from `chrome-plan`, not observed. 3. **Verify silence and not-yet-loaded stay visually distinct at both sizes.** Never checked at either. Note that reaching the log on a device is currently blocked by onboarding — see [#49](https://git.aiko.works/aiko/denpa/issues/49), which renders as a fixed 292x600 card and has to be got past first.
Author
Owner

The deletion is done in 3b5e507, merged as 257904d. The two device checks are not, so this stays open.

Item 1 of the rescope, complete. Deleted:

  • components/sidebar/chat-history-panel.tsx — the upstream chatscope log
  • components/sidebar/sidebar.tsx — its only parent, which nothing rendered
  • hooks/sidebar/use-sidebar.ts and hooks/sidebar/use-chat-history-panel.ts
  • the @chatscope/chat-ui-kit-react and @chatscope/chat-ui-kit-styles dependencies, with App.tsx's stylesheet import and main.tsx's console.error suppression that existed only to silence that library's warnings

use-sidebar.ts was also #50's third create-new-history caller, which is why the two went in one pass.

cut-surfaces.test.ts gained a block that fails if any of the four files or the names ChatHistoryPanel, useSidebar, useChatHistoryPanel or @chatscope reappear anywhere in the renderer. One existing assertion had to change: keeps name and avatar on AI messages pinned msg.avatar in the deleted panel. It now pins the field on the wire and in the context only, with a comment saying why there is no render site left — LogRail does not draw an avatar.

Not deleted, deliberately. bottom-tab.tsx, history-drawer.tsx, screen-panel.tsx, sidebar-styles.tsx and use-history-drawer.ts are now unreferenced too, since Sidebar was their last parent. cut-surfaces.test.ts:114-123 pins screen-panel.tsx and bottom-tab.tsx on purpose — 画面共有 stays in v1 per #45 — so removing them is a separate decision about where the screen grant lives, not part of this one. chat-bubble.tsx was already orphaned before this change.

Gate: 769 vitest across 50 files, 18 Rust, all passing.

What is left, and why I could not do it

Items 2 and 3 of the rescope both need hardware:

  • Rotation across the 900px breakpoint on a real device. Still reasoned from chrome-plan, still not observed.
  • Silence and not-yet-loaded staying visually distinct at both sizes. Never checked at either.

#49 (the 292x600 onboarding card) had to be got past first and has since landed, so the path to the log on a device should now be open. Leaving this issue open for those two.

**The deletion is done in `3b5e507`, merged as `257904d`. The two device checks are not, so this stays open.** Item 1 of the rescope, complete. Deleted: - `components/sidebar/chat-history-panel.tsx` — the upstream chatscope log - `components/sidebar/sidebar.tsx` — its only parent, which nothing rendered - `hooks/sidebar/use-sidebar.ts` and `hooks/sidebar/use-chat-history-panel.ts` - the `@chatscope/chat-ui-kit-react` and `@chatscope/chat-ui-kit-styles` dependencies, with `App.tsx`'s stylesheet import and `main.tsx`'s `console.error` suppression that existed only to silence that library's warnings `use-sidebar.ts` was also `#50`'s third `create-new-history` caller, which is why the two went in one pass. `cut-surfaces.test.ts` gained a block that fails if any of the four files or the names `ChatHistoryPanel`, `useSidebar`, `useChatHistoryPanel` or `@chatscope` reappear anywhere in the renderer. One existing assertion had to change: `keeps name and avatar on AI messages` pinned `msg.avatar` in the deleted panel. It now pins the field on the wire and in the context only, with a comment saying why there is no render site left — `LogRail` does not draw an avatar. **Not deleted, deliberately.** `bottom-tab.tsx`, `history-drawer.tsx`, `screen-panel.tsx`, `sidebar-styles.tsx` and `use-history-drawer.ts` are now unreferenced too, since `Sidebar` was their last parent. `cut-surfaces.test.ts:114-123` pins `screen-panel.tsx` and `bottom-tab.tsx` on purpose — 画面共有 stays in v1 per `#45` — so removing them is a separate decision about where the screen grant lives, not part of this one. `chat-bubble.tsx` was already orphaned before this change. Gate: **769 vitest across 50 files, 18 Rust**, all passing. ## What is left, and why I could not do it Items 2 and 3 of the rescope both need hardware: - **Rotation across the 900px breakpoint on a real device.** Still reasoned from `chrome-plan`, still not observed. - **Silence and not-yet-loaded staying visually distinct at both sizes.** Never checked at either. `#49` (the 292x600 onboarding card) had to be got past first and has since landed, so the path to the log on a device should now be open. Leaving this issue open for those two.
Author
Owner

This was generated by AI during triage.

Moved back to ready-for-human. Item 1 of the rescope — deleting the dead ChatHistoryPanel path — merged as 257904d. Both items that remain are device checks: rotation across the 900px breakpoint changing only placement and width, and silence versus not-yet-loaded staying visually distinct at both sizes. Neither is a test an agent can write, so the label was overstating what was takeable.

> *This was generated by AI during triage.* Moved back to `ready-for-human`. Item 1 of the rescope — deleting the dead `ChatHistoryPanel` path — merged as `257904d`. Both items that remain are device checks: rotation across the 900px breakpoint changing only placement and width, and silence versus not-yet-loaded staying visually distinct at both sizes. Neither is a test an agent can write, so the label was overstating what was takeable.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiko/denpa#34
No description provided.