Ariver
2026-07-07 d76f5d61a7463dee1600d6b40eb85cabfa75a914
release: prepare 8.3.6 settings header update
7 files modified
1 files added
69 ■■■■ changed files
C1.source/Apptag/ContentView.swift 8 ●●●●● patch | view | raw | blame | history
C1.source/Apptag/Info.plist 4 ●●●● patch | view | raw | blame | history
C1.source/Apptag/PreferencesView.swift 8 ●●●●● patch | view | raw | blame | history
C1.source/Apptag/ProEntitlement.swift 5 ●●●●● patch | view | raw | blame | history
C1.source/CHANGELOG.md 6 ●●●●● patch | view | raw | blame | history
C1.source/Docs/Requirements/2026-07-07-settings-pro-header-border-removal.md 28 ●●●●● patch | view | raw | blame | history
C1.source/Scripts/pro_feature_gate_qa.sh 4 ●●●● patch | view | raw | blame | history
CODEGRAPH.md 6 ●●●● patch | view | raw | blame | history
C1.source/Apptag/ContentView.swift
@@ -583,6 +583,10 @@
    }
    var body: some View {
        contentWithStateObservers
    }
    private var contentWithNotificationObservers: some View {
        contentStack
            .onAppear(perform: handleContentAppear)
            .onReceive(NotificationCenter.default.publisher(for: .tagLauncherOverlayDidShow), perform: handleOverlayDidShow)
@@ -593,6 +597,10 @@
            .onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification), perform: handleApplicationDidBecomeActive)
            .onReceive(NotificationCenter.default.publisher(for: .tagLauncherDataDidChange), perform: handleDataDidChange)
            .onReceive(NotificationCenter.default.publisher(for: .appLanguageDidChange), perform: handleAppLanguageDidChange)
    }
    private var contentWithStateObservers: some View {
        contentWithNotificationObservers
            .onChange(of: editPhase) { _, newPhase in
                let active = newPhase != .none
                dismissAppBubble()
C1.source/Apptag/Info.plist
@@ -19,7 +19,7 @@
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>8.3.5</string>
    <string>8.3.6</string>
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
@@ -32,7 +32,7 @@
        </dict>
    </array>
    <key>CFBundleVersion</key>
    <string>20260702.1046</string>
    <string>20260707.1242</string>
    <key>LSApplicationCategoryType</key>
    <string>public.app-category.utilities</string>
    <key>LSMinimumSystemVersion</key>
C1.source/Apptag/PreferencesView.swift
@@ -1022,14 +1022,6 @@
            .padding(.vertical, 10)
            .frame(width: dataPanelWidth, alignment: .leading)
            .frame(minHeight: 44)
            .background(
                RoundedRectangle(cornerRadius: 10, style: .continuous)
                    .fill(Color(nsColor: .controlBackgroundColor))
            )
            .overlay(
                RoundedRectangle(cornerRadius: 10, style: .continuous)
                    .stroke(Color.secondary.opacity(0.16), lineWidth: 1)
            )
        }
        .frame(maxWidth: .infinity, alignment: .center)
        .padding(.top, 12)
C1.source/Apptag/ProEntitlement.swift
@@ -680,11 +680,6 @@
            let verification = try await AppTransaction.shared
            switch verification {
            case .verified(let transaction):
                if #available(macOS 13.0, *) {
                    if transaction.revocationDate != nil {
                        return nil
                    }
                }
                return transaction
            case .unverified:
                return nil
C1.source/CHANGELOG.md
@@ -2,6 +2,12 @@
## [Unreleased]
## [8.3.6] — 2026-07-07
- 设置页顶部固定 Pro 状态 / 引导行移除外层圆角矩形背景和描边,保留原位置、身份文案、购买和恢复购买入口
- 扩展 Pro 门禁 QA,防止该固定 Pro 行回退为带外框样式
- 版本号更新为 `8.3.6`,Build 更新为 `20260707.1242`
## [8.3.5] — 2026-07-02
- 标签列表自身顺序不再作为 Pro 权益:免费用户拖动标签后也会持久保存容器显示顺序
C1.source/Docs/Requirements/2026-07-07-settings-pro-header-border-removal.md
New file
@@ -0,0 +1,28 @@
# Settings Pro Header Border Removal
Date: 2026-07-07
Target version: 8.3.6
## Requirement
Across all Settings tabs, the fixed Pro status / guidance row below the tab bar must no longer render an outer rounded rectangle frame.
## Keep
- Keep `settingsFixedProHeader` visible on Language, General, Theme, Hotkeys, Tags, Data, Pro, and About tabs.
- Keep the row width, vertical position, status text, Pro pill, purchase button, and restore purchase button behavior.
- Keep the centered unlocked identity layout for Language, Pro, and About after Pro unlock.
## Remove
- Remove only the outer rounded rectangle background and stroke from `settingsFixedProHeader`.
- Do not remove inner Pro pills, tab content cards, Pro comparison rows, data action cards, or modal prompt styling.
## Evidence
User screenshot: `/var/folders/s4/_92q_d2d7sxczn21bpxjhbv00000gp/T/codex-clipboard-b111590b-42cc-42e5-80f0-be58e0f68eb4.png`
## Validation
- Static QA must fail if `settingsFixedProHeader` reintroduces the old `controlBackgroundColor` rounded background or secondary stroke.
- Visual smoke must confirm the header content remains in the same position without the outer frame.
C1.source/Scripts/pro_feature_gate_qa.sh
@@ -176,6 +176,10 @@
    fail("fixed Pro header must no longer be hidden on Language and About tabs")
require(preferences, "if shouldShowSettingsFixedProHeader", "Settings body must conditionally render the fixed Pro header")
fixed_header_body = function_body(preferences, "private var settingsFixedProHeader: some View")
if "Color(nsColor: .controlBackgroundColor)" in fixed_header_body:
    fail("fixed Pro header must not render the removed outer rounded background")
if ".stroke(Color.secondary.opacity(0.16), lineWidth: 1)" in fixed_header_body:
    fail("fixed Pro header must not render the removed outer rounded border")
require(fixed_header_body, "if shouldCenterUnlockedIdentityHeader", "fixed Pro header must use the centered unlocked identity branch")
require(fixed_header_body, 'text: tr("pro.status.unlocked")', "centered Pro identity header must start with the Pro unlocked pill")
require(fixed_header_body, "style: .unlocked", "centered Pro identity pill must use the unlocked style")
CODEGRAPH.md
@@ -1,6 +1,6 @@
# TagLauncher CODEGRAPH
最后更新:2026-07-02
最后更新:2026-07-07
用途:本文件是 TagLauncher 的长期工程地图。修改用户可见行为、状态模型、构建/发布入口、核心源码或 QA 入口前,应先读本文件,再读指向的真实源码。若本文件与源码不一致,以源码为准,并在同一任务内更新本文件。
@@ -37,7 +37,7 @@
- `C1.source/Apptag/PreferencesView.swift`
  - `PreferencesView`:设置窗口、语言、通用、主题、快捷键、标签、数据、Pro、关于等设置页。
  - 顶部设置页签必须保持 8 个标签总宽不超过旧 7 标签宽度;图标统一使用线型 SF Symbols,`Pro` 页签位于数据之后、关于之前,使用线型皇冠。
  - 设置页签下方按页签渲染统一固定位置的 `settingsFixedProHeader`:语言 / 通用 / 主题 / 快捷键 / 标签 / 数据 / Pro / 关于 8 个页签都显示该行且位置不漂移。免费态左侧状态用“当前免费版用户”完整句而不是“免费版”胶囊;通用 / 主题 / 快捷键 / 标签 / 数据页显示当前 tab 对应购买引导和解锁/恢复按钮,语言和关于页只显示状态与操作按钮,不显示购买说明文字;已解锁 Pro 时,语言 / Pro / 关于页统一居中显示 `Pro 已解锁` 胶囊加 `settings.proStatus.proUser` 文案,不显示恢复购买按钮,且 `settings.proStatus.proUser` 本地化文字不再内置皇冠图标。
  - 设置页签下方按页签渲染统一固定位置的 `settingsFixedProHeader`:语言 / 通用 / 主题 / 快捷键 / 标签 / 数据 / Pro / 关于 8 个页签都显示该行且位置不漂移。免费态左侧状态用“当前免费版用户”完整句而不是“免费版”胶囊;通用 / 主题 / 快捷键 / 标签 / 数据页显示当前 tab 对应购买引导和解锁/恢复按钮,语言和关于页只显示状态与操作按钮,不显示购买说明文字;已解锁 Pro 时,语言 / Pro / 关于页统一居中显示 `Pro 已解锁` 胶囊加 `settings.proStatus.proUser` 文案,不显示恢复购买按钮,且 `settings.proStatus.proUser` 本地化文字不再内置皇冠图标。8.3.6 起该固定行不渲染包住整行的外层圆角矩形背景或描边。
  - Pro 专属主题、彩色容器 / 彩色网格、自定义快捷键、自定义标签颜色和数据导入导出入口即使已解锁,也应保留皇冠 Pro 标识。
  - Language tab 去掉重复标题说明,语言矩阵在主内容区域上下左右居中;About tab 应用信息块也在主内容区域居中。
  - Theme tab 只写视觉偏好 `appGridThemeID` 和炫彩主题调色值,炫彩滑轨只能影响 AppGrid 背景,不得改变标签、排序、备注或分类数据。
@@ -205,7 +205,7 @@
- `C1.source/Scripts/pro_localization_qa.sh`
  - Pro 文案 29 语种静态门禁;检查 `pro.*`、设置页 Pro 状态/对比表、自定义标签颜色、Quick Search 快捷键页和气泡提示设置键完整、占位符完整、无生成污染和非英文语言无英文兜底复制。
- `C1.source/Scripts/pro_feature_gate_qa.sh`
  - Pro 功能源码门禁;检查 StoreKit 权益、老用户自动 Pro、主题门禁、导入导出硬拦截、3 条备注额度、自定义标签颜色、自定义快捷键、容器内 App 排序预览、Pro UI 提示、设置页线型图标、轻量 Pro 权益行、Pro 页签、免费列“不支持”状态和 About 页不回归 Pro 汇总卡。
  - Pro 功能源码门禁;检查 StoreKit 权益、老用户自动 Pro、主题门禁、导入导出硬拦截、3 条备注额度、自定义标签颜色、自定义快捷键、容器内 App 排序预览、Pro UI 提示、设置页线型图标、轻量 Pro 权益行、固定 Pro 行不回归外层圆角矩形框、Pro 页签、免费列“不支持”状态和 About 页不回归 Pro 汇总卡。
- `C1.source/Scripts/pro_theme_preview_countdown_qa.sh`
  - Pro 主题 / 彩色显示模式预览倒计时门禁;检查状态行倒计时、当前预览卡片 `MM:SS`、到期清理、29 语种 `%time%` 占位符和禁止写死体验时长。
- `C1.source/Scripts/pro_display_mode_preview_qa.sh`