168 Commits

Author SHA1 Message Date
user.email 6a7c117ebc docs(agent-knowledge): 沉淀 PR #42 架构知识库,作为仓库规范
按 6 大主题记录代码架构与背景信息,供后续 agent 修改功能时快速建立上下文:
- architecture: 运行上下文/脚本加载顺序/模块职责/存储键/消息流
- chrome-tab-groups / session-restore / drag-batch / popup: 各子系统细节
- audit-hardening: 加固模式与已知 P2 边界
- pr42-change-map: 29 提交归因 + 关键决策记录
2026-08-20 23:45:15 +08:00
OO 9504d6f4ae Merge pull request #42 from Leexunhuan743/main
feat: 快捷链接/搜索引擎/popup 增强 + 审计修复批次
2026-08-20 23:31:38 +08:00
Leexunhuan743 90c57ccdd5 fix(sessions): sleep restored tabs after navigation commits; protect restore batches from blank-tab dedup
Discarding a freshly-created tab while its navigation is still pending
cancels the navigation and resets the tab to about:blank in Edge — the
recorded URL is lost and activating the tab later reloads a blank page.
discardRestoredTabAfterCommit polls tabs.get until the url is committed
(early in the load, page never fully rendered) and only then discards,
with a 15s timeout degrading to a normally-loading tab.

background's duplicate-blank-tab cleanup now exempts freshly-created
tabs for a 5s grace period (a restore batch's tabs have empty urls until
their navigation commits, which previously looked like a pile of blank
new-tab pages and got closed — the cause of 'No tab with id' during
group restore) and always exempts discarded tabs.

Tests: grace-period exemption probe, discard-after-commit probes for both
restore modes (background +2, restore probes updated).
2026-08-17 08:18:17 +08:00
Leexunhuan743 b88577def9 feat(sessions): restored tabs start asleep; suppress restore refresh echo
Background tabs created during session restore are discarded right after
creation so a large session does not load every page at once (the first
active tab stays loaded; Chrome reloads a discarded tab on activation and
natively refuses to discard an active tab, so no active-guard IPC is
needed). The restore runs under the refresh-suppression window so the
tabs.create/discard event echo does not cause a redundant post-restore
refresh (the explicit renderDashboard call is unaffected).

Adds behavioral probes asserting both restore modes discard every
background tab, keep the first active tab loaded, and leave the restored
id list intact (removing either discard call turns them red).
2026-08-17 07:45:02 +08:00
Leexunhuan743 1f50d7a6c4 refactor(dashboard): let tabGroups.query filter by window
queryUserChromeGroups, collapseChromeTabGroupsInWindow and
syncChromeTabGroupExpansionForTab pulled every window's groups and
filtered in JS; pass the windowId to tabGroups.query instead. The full
sync path (syncChromeTabGroups) intentionally keeps the unfiltered query
— it manages mirrors across every window in desired and cleans stale
mappings in other windows. Tests stub tabGroups.query with real
windowId-filtering semantics via a shared helper.
2026-08-16 17:53:38 +08:00
Leexunhuan743 be61745ce0 fix(sessions): pin restored chrome groups to the target window
chrome.tabs.group creates a NEW group in the CALLER's window by default,
so a new-window session restore dragged the chrome-group tabs out of the
fresh window into the dashboard window (observed: the session split across
two windows, chrome-group tabs flashing into the dashboard window). Pass
createProperties.windowId so the group is created directly in the restore
target window — tabs never move, no flash. The same-title conflict check
now lets tabGroups.query filter by the target window instead of pulling
every window's groups. Adds regression assertions for the pinned-window
creation path.
2026-08-16 17:53:32 +08:00
Leexunhuan743 6f6dc89dcd style(dashboard): enlarge workspace page switch target
Bump the workspace page-switch button to 14px/28px min-height for a
more comfortable hit target and scanable top nav.
2026-08-16 13:58:02 +08:00
Leexunhuan743 96f1a2a46c fix(dashboard): audit hardening — config export completeness, card re-entrancy, toggle cleanup safety
- config-sync: serialize unset storage keys as explicit null under real
  chrome.storage.get(keys[]) semantics (unset keys resolve as undefined,
  so the old 'key in data' check silently dropped 15 keys from exports);
  reset the import file input after a successful import
