feat: 无限画布滚轮缩放 + 项目管理入口 (0.0.26)
画布交互: - 滚轮缩放视口(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)
This commit is contained in:
49
electron/electron-env.d.ts
vendored
49
electron/electron-env.d.ts
vendored
@@ -21,6 +21,18 @@ declare namespace NodeJS {
|
||||
}
|
||||
}
|
||||
|
||||
/** 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;
|
||||
@@ -34,4 +46,41 @@ declare interface Window {
|
||||
/** 登录/登出后更新窗口标题中的版控后缀 */
|
||||
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 }>;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user