强制,2026-06-26 起生效;点击确认反馈与最短可见时长条款于 2026-07-29 补齐。 来源:早期从根协作规范沉淀到本目录;现行维护源为根
AGENTS.md。AGENTS.md只保留引用链接,不重复正文。 实现单一入口:Starcat/Shared/Components/SyncIconButton.swift
所有「刷新 / 重新拉取 / 同步列表」类 icon-only 触发器 必须走 SyncIconButton,禁止各 surface 自绘 arrow.clockwise 或 loading 时换成 ProgressView。
// ✅ 正确写法(尺寸按原占位传入 font / frameSize)
SyncIconButton(
isRefreshing: viewModel.isRefreshing,
disabled: viewModel.isRefreshing,
font: .caption,
frameSize: 18,
tooltip: String.l10n("activity.refresh")
) {
Task { await viewModel.refresh() }
}- SF Symbol:
arrow.triangle.2.circlepath(与 Manage「同步于」旁、Sidebar「仓库分组」刷新同款) - 静止:
.foregroundStyle(.secondary) - 刷新中 / 点击确认中:
.foregroundStyle(.accentColor)+ 线性 1 秒/圈repeatForever旋转(组件内rotationEffect实现) - 禁止用
ProgressView替代旋转中的图标 - 禁止用
.symbolEffect(.rotate, value:)/.symbolEffect(.variableColor)做刷新动效(行为与预期不符,见SyncIconButton.swift文件头)
手动点击刷新后,必须有可见的变蓝 + 转圈反馈。不得出现「点了完全没反应」。
覆盖两类情况:
| 情况 | 要求 |
|---|---|
| 真实刷新 | isRefreshing=true 期间持续转圈;结束后仍须满足下方「最短可见时长」 |
| 未发起 / 被门控拒绝 | 冷却未到、去重拦截、未登录等导致本次不拉网时,仍须变蓝并至少转 完整 1 圈(≥ 1s),表示点击已被接收 |
⚠️ 「冷却未到也要转一圈」与「请求极快也要转够最短时长」是同一产品原则的两端:前者解决门控吞点击,后者解决返回太快看不见。
SyncIconButton:只根据isRefreshing驱动变蓝与旋转;提供minVisibleDuration(默认应 ≥ 1s,与「完整一圈」对齐)。不负责业务冷却逻辑。- Caller / ViewModel:决定是否真正拉网;若点击被冷却等门控拒绝,仍须短暂拉高
isRefreshing(或走统一的 acknowledgement API),让按钮完成至少一圈确认反馈。禁止在action里静默return且不触动isRefreshing。 - 禁止各页面自写第二套空转 / 闪蓝动画绕过
SyncIconButton。
即便真实刷新在几毫秒内结束,按钮仍须至少保持转圈 minVisibleDuration(默认 1s = 完整一圈)。
SyncIconButton 内部用 enforcedRefreshing 状态机实现;调用方只需保证「进入刷新时 isRefreshing 至少闪过 true」。
特殊场景可显式传 minVisibleDuration: 0 关闭兜底(须在调用处注释原因)。
本规范为全项目强制原则。
仓库洞察(Repository Insights)页内全部手动刷新入口须完整落地(活动概览 / 提交活动 / Star 历史 / 顶栏全局刷新及同页其它 Sync)。其它 surface 新建或改动刷新时同步对齐;存量入口发现「点了没反馈」按本规范修。
- Manage 顶栏 Stars 全量同步(含 hover 取消 / rate limit):用
StarsSyncButton(内部同款图标与旋转;同步中同样变.accentColor) - 带文字的刷新行(如 Release「立即检查」):图标仍用
arrow.triangle.2.circlepath,静止.secondary、进行中.accentColor+ 旋转,与SyncIconButton同色同动效;若存在冷却门控,同样遵守「未拉网也要至少一圈」
- 菜单项
Label(..., systemImage: "arrow.clockwise")的「重新生成 / 恢复购买」等 文案动作(非 icon-only 刷新触发器) - 账户菜单「刷新个人信息」
- ❌
arrow.clockwise做列表 / toolbar / sheet header 刷新 - ❌ 刷新中只变
ProgressView、图标不转、不变蓝 - ❌ 冷却未到 / 门控拒绝时静默吞点击,图标无任何反馈
- ❌ 各页面 refresh 图标大小 / 颜色 / 动效不一致
- ❌ 页面自绘「空转一圈」绕过
SyncIconButton
SyncIconButton(共享组件 +minVisibleDuration/enforcedRefreshing)SidebarView(仓库分组)RepoListView(同步于)ActivityViewTrendingViewWeeklyContentViewRepoHealthSheetSmartSearchField(语义索引刷新)RepositoryInsightsView(仓库洞察各区块刷新)
# 刷新触发器不应再引入 arrow.clockwise(菜单 Label 除外,须注释说明非刷新触发器)
rg 'arrow\.clockwise' --type swift Starcat/Features/
# 手动刷新若有冷却 / guard,确认拒绝路径仍会拉高 isRefreshing(或等价 acknowledgement)
rg 'reserveManualRefresh|manualRefreshCooldown' --type swift Starcat/