- applyChromeTabGroupsToggle(off): clear stale imported-group metadata
  without deleting the session groups it once pointed to (they are now
  ordinary manual groups — deletion was an upgrade-residue data-loss path)
- card-level actions (close/sleep/merge/dedup per domain or section
  header) get a shared cardActionInFlight re-entrancy guard, matching the
  batch bar's batchActionInFlight; merge also clears the lingering handle
  selection like the batch path does
- discard-tab: stale (ghost) branch prunes dangling assignments up front
  like the success branch; success branch restores back-to-top visibility
- popup: loadPopupView writes the resolved view back to the localStorage
  first-frame mirror so config imports can no longer leave the two stores
  permanently diverged (stale first frame on every open)
- tests: real-semantics exportConfig discriminant case, hardened
  toggleGuardHit no-keydown-bypass regex, stale-branch shape sync
2026-08-16 13:57:48 +08:00
Leexunhuan743 9bf418aea7 fix(sessions): persist chrome group colors and restore every same-URL member
normalizeSessionTab/normalizeSessionGroup/buildSessionGroupsFromTabs and
the savedTab snapshot now carry chromeGroupColor through the whole
save->storage->reload->restore round-trip (previously stripped by the
double normalize, so restored native groups always fell back to grey).
createRestoredSessionGroups consumes every restored tab matching a
recorded url instead of one, so duplicate-URL group members no longer
drift out of the restored Chrome group. Adds round-trip, rebuild-color
and same-URL coverage tests with real normalize paths.
2026-08-16 13:57:41 +08:00
Leexunhuan743 0b145f587e fix(dashboard): audit conditions — selection retention, dead-code removal, sleep failure UX, group-name color
Follow-up fixes from the helpers-unify audit plus user-confirmed UX decisions.

Product:
- Batch sleep/dedup keep the ORIGINAL selection on chips that could not be
  resolved to a numeric tab id (they were not part of the operation), so a
  batch action never silently deselects untouched rows.
- closeTabOutDupes now closes through closeTabsSafely: the shared
  window-last-tab protection applies, so closing duplicate Tab Harbor pages
  never closes a window whose only tab would be removed.
- Removed three dead delegating wrappers (closeTabsByUrls/closeTabsExact/
  closeDuplicateTabs) that no longer had callers.
- Sleep failure UX: the per-chip sleep button is hidden on already-discarded
  rows (!tab.discarded), and group/global sleep filter out discarded tabs —
  an all-slept group is a silent no-op instead of a misleading
  'Failed to sleep' toast. Real discard failures still surface.
- Chrome-group card names use the PURE native group color again so they
  visually match the group chip in the browser tab strip (accepted contrast
  tradeoff on light palettes); hover/focus feedback is now an underline so
  keyboard focus stays visible without relying on color contrast.

Tests (406 -> 409):
- Behavioral tests for closeTabsByUrlsSafely (exact/file:// exact/hostname
  exact, unparseable skipped), closeDuplicatesByUrls (keepOne keeps the
  active copy) and the REAL ensureWindowsKeepLastTab implementation (was
  only mocked before).
- Hardened the shouldImportChromeGroupsIntoSessionState assertion (unconditional
  false anchored with doesNotMatch return true) and the sleepAllTabsButton
  i18n pair; updated the chip-discard button and color assertions.
2026-08-16 12:59:15 +08:00
Leexunhuan743 afed14218e fix(dashboard): audit hardening — failure-safe Chrome groups, scoped card actions, batch re-entrancy
Audit-fix round (C1-C23) plus follow-up fixes and comment polish.

Product:
- Native Chrome group writes are the source of truth: drag into/out of
  Chrome groups aborts with a toast on API failure instead of silently
  clearing session state (C1); stale-id retries via
  groupTabsWithStaleRetry(IntoGroup)/ungroupTabsWithStaleRetry return the
  actual merged ids so counts/cleanup never use the pre-retry list (C2/C5).
- Batch merge now merges tabs already inside Chrome groups (pinned stays
  outside); count-based group titles resolve from the ACTUAL merged ids.
- Batch handlers are re-entrancy safe: batchActionInFlight guard + finally
  resets the refresh-suppression window on every path (C22).
