feat(frontend): viewer humain fil-par-paire en lecture seule (LS7)
Frontend pur, lecture seule, consomme read_conversation_page (LS6) ; aucun changement backend. - adapters : conversation.ts (gateway) + conversationNormalization.ts. - features/conversations : useConversationThread, ConversationViewer, index. - domain (types LS7), ports (port + Gateways.conversation), adapters/index, mock (+ clé inventaire). - features/workstate : ProjectWorkStatePanel prop onOpenConversation. - features/projects : ProjectsView swap viewer. - tests (QA, verts) : conversationNormalization, mock/conversationGateway, useConversationThread, ConversationViewer, ProjectsView.ls7. tsc 0, vitest 443/443 (+36). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
42
frontend/src/adapters/conversation.ts
Normal file
42
frontend/src/adapters/conversation.ts
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Tauri adapter for {@link ConversationGateway} (LS7 human transcript viewer).
|
||||
*
|
||||
* This is the only frontend place that knows the `read_conversation_page`
|
||||
* command name and its argument shape; features consume the gateway port
|
||||
* through DI.
|
||||
*
|
||||
* **Wire contract (verified against LS6 — `crates/app-tauri/src/commands.rs`
|
||||
* + `dto.rs`):** the command takes a *single* `request` argument deserialized
|
||||
* into `ReadConversationPageRequestDto` (`#[serde(rename_all = "camelCase")]`)
|
||||
* with flat fields `projectId`, `conversationId`, `anchor` (optional turn id),
|
||||
* `direction` (`"forward"`/`"backward"`, default backward) and `limit`
|
||||
* (optional, `0`/omit ⇒ default 50, clamped to `[1, 200]`). It returns a
|
||||
* `TurnPageDto` (`turns` / `hasMore` / `nextAnchor`). Note: there is **no**
|
||||
* nested `cursor` object on the wire — the backend builds the domain
|
||||
* `PageCursor` itself from the flat `anchor`/`direction` fields.
|
||||
*/
|
||||
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
import type { TurnPage } from "@/domain";
|
||||
import type { ConversationGateway, ConversationPageRequest } from "@/ports";
|
||||
import { normalizeTurnPage } from "./conversationNormalization";
|
||||
|
||||
export class TauriConversationGateway implements ConversationGateway {
|
||||
async readPage(
|
||||
projectId: string,
|
||||
conversationId: string,
|
||||
request?: ConversationPageRequest,
|
||||
): Promise<TurnPage> {
|
||||
const page = await invoke<unknown>("read_conversation_page", {
|
||||
request: {
|
||||
projectId,
|
||||
conversationId,
|
||||
anchor: request?.anchor,
|
||||
direction: request?.direction ?? "backward",
|
||||
limit: request?.limit,
|
||||
},
|
||||
});
|
||||
return normalizeTurnPage(page);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user