画布交互: - 滚轮缩放视口(2%~1600%),纯滚轮 10%/tick,Ctrl/Cmd+滚轮 3%/tick 精细控制 - 鼠标拖拽平移画布,Ctrl/Cmd+0 重置缩放 - 预览打开时锁定底层视口(previewActiveRef 事件穿透防护) - 预览内图片独立滚轮缩放 + 拖拽平移 + 缩放指示器 文件拖拽: - 画布缩略图/预览支持原生文件拖拽到外部应用(startDrag IPC) Bug 修复: - local-media:// 协议支持 UNC 网络路径 - passive event listener 报错:window 级原生 wheel listener 替代 React onWheel - Zustand v5 getState() 批处理旧值:改用 ref(currentZoomRef + setZoomRef)读写 主进程(electron/main.ts): - 画布窗口 before-input-event 拦截 Chromium 页面缩放 - 新增 canvas-ipc.ts(startDrag、文件扫描等 IPC handler)
87 lines
4.2 KiB
TypeScript
87 lines
4.2 KiB
TypeScript
/// <reference types="vite-plugin-electron/electron-env" />
|
||
|
||
declare namespace NodeJS {
|
||
interface ProcessEnv {
|
||
/**
|
||
* The built directory structure
|
||
*
|
||
* ```tree
|
||
* ├─┬─┬ dist
|
||
* │ │ └── index.html
|
||
* │ │
|
||
* │ ├─┬ dist-electron
|
||
* │ │ ├── main.js
|
||
* │ │ └── preload.js
|
||
* │
|
||
* ```
|
||
*/
|
||
APP_ROOT: string;
|
||
/** /dist/ or /public/ */
|
||
VITE_PUBLIC: string;
|
||
}
|
||
}
|
||
|
||
/** sharp 图片处理库(可选依赖,运行时动态加载) */
|
||
declare module 'sharp' {
|
||
interface SharpInstance {
|
||
metadata(): Promise<{ width?: number; height?: number; format?: string }>;
|
||
resize(width?: number, height?: number, options?: { fit?: string; withoutEnlargement?: boolean }): SharpInstance;
|
||
jpeg(options?: { quality?: number }): SharpInstance;
|
||
toBuffer(): Promise<Buffer>;
|
||
}
|
||
function sharp(input: string | Buffer): SharpInstance;
|
||
export = sharp;
|
||
}
|
||
|
||
// Used in Renderer process, expose in `preload.ts`
|
||
declare interface Window {
|
||
ipcRenderer: import('electron').IpcRenderer;
|
||
/** safeStorage 安全加密 API(基于 OS 原生密钥链) */
|
||
safeStorage: {
|
||
encrypt(plaintext: string): Promise<string | null>;
|
||
decrypt(encryptedBase64: string): Promise<string | null>;
|
||
};
|
||
/** 应用运行时 API */
|
||
appRuntime: {
|
||
/** 登录/登出后更新窗口标题中的版控后缀 */
|
||
setWindowEdition(edition: string | null): void;
|
||
};
|
||
/** 无限画布 API(由 preload 注入) */
|
||
canvas: {
|
||
/** 打开画布窗口 */
|
||
openWindow(projectPath?: string): void;
|
||
/** 扫描目录 */
|
||
scanDirectory(params: {
|
||
roots: string[];
|
||
extensions: string[];
|
||
recursive: boolean;
|
||
}): Promise<{ success: boolean; data: Array<{ path: string; fileName: string; ext: string; fileSize: number; modifiedAt: string }>; error?: string }>;
|
||
/** 读取 sidecar 元数据 */
|
||
readSidecar(params: { filePath: string }): Promise<{ success: boolean; data: object | null }>;
|
||
/** 写入 sidecar 元数据 */
|
||
writeSidecar(params: { filePath: string; metadata: object }): Promise<{ success: boolean; error?: string }>;
|
||
/** 生成缩略图 */
|
||
generateThumbnail(params: { filePath: string; size: number }): Promise<{
|
||
success: boolean;
|
||
data: { data: string; mimeType: string; width: number; height: number };
|
||
error?: string;
|
||
}>;
|
||
/** 扫描项目 */
|
||
scanProject(params: { projectPath: string; stage: string; assetTypeFilter: string; shotQuery: string }): Promise<{ success: boolean; data: Array<{ path: string; fileName: string; ext: string; fileSize: number; modifiedAt: string }>; error?: string }>;
|
||
/** 复制文件 */
|
||
copyFile(params: { src: string; destDir: string; fileName: string }): Promise<{ success: boolean; data: string; error?: string }>;
|
||
/** 列出目录下的子文件夹(非递归,排除隐藏) */
|
||
listSubdirs(params: { parentPath: string }): Promise<{ success: boolean; data: string[]; error?: string }>;
|
||
/** 扫描阶段文件(单个 episode/shot/stage 组合) */
|
||
scanStageFiles(params: { projectPath: string; episode: string; shot: string; stage: string }): Promise<{ success: boolean; data: Array<{ path: string; fileName: string; ext: string; fileSize: number; modifiedAt: string }>; error?: string }>;
|
||
/** 扫描资产文件(深度递归扫描 assets/ 目录) */
|
||
scanAssetFiles(params: { projectPath: string; assetTypeFilter: string }): Promise<{ success: boolean; data: Array<{ path: string; fileName: string; ext: string; fileSize: number; modifiedAt: string }>; error?: string }>;
|
||
/** 创建目录 */
|
||
createDirectory(params: { parentPath: string; dirName: string }): Promise<{ success: boolean; data: string; error?: string }>;
|
||
/** 将本地文件路径转换为 local-media:// 协议 URL */
|
||
getMediaUrl(filePath: string): string;
|
||
/** 启动原生文件拖拽(从缩略图拖放媒体文件到外部应用) */
|
||
startDrag(params: { filePath: string; fileName: string }): Promise<{ success: boolean; error?: string }>;
|
||
};
|
||
}
|