feat(ios,android): P2 wave, git panel, token UX, per-host WS token, docs
App layer, four sequential slices (a shared .xcodeproj means adding files regenerates it, so these could not run in parallel): - token UX end to end: pairing prompts for a token when a host 401s, POST /auth validates it, and 204-without-Set-Cookie is correctly read as "this server has auth disabled" rather than "authenticated". A host paired before the token was turned on recovers by re-pairing in place. Remove-host now exists and finally gives PushRegistrar.handleHostRemoved a caller. - project git panel + worktree lifecycle (T-iOS-32) + claude --resume history — the parity gap with Android and the web front end. - terminal search (T-iOS-33) and voice PTT (T-iOS-31) with an epoch guard so a session switch between dictation and confirm cannot inject into the wrong session. - theme + Dynamic Type (T-iOS-34) and web ?join= interop (T-iOS-35). RootView no longer hard-locks .preferredColorScheme(.dark). Also unpins SwiftTerm to 1.15.0 by dropping the local hasActiveSelection that collided with the upstream one, verified green from a fresh derivedDataPath. Includes the two HIGH fixes the security review found: - iOS resolved the WS token host-independently, so a token-gated host sitting next to an open one could never open a terminal and no on-screen remedy could fix it. Now one transport per host; cross-host leakage is structurally impossible since both read paths return only that host's own value. - Android reported the host's own git-credential 401 (git-ops.ts:108, "Push authentication required on the host.") as "your access token is wrong", because a blanket 401 mapping ran ahead of the per-route one. Git-write routes are now ROUTE_DEFINED and keep the server's message. And the doc sync: README/ios README no longer claim the client is unmerged on feat/ios-client, the Clients section finally lists Android, and the plan checkboxes reflect what is actually built. iOS 534 app tests + 452 package tests; Android 687 tests.
This commit is contained in:
@@ -37,6 +37,23 @@ extension DS {
|
||||
|
||||
/// The canonical meta-number font: caption-sized mono + tabular.
|
||||
static let metaMono = mono(.caption)
|
||||
|
||||
// ── Dynamic Type clamp for dense numerics (T-iOS-34) ────────────────
|
||||
|
||||
/// Upper bound applied to **numeric / meta** text only (telemetry chips,
|
||||
/// `dsMetaText` rows: `ctx 92% · $0.1234 · 161×50`).
|
||||
///
|
||||
/// Prose scales all the way to `.accessibility5` — that is the point of
|
||||
/// Dynamic Type and nothing here caps it. Tabular numerics are different:
|
||||
/// they live in one-line rows next to a status badge, and at AX4/AX5 a
|
||||
/// single chip row becomes three wrapped lines that push the row's real
|
||||
/// content off screen. Capping them at `.accessibility2` (already ~2×
|
||||
/// the default size) keeps the meta line legible AND keeps the row's
|
||||
/// primary text — the session name — visible.
|
||||
///
|
||||
/// Pinned in `DynamicTypeLayoutTests` both as a policy value and
|
||||
/// behaviorally (AX2 and AX5 must measure the same height).
|
||||
static let numericClamp: DynamicTypeSize = .accessibility2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,11 +61,15 @@ extension DS {
|
||||
|
||||
/// Secondary + monospaced-tabular styling for a row's numeric meta line
|
||||
/// ("N 台设备在看 · 161×50"). Apply via `.dsMetaText()`.
|
||||
///
|
||||
/// T-iOS-34 · carries the `numericClamp` so every meta line in the app gets the
|
||||
/// same Dynamic Type ceiling from ONE place (per-screen clamps would drift).
|
||||
struct MetaText: ViewModifier {
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.font(DS.Typography.metaMono)
|
||||
.foregroundStyle(DS.Palette.textSecondary)
|
||||
.dynamicTypeSize(...DS.Typography.numericClamp)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user