feat(keyboard): harden clipboard command and add What's New sheet

Stabilize clipboard long-press prepare/resume across paste alerts and cold start, add an in-app release-notes sheet with remote bilingual HTML, localize typing input settings, and bump build to 55.
This commit is contained in:
Rocky
2026-08-08 00:20:42 +08:00
parent f197b68573
commit 9da32b81e9
45 changed files with 3670 additions and 422 deletions
@@ -330,4 +330,113 @@ final class FlowHandoffPolicyTests: XCTestCase {
.silence
)
}
// MARK: - Proactive PiP arm (no re-jump)
func testProactivePiPArmSkippedWhenHostReady() {
XCTAssertFalse(
FlowHandoffPolicy.shouldProactivePiPArm(
hostReady: true,
snapshotReason: .ready,
sessionActive: true,
hostReachable: true,
hostStale: false,
withinReadyGrace: false,
inCooldown: false
)
)
}
func testProactivePiPArmSkippedWhileStartingOrCooldown() {
XCTAssertFalse(
FlowHandoffPolicy.shouldProactivePiPArm(
hostReady: false,
snapshotReason: .starting,
sessionActive: true,
hostReachable: true,
hostStale: false,
withinReadyGrace: false,
inCooldown: false
),
"Warming session must not re-open startflow on Voice tab"
)
XCTAssertFalse(
FlowHandoffPolicy.shouldProactivePiPArm(
hostReady: false,
snapshotReason: nil,
sessionActive: false,
hostReachable: false,
hostStale: false,
withinReadyGrace: false,
inCooldown: true
),
"Cooldown after a recent arm must block re-jump"
)
}
func testProactivePiPArmAllowsForceQuitZombieSessionAfterHeartbeatGrace() {
// sessionActive still true, but heartbeat gone > 8s allow one arm.
XCTAssertTrue(
FlowHandoffPolicy.shouldProactivePiPArm(
hostReady: false,
snapshotReason: .ready,
sessionActive: true,
hostReachable: false,
hostStale: false,
withinReadyGrace: false,
inCooldown: false,
heartbeatStaleness: FlowHandoffPolicy.proactiveUnreachableArmGrace
)
)
// Brief switcher flap (< grace) must NOT re-jump.
XCTAssertFalse(
FlowHandoffPolicy.shouldProactivePiPArm(
hostReady: false,
snapshotReason: .ready,
sessionActive: true,
hostReachable: false,
hostStale: false,
withinReadyGrace: false,
inCooldown: false,
heartbeatStaleness: 3
)
)
// Cooldown still wins after a recent arm.
XCTAssertFalse(
FlowHandoffPolicy.shouldProactivePiPArm(
hostReady: false,
snapshotReason: .ready,
sessionActive: true,
hostReachable: false,
hostStale: false,
withinReadyGrace: false,
inCooldown: true,
heartbeatStaleness: 30
)
)
}
func testProactivePiPArmAllowedWhenHostTrulyDead() {
XCTAssertTrue(
FlowHandoffPolicy.shouldProactivePiPArm(
hostReady: false,
snapshotReason: .noSession,
sessionActive: false,
hostReachable: false,
hostStale: false,
withinReadyGrace: false,
inCooldown: false
)
)
}
func testPiPArmCooldownRoundTrip() {
let suite = "PiPArmCooldown.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suite)!
defer { defaults.removePersistentDomain(forName: suite) }
XCTAssertFalse(FlowSessionBridge.isPiPArmInCooldown(defaults: defaults))
FlowSessionBridge.markPiPArmAttempt(defaults: defaults)
XCTAssertTrue(FlowSessionBridge.isPiPArmInCooldown(defaults: defaults))
}
}