feat(preload): expose typed InklingApi (v0.2: intent + continuity)
Task 3 of the slice plan. Replaces the minimum @shared/types augmentation with the full domain model: Note (with v0.2 intent + edited-flag fields), NoteTag, NoteMedia, AiStatus, WeeklyContinuity, CaptureApi, InboxApi, and the InklingApi aggregate exposed on window.inkling. Adds the preload bridge that wires every InklingApi method to its IPC channel via contextBridge.exposeInMainWorld. Verification: `npm run typecheck` exits 0. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
27
src/preload/index.ts
Normal file
27
src/preload/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { contextBridge, ipcRenderer } from 'electron';
|
||||
import type { InklingApi, Note } from '@shared/types';
|
||||
|
||||
const api: InklingApi = {
|
||||
capture: {
|
||||
submit: (payload) => ipcRenderer.invoke('capture:submit', payload),
|
||||
hide: () => ipcRenderer.send('capture:hide')
|
||||
},
|
||||
inbox: {
|
||||
listNotes: (opts) => ipcRenderer.invoke('inbox:list', opts),
|
||||
updateAiFields: (noteId, fields) =>
|
||||
ipcRenderer.invoke('inbox:updateAi', { noteId, fields }),
|
||||
deleteNote: (noteId) => ipcRenderer.invoke('inbox:delete', noteId),
|
||||
setIntent: (noteId, text) => ipcRenderer.invoke('inbox:setIntent', { noteId, text }),
|
||||
dismissIntent: (noteId) => ipcRenderer.invoke('inbox:dismissIntent', noteId),
|
||||
getContinuity: () => ipcRenderer.invoke('inbox:continuity'),
|
||||
getPendingCount: () => ipcRenderer.invoke('inbox:pendingCount'),
|
||||
getOllamaStatus: () => ipcRenderer.invoke('inbox:ollamaStatus'),
|
||||
onNoteUpdated: (cb) => {
|
||||
const listener = (_e: unknown, note: Note) => cb(note);
|
||||
ipcRenderer.on('note:updated', listener);
|
||||
return () => ipcRenderer.off('note:updated', listener);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
contextBridge.exposeInMainWorld('inkling', api);
|
||||
@@ -1,6 +1,74 @@
|
||||
declare global {
|
||||
namespace Electron {
|
||||
interface App { isQuitting?: boolean; }
|
||||
}
|
||||
namespace Electron { interface App { isQuitting?: boolean; } }
|
||||
interface Window { inkling: InklingApi; }
|
||||
}
|
||||
|
||||
export interface NoteMedia {
|
||||
id: string;
|
||||
kind: 'image';
|
||||
relPath: string;
|
||||
mime: string;
|
||||
bytes: number;
|
||||
}
|
||||
|
||||
export type AiStatus = 'pending' | 'done' | 'failed';
|
||||
|
||||
export interface NoteTag {
|
||||
name: string;
|
||||
source: 'ai' | 'user';
|
||||
}
|
||||
|
||||
export interface Note {
|
||||
id: string;
|
||||
rawText: string;
|
||||
aiTitle: string | null;
|
||||
aiSummary: string | null;
|
||||
aiStatus: AiStatus;
|
||||
aiError: string | null;
|
||||
aiProvider: string | null;
|
||||
aiGeneratedAt: string | null;
|
||||
titleEditedByUser: boolean;
|
||||
summaryEditedByUser: boolean;
|
||||
userIntent: string | null;
|
||||
intentPromptedAt: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
tags: NoteTag[];
|
||||
media: NoteMedia[];
|
||||
}
|
||||
|
||||
export interface WeeklyContinuity {
|
||||
weekStart: string; // ISO date (KST 월요일)
|
||||
weekCount: number;
|
||||
weekTarget: number; // 7
|
||||
consecutiveCompleteWeeks: number;
|
||||
showRecoveryToast: boolean;
|
||||
lastNoteAt: string | null;
|
||||
}
|
||||
|
||||
export interface CaptureApi {
|
||||
submit(payload: { text: string; images: ArrayBuffer[] }): Promise<{ noteId: string }>;
|
||||
hide(): void;
|
||||
}
|
||||
|
||||
export interface InboxApi {
|
||||
listNotes(opts: { limit: number; cursor?: string }): Promise<Note[]>;
|
||||
updateAiFields(
|
||||
noteId: string,
|
||||
fields: { title?: string; summary?: string; tags?: string[] }
|
||||
): Promise<void>;
|
||||
deleteNote(noteId: string): Promise<void>;
|
||||
setIntent(noteId: string, text: string): Promise<void>;
|
||||
dismissIntent(noteId: string): Promise<void>;
|
||||
getContinuity(): Promise<WeeklyContinuity>;
|
||||
getPendingCount(): Promise<number>;
|
||||
getOllamaStatus(): Promise<{ ok: boolean; reason?: string }>;
|
||||
onNoteUpdated(cb: (note: Note) => void): () => void;
|
||||
}
|
||||
|
||||
export interface InklingApi {
|
||||
capture: CaptureApi;
|
||||
inbox: InboxApi;
|
||||
}
|
||||
|
||||
export {};
|
||||
|
||||
Reference in New Issue
Block a user