From 084e080a55dfaa60ae72779f69bd120e5362f55c Mon Sep 17 00:00:00 2001 From: meidlinger Date: Mon, 7 Sep 2026 15:25:51 +0800 Subject: [PATCH] =?UTF-8?q?Update=20plugin=20=E9=9A=90=E9=98=85=E7=9B=92?= =?UTF-8?q?=20v1.4.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - feat: 初始化ZTools插件项目 - feat: 实现隐阅盒阅读器插件 - chore(gitignore): add ignore rules - chore: 相关标识重命名 - chore: add changelog - fix: 修复书架导入书籍异常未捕获、完善本地存储数据兼容逻辑 - docs: 更新README - docs: 重写README - feat: 发布1.1.0版本,新增多项功能并修复多个bug - fix(窗口拖动): 修复阅读窗口拖动拉伸卡顿问题 - chore: bump plugin version to 1.1.1 - chore: 重命名部分称呼 - feat(setting): add plain cover option, remove epub cache storage - feat: 新增MOBI电子书格式支持 - feat: 迁移封面和章节缓存到ztools.db - feat: 新增主题模式切换功能,优化深色主题样式 - chore: release v1.3.0, update plugin info and changelog - style: 优化窗口进度显示 - chore: 发布v1.3.1版本,更新功能与修复问题 - chore: bump plugin version to 1.3.1 - fix: 修复多个已知问题并优化部分功能 - style(settings): 优化设置项的封面提示文案 - fix(bookshelf): 修复纯色封面关闭后MOBI封面未恢复的问题 - docs: 更新README中的截图 - feat(bookshelf): 实现拖拽导入书籍功能 - feat(bookshelf): 增加快捷导入命令 - chore: update gitignore and changelog - feat(tips): 增加提示文本 ,更新版本标识 - feat: 新增多选批量操作、重载元数据和恢复封面功能 - style(plugin.json): 调整插件命令列表的排序顺序 - feat: 新增书籍信息弹窗与阅读数据追踪,优化元数据解析 - refactor: 完成bug修复 ### 详细变更 1. 修复MOBI封面解析:将Blob URL替换为可持久化的Base64格式,解决IndexedDB缓存失效问题 2. 优化书籍导入查重逻辑:通过文件名匹配避免重复导入同书籍 3. 重构阅读时长与速度统计:新增会话计时器避免跨会话闲置时间被计入,修复首页阅读时间丢失问题 4. 完善元数据加载容错:文件读取失败时不再静默清空原有元数据,抛出明确错误提示 5. 优化书籍信息编辑交互:新增分类批量添加、快捷键触发功能,修复分类选择UI缺陷 - docs: update README - release: bump version to 1.3.2 and update docs - feat: 发布v1.3.3版本,新增多项功能与优化 - release: bump version to 1.3.3 - refactor(settings): 分离配置和书籍的导入导出,修复配置导入问题 - fix: 修复多项问题并调整阅读定时器通知逻辑 - fix(Settings): 为新书籍数组添加类型声明,修复build错误 - feat: 发布v1.4.0版本,新增书签、已读标记等功能 - feat(bookshelf): 新增全文搜索跳转和批量设置分类功能 - feat(bookshelf): 新增视图切换按钮,增加书记格式标识,优化已读完标识的显示逻辑 - fix: 修复多个bug,重构搜索逻辑优化性能,修复XSS安全隐患、封面残留和多选布局重叠等问题,完善窗口销毁逻辑和书架统计规则 - feat: 新增 hushreader-close feature - fix: 优化隐阅窗口拖拽和拉伸逻辑,减少粘滞感 --- plugins/hushreader/CHANGELOG.md | 6 ++++ plugins/hushreader/package.json | 2 +- plugins/hushreader/public/hushreader.html | 10 ++++++ plugins/hushreader/public/plugin.json | 2 +- plugins/hushreader/src/App.vue | 40 +++++++++++++++++++---- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/plugins/hushreader/CHANGELOG.md b/plugins/hushreader/CHANGELOG.md index bf2be3752..56797d583 100644 --- a/plugins/hushreader/CHANGELOG.md +++ b/plugins/hushreader/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## [1.4.2] - 2026-09-07 + +### Fixed +- **优化隐阅窗口拖拽和拉伸逻辑%**:优化隐阅窗口拖拽和拉伸逻辑,减少粘滞感 + + ## [1.4.1](https://github.com/me1dlinger/hushreader/releases/tag/v1.4.1) - 2026-09-01 ### Added diff --git a/plugins/hushreader/package.json b/plugins/hushreader/package.json index 868302bca..6288ba550 100644 --- a/plugins/hushreader/package.json +++ b/plugins/hushreader/package.json @@ -1,7 +1,7 @@ { "name": "hushreader", "private": true, - "version": "1.4.1", + "version": "1.4.2", "type": "module", "scripts": { "dev": "vite", diff --git a/plugins/hushreader/public/hushreader.html b/plugins/hushreader/public/hushreader.html index b6e48a0da..78df9b46c 100644 --- a/plugins/hushreader/public/hushreader.html +++ b/plugins/hushreader/public/hushreader.html @@ -500,6 +500,8 @@ let pendingMove = null let currentResizeSize = null let currentMovePosition = null + let lastResizeSent = null + let lastMoveSent = null let resizeFrame = 0 let moveFrame = 0 let isAutoHidden = false @@ -757,6 +759,9 @@ const nextSize = pendingResize pendingResize = null + // 位置没变化则跳过,避免无谓的 IPC 往返 + if (lastResizeSent && nextSize.width === lastResizeSent.width && nextSize.height === lastResizeSent.height) return + lastResizeSent = nextSize sendCommand({ type: "resize-preview", width: nextSize.width, @@ -775,6 +780,7 @@ normalizeResizeSize(resizeState?.startWidth || window.innerWidth, resizeState?.startHeight || window.innerHeight) pendingResize = null currentResizeSize = null + lastResizeSent = null sendCommand({ type: "resize", width: nextSize.width, @@ -799,6 +805,9 @@ const nextPosition = pendingMove pendingMove = null + // 位置没变化则跳过,避免无谓的 IPC 往返 + if (lastMoveSent && nextPosition.x === lastMoveSent.x && nextPosition.y === lastMoveSent.y) return + lastMoveSent = nextPosition sendCommand({ type: "move-preview", x: nextPosition.x, @@ -815,6 +824,7 @@ const nextPosition = currentMovePosition || normalizeMovePosition(moveState?.startWindowX || 0, moveState?.startWindowY || 0) pendingMove = null currentMovePosition = null + lastMoveSent = null sendCommand({ type: "move", x: nextPosition.x, diff --git a/plugins/hushreader/public/plugin.json b/plugins/hushreader/public/plugin.json index 4996c2b2d..cc1a59a4a 100644 --- a/plugins/hushreader/public/plugin.json +++ b/plugins/hushreader/public/plugin.json @@ -4,7 +4,7 @@ "title": "隐阅盒", "description": "ZTools自己的摸鱼阅读,支持TXT/EPUB/MOBI格式,沉浸式阅读", "author": "meidlinger", - "version": "1.4.1", + "version": "1.4.2", "main": "index.html", "preload": "preload/services.js", "logo": "logo.png", diff --git a/plugins/hushreader/src/App.vue b/plugins/hushreader/src/App.vue index 955c5e5d6..20da22856 100644 --- a/plugins/hushreader/src/App.vue +++ b/plugins/hushreader/src/App.vue @@ -25,6 +25,8 @@ type AppBrowserWindow = { setSize?: (width: number, height: number) => void setContentSize?: (width: number, height: number) => void setContentBounds?: (bounds: HushreaderBounds) => void + setBounds?: (bounds: HushreaderBounds) => void + setResizable?: (flag: boolean) => void setPosition?: (x: number, y: number) => void setAlwaysOnTop?: (flag: boolean) => void moveTop?: () => void @@ -97,9 +99,22 @@ function clampNumber(value: number, min: number, max: number) { return Math.min(safeMax, Math.max(safeMin, Math.round(safeValue))) } -function getWorkArea() { +// 工作区(显示器可用区域)缓存:拖动/缩放预览期间不反复走 +// ztools.getPrimaryDisplay() 的 IPC,改为短 TTL 缓存,避免每帧一次跨进程查询。 +const WORK_AREA_CACHE_MS = 1000 +let cachedWorkArea: HushreaderBounds | null = null +let cachedWorkAreaAt = 0 + +function getWorkArea(): HushreaderBounds { + const now = Date.now() + if (cachedWorkArea && now - cachedWorkAreaAt < WORK_AREA_CACHE_MS) { + return cachedWorkArea + } const display = (window as any).ztools?.getPrimaryDisplay?.() - return display?.workArea ?? { x: 0, y: 0, width: window.screen.availWidth, height: window.screen.availHeight } + const area: HushreaderBounds = display?.workArea ?? { x: 0, y: 0, width: window.screen.availWidth, height: window.screen.availHeight } + cachedWorkArea = area + cachedWorkAreaAt = now + return area } function getHushreaderSizeLimits() { @@ -227,13 +242,25 @@ function getHushreaderPayload(bounds = getHushreaderWindowBounds()) { } } +// 更新隐阅窗口的位置/尺寸。 +// 关键:每帧(拖动/缩放预览)只发 1 次窗口调用,避免多方法冗余调用。 +// ztools.createBrowserWindow 返回的 Proxy 每个方法都是一次跨进程 IPC, +// 原来连调 setContentBounds / setContentSize / setSize / setPosition 四个方法(它们互相 +// 冗余,setBounds 本来就同时携带位置与尺寸),导致拖动/缩放时每帧多次 IPC 往返、严重不跟手。 +// 阅读窗每帧只发 1 条消息,主窗口只 setBounds 1 次。 +// 窗口为无边框(frame:false)+无阴影,窗口 bounds 与内容 bounds 一致,单次 setBounds 即可。 function applyHushreaderWindowBounds(bounds: HushreaderBounds, positionOnly = false) { if (!hushreaderWindow || hushreaderWindow.isDestroyed?.()) return hushreaderWindowAnchor = { x: bounds.x, y: bounds.y } - hushreaderWindow.setContentBounds?.(bounds) - hushreaderWindow.setContentSize?.(bounds.width, bounds.height) - hushreaderWindow.setSize?.(bounds.width, bounds.height) - hushreaderWindow.setPosition?.(bounds.x, bounds.y) + const rect: HushreaderBounds = { x: bounds.x, y: bounds.y, width: bounds.width, height: bounds.height } + if (hushreaderWindow.setBounds) { + hushreaderWindow.setBounds(rect) + } else if (hushreaderWindow.setContentBounds) { + hushreaderWindow.setContentBounds(rect) + } else { + hushreaderWindow.setSize?.(bounds.width, bounds.height) + hushreaderWindow.setPosition?.(bounds.x, bounds.y) + } if (!positionOnly) { hushreaderWindow.setAlwaysOnTop?.(true) hushreaderWindow.setSkipTaskbar?.(true) @@ -314,6 +341,7 @@ function ensureHushreaderWindow(options?: { skipShow?: boolean }) { focusable: true, acceptFirstMouse: true, alwaysOnTop: true, + useContentSize: true, webPreferences: { devTools: false, zoomFactor: 1,