- Chrome-group card close/dedup are scoped to the card's own tabs; URL-wide
  matching never touches tabs outside the group (C12). Placeholder rows
  (lagging snapshot) render no save/close controls and never count as
  duplicates (C13).
- Unmanaged native-group tabs are never pulled into dashboard mirrors:
  buildDomainGroups snapshot fallback is gated on queryUserChromeGroups
  failing or partially failing (C7), partial failures keep their diagnostic
  without misreporting a global toast (C6).
- Ambiguous title+color fingerprints no longer churn mirrors on reload:
  the in-session mapping is kept when still among the candidates, new
  mirrors pick a non-colliding color (C4), including legacy flat meta keys.
- Disabling the Chrome-group toggle tears down managed mirrors (C16);
  the retired import pipeline short-circuits before any fetch work (C17);
  Chrome-group card row order is never persisted into the durable order (C18).
- closeTabsSafely/sleepTabsByIds run in parallel (Promise.allSettled/all)
  with the same window-last-tab protection.
- Chrome-group card names use a 35% ink mix (AA >= 4.5:1 on light palettes)
  with a 55% hover/focus step so keyboard focus stays visible.

Tests (386 -> 406):
- Behavioral tests for all three stale-retry helpers, the C15 superset
  filter, and the C4 keeper/collision-avoidance paths; discriminating
  assertions for C12/C13/C16/C17/C22 and the dedup suppression ordering;
  the C6 partial-failure diagnostic; split the dedup alternation regex into
  two discriminating assertions; storage mock gained remove() so
  resetChromeGroupState clears persisted meta between tests.

Comments:
- Full-branch comment review (3 read-only reviewers, ~1200 lines): fixed
  26 stale/misleading comments across all six files and removed an inert
  column-span rule; no audit-internal jargon remains.
2026-08-16 10:37:03 +08:00
Leexunhuan743 54444c41d0 fix(dashboard): apply audit fixes for tab actions and Chrome groups
Batch 1 (Chrome groups/platform):
- tabGroups.onUpdated single-arg contract; C14 onAttached live cleanup
- full drop-order reorder for Chrome group joins; mute group-card merge
- remove dead reorderWindowTabsByDesiredOrder; legacy meta ambiguity guard
- surface Chrome group query failures via toast + getter

Batch 2 (batch/drag/UX):
- mergeTabsIntoChromeGroup returns {groupId, updated}; compensate cleanup failures
- commit-in-flight guard for Escape; saveGroupOrder/loadGroupOrder filter chrome keys
- Chrome cards follow native strip order; placeholder rows read-only
- merge empty/skipped feedback; handle hover/focus via --chrome-group-color

Batch 3 (tests/docs):
- real friendlyDomain behavior test; merge/sleep/close behavior tests
- six sync discrimination tests; contrast mix 35/65; lat.md wording

Tests: 385/385; lat check passes.
2026-08-16 00:13:27 +08:00
Leexunhuan743 1e9fa57c4c refactor(dashboard): unify session-picker entry points 2026-08-15 23:46:07 +08:00
Leexunhuan743 3c6fd41778 test: align regression assertions with unified tab action helpers 2026-08-15 23:44:45 +08:00
Leexunhuan743 7136171788 refactor(dashboard): restore unified tab action helpers from backup checkpoint 2026-08-15 23:38:36 +08:00
Leexunhuan743 c886d58c4f refactor(dashboard): unify tab action helpers for close/merge/sleep/dedup 2026-08-15 23:36:48 +08:00
Leexunhuan743 8ea648e9f7 fix(dashboard+popup): 拖拽/多选交互收尾、区块头部全局动作、审计修复与样式调整
交互(dashboard-runtime.js + tests):
- 整行即拖拽面:不再必须瞄准 30px 把手,按行体任意位置都能起拖(originatedFromHandle 区分手势来源)
- 多选激活时点击标签行切换选中而非跳转(focus-tab 变 toggle);toggleGuardHit 守卫防重复切换,
  守卫不再带 keydown 豁免(行体不可键盘聚焦,避免窄窗口双切换/误跳转)
- 拖拽完成同步抑制跟随 click(松手不误跳);非切换 pointerup 清除守卫(取消选择后可立即重选/跳转)

