The shield titled itself with the first enabled rule whose selection contained the app, regardless of whether that rule was the one actually blocking. When several rules covered the same app (e.g. a dormant schedule + the active limit) it named the wrong rule. Drop the rule-name lookup entirely: every shield now carries a generic "App Blocked" title. Open-limit shields keep their functional detail (running count + "Open (N left)" button) beneath that title. The text-only decision moves into a pure, unit-tested ShieldPresentation in Shared/, and the now-dead ShieldLookup.snapshot(containingApplication:) is removed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
33 lines
1.1 KiB
Swift
33 lines
1.1 KiB
Swift
//
|
|
// ShieldLookup.swift
|
|
// OpenAppLock
|
|
//
|
|
|
|
import FamilyControls
|
|
import Foundation
|
|
import ManagedSettings
|
|
|
|
/// Matches shielded tokens back to the rule that shields them, so the shield
|
|
/// UI can offer "Open" with the right counts for open-limit rules.
|
|
enum ShieldLookup {
|
|
static func openLimitSnapshot(
|
|
containingApplication token: ApplicationToken, in snapshots: [RuleSnapshot]
|
|
) -> RuleSnapshot? {
|
|
snapshots.first { snapshot in
|
|
guard snapshot.kind == .openLimit, snapshot.isEnabled else { return false }
|
|
return AppSelectionCodec.decode(snapshot.selectionData)
|
|
.applicationTokens.contains(token)
|
|
}
|
|
}
|
|
|
|
static func openLimitSnapshot(
|
|
containingCategory token: ActivityCategoryToken, in snapshots: [RuleSnapshot]
|
|
) -> RuleSnapshot? {
|
|
snapshots.first { snapshot in
|
|
guard snapshot.kind == .openLimit, snapshot.isEnabled else { return false }
|
|
return AppSelectionCodec.decode(snapshot.selectionData)
|
|
.categoryTokens.contains(token)
|
|
}
|
|
}
|
|
}
|