雨见浏览器PC测试版1.3.3
本阶段(1.3.2 → 1.3.3)的主线是「**翻译能力重建**」——把原先写死的云端 Google 翻译组件整体推翻,重构为一套「**引擎无关、可插拔**」的翻译架构(7 个提交、约 2500 行):主进程 `translate/` 目录下统一调度,微软 / 雨见 LLM / 自定义 LLM 三引擎随意切换,网页翻译与划词翻译共用同一引擎设置,引导脚本只管 collect / apply / revert 不随引擎变化;新增 `MutationObserver` 动态内容增量翻译、LLM 批量翻译的递归切分回退、以及一套「只翻自然语言、跳过代码 / 数字 / URL」的精细化规则,并配套新建 PHP 后端 `Translate.php` 与 `rainsee_translate.sql`。紧随其后的是两件用户可感知的大件:**Edge 风格「下载提示对话框」**(先问文件名 / 存储位置 / 下载方式再下,串接 IDM / 迅雷 / aria2 等外部下载器,注册表自动发现、命令注入安全)与 **uBlock Lite 卡顿修复**(重写 webRequest 事件分发为单监听器多路复用 + 阻塞响应合并 + 性能可观测)。此外还落地了沉浸浏览悬浮头部的「白闪」根治、`window.open` 弹窗按真实 opener 关系接管成标签、网页暗色模式注入的提前下发与多帧支持,并修掉了一批书签弹窗、历史日期分组、媒体播放器等细节问题。
## 主要更新
### 1. AI 翻译重建:可插拔引擎 + 动态内容增量翻译 + 批量回退
本阶段体量最大的改动,目标是把翻译从「绑死单一云端组件」改造为「引擎可切换、网页与划词统一、动态页面也能跟译」的通用能力:
- **引擎无关的调度层**:主进程新增 `src/main/services/translate/` 目录,`index.ts` 作为唯一调度入口暴露 `runTranslate(engine, …)` / `translateAbort`;`engine.ts` 定义 `TranslateEngine` 接口(`translateBatch`)与 `chunkTexts` 分批工具;`registry.ts` 按当前设置返回活动引擎。**网页翻译与划词翻译共用同一个 `translateEngine` 设置**(`microsoft` / `rainsee-llm` / `custom-llm`,默认 `microsoft`),换引擎即两处同时生效。
- **三引擎实现**:`microsoft.ts`(无状态单例,引导 `static/scripts/ms-translate.js` 负责文本节点收集 / 回填 / 还原,这部分**不随引擎变化**,只有 `translateBatch` 随引擎变);`rainsee-llm.ts`(雨见自研 LLM,只发身份头,密钥由网关注入);`custom-llm.ts`(按运行时可变的 `customLlmConfig` 即时构造,支持 `baseUrl / apiKey / model / apiType`)。微软与雨见为单例,自定义引擎因配置可变每次新建。
- **主进程为唯一可信源**:网页无 `ipcRenderer`,**不向任意网页暴露翻译 IPC**;主进程通过 `executeJavaScript` + 改写 `nodeValue` 注入与回填,不受页面 CSP 约束(原云端 Google 组件因远程 `<script>` 被 CSP 拦截而废弃)。
- **动态内容增量翻译**(`514e83f`):初始翻译完成后,页面交互(点按钮展开 / 弹窗 / SPA 局部刷新)新增的文本节点由引导脚本的 `MutationObserver` 累积,主进程每 1s 增量 collect → translateBatch → apply;fire-and-forget,靠 `stop()` / `signal` 退出(引擎切换 / 关翻译 / 导航 / 换页),不再「翻完一锤子、后续动态内容是原文」。
- **LLM 批量翻译 + 递归切分回退**(`14d1a2b`):LLM 引擎走 JSON-array 批量 prompt(要求输出与输入等长、同序、逐条独立翻译),整批失败时**递归二分切分**逐段重试,再退到逐条翻译,最大化吞吐的同时保证不丢句。
- **精细化翻译规则**(`bcf26b0`):后端 prompt 收紧——**不翻译**数字、日期、版本号、纯标点 / 符号、代码片段、URL、标识符(变量 / 函数名),只翻自然语言;同时要求保留 `{0}` / `%s` / `<br>` / HTML 实体等占位符原样,用页面上下文仅做歧义消解而不翻译上下文本身。
- **主帧优先执行**(`b414df3`):新增 `execInPagePreferMainFrame`,保证引导与回填脚本在顶层帧可靠执行;划词翻译 preload(`selection-translate.ts`)同步增强。
- **错误处理与端点更新**(`862e29f` / `14d1a2b`):messaging 与翻译服务的错误路径整体加固,AI 端点更新。
- **新建后端**:PHP 后端新增 `Translate.php`(538 行)与 `rainsee_translate.sql`(31 行),承载 LLM 翻译的转发、批量 prompt 组装与限流。
### 2. 下载提示对话框:Edge 风格「先问再下」+ 外部下载器串接
把「点下载链接 → 直接开始下载」升级为 Edge / Chrome 那样「**先弹窗确认文件名、存储位置、用哪种方式下载**」的完整闭环:
- **新建持久浮层 `DownloadPromptDialog`**(`src/main/dialogs/download-prompt.ts`):单个持久浮层**串行处理** `will-download` 中暂停的任务,避免并发下载互相覆盖;浮层内置文件名输入、存储位置选择、下载方式下拉,返回 `open`(打开)/ `save`(保存)/ `cancel` 三种动作。
- **`will-download` 拦截 + 占位路径**(`sessions-service.ts`):下载触发时先算出一个 `uniqueDownloadPath`(同名时自动追加 ` (1)` / ` (2)`),把它设为 `item.savePath` **阻止 Electron 自己弹另存为窗口**,再 `item.pause()` 暂停,等自定义浮层返回结果后按选择放行(浏览器下载 / 唤起外部下载器 / 取消)。
- **外部下载器注册表自动发现**(`external-downloader.ts`):内置 IDM / 迅雷 / aria2 / 自定义四类预设——IDM 按 `HKCU\Software\DownloadManager` 等 3 个注册表键自动发现可执行路径;迅雷走 `thunder://` 系统协议;aria2 需用户在设置中手动指定路径;自定义支持 `{url}` / `{path}` / `{filename}` 占位符参数模板。`getAvailableDownloaders` 在弹层前探活,只列出当前装了或配了的下载器。
- **命令注入安全**:外部下载器一律走 `execFile(path, argvArray)` **永不拼 shell 字符串**,URL / 路径作为独立 argv 元素——既避免嗅探 / 右键得到的 url(可能含攻击者可控字符)造成的命令注入,也避免「浏览器进程派生 cmd.exe」的启发式特征。
- **文件名校验 + 来源受限**:文件名走非法字符(`<>:"/\\|?*`、控制字符)、保留名(`CON` / `PRN` / `AUX` / `NUL` / `COM1-9` / `LPT1-9`)、尾点尾空等校验;`blob:` 与 `.crx` 来源**只允许浏览器下载**,不进入外部下载器列表。
- **样式与交互打磨**(`d767b28`):浮层高度、图标、按钮样式按体验反馈整体重做。
### 3. uBlock Lite 卡顿修复:webRequest 事件多路复用 + 阻塞响应合并 + 性能可观测
承接此前对扩展 webRequest 框架的治理,本阶段彻底修掉 uBlock Lite 安装后的「全站卡顿 / 偶发全拦」:
- **单监听器多路复用**(`renderer/event.ts`):此前每调一次 `addExtensionListener` 就绑一个 `ipcRenderer` 监听器,而 uBlock 会给 `onBeforeRequest` 注册**两个** listener(WAR guard + 主过滤),导致同一请求触发两次回调、且各自的 URL filter 被丢弃 → guard 对**所有 URL** 返回 `{cancel: true}` → 全站被拦。现改为**每个事件名只绑一个 ipcRenderer 监听器**(multiplex),分发时按各 listener 自带的 `{urls}` filter 决定是否调用。
- **阻塞响应合并**:对 `webRequest` 阻塞事件(`onBeforeRequest` / `onBeforeSendHeaders` / `onHeadersReceived` 等),收集所有命中 listener 的返回值后**合并**——`cancel` 胜出,只回主进程一个最终决定,既避免重复回调又避免 guard 与主过滤打架。
- **filter 透传**:`crx-add-listener` 现在把 webRequest 注册记录(`filter` + `extraInfoSpec`)一并带给主进程,主进程侧按 filter 分发;待处理事件桶做自清理(过期剔除、每桶上限 4 条),避免 `onInstalled` / `onStartup` 这类无人监听的事件长期堆积。
- **DNR 独立执行路径加固**:`declarative-net-request.ts` 配套硬化(`decideBeforeRequest` 同步决策、allow 豁免 cliqz、持久化 `crx-dnr-rules.json`、ReDoS 守卫、eTLD 多段后缀),新增 `scripts/test-dnr-index.js` 回归测试。
- **性能可观测**:renderer 侧新增 `recordEventPerf`,按事件名统计 dispatches / callbacks / totalMs / maxMs / maxCallbackMs,每 10s 经 `crx-perf-renderer` 上报,卡顿瓶颈一目了然;扩展存储补丁与会话扩展移除逻辑同步加固,`test-extension-storage-patch.js` 扩充用例。
- **配套:无接收者消息不再拖延**(`messaging.ts`,`8aa2bc0`):`runtime.sendMessage` 在没有接收者时立即返回,避免 uBlock 这类高频通信扩展被无谓延迟。
### 4. 沉浸浏览悬浮头部:消除「白闪」+ 标签分组重排 + 沉浸搜索
沉浸浏览(鼠标移到顶部唤出悬浮标签栏)在本阶段做了四轮打磨,重点是消除 Windows 上的「出现前闪白色」顽疾:
- **白闪根治**(`aa2fddd`):根因是透明 `BrowserWindow` 在扩容阶段先于渲染端首帧合成,Windows 偶尔会先合成默认白底。改为**主进程在收到渲染端 `immersive-header-ready` 信号前保持窗口隐藏**——渲染端在 `expanding` 态提交首帧后(16ms timer)发信号,主进程才 `showInactive`,从源头避免白底露出。
- **显隐与瞬时落位**(`b5db66f`):显隐逻辑整体重写,记录 `expandedHeight` 与 `backgroundColor`,确保内部标签布局**瞬时落位**,消除动画过渡导致的视觉抖动。
- **标签分组与重排一致性**(`6915df2`):沉浸头部的标签分组与重排逻辑对齐主窗口数据源,拖动过程中的视觉效果与主窗口一致。
- **沉浸搜索体验**(`5599ca6`):新增沉浸状态管理(`store` 沉浸态字段)、地址栏预览、沉浸态下的搜索弹层尺寸与交互优化(`search` 弹层 store / 样式 / `App` 组件),沉浸模式下搜索体验与正常态对齐。
### 5. window.open 弹窗接管:按真实 opener 关系收养成标签
把网页 `window.open` 弹出的窗口接管成真正的标签页,并保留脚本所需的 opener / `WindowProxy` 关系:
- **`WebContentsView` 收养已有 WebContents**(`view.ts`,`66c2b53`):`window.open` 已由 Chromium 创建了带真实 opener / `WindowProxy` 的 `WebContents`,`WebContentsView` 可直接收养它(保证脚本写入对象与标签内容区展示对象是同一个),而 `BrowserView` 无法收养已有 `WebContents`。`View` 现支持 `BrowserView | WebContentsView` 两种后端,新增 `adoptedWebContents` 构造分支与 `contentViewBacked` 标记。
- **关闭令牌 + 页面关闭守卫**(`page-close-guard.ts`):新增 `beginPageClose` / `consumePendingPageClose` / `expirePageClose`(2s 过期、`.unref`),配合 `popupCloseToken` 精确协调弹窗与标签的关闭时序,避免「关弹窗误关标签 / 关标签漏关弹窗」。
- **按 opener frame 查找目标**(`view-manager.ts`,`bf582c8`):新增 `findViewByOpener`(按 Chromium opener frame 在当前窗口内找最新 popup 标签)与 `findWindowOpenTarget`(找 Chromium 为 `window.open` 预创建、尚未注册成标签的真实目标),匹配依据是 `opener.processId + opener.routingId`,把「同一脚本连续 `window.open`」的标签归属与复用做对。
### 6. 网页暗色模式注入增强:提前下发 + 多帧支持
- **提前注入 CSS + 多帧支持**(`web-dark-mode-inject.ts`,`d7cd3b6`):浏览器实现的网页暗色模式(`webDarkMode: browser`,经 `executeJavaScript` 注入 Dark Reader 4.9.58 引擎,不受 CSP 约束)整体增强——切换到 `execInPagePreferMainFrame` 在主帧可靠执行,CSS 提前下发减少「先白后黑」的闪烁,并补上子帧(iframe)的覆盖;`view.ts` 与 `view-preload.ts` 配套调整注入时机。
## 体验与细节打磨
- **书签栏文件夹弹窗**:三处一并优化——① 鼠标移出弹窗口自动隐藏(`bookmark-overflow`,此前需点别处才关);② 单列情况下弹窗高度**自适应**(文件少时不再留大片垂直空白);③ 新建文件夹后名字刷新不及时的问题修复(`bookmark-bar` store)。
- **历史记录日期分组错乱**:修复「从上往下分别是周六、昨天、今天、昨天、周六、今天」的日期分组乱序——日期分组键的生成与排序逻辑(`storage.ts` + `history/utils`)整体校正,分组按时间单调回落。
- **媒体播放器实例管理重构**(`media-player.ts`):实例管理与会话处理、数据同步整体重构(+125 / −89),`media-player.html` 配套更新,修复多实例下的状态串扰。
- **弹窗偏好尺寸振荡锁**(`dialogs/popup.ts`,`6e476a0`):`setContentBounds` 会改变页面可用宽度,部分扩展会因此在两个 preferred size 间来回报告;检测到 `A → B → A` 振荡后**先锁定在较大尺寸 1000ms**,截断这个反馈环,避免扩展弹窗反复抖动尺寸。
- **`blurNow` 空引用崩溃**(`store/index.ts`,`508f5a3`):修复 `Cannot read properties of null (reading 'blur')` 的渲染崩溃,对失焦目标加存在性守卫。
- **无操作扩展的管理页图标**(`browser-action` / `management`,`c499f98`):无 `default_action` 的扩展此前管理页 / 工具栏拿不到图标,增强图标处理逻辑后这类扩展也能正常显示。
- **会话重载订阅规则即时生效**(`adblock.ts`,`37618ee`):订阅规则变更后会话重载逻辑收紧,规则改动立即生效,无需重启。
- **暗色模式样式一致性**(`0892095` / `de493ce`):主题处理逻辑与 `StyledApp` 阴影样式调整,增强暗色模式下的样式一致性与阴影层次。
## 主要更新
### 1. AI 翻译重建:可插拔引擎 + 动态内容增量翻译 + 批量回退
本阶段体量最大的改动,目标是把翻译从「绑死单一云端组件」改造为「引擎可切换、网页与划词统一、动态页面也能跟译」的通用能力:
- **引擎无关的调度层**:主进程新增 `src/main/services/translate/` 目录,`index.ts` 作为唯一调度入口暴露 `runTranslate(engine, …)` / `translateAbort`;`engine.ts` 定义 `TranslateEngine` 接口(`translateBatch`)与 `chunkTexts` 分批工具;`registry.ts` 按当前设置返回活动引擎。**网页翻译与划词翻译共用同一个 `translateEngine` 设置**(`microsoft` / `rainsee-llm` / `custom-llm`,默认 `microsoft`),换引擎即两处同时生效。
- **三引擎实现**:`microsoft.ts`(无状态单例,引导 `static/scripts/ms-translate.js` 负责文本节点收集 / 回填 / 还原,这部分**不随引擎变化**,只有 `translateBatch` 随引擎变);`rainsee-llm.ts`(雨见自研 LLM,只发身份头,密钥由网关注入);`custom-llm.ts`(按运行时可变的 `customLlmConfig` 即时构造,支持 `baseUrl / apiKey / model / apiType`)。微软与雨见为单例,自定义引擎因配置可变每次新建。
- **主进程为唯一可信源**:网页无 `ipcRenderer`,**不向任意网页暴露翻译 IPC**;主进程通过 `executeJavaScript` + 改写 `nodeValue` 注入与回填,不受页面 CSP 约束(原云端 Google 组件因远程 `<script>` 被 CSP 拦截而废弃)。
- **动态内容增量翻译**(`514e83f`):初始翻译完成后,页面交互(点按钮展开 / 弹窗 / SPA 局部刷新)新增的文本节点由引导脚本的 `MutationObserver` 累积,主进程每 1s 增量 collect → translateBatch → apply;fire-and-forget,靠 `stop()` / `signal` 退出(引擎切换 / 关翻译 / 导航 / 换页),不再「翻完一锤子、后续动态内容是原文」。
- **LLM 批量翻译 + 递归切分回退**(`14d1a2b`):LLM 引擎走 JSON-array 批量 prompt(要求输出与输入等长、同序、逐条独立翻译),整批失败时**递归二分切分**逐段重试,再退到逐条翻译,最大化吞吐的同时保证不丢句。
- **精细化翻译规则**(`bcf26b0`):后端 prompt 收紧——**不翻译**数字、日期、版本号、纯标点 / 符号、代码片段、URL、标识符(变量 / 函数名),只翻自然语言;同时要求保留 `{0}` / `%s` / `<br>` / HTML 实体等占位符原样,用页面上下文仅做歧义消解而不翻译上下文本身。
- **主帧优先执行**(`b414df3`):新增 `execInPagePreferMainFrame`,保证引导与回填脚本在顶层帧可靠执行;划词翻译 preload(`selection-translate.ts`)同步增强。
- **错误处理与端点更新**(`862e29f` / `14d1a2b`):messaging 与翻译服务的错误路径整体加固,AI 端点更新。
- **新建后端**:PHP 后端新增 `Translate.php`(538 行)与 `rainsee_translate.sql`(31 行),承载 LLM 翻译的转发、批量 prompt 组装与限流。
### 2. 下载提示对话框:Edge 风格「先问再下」+ 外部下载器串接
把「点下载链接 → 直接开始下载」升级为 Edge / Chrome 那样「**先弹窗确认文件名、存储位置、用哪种方式下载**」的完整闭环:
- **新建持久浮层 `DownloadPromptDialog`**(`src/main/dialogs/download-prompt.ts`):单个持久浮层**串行处理** `will-download` 中暂停的任务,避免并发下载互相覆盖;浮层内置文件名输入、存储位置选择、下载方式下拉,返回 `open`(打开)/ `save`(保存)/ `cancel` 三种动作。
- **`will-download` 拦截 + 占位路径**(`sessions-service.ts`):下载触发时先算出一个 `uniqueDownloadPath`(同名时自动追加 ` (1)` / ` (2)`),把它设为 `item.savePath` **阻止 Electron 自己弹另存为窗口**,再 `item.pause()` 暂停,等自定义浮层返回结果后按选择放行(浏览器下载 / 唤起外部下载器 / 取消)。
- **外部下载器注册表自动发现**(`external-downloader.ts`):内置 IDM / 迅雷 / aria2 / 自定义四类预设——IDM 按 `HKCU\Software\DownloadManager` 等 3 个注册表键自动发现可执行路径;迅雷走 `thunder://` 系统协议;aria2 需用户在设置中手动指定路径;自定义支持 `{url}` / `{path}` / `{filename}` 占位符参数模板。`getAvailableDownloaders` 在弹层前探活,只列出当前装了或配了的下载器。
- **命令注入安全**:外部下载器一律走 `execFile(path, argvArray)` **永不拼 shell 字符串**,URL / 路径作为独立 argv 元素——既避免嗅探 / 右键得到的 url(可能含攻击者可控字符)造成的命令注入,也避免「浏览器进程派生 cmd.exe」的启发式特征。
- **文件名校验 + 来源受限**:文件名走非法字符(`<>:"/\\|?*`、控制字符)、保留名(`CON` / `PRN` / `AUX` / `NUL` / `COM1-9` / `LPT1-9`)、尾点尾空等校验;`blob:` 与 `.crx` 来源**只允许浏览器下载**,不进入外部下载器列表。
- **样式与交互打磨**(`d767b28`):浮层高度、图标、按钮样式按体验反馈整体重做。
### 3. uBlock Lite 卡顿修复:webRequest 事件多路复用 + 阻塞响应合并 + 性能可观测
承接此前对扩展 webRequest 框架的治理,本阶段彻底修掉 uBlock Lite 安装后的「全站卡顿 / 偶发全拦」:
- **单监听器多路复用**(`renderer/event.ts`):此前每调一次 `addExtensionListener` 就绑一个 `ipcRenderer` 监听器,而 uBlock 会给 `onBeforeRequest` 注册**两个** listener(WAR guard + 主过滤),导致同一请求触发两次回调、且各自的 URL filter 被丢弃 → guard 对**所有 URL** 返回 `{cancel: true}` → 全站被拦。现改为**每个事件名只绑一个 ipcRenderer 监听器**(multiplex),分发时按各 listener 自带的 `{urls}` filter 决定是否调用。
- **阻塞响应合并**:对 `webRequest` 阻塞事件(`onBeforeRequest` / `onBeforeSendHeaders` / `onHeadersReceived` 等),收集所有命中 listener 的返回值后**合并**——`cancel` 胜出,只回主进程一个最终决定,既避免重复回调又避免 guard 与主过滤打架。
- **filter 透传**:`crx-add-listener` 现在把 webRequest 注册记录(`filter` + `extraInfoSpec`)一并带给主进程,主进程侧按 filter 分发;待处理事件桶做自清理(过期剔除、每桶上限 4 条),避免 `onInstalled` / `onStartup` 这类无人监听的事件长期堆积。
- **DNR 独立执行路径加固**:`declarative-net-request.ts` 配套硬化(`decideBeforeRequest` 同步决策、allow 豁免 cliqz、持久化 `crx-dnr-rules.json`、ReDoS 守卫、eTLD 多段后缀),新增 `scripts/test-dnr-index.js` 回归测试。
- **性能可观测**:renderer 侧新增 `recordEventPerf`,按事件名统计 dispatches / callbacks / totalMs / maxMs / maxCallbackMs,每 10s 经 `crx-perf-renderer` 上报,卡顿瓶颈一目了然;扩展存储补丁与会话扩展移除逻辑同步加固,`test-extension-storage-patch.js` 扩充用例。
- **配套:无接收者消息不再拖延**(`messaging.ts`,`8aa2bc0`):`runtime.sendMessage` 在没有接收者时立即返回,避免 uBlock 这类高频通信扩展被无谓延迟。
### 4. 沉浸浏览悬浮头部:消除「白闪」+ 标签分组重排 + 沉浸搜索
沉浸浏览(鼠标移到顶部唤出悬浮标签栏)在本阶段做了四轮打磨,重点是消除 Windows 上的「出现前闪白色」顽疾:
- **白闪根治**(`aa2fddd`):根因是透明 `BrowserWindow` 在扩容阶段先于渲染端首帧合成,Windows 偶尔会先合成默认白底。改为**主进程在收到渲染端 `immersive-header-ready` 信号前保持窗口隐藏**——渲染端在 `expanding` 态提交首帧后(16ms timer)发信号,主进程才 `showInactive`,从源头避免白底露出。
- **显隐与瞬时落位**(`b5db66f`):显隐逻辑整体重写,记录 `expandedHeight` 与 `backgroundColor`,确保内部标签布局**瞬时落位**,消除动画过渡导致的视觉抖动。
- **标签分组与重排一致性**(`6915df2`):沉浸头部的标签分组与重排逻辑对齐主窗口数据源,拖动过程中的视觉效果与主窗口一致。
- **沉浸搜索体验**(`5599ca6`):新增沉浸状态管理(`store` 沉浸态字段)、地址栏预览、沉浸态下的搜索弹层尺寸与交互优化(`search` 弹层 store / 样式 / `App` 组件),沉浸模式下搜索体验与正常态对齐。
### 5. window.open 弹窗接管:按真实 opener 关系收养成标签
把网页 `window.open` 弹出的窗口接管成真正的标签页,并保留脚本所需的 opener / `WindowProxy` 关系:
- **`WebContentsView` 收养已有 WebContents**(`view.ts`,`66c2b53`):`window.open` 已由 Chromium 创建了带真实 opener / `WindowProxy` 的 `WebContents`,`WebContentsView` 可直接收养它(保证脚本写入对象与标签内容区展示对象是同一个),而 `BrowserView` 无法收养已有 `WebContents`。`View` 现支持 `BrowserView | WebContentsView` 两种后端,新增 `adoptedWebContents` 构造分支与 `contentViewBacked` 标记。
- **关闭令牌 + 页面关闭守卫**(`page-close-guard.ts`):新增 `beginPageClose` / `consumePendingPageClose` / `expirePageClose`(2s 过期、`.unref`),配合 `popupCloseToken` 精确协调弹窗与标签的关闭时序,避免「关弹窗误关标签 / 关标签漏关弹窗」。
- **按 opener frame 查找目标**(`view-manager.ts`,`bf582c8`):新增 `findViewByOpener`(按 Chromium opener frame 在当前窗口内找最新 popup 标签)与 `findWindowOpenTarget`(找 Chromium 为 `window.open` 预创建、尚未注册成标签的真实目标),匹配依据是 `opener.processId + opener.routingId`,把「同一脚本连续 `window.open`」的标签归属与复用做对。
### 6. 网页暗色模式注入增强:提前下发 + 多帧支持
- **提前注入 CSS + 多帧支持**(`web-dark-mode-inject.ts`,`d7cd3b6`):浏览器实现的网页暗色模式(`webDarkMode: browser`,经 `executeJavaScript` 注入 Dark Reader 4.9.58 引擎,不受 CSP 约束)整体增强——切换到 `execInPagePreferMainFrame` 在主帧可靠执行,CSS 提前下发减少「先白后黑」的闪烁,并补上子帧(iframe)的覆盖;`view.ts` 与 `view-preload.ts` 配套调整注入时机。
## 体验与细节打磨
- **书签栏文件夹弹窗**:三处一并优化——① 鼠标移出弹窗口自动隐藏(`bookmark-overflow`,此前需点别处才关);② 单列情况下弹窗高度**自适应**(文件少时不再留大片垂直空白);③ 新建文件夹后名字刷新不及时的问题修复(`bookmark-bar` store)。
- **历史记录日期分组错乱**:修复「从上往下分别是周六、昨天、今天、昨天、周六、今天」的日期分组乱序——日期分组键的生成与排序逻辑(`storage.ts` + `history/utils`)整体校正,分组按时间单调回落。
- **媒体播放器实例管理重构**(`media-player.ts`):实例管理与会话处理、数据同步整体重构(+125 / −89),`media-player.html` 配套更新,修复多实例下的状态串扰。
- **弹窗偏好尺寸振荡锁**(`dialogs/popup.ts`,`6e476a0`):`setContentBounds` 会改变页面可用宽度,部分扩展会因此在两个 preferred size 间来回报告;检测到 `A → B → A` 振荡后**先锁定在较大尺寸 1000ms**,截断这个反馈环,避免扩展弹窗反复抖动尺寸。
- **`blurNow` 空引用崩溃**(`store/index.ts`,`508f5a3`):修复 `Cannot read properties of null (reading 'blur')` 的渲染崩溃,对失焦目标加存在性守卫。
- **无操作扩展的管理页图标**(`browser-action` / `management`,`c499f98`):无 `default_action` 的扩展此前管理页 / 工具栏拿不到图标,增强图标处理逻辑后这类扩展也能正常显示。
- **会话重载订阅规则即时生效**(`adblock.ts`,`37618ee`):订阅规则变更后会话重载逻辑收紧,规则改动立即生效,无需重启。
- **暗色模式样式一致性**(`0892095` / `de493ce`):主题处理逻辑与 `StyledApp` 阴影样式调整,增强暗色模式下的样式一致性与阴影层次。
· 0 个赞