/** Message contract between content scripts, the options page and the background worker. */
import type { AnnotationShape, ElementContext, RecordingStep } from "@ltt/shared";
export interface RecordEvent {
type: RecordingStep["type"];
data: Record<string, unknown>;
/** client timestamp (Date.now()) — background converts to offset_ms */
at: number;
}
export type ExtensionMessage =
| { type: "start_picker" }
| { type: "cancel_picker" }
| { type: "picked"; element: ElementContext }
| { type: "capture" }
| { type: "submit_note"; payload: SubmitNotePayload }
| { type: "recorder_start" }
| { type: "recorder_stop" }
| { type: "recorder_event"; event: RecordEvent }
| { type: "recorder_note"; text: string }
| { type: "recorder_screenshot" }
| { type: "recorder_state"; recording: boolean }
| { type: "settings_changed" };
export interface SubmitNotePayload {
element: ElementContext;
screenshotDataUrl: string;
annotationShapes: AnnotationShape[] | null;
comment: string;
title: string;
pageUrl: string;
pageTitle: string;
environment: Record<string, unknown>;
/** attachments converted to data URLs for background transport */
files: { filename: string; mime: string; dataUrl: string }[];
links: string[];
}
/** Responses from the background worker. */
export interface BackgroundResponse<T = unknown> {
ok: boolean;
data?: T;
error?: string;
}
export interface CaptureResponse {
dataUrl: string;
}
export interface SubmitResult {
report_token: string;
}
export interface RecorderState {
recording: boolean;
stepCount: number;
startedAt: number | null;
}