Ariver
2026-07-02 01bab5422712299b49f656e6b4c42a3bf314f519
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/bin/bash
set -euo pipefail
 
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
APP_DIR="$ROOT_DIR/Apptag"
 
python3 - "$APP_DIR" <<'PY'
import json
import re
import sys
from pathlib import Path
 
app_dir = Path(sys.argv[1])
theme_file = app_dir / "AppGridTheme.swift"
preferences_file = app_dir / "PreferencesView.swift"
defaults_file = app_dir / "AppDefaults.swift"
content_file = app_dir / "ContentView.swift"
grid_file = app_dir / "AppGridCollectionView.swift"
localization_dir = app_dir / "Localization"
 
theme_source = theme_file.read_text(encoding="utf-8")
preferences_source = preferences_file.read_text(encoding="utf-8")
defaults_source = defaults_file.read_text(encoding="utf-8")
content_source = content_file.read_text(encoding="utf-8")
grid_source = grid_file.read_text(encoding="utf-8")
edit_views_source = (app_dir / "EditModeViews.swift").read_text(encoding="utf-8")
 
expected_cases = [
    "defaultLight",
    "deepBlue",
    "black",
    "pink",
    "purple",
    "green",
    "blue",
    "colorful",
]
for case in expected_cases:
    if not re.search(rf"case\s+{re.escape(case)}\b", theme_source):
        raise SystemExit(f"missing AppGridTheme case: {case}")
 
if "case theme" not in preferences_source:
    raise SystemExit("SettingsTab is missing the theme tab")
if "settings.darkAppGrid" in preferences_source:
    raise SystemExit("legacy dark grid copy is still referenced by PreferencesView")
if "Toggle(tr(\"settings.darkAppGrid\")" in preferences_source:
    raise SystemExit("legacy dark grid toggle is still visible")
if "useDarkAppGrid" in content_source or "useDarkAppGrid" in grid_source:
    raise SystemExit("legacy dark grid boolean still drives AppGrid rendering")
if "CAGradientLayer" in grid_source:
    raise SystemExit("AppGridCollectionView still owns a background gradient layer")
if "useDarkAppGrid" not in defaults_source or "AppGridTheme.deepBlue.rawValue" not in defaults_source:
    raise SystemExit("legacy dark preference migration is missing")
if "var usesVisualEffectBackdrop: Bool" not in theme_source:
    raise SystemExit("theme visual-effect backdrop policy is missing")
if "static let settingsDisplayOrder: [AppGridTheme]" not in theme_source:
    raise SystemExit("settings theme display order is missing")
if "var supportsColorTuning: Bool" not in theme_source:
    raise SystemExit("colorful theme tuning policy is missing")
if "func backgroundBaseColors(tuning: Double?)" not in theme_source or "func backgroundAccentColors(tuning: Double?)" not in theme_source:
    raise SystemExit("tunable AppGrid background color functions are missing")
if "AppGridTheme.settingsDisplayOrder" not in preferences_source:
    raise SystemExit("Preferences theme grid does not use the curated theme order")
if "themeColorTuningSection" not in preferences_source or "Slider(value: themeTuningBinding" not in preferences_source:
    raise SystemExit("Preferences theme tuning slider is missing")
if 'Text(tr("settings.theme"))\n                            .font(.headline)' in preferences_source:
    raise SystemExit("Theme content area must not repeat the Theme heading")
if 'Text(tr("settings.themeScopeDesc"))' in preferences_source:
    raise SystemExit("Theme scope copy must be merged into the tuning description, not rendered as a standalone bottom line")
if not re.search(r"case\s+\.colorful:\s*return\s+0\b", theme_source):
    raise SystemExit("Light Colorful default tuning must start at the far left of the slider")
if "AppGridTheme.deepBlueTuningStorageKey" not in defaults_source or "AppGridTheme.colorfulTuningStorageKey" not in defaults_source:
    raise SystemExit("theme tuning defaults are missing")
if "static let iconSize: Double = 56" not in defaults_source:
    raise SystemExit("new-install default icon size must be 56")
if 'static let displayMode = "gridContainer"' not in defaults_source:
    raise SystemExit("new-install default display mode must remain a free mode")
if "var isPureBlackBackground: Bool" not in theme_source or "self == .black" not in theme_source:
    raise SystemExit("pure black background policy is missing")
if "case .deepBlue, .black:" not in theme_source or "return true" not in theme_source:
    raise SystemExit("dark glass must be limited to deepBlue and black")
if "case .defaultLight, .pink, .purple, .green, .blue, .colorful:" not in theme_source or "return false" not in theme_source:
    raise SystemExit("bright themes must keep light glass")
if "backgroundDimmingOpacity" not in theme_source or "case .deepBlue:" not in theme_source:
    raise SystemExit("theme background dimming policy is missing")
