diff --git a/Sources/AgentBar/App.swift b/Sources/AgentBar/App.swift index 08f801d..9609578 100644 --- a/Sources/AgentBar/App.swift +++ b/Sources/AgentBar/App.swift @@ -252,11 +252,11 @@ final class IslandWindowController { let screen = overlay.screen let topBarHeight = screen.agentBarTopBarHeight if let notchFrame = screen.agentBarNotchFrame { - overlay.panel.level = .screenSaver + overlay.panel.level = overlay.autoHideEligible ? .screenSaver : .statusBar overlay.view.configure(.notch( height: max(topBarHeight, notchFrame.height), gapWidth: notchFrame.width, - showsPin: false, + showsPin: overlay.autoHideEligible, showsSettings: true)) let maxWidth = min(max(320, notchFrame.width + 240), screen.frame.width - 80) @@ -267,7 +267,9 @@ final class IslandWindowController { let y = screen.frame.maxY - height let frame = NSRect(x: x, y: y, width: width, height: height) overlay.visibleFrame = frame - return frame + + guard overlay.isCollapsed else { return frame } + return NSRect(x: x, y: screen.frame.maxY, width: width, height: height) } overlay.panel.level = overlay.autoHideEligible ? .screenSaver : .statusBar @@ -2103,7 +2105,7 @@ private extension NSScreen { } var agentBarSupportsAutoHide: Bool { - agentBarNotchFrame == nil + true } } diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index c590faf..966b695 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -4,7 +4,7 @@ ## 运行结构 -- `Sources/AgentBar/`:AppKit 入口,创建无 Dock 图标的顶部浮窗;刘海屏和无 notch 普通屏幕都使用各自的 island 布局,刘海屏支持设置入口(不显示 pin)、无 notch 支持 pin 与齿轮设置入口,并通过 Sparkle 检查 GitHub Release appcast 更新。 +- `Sources/AgentBar/`:AppKit 入口,创建无 Dock 图标的顶部浮窗;刘海屏和无 notch 普通屏幕都使用各自的 island 布局,并统一支持 pin/unpin 与齿轮设置入口,通过 Sparkle 检查 GitHub Release appcast 更新。 - `Sources/AgentBarCore/`:数据读取、token/cost 扫描、价格计算、日级和小时级 token 历史聚合、Vibe Coding 活跃时间扫描、显示格式化。 - `Tests/AgentBarCoreTests/`:核心格式化和本地 session 扫描的 smoke coverage。 - `scripts/build-agent-bar-dmg.sh`:把 SwiftPM executable 打成 `AgentBar.app`,嵌入 `Sparkle.framework`,支持 universal DMG、Developer ID 签名和 release notarization。 @@ -18,8 +18,8 @@ 3. `CodexCostScanner` 扫描最近约 30 天 `sessions/YYYY/MM/DD/*.jsonl`,使用用户本机 `TimeZone.autoupdatingCurrent` 对 `token_count` timestamp 做本地自然日/小时归属并估算 cost;设置页 Usage 复用同一个 scanner 按年份读取 Jan-Dec 日级 token 历史,并按 Day 视图选中的本地自然日读取 00-23 点小时级模型拆分。Usage 设置页按当前 Day/Year 模式只刷新当前可见视图,不再每次切换都同时计算两套数据;日期/年份快速连续切换时会短暂 debounce,并用刷新序号丢弃旧请求结果,保证 UI 只展示最后停留的目标日期或年份。 4. `AgentBarCacheStore` 把最后一次完整快照、每个 session 文件的计算结果和 Usage 视图级 snapshot 缓存在 `~/.agentbar/cache.json`。启动时先用缓存快照显示旧值;如果完整快照缺失但 cost 文件缓存还在,则先从 cost 文件缓存恢复 Today/~30 Days,避免启动时退回 `$0.00`。Settings 的 Accounts 页同样优先复用顶部浮窗当前账号快照和 latest snapshot 里的账号 quota,只有没有 snapshot 时才回落到只含账号身份的 `accounts.json`。后台刷新时按文件 size/mtime 和聚合时区复用未变化文件,只解析新增、更新过、价格表需要重算或时区不一致的 session。cost 文件缓存按 session 文件保存 day/model 和 day/hour/model 聚合;Usage 视图级缓存按时区保存 Year 日级 snapshot、Day 小时级 token snapshot 和 Day Vibe Coding Time snapshot,过去日期和过去年份直接复用,今天和当前年使用短时缓存吸收快速切换。分日和分小时都依据每条 `token_count` 的 timestamp 在用户本地时区归属,所以同一个长期 session 今天消耗 N、明天继续消耗 M 时会分别落到对应本地日期和小时。`CodexActivityScanner` 独立读取同一批本地 session JSONL 的用户消息、token_count、命令/patch/collab/diff 等活动事件时间戳,把相邻间隔不超过 10 分钟的事件归为 active block,再按用户本地时区分摊到所选日期的 24 小时。扫描还会补捞最近修改过的旧日期目录文件,避免长期 session 仍存放在创建日目录时漏算后续日期。 5. `CodexAccountStore` 在每次读取或刷新当前 Codex OAuth auth 时,把账号凭据同步到 `~/.agentbar/accounts.json`;后台刷新会遍历这些已见账号,必要时刷新 token,并为展开态生成每账号一行的 quota 快照。顶部展开区只展示当前账号和最近账号的轻量列表:无 notch 普通屏只有 1 个账号时保持单列满宽,超过 1 个账号后利用较宽空间按两列最多展示 8 个账号,刘海屏保持单列最多展示 4 个账号;超过当前屏幕展示上限时显示更多账号入口并打开 Settings 的 Accounts 页。用户在展开区或 Accounts 页点击切换控件时,`CodexAccountSwitcher` 会把目标账号凭据写回当前 Codex live `auth.json`,后续新开的 Codex CLI 会话使用该账号。 -6. `AgentBarDisplayFormatting` 输出单行文案,`IslandWindowController` 为每块 `NSScreen` 建立 overlay,并每 60 秒静默刷新一次;刷新过程不显示状态点,先用 quick quota 更新顶部百分比,如果展开区账号 quota 仍为空则先单独拉取账号 usage,再等待完整 cost 扫描完成后写回缓存并更新文案。数字变化由 `RollingTextLabel` 做短时向上滚动,位数变化带来的 island 宽度变化用 0.44s ease-in-out 过渡,并遵守系统 Reduce Motion。所有屏幕都使用贴住顶部、水平居中的黑色 island shell,高度优先采用 Window Server 暴露的当前屏 `Menubar` 窗口并归一化为视觉菜单栏高度,再回退到该屏 `frame.maxY - visibleFrame.maxY`、`safeAreaInsets.top` 和物理 notch 高度推导;这样普通桌面、全屏 app 顶部 hover 下拉菜单栏、刘海屏和无 notch 屏都保持与系统顶栏同高。刘海屏通过 `safeAreaInsets` 与 `auxiliaryTopLeftArea`/`auxiliaryTopRightArea` 计算物理 notch,把 notch 本体作为中心禁区,默认仅显示 Codex icon 和两个 quota 百分比,hover 或展开后才显示右侧设置入口;普通屏幕保留相同视觉语言,但用连续 island 显示更紧凑的完整信息。账号展开区在鼠标离开面板后开始计时,默认连续离开 200ms 自动收回;设置窗口可调整 100 到 5000ms,鼠标回到面板内会重新计算。 -7. 无 notch 的普通屏幕启用 auto-hide eligibility:新用户首次启动默认 pinned open,避免安装后看不到 AgentBar;用户取消 pin 后,island 收到屏幕顶部外,鼠标进入顶部唤出区或 island 区域时用 0.26s ease-in-out 动画滑出。鼠标悬停到 island 后,右侧 SF Symbols pin 和 gear 才随宽度动画显现,展开账号面板时保持可见。pin 状态写入 `UserDefaults` 的 `AgentBar.pinnedOpen`,重启后继续沿用;缺少该 key 时按 pinned open 处理。刘海屏 notch-aware island 固定在顶部,不参与 auto-hide,右侧 gear 同样只在悬停或展开时显现。 +6. `AgentBarDisplayFormatting` 输出单行文案,`IslandWindowController` 为每块 `NSScreen` 建立 overlay,并每 60 秒静默刷新一次;刷新过程不显示状态点,先用 quick quota 更新顶部百分比,如果展开区账号 quota 仍为空则先单独拉取账号 usage,再等待完整 cost 扫描完成后写回缓存并更新文案。数字变化由 `RollingTextLabel` 做短时向上滚动,位数变化带来的 island 宽度变化用 0.44s ease-in-out 过渡,并遵守系统 Reduce Motion。所有屏幕都使用贴住顶部、水平居中的黑色 island shell,高度优先采用 Window Server 暴露的当前屏 `Menubar` 窗口并归一化为视觉菜单栏高度,再回退到该屏 `frame.maxY - visibleFrame.maxY`、`safeAreaInsets.top` 和物理 notch 高度推导;这样普通桌面、全屏 app 顶部 hover 下拉菜单栏、刘海屏和无 notch 屏都保持与系统顶栏同高。刘海屏通过 `safeAreaInsets` 与 `auxiliaryTopLeftArea`/`auxiliaryTopRightArea` 计算物理 notch,把 notch 本体作为中心禁区,默认仅显示 Codex icon 和两个 quota 百分比,hover 或展开后才显示右侧 pin/settings 控制;普通屏幕保留相同视觉语言,但用连续 island 显示更紧凑的完整信息。账号展开区在鼠标离开面板后开始计时,默认连续离开 200ms 自动收回;设置窗口可调整 100 到 5000ms,鼠标回到面板内会重新计算。 +7. 所有屏幕都启用 auto-hide eligibility:新用户首次启动默认 pinned open,避免安装后看不到 AgentBar;用户取消 pin 后,island 收到屏幕顶部外,鼠标进入顶部唤出区或 island 区域时用 0.26s ease-in-out 动画滑出。鼠标悬停到 island 后,右侧 SF Symbols pin 和 gear 才随宽度动画显现,展开账号面板时保持可见。pin 状态写入 `UserDefaults` 的 `AgentBar.pinnedOpen`,重启后继续沿用;缺少该 key 时按 pinned open 处理。刘海屏继续使用 notch-aware 紧凑布局和中心物理 notch 禁区,但不再作为 pin/unpin 或 auto-hide 的例外。 8. PIN 右侧的 gear icon 打开独立设置窗口。窗口采用紧凑 macOS preferences 布局,默认宽度 640pt,最小宽度 480pt:Light 模式下左侧 sidebar 使用 `#E6E5E3`,右侧正文使用 `#F3F1EF`,grouped settings 卡片使用 `#EFEDEB`,列表选中态使用 `#226CFF`;Dark 模式下这些背景、边框、分隔线和 Usage heatmap 辅助色跟随系统 appearance 切到深色 token,文字继续使用系统动态 label 色,避免浅底白字或深底黑字。General 页的 `Launch at Login` 调用 `SMAppService.mainApp` 注册/取消开机启动,`Automatic Updates` 控制 Sparkle 的自动下载/安装模式,更新检查始终保持开启,`Auto Collapse Delay` 写入 `UserDefaults` 的 `AgentBar.expansionAutoCollapseDelayMilliseconds`;Accounts 页展示所有已见 Codex 账号、当前账号状态、邮箱下方的 5h/7d quota 进度条,以及贴在 plan chip 右侧的小型切换控件,账号列表按内容完整撑开,滚动发生在右侧正文主体但不显示滚动条;Usage 页 header 第一行显示 `Daily Tokens`,第二行左侧提供 Day/Year segmented control,中间居中显示日期/年份切换,右侧显示 `Total x Tokens`;Year 保持类似 GitHub contribution calendar 的年度 token 热力图并支持在当前年份和最早有数据年份之间切换,年度热力图保持完整宽度但在设置窗口较窄时由卡片内部横向滚动承载,横向滚动同样不显示滚动条;Day 提供按自然日左右切换的日期控制,跨月和跨年由 Calendar 加减天处理,下面先展示所选日期 24 小时 token 消耗堆叠柱状图,再展示 Vibe Coding Time 折线/面积图和当日活跃总时长;Day 只为当天实际出现的模型生成颜色和 legend,不预置未出现的模型名称,图表不声明固定宽度,窗口变窄时按可用宽度重排,柱间距逐步缩小,最窄时允许柱子贴合,hover 单小时柱子时只向上展开 tooltip,显示该小时 token 总量和模型拆分;About 页展示当前版本、更新状态、手动检查/更新按钮和 GitHub 仓库入口。设置窗口使用普通 window level,避免打开后阻止用户切换到其他窗口;打开设置时 app 临时切到 `.regular` 以进入 Command+Tab,关闭设置后切回 `.accessory`,保持平时无 Dock 图标。启动和切入 `.regular` 时显式从 `AgentBar.icns` 设置 `NSApp.applicationIconImage` 并刷新 `NSDockTile`,保证临时 Dock 图标使用 AgentBar logo。 9. `AgentBarUpdater` 启动 Sparkle 后按 `SUFeedURL` 检查 `https://github.com/iFurySt/agent-bar/releases/latest/download/appcast.xml`。它维护一个轻量 `AgentBarUpdateStatus` 供 About 页显示当前版本、最新可用版本、检查中、已最新或失败状态;About 打开时用 `checkForUpdateInformation()` 做不打扰的探测,用户点击按钮时再调用 `checkForUpdates()` 触发 Sparkle 的下载/安装流程。发现可更新版本时,自定义 `SPUUserDriver` 先选择安装以触发后台下载;如果 `Automatic Updates` 已开启,下载和解包完成后直接交给 Sparkle 退出、替换并重启,不再二次确认。未开启时才在准备安装后弹出确认框,用户可选择立即安装、跳过此版本,或打开以后自动更新并安装当前版本;跳过会记录 `AgentBar.updater.skippedVersion`,同一个 `sparkle:version` 不再提醒。安装前会把当前版本和目标版本临时写入 `UserDefaults`,新版本启动后用 macOS 通知提示 `Updated from x to y`,成功投递或发现版本不匹配后清掉这条待通知记录,避免重复提醒。 diff --git a/docs/FRONTEND.md b/docs/FRONTEND.md index c3011fb..229dbf3 100644 --- a/docs/FRONTEND.md +++ b/docs/FRONTEND.md @@ -8,11 +8,11 @@ - 视觉风格坚持 less is more。新增入口、状态、文案、装饰和动效前要先证明它确实减少认知负担;能用留白、对齐、层级、系统色和 SF Symbols 解决的,不引入额外装饰、复杂配色或营销化视觉。 - 首屏就是顶部浮窗,不做 landing page、设置页或复杂菜单。 - 浮窗只展示一行:`5h`、`7d`、Today cost/tokens、约 30 天 cost/tokens。 -- 所有屏幕都使用贴住顶部、水平居中的黑色 island,高度对齐各自屏幕当前系统菜单栏的视觉高度;全屏应用左上角绿色 Full Screen 后,系统顶栏 hover 下拉时也按实时 `Menubar` 高度归一化重算,不使用固定 24pt 近似值,也不把菜单栏窗口底部额外边缘算进黑色高度。普通屏幕显示完整信息且中间不留空区,文本分隔保持紧凑,`Tokens` 右侧 padding 和左侧 logo 前 padding 对称;无 notch 的普通屏幕新用户首次启动默认 pinned open,取消 pin 后才自动收起,顶边悬停时按 0.26s ease-in-out 滑出,鼠标悬停到 island 后右侧 pin icon 和 gear icon 才随宽度动画显现;gear 打开轻量设置窗口,窗口使用紧凑 macOS preferences 风格:sidebar、正文、grouped settings 卡片、边框、分隔线和 Usage heatmap 辅助色必须跟随系统 Light/Dark appearance 自动切换,Light 模式保留 sidebar `#E6E5E3`、正文 `#F3F1EF`、卡片 `#EFEDEB`,`#226CFF` 选中态和原生开关保持一致,不能出现浅色背景配白字或深色背景配黑字。Accounts 作为独立页面展示所有已见 Codex 账号,每行在邮箱下方用两条低对比 5h/7d quota bar 表达剩余量,切换控件使用贴在 plan chip 右侧的小型符号按钮;账号列表不在 grouped block 内部滚动,block 随账号数量完整撑开,由右侧正文主体承担纵向滚动,但不显示滚动条。Usage 作为独立页面在 header 第一行显示 `Daily Tokens`,第二行左侧使用原生 segmented control 切换 Day/Year,中间居中显示日期/年份切换,右侧总量只写 `Total x Tokens`;Year 展示类似 GitHub contribution calendar 的年度 token 热力图并提供年份左右切换,热力图顶部显示月份、左侧显示 Mon/Wed/Fri,hover 单元格时用自适应宽高的深色浮层展示缩写日期、美元消耗和 Tokens,所有日期都按用户本地时区归属和显示,年度热力图宽于默认设置窗口时只在卡片内部横向滚动且不显示滚动条,不应撑宽整个设置窗口;Day 在同一控制行提供日期左右切换,跨月和跨年都用用户本地 Calendar 自然日加减,并展示所选本地日期 00-24 的小时级 token 堆叠柱状图和跟在下方的独立 Vibe Coding Time block,token 图标题为 `Tokens`,横轴按 4 小时间隔标注,末尾使用 `Hours` 表示小时轴,纵轴使用紧凑 token 单位,只为当天实际出现的模型生成柱段颜色和底部 legend,legend 与柱状图/横轴标签之间必须保留清楚间距,legend 每行居中且过多时自动换行继续居中;Vibe Coding Time 使用紫色低对比面积图展示每小时 active block 分布,并在标题旁显示当日总活跃时长;堆叠柱内部和底部保持直角,只允许最上方柱段的上两角圆角;hover 单小时柱子时 tooltip 只向上展开,避免挡住鼠标,并显示总 tokens 和模型拆分;Day 图表不能撑宽设置窗口,窗口变窄时柱间距逐步缩小,极窄时允许柱子贴合;About 作为独立页面展示当前版本、更新状态、紧凑的 Check/Update 按钮和 GitHub 仓库入口;刘海屏绘制和 notch 等高的小型黑色 island,把物理 notch 作为中心禁区,不显示 `5h`/`7d` 文本标签,并在右侧保留 hover 显现的 gear icon(无 pin)。 +- 所有屏幕都使用贴住顶部、水平居中的黑色 island,高度对齐各自屏幕当前系统菜单栏的视觉高度;全屏应用左上角绿色 Full Screen 后,系统顶栏 hover 下拉时也按实时 `Menubar` 高度归一化重算,不使用固定 24pt 近似值,也不把菜单栏窗口底部额外边缘算进黑色高度。普通屏幕显示完整信息且中间不留空区,文本分隔保持紧凑,`Tokens` 右侧 padding 和左侧 logo 前 padding 对称;所有屏幕新用户首次启动默认 pinned open,取消 pin 后才自动收起,顶边悬停时按 0.26s ease-in-out 滑出,鼠标悬停到 island 后右侧 pin icon 和 gear icon 才随宽度动画显现;gear 打开轻量设置窗口,窗口使用紧凑 macOS preferences 风格:sidebar、正文、grouped settings 卡片、边框、分隔线和 Usage heatmap 辅助色必须跟随系统 Light/Dark appearance 自动切换,Light 模式保留 sidebar `#E6E5E3`、正文 `#F3F1EF`、卡片 `#EFEDEB`,`#226CFF` 选中态和原生开关保持一致,不能出现浅色背景配白字或深色背景配黑字。Accounts 作为独立页面展示所有已见 Codex 账号,每行在邮箱下方用两条低对比 5h/7d quota bar 表达剩余量,切换控件使用贴在 plan chip 右侧的小型符号按钮;账号列表不在 grouped block 内部滚动,block 随账号数量完整撑开,由右侧正文主体承担纵向滚动,但不显示滚动条。Usage 作为独立页面在 header 第一行显示 `Daily Tokens`,第二行左侧使用原生 segmented control 切换 Day/Year,中间居中显示日期/年份切换,右侧总量只写 `Total x Tokens`;Year 展示类似 GitHub contribution calendar 的年度 token 热力图并提供年份左右切换,热力图顶部显示月份、左侧显示 Mon/Wed/Fri,hover 单元格时用自适应宽高的深色浮层展示缩写日期、美元消耗和 Tokens,所有日期都按用户本地时区归属和显示,年度热力图宽于默认设置窗口时只在卡片内部横向滚动且不显示滚动条,不应撑宽整个设置窗口;Day 在同一控制行提供日期左右切换,跨月和跨年都用用户本地 Calendar 自然日加减,并展示所选本地日期 00-24 的小时级 token 堆叠柱状图和跟在下方的独立 Vibe Coding Time block,token 图标题为 `Tokens`,横轴按 4 小时间隔标注,末尾使用 `Hours` 表示小时轴,纵轴使用紧凑 token 单位,只为当天实际出现的模型生成柱段颜色和底部 legend,legend 与柱状图/横轴标签之间必须保留清楚间距,legend 每行居中且过多时自动换行继续居中;Vibe Coding Time 使用紫色低对比面积图展示每小时 active block 分布,并在标题旁显示当日总活跃时长;堆叠柱内部和底部保持直角,只允许最上方柱段的上两角圆角;hover 单小时柱子时 tooltip 只向上展开,避免挡住鼠标,并显示总 tokens 和模型拆分;Day 图表不能撑宽设置窗口,窗口变窄时柱间距逐步缩小,极窄时允许柱子贴合;About 作为独立页面展示当前版本、更新状态、紧凑的 Check/Update 按钮和 GitHub 仓库入口;刘海屏绘制和 notch 等高的小型黑色 island,把物理 notch 作为中心禁区,不显示 `5h`/`7d` 文本标签,并在右侧保留 hover 显现的 pin icon 和 gear icon。 - Vibe Coding Time 的坐标轴要和 Day token 图保持一致:Y 轴放左侧,轴标签使用 `heatmapLabel` 和 10.8pt monospaced 字体,横轴末尾写 `Hours`;hover 小时点时复用 Usage 页面级 tooltip 显示该小时活跃时长。 - Day 模式的 total 不放在 Usage 页面 header 右侧;token 总量放在 `Tokens` 标题行右侧并带模型色小圆点,Vibe 总时长放在 `Vibe Coding Time` 标题行右侧并带紫色小圆点,圆点与文字保持垂直居中。 - 刘海屏黑底遵循 X Island 同类 macOS notch 轮廓:顶边贴住屏幕直线,左右侧从顶边用小半径收进,底部两侧使用更大的圆角;不要用 iPhone Dynamic Island 那种双边胶囊形,也不要用透明圆形直接挖出大缺口。 -- 无 notch 的自动隐藏 island 默认忽略鼠标事件;悬停唤出或点击 pin/settings 时临时接管鼠标,避免平时挡住菜单栏交互;刘海屏 island 保持常驻交互,悬停后才展示设置入口。 +- 自动隐藏 island 默认忽略鼠标事件;悬停唤出或点击 pin/settings 时临时接管鼠标,避免平时挡住菜单栏交互;刘海屏也使用同一套 pin/unpin 与 auto-hide 语义,只保留 notch-aware 的紧凑视觉布局。 - 账号展开区只在鼠标离开整个 island 面板后开始自动收回倒计时,默认 200ms,设置窗口以 ms 为单位可调 100 到 5000ms;鼠标回到面板内要取消并重新计算,停留在面板内时不得自动收回。 - 账号展开区在无 notch 普通屏只有 1 个账号时保持单列满宽,超过 1 个账号后按两列最多展示 8 个账号;刘海屏仍保持单列,最多展示当前账号和最近 3 个账号。超过当前屏幕展示上限时不要把顶部浮窗变成滚动列表,而是在底部显示更多账号入口,打开 Settings 的 Accounts 页查看和切换全部账号。 - 文本过长时允许中间截断,但不换行、不改变浮窗高度。 diff --git a/docs/QUALITY_SCORE.md b/docs/QUALITY_SCORE.md index db0caa9..1142b96 100644 --- a/docs/QUALITY_SCORE.md +++ b/docs/QUALITY_SCORE.md @@ -13,7 +13,7 @@ | 区域 | 评分 | 原因 | 下一步 | | --- | --- | --- | --- | -| 产品面 | B | 已有最小可用顶部浮窗,范围清楚,只展示 Codex quota 与 token/cost,并具备 tag 驱动 DMG 分发、Sparkle 更新、About 手动检查更新入口、外接屏 auto-hide/pin、轻量设置窗口、Usage Year 热力图、Day 小时柱状图和数字刷新动效。 | 真实使用后再决定是否需要菜单栏状态项或更多诊断入口。 | +| 产品面 | B | 已有最小可用顶部浮窗,范围清楚,只展示 Codex quota 与 token/cost,并具备 tag 驱动 DMG 分发、Sparkle 更新、About 手动检查更新入口、全屏幕 auto-hide/pin、轻量设置窗口、Usage Year 热力图、Day 小时柱状图和数字刷新动效。 | 真实使用后再决定是否需要菜单栏状态项或更多诊断入口。 | | 架构文档 | B | 已替换为 SwiftPM/AppKit/Core 的真实结构,并补齐 macOS DMG、Sparkle appcast 与 GitHub Release 更新边界。 | 后续如果加入登录流程、Homebrew 或 App Store 分发,同步更新边界。 | | 测试 | B | 覆盖了显示格式、本地 token 扫描、跨天日级聚合、指定日期小时级模型聚合、长期 session 旧目录补捞、缓存失效、Usage 视图级缓存复用和 fallback scanner smoke path;CI 已运行 `swift test`。 | 补 API response fixture 与更完整的 UI 刷新节奏测试。 | | 可观测性 | B | UI 刷新保持静默以减少打扰,缓存可从 `~/.agentbar/cache.json` 直接检查。 | 如果出现 quota 读取问题,再补本地 debug 输出。 | diff --git a/docs/RELIABILITY.md b/docs/RELIABILITY.md index 98f0f22..d812395 100644 --- a/docs/RELIABILITY.md +++ b/docs/RELIABILITY.md @@ -13,7 +13,7 @@ - cost/token 和 Vibe Coding Time 扫描在后台任务中运行,避免阻塞 AppKit 主线程。 - 后台刷新保持静默,不显示状态点,避免快速刷新时造成视觉闪烁。 - 刷新后的数字变化只触发短时本地绘制动画,宽度变化使用 AppKit frame 动画;系统开启 Reduce Motion 时直接更新,不额外制造动画负担。 -- 无 notch 普通屏幕用 30Hz 主线程 timer 轮询鼠标位置来做顶部唤出,不依赖额外 Accessibility 权限;窗口平时仍默认透传鼠标事件。 +- 所有顶部 island 用 30Hz 主线程 timer 轮询鼠标位置来做顶部唤出,不依赖额外 Accessibility 权限;未 hover 的自动隐藏窗口平时仍默认透传鼠标事件。 - Sparkle 按 24 小时间隔检查 GitHub Release appcast。About 页打开时用 Sparkle 的 probing check 刷新当前版本是否最新,点击 Check/Update 时才启动用户触发的更新检查与后续下载/安装流程。发现更新后先后台下载;如果设置里的 `Automatic Updates` 已开启,下载和解包完成后通过 Sparkle 的 immediate installation block 直接退出、替换并重启安装,避免常驻小组件一直等到用户手动退出。未开启时才弹出安装确认,用户可选择立即安装、跳过此版本,或打开以后自动更新并安装当前版本;用户跳过后,同一个 `sparkle:version` 不再提醒。升级安装前会记录旧版本和目标版本,新版本启动后尝试发送一次系统通知告知 `Updated from x to y`,通知记录随后清理。 - 设置窗口里的开机启动开关使用 macOS `SMAppService.mainApp`;如果当前运行形态不是可注册 app bundle,失败会回退开关状态并显示系统错误。 - 设置窗口打开时只激活应用并使用普通 window level 展示,避免窗口置顶后阻止用户切换到其他应用或窗口。由于 `.accessory` app 默认不会进入 Command+Tab,打开设置时临时切到 `.regular`,关闭设置后切回 `.accessory`;启动和切入 `.regular` 时显式设置 `NSApp.applicationIconImage` 并刷新 `NSDockTile`,避免临时 Dock 图标退回默认图标。设置窗口自身处理 `Command+W`,不依赖标准 app 菜单也能关闭。 diff --git a/docs/histories/2026-05/20260511-1430-notch-pin-unpin-auto-hide.md b/docs/histories/2026-05/20260511-1430-notch-pin-unpin-auto-hide.md new file mode 100644 index 0000000..b49bf6e --- /dev/null +++ b/docs/histories/2026-05/20260511-1430-notch-pin-unpin-auto-hide.md @@ -0,0 +1,35 @@ +## [2026-05-11 14:30] | Task: 支持刘海屏 pin/unpin + +### 🤖 Execution Context + +- **Agent ID**: `Codex` +- **Base Model**: `GPT-5` +- **Runtime**: `Codex CLI` + +### 📥 User Query + +> 现在 mac 14 寸刘海屏是不是不支持 pin/unpin,改成也支持 + +### 🛠 Changes Overview + +**Scope:** `Sources/AgentBar` 顶部 island 行为与相关文档 + +**Key Actions:** + +- **[Action 1]**: 让 notch 屏幕也通过 `agentBarSupportsAutoHide` 参与 auto-hide eligibility。 +- **[Action 2]**: notch 布局改为显示 pin 与 settings 两个 hover 控制,取消 pin 后可收进屏幕顶边。 +- **[Action 3]**: 同步架构、前端、稳定性、质量评分和用户发布记录,移除“刘海屏无 pin/固定常驻”的旧描述。 + +### 🧠 Design Intent (Why) + +14 寸内建刘海屏和外接普通屏都需要同一套“默认固定、用户取消 pin 后低打扰自动隐藏”的控制语义。刘海屏的差异应该只体现在 notch-aware 紧凑视觉布局和中心物理 notch 禁区,而不是功能能力缺失。 + +### 📁 Files Modified + +- `Sources/AgentBar/App.swift` +- `docs/ARCHITECTURE.md` +- `docs/FRONTEND.md` +- `docs/RELIABILITY.md` +- `docs/QUALITY_SCORE.md` +- `docs/releases/feature-release-notes.md` +- `docs/histories/2026-05/20260511-1430-notch-pin-unpin-auto-hide.md` diff --git a/docs/releases/feature-release-notes.md b/docs/releases/feature-release-notes.md index fa791d9..197484b 100644 --- a/docs/releases/feature-release-notes.md +++ b/docs/releases/feature-release-notes.md @@ -1,5 +1,11 @@ # 功能发布记录 +## 2026-05 + +| 日期 | 功能域 | 用户价值 | 变更摘要 | +| --- | --- | --- | --- | +| 2026-05-11 | 多屏体验 | 14 寸等内建刘海屏也支持右侧 pin/unpin;取消 pin 后同样会自动收起,悬停屏幕顶边再唤出。 | 刘海屏保留 notch-aware 紧凑 island 和物理 notch 中心禁区,但不再作为 auto-hide/pin 的例外;pin 偏好继续复用 `AgentBar.pinnedOpen`。 | + ## 2026-04 | 日期 | 功能域 | 用户价值 | 变更摘要 |