Files
OpenAppLock/Shared/RuleConfiguration.swift
Brendan Chen d005ed4fb1 docs: remove references to the source app and recording
Prepare for open-sourcing: scrub the prior-art attribution from the spec,
agent guide, and code comments so the project documents its own behavior.

- Reword RULES_FEATURE_SPEC.md to describe OpenAppLock's rules feature
  directly (drop the screen-recording source line and "as observed"/
  "not demoed"/"as shown" framing)
- Replace "the reference app/UI/style/defaults" comments and test names
  with direct descriptions of the behavior
- No behavior change; comments, docs, and @Test display names only

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 22:23:14 -04:00

91 lines
2.8 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// RuleConfiguration.swift
// OpenAppLock
//
import Foundation
/// The kind-specific options of a rule, modelled as a sum type so a rule can
/// only carry the options that belong to its kind. This makes illegal states
/// unrepresentable: an Open Limit rule cannot hold a time window, a Time Limit
/// rule cannot hold a Block/Allow-Only mode, and neither limit kind can hold
/// Block Adult Content those are Schedule-only options.
///
/// Kind-common attributes (name, days, hardMode, isEnabled, appList,
/// pausedUntil) live on the owning `BlockingRule` / `RuleDraft`, not here.
enum RuleConfiguration: Hashable, Sendable {
case schedule(ScheduleConfig)
case timeLimit(TimeLimitConfig)
case openLimit(OpenLimitConfig)
var kind: RuleKind {
switch self {
case .schedule: .schedule
case .timeLimit: .timeLimit
case .openLimit: .openLimit
}
}
/// The default configuration for a brand-new rule of the given kind
/// (95 schedule, 45m/day, 5 opens/day).
static func `default`(for kind: RuleKind) -> RuleConfiguration {
switch kind {
case .schedule: .schedule(ScheduleConfig())
case .timeLimit: .timeLimit(TimeLimitConfig())
case .openLimit: .openLimit(OpenLimitConfig())
}
}
var scheduleConfig: ScheduleConfig? {
if case .schedule(let config) = self { config } else { nil }
}
var timeLimitConfig: TimeLimitConfig? {
if case .timeLimit(let config) = self { config } else { nil }
}
var openLimitConfig: OpenLimitConfig? {
if case .openLimit(let config) = self { config } else { nil }
}
}
/// Schedule-rule options: a recurring time window, how the app list is
/// interpreted, and whether the adult-website filter engages while the window
/// is active. A window whose end is at or before its start crosses midnight.
struct ScheduleConfig: Hashable, Sendable {
var startMinutes: Int
var endMinutes: Int
var selectionMode: SelectionMode
var blockAdultContent: Bool
init(
startMinutes: Int = 9 * 60,
endMinutes: Int = 17 * 60,
selectionMode: SelectionMode = .block,
blockAdultContent: Bool = false
) {
self.startMinutes = startMinutes
self.endMinutes = endMinutes
self.selectionMode = selectionMode
self.blockAdultContent = blockAdultContent
}
}
/// Time Limit option: a daily cumulative-usage budget in minutes.
struct TimeLimitConfig: Hashable, Sendable {
var dailyLimitMinutes: Int
init(dailyLimitMinutes: Int = 45) {
self.dailyLimitMinutes = dailyLimitMinutes
}
}
/// Open Limit option: a daily budget of app opens.
struct OpenLimitConfig: Hashable, Sendable {
var maxOpens: Int
init(maxOpens: Int = 5) {
self.maxOpens = maxOpens
}
}