if "theme.usesVisualEffectBackdrop" not in content_source or "theme.isPureBlackBackground" not in content_source:
    raise SystemExit("ContentView does not apply backdrop/pure-black theme policy")
required_edit_tokens = {
    "editPrimaryTextColor",
    "editSecondaryTextColor",
    "editTertiaryTextColor",
    "editDividerColor",
    "editToolbarSurfaceColor",
    "editControlSurfaceColor",
    "editControlStrokeColor",
    "editInactiveIndicatorColor",
    "editDisabledTextColor",
    "editDisabledSurfaceColor",
    "editButtonShadowColor",
    "editAccentColor",
    "editConfirmForegroundColor",
}
missing_tokens = [token for token in sorted(required_edit_tokens) if token not in theme_source]
if missing_tokens:
    raise SystemExit(f"AppGridTheme missing edit-mode contrast tokens: {missing_tokens}")
if "private var renderedAppGridTheme: AppGridTheme" not in content_source:
    raise SystemExit("ContentView is missing the runtime theme override")
if not re.search(
    r"private\s+var\s+renderedAppGridTheme\s*:\s*AppGridTheme\s*\{.*?"
    r"editPhase\s*==\s*\.none.*?"
    r"ProEntitlementPolicy\.effectiveTheme\(for:\s*appGridTheme\).*?"
    r":\s*\.defaultLight",
    content_source,
    re.S,
):
    raise SystemExit("edit mode must temporarily render with the default light AppGrid theme")
if "let theme = renderedAppGridTheme" not in content_source:
    raise SystemExit("AppGrid background does not use the runtime rendered theme")
if "let tuning = renderedAppGridThemeTuning" not in content_source:
    raise SystemExit("AppGrid background does not use runtime theme tuning")
if "AppGridCollectionView(" in content_source and "appGridTheme: renderedAppGridTheme" not in content_source:
    raise SystemExit("AppGridCollectionView is not passed the runtime rendered theme")
if "EditAppsHeaderView(" in content_source and "theme: renderedAppGridTheme" not in content_source:
    raise SystemExit("edit apps header is not passed the runtime rendered theme")
if "theme: renderedAppGridTheme" not in content_source:
    raise SystemExit("edit mode selectable controls are not passed the runtime rendered theme")
for view_name in ["EditAppsHeaderView", "EditOperationPicker", "EditConfirmButton", "EditAppsSidebarIntroView", "EditSelectableTagItem", "EditableAppSelectionItem"]:
    if f"let theme: AppGridTheme" not in edit_views_source:
        raise SystemExit("edit mode views do not accept AppGridTheme")
    if view_name not in edit_views_source:
        raise SystemExit(f"missing edit mode view: {view_name}")
for token in ["theme.editPrimaryTextColor", "theme.editAccentColor", "theme.editControlSurfaceColor", "theme.editDisabledSurfaceColor"]:
    if token not in edit_views_source:
        raise SystemExit(f"edit mode views do not use contrast token: {token}")
if ".buttonStyle(.bordered)" in edit_views_source:
    raise SystemExit("edit mode views still rely on default bordered button styling")
if ".buttonStyle(.bordered)" in content_source and "editTagsView" in content_source:
    raise SystemExit("ContentView still relies on default bordered button styling in edit mode")
 
required_keys = {
    "settings.theme",
    "settings.themeDesc",
    "settings.themeScopeDesc",
    "theme.tuning.dark",
    "theme.tuning.light",
    "theme.tuning.desc",
    "theme.default",
    "theme.deepBlue",
    "theme.black",
    "theme.pink",
    "theme.purple",
    "theme.green",
    "theme.blue",
    "theme.colorful",
}
files = sorted(localization_dir.glob("*.json"))
if len(files) != 29:
    raise SystemExit(f"expected 29 localization files, found {len(files)}")
for path in files:
    data = json.loads(path.read_text(encoding="utf-8"))
    legacy = {"settings.darkAppGrid", "settings.darkAppGridDesc"} & set(data)
    if legacy:
        raise SystemExit(f"{path.name} still has legacy dark grid keys: {sorted(legacy)}")
    missing = required_keys - set(data)
    if missing:
        raise SystemExit(f"{path.name} missing keys: {sorted(missing)}")
    raw_values = [
        key for key in required_keys
        if str(data.get(key, "")).startswith("settings.") or str(data.get(key, "")).startswith("theme.")
    ]
    if raw_values:
        raise SystemExit(f"{path.name} has raw key values: {raw_values}")
    if data["settings.themeScopeDesc"].strip() not in data["theme.tuning.desc"]:
        raise SystemExit(f"{path.name} theme tuning description must include the theme scope copy")
 
print("PASS theme settings QA: 8 themes, Theme tab, migration, AppGrid-only rendering, glass policy, edit-mode default-theme override, and 29-language keys are present")
PY