refactor: model rule options as a per-kind sum type
Replace the wide BlockingRule/RuleDraft "god struct" — where every option existed for every kind — with a RuleConfiguration sum type that carries only the options each kind actually has: .schedule(ScheduleConfig: window + selectionMode + blockAdultContent) .timeLimit(TimeLimitConfig: dailyLimitMinutes) .openLimit(OpenLimitConfig: maxOpens) Name, days, Hard Mode, app list, and pause stay common to all kinds. This makes illegal states unrepresentable: Block / Allow Only and Block Adult Content are now structurally Schedule-only. User-visible behavior change: the Time Limit and Open Limit editors no longer offer a Block Adult Content toggle, and their detail sheets drop the "Adult websites" row — those never made sense for a usage budget. Limit rules are always Block and never engage the web-content filter. BlockingRule keeps flat columns as raw persistence behind a computed `configuration` bridge (lowest SwiftData risk; the cross-process RuleSnapshot wire format and the Screen Time extensions are untouched). Logic, the editors, and the detail sheet all switch on the sum type. Spec (§1, §3.5/§3.6, §5.2) updated first; tests reworked to the new API with new structural-guarantee unit tests and a UI test asserting the Time Limit editor/detail omit adult content. Full suite green (180 tests).
This commit is contained in:
@@ -41,7 +41,9 @@ struct RuleSnapshotTests {
|
||||
let context = try makeInMemoryContext()
|
||||
let list = AppList(name: "Distractions", selectionData: Data([9]), selectionCount: 1)
|
||||
let rule = BlockingRule(
|
||||
name: "Gate Keeper", kind: .openLimit, days: Weekday.weekends, maxOpens: 3)
|
||||
name: "Gate Keeper",
|
||||
configuration: .openLimit(OpenLimitConfig(maxOpens: 3)),
|
||||
days: Weekday.weekends)
|
||||
context.insert(list)
|
||||
context.insert(rule)
|
||||
rule.appList = list
|
||||
@@ -135,7 +137,8 @@ struct RuleSchedulerTests {
|
||||
private func limitRule(kind: RuleKind, name: String) throws -> BlockingRule {
|
||||
let context = try makeInMemoryContext()
|
||||
let list = AppList(name: "Apps", selectionData: Data([1]), selectionCount: 1)
|
||||
let rule = BlockingRule(name: name, kind: kind, days: Weekday.everyDay)
|
||||
let rule = BlockingRule(
|
||||
name: name, configuration: .default(for: kind), days: Weekday.everyDay)
|
||||
context.insert(list)
|
||||
context.insert(rule)
|
||||
rule.appList = list
|
||||
@@ -148,7 +151,9 @@ struct RuleSchedulerTests {
|
||||
) throws -> BlockingRule {
|
||||
let context = try makeInMemoryContext()
|
||||
let rule = BlockingRule(
|
||||
name: name, kind: .schedule, days: days, startMinutes: start, endMinutes: end)
|
||||
name: name,
|
||||
configuration: .schedule(ScheduleConfig(startMinutes: start, endMinutes: end)),
|
||||
days: days)
|
||||
context.insert(rule)
|
||||
if withApps {
|
||||
let list = AppList(name: "Apps", selectionData: Data([7]), selectionCount: 1)
|
||||
@@ -186,7 +191,7 @@ struct RuleSchedulerTests {
|
||||
let (scheduler, monitor, _) = makeScheduler()
|
||||
let context = try makeInMemoryContext()
|
||||
let applessSchedule = BlockingRule(name: "Work Time")
|
||||
let applessLimit = BlockingRule(name: "Empty", kind: .timeLimit)
|
||||
let applessLimit = BlockingRule(name: "Empty", configuration: .timeLimit(TimeLimitConfig()))
|
||||
context.insert(applessSchedule)
|
||||
context.insert(applessLimit)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user