edit | blame | history | raw

Taglauncher 会话记录 - 2026-06-08 AppGrid抖动排查

用户目标

用户提供 /Users/ar/Desktop/奇怪的抖动问题.mp4,要求先判断奇怪交互抖动的成因,并评估修复风险。

已完成事项

  • 读取并遵守 ~/.codex/rules/qa-workflow.md~/.codex/rules/delivery-gate.md
  • 使用 ffprobe 检查视频:8.88 秒,1920x1080,约 19.49 fps。
  • 使用 ffmpeg 抽取 contact sheet:
  • /private/tmp/taglauncher-jitter-frames/contact.jpg
  • /private/tmp/taglauncher-jitter-frames/contact-4fps.jpg
  • 读取并分析相关源码:
  • /Users/ar/Projects/Taglauncher/src/Apptag/ContentView.swift
  • /Users/ar/Projects/Taglauncher/src/Apptag/AppGridCollectionView.swift
  • /Users/ar/Projects/Taglauncher/src/Apptag/TagNavigationView.swift
  • /Users/ar/Projects/Taglauncher/src/Apptag/AppGridSupport.swift

初步判断

  • 视频中的抖动主要表现为 AppGrid 内容在不同分组位置之间跳动,而不是单个图标 hover 的局部放大。
  • 代码中的主要触发点是 ContentView.handleTagNavigationHover()
  • tag hover 会设置 tagNavigationHoveredGroupName
  • 色块模式下会 fillColorlessContainer(id)
  • 还会调用 scrollToTagFromHover(id),进而 scrollTo(id),让 AppGrid 自动滚到对应分组。
  • 因此鼠标在顶部 tag 条、顶部 App 名称气泡附近或快速经过多个 tag 时,会出现“hover tag -> 自动滚动到分组 -> 屏幕内容改变 -> hover 状态变化/再次触发”的循环,视觉上像整屏抖动。
  • 另一个需要留意但不是首要证据的点:AppGridContainerCollectionLayout.shouldInvalidateLayout(forBoundsChange:) 返回 false,如果 collection view 实际宽度在窗口/clip view 过渡中变化,可能出现旧宽度/新宽度两次排版。但从视频现象看,主要不是宽度抖动,而是 hover 自动滚动。

风险评估

  • 低风险修复方向:保留 tag hover 高亮/填色,但取消或限制 hover 自动滚动;点击 tag 继续滚动。改动范围主要在 ContentView.swift 的 hover 处理和 scrollToTagFromHover()
  • 中等风险修复方向:增加 dwell debounce、滚动中抑制、气泡显示时抑制 tag hover scroll。这会保留部分 hover 自动滚动体验,但状态机更复杂,需要更完整 QA。
  • 不建议优先从 AppGrid 布局算法大改入手,因为会扩大 Masonry/Grid/Flat 多显示模式的回归范围。

文件变更

  • 未修改源码。
  • 新增本会话记录文件。

未决问题

  • 需要用户确认希望保留“鼠标悬停 tag 自动滚到分组”的功能,还是改成“只有点击 tag 才滚动”。

后续建议

  • 若用户同意低风险方案,优先把 hover 行为收敛为只高亮/填色、不滚动;点击 tag 继续滚动。
  • 修复后补充回归:顶部 tag 快速扫过、App 名称气泡出现/消失、点击 tag 滚动、侧边 tag、拖拽 tag/app、coloredGridContainer 与 colorless grid/container 模式。