feat(viewer): IPC types, wrappers and Rust module skeleton for the file viewer

Task 0 of the terminal file viewer plan: the shared interfaces that seven
later tasks build against in parallel. Adds ViewerLocation/ViewerTargetState/
ViewerState/ViewerFile/ViewerPoll to types.ts and their invoke() wrappers to
tauri-commands.ts, creates the file_viewer Rust module (mod.rs with
MAX_VIEWER_WINDOWS/VIEWER_LABEL_PREFIX/is_viewer_label, plus placeholder
registry/resolve/poll/write/window submodules), wires it into lib.rs, and
loosens visibility on the file_commands.rs helpers the viewer commands will
reuse (MAX_READ_BYTES, validate_container_path, validate_container_write_path,
FetchedFile, fetch_container_file, require_running, clip_container_text).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-22 20:56:33 -07:00
co-authored by Claude Opus 5.5
parent 20befa1320
commit 3c1d120305
10 changed files with 110 additions and 11 deletions
+20 -1
View File
@@ -1,5 +1,5 @@
import { invoke } from "@tauri-apps/api/core";
import type { Project, ProjectPath, ProjectRemovalReport, ProjectResetOutcome, ContainerInfo, AppSettings, SettingsImportPreview, SettingsImportOutcome, UpdateInfo, ImageUpdateInfo, FileEntry, FileContents, WebTerminalInfo, SttStatus, GatewayStatus, InstallOptions, ClaudeSession, ContainerCapabilities, ScheduledTask, ScheduledTaskInput, SchedulerNotification, AuthBridgeStatus, BrowserViewStatus, BrowserViewPopoutState, BrowserPageState, PlaywrightDetection, BrowserSetupOutcome, BrowserInstallTarget, ContainerStaleness, MigrationOptions, MigrationReport, MigrationState, ClearTokenOutcome, CaCertInfo, UploadOutcome, Note } from "./types";
import type { Project, ProjectPath, ProjectRemovalReport, ProjectResetOutcome, ContainerInfo, AppSettings, SettingsImportPreview, SettingsImportOutcome, UpdateInfo, ImageUpdateInfo, FileEntry, FileContents, WebTerminalInfo, SttStatus, GatewayStatus, InstallOptions, ClaudeSession, ContainerCapabilities, ScheduledTask, ScheduledTaskInput, SchedulerNotification, AuthBridgeStatus, BrowserViewStatus, BrowserViewPopoutState, BrowserPageState, PlaywrightDetection, BrowserSetupOutcome, BrowserInstallTarget, ContainerStaleness, MigrationOptions, MigrationReport, MigrationState, ClearTokenOutcome, CaCertInfo, UploadOutcome, Note, ViewerFile, ViewerPoll, ViewerState } from "./types";
// Docker
export const checkDocker = () => invoke<boolean>("check_docker");
@@ -413,3 +413,22 @@ export const getMigrationState = (projectId: string) =>
* Rejects with a string already phrased for a toast. */
export const openUrlExternal = (url: string) =>
invoke<void>("open_url_external", { url });
// ---- Terminal file viewer ----
export const openFileViewer = (
projectId: string,
path: string,
line?: number,
col?: number,
endLine?: number,
) => invoke<void>("open_file_viewer", { projectId, path, line, col, endLine });
export const viewerGetState = () => invoke<ViewerState>("viewer_get_state");
export const viewerReadFile = (maxBytes: number) =>
invoke<ViewerFile>("viewer_read_file", { maxBytes });
export const viewerPollFile = () => invoke<ViewerPoll>("viewer_poll_file");
export const viewerWriteFile = (contentsBase64: string, baseHash: string) =>
invoke<string>("viewer_write_file", { contentsBase64, baseHash });
export const viewerChooseFile = (index: number) =>
invoke<ViewerState>("viewer_choose_file", { index });
+38
View File
@@ -954,3 +954,41 @@ export interface MigrationState {
options: MigrationOptions;
plan: MigrationPlan | null;
}
// ---- Terminal file viewer (commands/file_viewer_commands.rs) ----
export interface ViewerLocation {
line: number | null;
col: number | null;
end_line: number | null;
}
export type ViewerTargetState =
| { kind: "resolved"; container_path: string }
| { kind: "choose"; candidates: string[] }
| { kind: "not_found"; tried: string[] };
export interface ViewerState {
project_id: string;
project_name: string;
/** What was clicked, for the title and the not-found message. */
raw_path: string;
state: ViewerTargetState;
initial: ViewerLocation;
}
export interface ViewerFile {
contents_base64: string;
truncated: boolean;
size: number;
/** SHA-256 hex of the returned bytes; equals the file's hash when `truncated` is false. */
hash: string;
editable: boolean;
readonly_reason: string | null;
}
export interface ViewerPoll {
exists: boolean;
hash: string | null;
size: number | null;
}