区块头部与卡片(dashboard + ui-helpers + i18n):
- 卡片头部动作图标化(action-btn → group-action-icon),关闭重复/组合标签组并入 mission-actions,移除底部 actions 行
- 区块头部新增:全局关闭重复(getRealTabs 口径,排除内部页/自身页面)与「合并全部为一个 Chrome 标签组」
  (data-scope=all,排除 pinned,标题带真实数量 mergeAllGroupTitle)
- chrome.tabs.group 失败时过滤存活 id 重试一次(groupTabsWithStaleRetry)
- 区块头部容器自适应宽度 + gap 8px + flex-shrink:0,5 个图标不再被压缩

审计修复(dashboard + tests):
- 批量休眠改用 live chrome.tabs.get 预检,幽灵 id 正确计入 stale(toast「标签页已关闭」而非「休眠失败」)
- 单标签关闭 removeOpenTabByIdOrUrl 容错(stale id 不再产生未处理 rejection)
- closeDuplicateTabs 套 ensureWindowsKeepLastTab,去重永不关窗口最后一页
- 删除死 CSS .actions;契约测试钉住重渲染后批量栏重同步
- 扩展重载/更新后上下文失效自动恢复(isExtensionContextInvalidated + 单次重载 + unhandledrejection 兜底)

样式(style.css + popup.css):
- popup 关闭按钮 22→34×34、图标 13→19px
- 导航按钮 hover 上浮不再被容器裁切(两处导航容器 2px 顶部余量)
- popup 分组导航下边距修正:覆盖共享 .group-nav 的 14px margin(margin:0),下边距 2px
- fadeUp 12→8px、tab-rise 5→3px(入场动画位移低于元素间距,不再压住下方元素)

测试:352 项全部通过;lat check 通过。
2026-08-15 18:50:57 +08:00
Leexunhuan743 40e54873f6 fix(dashboard): 休眠幽灵 chip 不再破坏分组——监听 tabs.onReplaced + 休眠前校验标签存活
- 根因:标签被替换/关闭(OAuth/重定向流程)后仪表盘未刷新,chip 残留死 tab id;对其休眠是静默 no-op,重渲染时悬空的手动分组 assignment 被剪除导致分组解散
- background 新增 tabs.onReplaced 广播,替换标签后页面立即刷新
- per-chip 休眠前 chrome.tabs.get 校验:id 不存在则重渲染清幽灵行 + 剪悬空 assignment + toast「标签页已关闭」
- 批量休眠将幽灵 id 计为 stale 跳过,不再冒充已休眠
- i18n 新增 toastTabAlreadyClosed(中/英);测试 337 通过
2026-08-15 14:37:54 +08:00
Leexunhuan743 22871f15b2 fix(dashboard): 拖拽系统收尾——溢出展开持久化、死区取消、键盘焦点、批量栏标题内嵌
- 溢出标签行:全部行共用渲染器;折叠行作为列表直接子节点;展开状态会话内持久,拖拽/刷新不再关闭展开;底部落点保持在可见区,不落入折叠区
- 拖拽修复:占位符缺失回退全量重渲染;空白处释放取消拖拽(不再隐藏行);范围选择只遍历可见行
- 键盘等价物收尾:移除 Space keydown preventDefault(交还原生按钮激活,修复 Space 切换失效);键盘展开后焦点移交首个展开行
- 批量栏改为内嵌 section 标题(标题即选中计数,替换原图标动作)
- 测试:行为测试真执行顺序构建函数;契约断言覆盖上述修复(334 通过)
2026-08-15 00:02:18 +08:00
Leexunhuan743 b37935dffb fix(dashboard): 批量拖拽审计修复与功能完善(键盘/批量操作/顺序语义/测试)
修复(审计确认):
- 同组重排改用拖拽开始时快照,消除与跨组/新建组路径的不一致
- Escape 拖拽中先取消拖拽再清空选择;手柄 Space 防页面滚动
- 跨组批量落地前移除目标卡已有行,整批连续无重复;overflow 行不再使插入索引错位
- 同组/跨组批量统一按视觉 DOM 顺序(orderChipIdsByDom)
- ×N 徽标按落点上下文计数;快速甩动落点随释放位置;拖回原点不误判为切换
- 选择集渲染时裁剪已关闭标签;拖拽防重入守卫;手柄 aria-pressed/aria-label 更新
- 跨组/新建组提交后清空选择

