feat: track limit budgets in a usage ledger and surface them in a Usage section
- RuleUsage + UsageLedger: per-rule, per-day minutes/opens in app-group defaults (monotonic minutes, incrementing opens, midnight rollover by day-keying); MockUsageLedger for tests and seeded UI scenarios - usage-aware status: a limit rule whose daily budget is spent on an enabled day is active (blocking) until next midnight; Hard Mode gating and app-list locking honor it; soft unblock pauses until midnight - RuleEnforcer shields spent limit rules (always Block mode) while the app runs - new Usage section under Blocked Apps: '18m of 45m used today · 27m left', '2 of 5 opens today · 3 opens left', 'Blocked until tomorrow' - new 'limits' seed scenario + UI tests
This commit is contained in:
@@ -15,6 +15,7 @@ struct AppListPickerSheet: View {
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
@Environment(RuleEnforcer.self) private var enforcer
|
||||
@Query(sort: \AppList.createdAt) private var lists: [AppList]
|
||||
@Query private var rules: [BlockingRule]
|
||||
|
||||
@@ -22,10 +23,11 @@ struct AppListPickerSheet: View {
|
||||
@State private var creatingList = false
|
||||
@State private var deletionBlocked = false
|
||||
|
||||
/// While any hard-mode rule is actively blocking, lists are read-only —
|
||||
/// editing one would be a back door out of the hard block.
|
||||
/// While any hard-mode rule is actively blocking (by the clock or a spent
|
||||
/// limit budget), lists are read-only — editing one would be a back door
|
||||
/// out of the hard block.
|
||||
private var listsLocked: Bool {
|
||||
!RulePolicy.canEditAppLists(rules: rules)
|
||||
!RulePolicy.canEditAppLists(rules: rules, usageFor: { enforcer.usage(for: $0) })
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
||||
Reference in New Issue
Block a user