完善:
- 键盘等价物:手柄 Enter/Space 切换选择、Shift 范围选择
- 批量操作:选中时 open-tabs 头部就地变为「已选 N 行 关闭所选 休眠所选
  保存会话 取消选择」,批量关闭/休眠/保存会话(i18n 中英)
- 批量关闭复用 ensureWindowsKeepLastTab 保活;休眠区分失败/活动页提示

测试:
- 新增 batch-drag.test.js:直接执行真实顺序构建函数的行为测试 +
  流程级契约断言(21 项);ui-regression 断言同步更新(324 pass)
2026-08-14 23:03:45 +08:00
Leexunhuan743 40378a8794 feat(dashboard): 标签行手柄多选 + 批量拖动(同组重排/跨卡片移动),拖拽系统打磨
- 手柄单击切换多选(高亮),点击卡片外或 Escape 清除选择
- 拖动选中行:同组批量重排(保持相对顺序并落盘);拖到其他卡片/下方新建组
  时整组移动(支持跨卡片选择,按每个选中行所属卡片分别收集)
- 修复:批量跨组移动只刷新拖动行所在卡片,其他源卡片残留被移走的行
  (changedGroupKeys 现包含全部受影响源组)
- 修复:拖拽门控收窄后行体按下会选中文本(pointerdown preventDefault)
- 修复:拖拽中读取实时选择集存在竞态(改用拖拽开始时的快照)
- 反馈:拖动时显示 ×N 数量徽标、其余选中行变暗、手柄 touch-action:none
- 手柄抓取区 30×36;回归断言同步更新(303 pass)
2026-08-14 19:45:27 +08:00
Leexunhuan743 0840756813 fix(dashboard+i18n): 关闭分组/关闭全部即时反馈,不再关闭浏览器窗口
- close-domain-tabs 点击立即退场卡片(animateCardOut 前置),标签后台关闭
  后 renderDashboard 同步导航与其余卡片
- closeTabsByUrls/closeTabsExact 增加 ensureWindowsKeepLastTab 守卫:任何
  窗口绝不关闭最后一个标签,窗口与浏览器不会因关闭标签而退出
- zh 搜索占位符 '用{engine}搜索...' → '用 {engine} 搜索...'
- 回归断言同步更新(303 pass)
2026-08-14 18:38:19 +08:00
Leexunhuan743 4bbf6a7690 fix(popup): 降低 popup 最大高度至 520px,消除内容区溢出滚动条
- html/body 与 .popup-app 的 max-height 由 600px 降至 520px,文档不再超出
  实际窗口内容区(约 561px),视口级滚动条不再出现
- ui-regression 断言同步更新(303 pass)
2026-08-14 18:22:04 +08:00
Leexunhuan743 6f460ba11c fix(popup): 入场动画仅视图切换播放,首帧即正确视图,隐藏全部滚动条
- 动画绑定 .is-entering.is-ready(syncPopupView 独占 is-entering,渲染器不触碰;
  同视图刷新清除),内容刷新不再重播 opacity 0 淡入
- .is-entering 不再隐藏容器本身,滞留期间不再致面板空白
- 打开标签页视图时首帧即正确面板:localStorage 同步解析视图 + 模块加载时
  先于首帧 syncPopupView(chrome.storage 仅作导入/导出对账),消除
  快捷方式面板闪现
- 列表与快捷网格滚动条完全隐藏(scrollbar-width:none + webkit display:none,
  与导航一致),瞬时溢出不再闪现滚动条
- 测试与回归断言同步更新(303 pass)
2026-08-14 18:05:36 +08:00
Leexunhuan743 fcce2bc8ec feat(dashboard): 卡片支持合并为 Chrome 标签组;关闭重复后立即重渲染
- 域名卡片新增「合并为 Chrome 标签组」按钮(tabs.group + tabGroups.update
  命名着色,合并卡片全部标签),i18n 双语
- dedup-keep-one 补 renderDashboard,关闭重复标签后芯片立即更新
- 收窄跨窗口 catch(windows.update 降为 best-effort),收紧 suspended
  保留条件(需 originalUrl 非空)
2026-08-14 16:57:24 +08:00
Leexunhuan743 515a002892 fix(popup): 修复审计确认的交互回归与对齐缺口,完善健壮性
- 修复 tabs 面板后台刷新闪烁:入场动画仅视图切换时重播(renderer 不再加
  is-entering,syncPopupView viewChanged 分支控制);popup 窗口高度适配内容
  (min-height:0,不再恒 600px)
- 导航滚轮劫持加溢出守卫:无横向溢出时滚轮直通,消除 dashboard 导航条死区
- 移除 popup 重复图片 fallback 监听器(ui-helpers 统一消费,修复跳级/提前
  字母 chip);删除 tabGroups 死字段
- 跨窗口标签点击改为激活原窗口标签(tabs.update+windows.update)不再复制;
  双击关闭按钮穿透防护
- suspended 标签解包对齐主页面(popup 加载 tab-url-utils);会话组按 createdAt
  排序对齐主页面
- 关闭标签走 refreshPopupSafely 安全管线;搜索导航失败回退默认搜索(仅无效
  URL 弹 toast);popupView 纳入配置导出/导入
- README 限定"新标签页上的快捷链接"打开方式范围;补强单测与回归断言
2026-08-14 16:22:41 +08:00
Leexunhuan743 0559567b1f fix(popup): 修复打开的标签页面板与刷新逻辑,对齐主页面行为
- 修复面板空白回归:is-entering(opacity:0) 在内容变更后滞留容器,现于入场动画应用时移除
- 后台刷新不再重渲染/重播快捷方式动画(签名守卫 + viewChanged 守卫),刷新失败保留旧快照、不再产生未处理拒绝
- 快捷方式网格跟随「快捷链接每行」设置(自动/4/5 列),popup 窗口宽度固定 400px、不再随视图切换跳动
- 打开的标签页对齐主页面:重复 URL 标签全显(移除组内去重)、按主域归一分组(www 变体合并)、合并列表单次应用组顺序、显示重命名分组标签(groupLabelOverrides)、自定义分组显示自定义标签
- 空/不可解析 URL 标签进入「未分组」桶而非静默丢弃
- 修正 Gmail 落地页规则:裸 #inbox/#sent 视为内容页(popup 与主页面一致)
- 移除无效的 chrome.tabGroups.query 死读取;刷新按钮走安全管线;补强测试与修复测试 mock
2026-08-14 14:56:43 +08:00
Leexunhuan743 586537d6ae feat(popup+shortcuts): 记忆 popup 视图、统一滚动条;快捷链接支持 Ctrl/Shift 修饰键;导航横向滚动 2026-08-14 13:21:43 +08:00
Leexunhuan743 2b00eb40f9 feat(search): 搜索框支持自定义搜索引擎(预设/自定义 URL)与占位符同步 2026-08-14 12:34:32 +08:00
Leexunhuan743 84a584a06b feat(shortcuts): 新增快捷链接每行数量设置(自动/4 列/5 列),固定列数形成肌肉记忆 2026-08-14 11:22:19 +08:00
Leexunhuan743 bef0641af0 feat(shortcuts): 快捷链接支持在当前标签页打开,桌面设置→功能可切换 2026-08-14 10:27:31 +08:00
Han Zheng 979a14ea85 docs(release): 准备 1.1.2 发布说明 v1.1.2 2026-07-23 18:41:05 +08:00
Han Zheng ffbf9ec295 fix(shortcuts): 统一快捷链接新开标签页 2026-07-23 17:57:18 +08:00
OO 993f0fa4f3 feat(config): 合并完整配置备份功能
本次合并内容:\n\n- 完整导出主题、快捷方式、已保存标签页、语言、待办、分组、排序及相关持久化状态。\n- 保留快捷方式自定义图标,导入 null 值时清理旧状态。\n- 增加配置版本校验,拒绝未知未来版本。\n- 导入成功后重载页面,保证内存状态同步。\n- 同步 manifest 版本并修复 CSS 回归断言。\n\n验证:node --test extension/*.test.js,285/285 通过。
2026-07-23 17:31:56 +08:00
Han Zheng 386ef79330 feat(config): 完善配置备份与导入校验 2026-07-23 17:30:01 +08:00
OO 30cbccf98c Merge pull request #40 from KanoCifer/fix/tab-change-notify-runtime-channel
fix: 修复 dashboard 自动刷新失效
2026-07-22 18:08:15 +08:00
Han Zheng e78f92a9f3 fix(manifest): 同步扩展版本号 2026-07-22 18:07:22 +08:00
Kuroome 58e0ef144d style:微调开关按钮样式 2026-07-13 18:13:50 +08:00
Kuroome 7cc1c9362b feat(extension): 在设置面板添加导出/导入按钮与事件处理
在 Features 标签页新增 Export & import 区域,调用 config-sync
模块实现配置文件的下载与恢复。导入后自动刷新主题、快捷方式
及已保存标签页,无需重启页面。
2026-07-13 17:57:04 +08:00
Kuroome c152b43964 feat(extension): 添加 config-sync 模块,支持配置导出导入
新增 config-sync.js,将 themePreferences / quickShortcuts /
savedTabSessions 三类数据序列化为 JSON,支持从 JSON 文件恢复。
附带 9 个单端测试覆盖正常路径与非法输入校验。
2026-07-13 17:50:16 +08:00
Kuroome f413433f9a fix(extension): 静默吞掉无接收方的 runtime 广播错误
chrome.runtime.sendMessage 在 dashboard 与 popup 都关闭时必定抛
"Receiving end does not exist",这是正常现象。原 catch 仍 console.warn
产生噪音日志。改为仅当错误非该连接错误时才告警。
2026-07-09 01:46:17 +08:00
Kuroome efa6c00528 fix(extension): 移除 buildDomainGroups 中多余的 undefined 赋值
groupMap.__landing_pages__ = undefined 在 groupMap 中残留一个
undefined 值,导致 Object.values 后 sort 比较器访问 a.domain
时抛出 TypeError。当用户打开了落地页域名根路径的标签页时触发,
表现为标签页变更后 dashboard 渲染失败。
2026-07-09 01:43:14 +08:00
Kuroome c028416d4a Merge commit '8173cd3b8f86aa6f0a6f73994f5f46efaf3a87c0' into fix/tab-change-notify-runtime-channel 2026-07-09 01:29:04 +08:00
LiuDeTao 8173cd3b8f Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-09 01:23:28 +08:00
Kuroome d2528be20f fix(extension): 修复 dashboard 自动刷新失效
将 tab 变更通知从 content script 通道改为 chrome.runtime.sendMessage
广播,命中 dashboard 与 popup 的 runtime.onMessage 监听。

- 静默吞掉无接收方时的连接错误(兼容中英双语消息)
- 非连接类异常添加去重保护避免刷屏
- 新增 background-notify.test.js 行为测试
- 同步更新 ui-regression.test.js 断言,收紧 chrome.tabs.sendMessage 检查
- manifest.json 版本号 1.1.1 -> 1.1.2
2026-07-09 01:20:54 +08:00
Kuroome 9981fb8c01 fix(extension): 兼容本地化错误消息并收紧 tabs.sendMessage 断言
背景广播无接收方错误消息匹配中英双语(/接收端不存在|Receiving end/i)
  真正异常添加去重保护避免刷屏(notifyTabHarborPages._lastWarn)
  ui-regression 断言收紧禁止任何形式 chrome.tabs.sendMessage
  (此前仅排除 await 前缀写法)
2026-07-09 01:18:07 +08:00
Kuroome 51febce621 fix:修复Copilot Review问题 2026-07-09 01:06:50 +08:00
Kuroome 01e9a5e9f0 fix: 修复 dashboard 自动刷新失效
- 改为 chrome.runtime.sendMessage 广播,命中 dashboard 与 popup 两个
  runtime 监听。

- 测试:新增 background-notify.test.js 行为测试(广播通道、错误吞掉逻辑),
  并修正 ui-regression.test.js 对注释中残留旧 API 的假阳性断言。

- manifest.json: 版本号 1.1.1->1.1.2。
2026-07-09 00:44:40 +08:00
Han Zheng 93afe5b359 fix: 保留批量恢复中的待加载标签页 2026-05-30 11:43:15 +08:00
OO 8dcc6b27ec Merge pull request #37 from V-IOLE-T/pr/36
fix: 隔离新标签页窗口状态
2026-05-28 15:35:43 +08:00