feat: replace the preset gallery with original schedules

Swap the six suggested rules for an original set so the preset offerings
are OpenAppLock's own:

- Focus Time: Morning Focus (08:00-11:30 weekdays), Deep Work (13:30-16:00 weekdays)
- Rest & Recharge: Evening Reset (21:00-23:00), Lights Out (23:00-06:30, crosses midnight)
- Healthy Balance: Family Dinner (18:00-19:30), Screen-Free Sunday (09:00-20:00, Sundays)

Update the spec preset gallery (sections 1, 3.3, 4) and the preset
unit/UI tests to the new ids, names, and times. Build green; the preset
draft unit test and the two preset UI tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-13 22:32:05 -04:00
parent d005ed4fb1
commit 44e6086e29
4 changed files with 51 additions and 51 deletions

View File

@@ -22,7 +22,7 @@ struct RulePreset: Identifiable, Hashable, Sendable {
}
}
/// A titled group of presets ("Get More Done", "Sleep, Relax and Reset", ).
/// A titled group of presets ("Focus Time", "Rest & Recharge", ).
struct RulePresetSection: Identifiable, Hashable, Sendable {
let id: String
let title: String
@@ -31,20 +31,20 @@ struct RulePresetSection: Identifiable, Hashable, Sendable {
static let all: [RulePresetSection] = [
RulePresetSection(
id: "productivity",
title: "Get More Done",
subtitle: "Maximize your productivity while staying sane.",
id: "focus",
title: "Focus Time",
subtitle: "Protect your deep-work hours.",
presets: [
RulePreset(
id: "work-time", name: "Work Time",
startMinutes: 9 * 60, endMinutes: 17 * 60, days: Weekday.weekdays,
symbolName: "briefcase.fill",
gradientTop: Color(red: 0.16, green: 0.27, blue: 0.22),
gradientBottom: Color(red: 0.05, green: 0.10, blue: 0.08)
id: "morning-focus", name: "Morning Focus",
startMinutes: 8 * 60, endMinutes: 11 * 60 + 30, days: Weekday.weekdays,
symbolName: "sunrise.fill",
gradientTop: Color(red: 0.33, green: 0.23, blue: 0.13),
gradientBottom: Color(red: 0.12, green: 0.07, blue: 0.03)
),
RulePreset(
id: "laser-focus", name: "Laser Focus",
startMinutes: 14 * 60, endMinutes: 18 * 60, days: Weekday.weekdays,
id: "deep-work", name: "Deep Work",
startMinutes: 13 * 60 + 30, endMinutes: 16 * 60, days: Weekday.weekdays,
symbolName: "scope",
gradientTop: Color(red: 0.13, green: 0.20, blue: 0.33),
gradientBottom: Color(red: 0.04, green: 0.06, blue: 0.12)
@@ -52,20 +52,20 @@ struct RulePresetSection: Identifiable, Hashable, Sendable {
]
),
RulePresetSection(
id: "sleep",
title: "Sleep, Relax and Reset",
subtitle: "Sleep better, rise refreshed.",
id: "rest",
title: "Rest & Recharge",
subtitle: "Wind the day down on schedule.",
presets: [
RulePreset(
id: "wind-down", name: "Wind Down",
startMinutes: 20 * 60, endMinutes: 22 * 60, days: Weekday.everyDay,
id: "evening-reset", name: "Evening Reset",
startMinutes: 21 * 60, endMinutes: 23 * 60, days: Weekday.everyDay,
symbolName: "moon.haze.fill",
gradientTop: Color(red: 0.25, green: 0.18, blue: 0.33),
gradientBottom: Color(red: 0.08, green: 0.05, blue: 0.12)
),
RulePreset(
id: "deep-sleep", name: "Deep Sleep",
startMinutes: 22 * 60, endMinutes: 6 * 60, days: Weekday.everyDay,
id: "lights-out", name: "Lights Out",
startMinutes: 23 * 60, endMinutes: 6 * 60 + 30, days: Weekday.everyDay,
symbolName: "moon.zzz.fill",
gradientTop: Color(red: 0.10, green: 0.13, blue: 0.30),
gradientBottom: Color(red: 0.02, green: 0.03, blue: 0.10)
@@ -73,21 +73,21 @@ struct RulePresetSection: Identifiable, Hashable, Sendable {
]
),
RulePresetSection(
id: "habits",
title: "Build Healthy Habits",
subtitle: "Spend time on important things.",
id: "balance",
title: "Healthy Balance",
subtitle: "Make room for what matters.",
presets: [
RulePreset(
id: "reading-time", name: "Reading Time",
startMinutes: 19 * 60 + 45, endMinutes: 20 * 60 + 45, days: Weekday.everyDay,
symbolName: "book.fill",
gradientTop: Color(red: 0.33, green: 0.23, blue: 0.13),
gradientBottom: Color(red: 0.12, green: 0.07, blue: 0.03)
id: "family-dinner", name: "Family Dinner",
startMinutes: 18 * 60, endMinutes: 19 * 60 + 30, days: Weekday.everyDay,
symbolName: "fork.knife",
gradientTop: Color(red: 0.16, green: 0.27, blue: 0.22),
gradientBottom: Color(red: 0.05, green: 0.10, blue: 0.08)
),
RulePreset(
id: "gym-time", name: "Gym Time",
startMinutes: 17 * 60 + 30, endMinutes: 18 * 60 + 30, days: Weekday.everyDay,
symbolName: "figure.run",
id: "screen-free-sunday", name: "Screen-Free Sunday",
startMinutes: 9 * 60, endMinutes: 20 * 60, days: [.sunday],
symbolName: "leaf.fill",
gradientTop: Color(red: 0.13, green: 0.30, blue: 0.30),
gradientBottom: Color(red: 0.03, green: 0.10, blue: 0.10)
),

View File

@@ -177,12 +177,12 @@ struct RuleDraftTests {
let preset = try #require(
RulePresetSection.all
.flatMap(\.presets)
.first { $0.id == "deep-sleep" }
.first { $0.id == "lights-out" }
)
let draft = RuleDraft(preset: preset)
#expect(draft.name == "Deep Sleep")
#expect(draft.scheduleConfig.startMinutes == 22 * 60)
#expect(draft.scheduleConfig.endMinutes == 6 * 60)
#expect(draft.name == "Lights Out")
#expect(draft.scheduleConfig.startMinutes == 23 * 60)
#expect(draft.scheduleConfig.endMinutes == 6 * 60 + 30)
#expect(draft.kind == .schedule)
}
}

View File

@@ -37,11 +37,11 @@ final class RuleCreationUITests: XCTestCase {
app.goToRulesTab()
app.buttons["newRuleButton"].waitToAppear().tap()
app.buttons["preset-work-time"].waitToAppear().tap()
XCTAssertEqual(app.staticTexts["ruleEditorTitle"].waitToAppear().label, "Work Time")
app.buttons["preset-morning-focus"].waitToAppear().tap()
XCTAssertEqual(app.staticTexts["ruleEditorTitle"].waitToAppear().label, "Morning Focus")
app.buttons["commitRuleButton"].waitToAppear().tap()
app.buttons["ruleCard-Work Time"].waitToAppear()
app.buttons["ruleCard-Morning Focus"].waitToAppear()
}
func testRenameRuleInEditor() throws {
@@ -190,8 +190,8 @@ final class RuleCreationUITests: XCTestCase {
app.buttons["ruleKind-schedule"].waitToAppear()
XCTAssertTrue(app.buttons["ruleKind-timeLimit"].exists)
XCTAssertTrue(app.buttons["ruleKind-openLimit"].exists)
XCTAssertTrue(app.staticTexts["Get More Done"].exists)
XCTAssertTrue(app.buttons["preset-work-time"].exists)
XCTAssertTrue(app.buttons["preset-laser-focus"].exists)
XCTAssertTrue(app.staticTexts["Focus Time"].exists)
XCTAssertTrue(app.buttons["preset-morning-focus"].exists)
XCTAssertTrue(app.buttons["preset-deep-work"].exists)
}
}

View File

@@ -20,7 +20,7 @@ offered, presented on the "New Rule" sheet:
**Common attributes** — present for *every* rule kind:
- **Name** — user-editable, free text (presets: "Work Time", "Weekend Zen", "Locked In", "Sleep", "Wind Down", "Deep Sleep", "Laser Focus", "Reading Time", "Gym Time"; defaults for new rules: "In the Zone" (schedule), "Time Keeper" (time limit))
- **Name** — user-editable, free text (presets: "Morning Focus", "Deep Work", "Evening Reset", "Lights Out", "Family Dinner", "Screen-Free Sunday"; defaults for new rules: "In the Zone" (schedule), "Time Keeper" (time limit))
- **Days of week** — 7-day toggle set, summarized as "Weekdays" / "Weekends" / "Every day" / custom
- **App List** *(OpenAppLock refinement)* — each rule points to exactly one
**App List**: a named, reusable selection of apps/categories/websites stored
@@ -145,15 +145,15 @@ Presented from "+ New". Full-height sheet, scrollable.
defaults.
- **Preset gallery** — vertically scrolling sections, each with a bold header
+ grey subtitle, containing a 2-up grid of photo-backed preset cards:
- **Get More Done** — "Maximize your productivity while staying sane."
- Work Time (Schedule 09:0017:00, Block, weekdays)
- Laser Focus (Schedule 14:0018:00, Block)
- **Sleep, Relax and Reset** — "Sleep better, rise refreshed."
- Wind Down (Schedule 20:0022:00, Block)
- Deep Sleep (Schedule 22:0006:00, Block)
- **Build Healthy Habits** — "Spend time on important things."
- Reading Time (Schedule ~19:4520:45, Block)
- Gym Time (Schedule 17:3018:30, Block)
- **Focus Time** — "Protect your deep-work hours."
- Morning Focus (Schedule 08:0011:30, Block, weekdays)
- Deep Work (Schedule 13:3016:00, Block, weekdays)
- **Rest & Recharge** — "Wind the day down on schedule."
- Evening Reset (Schedule 21:0023:00, Block)
- Lights Out (Schedule 23:0006:30, Block)
- **Healthy Balance** — "Make room for what matters."
- Family Dinner (Schedule 18:0019:30, Block)
- Screen-Free Sunday (Schedule 09:0020:00, Block, Sundays)
- **Preset card** anatomy: full-bleed background photo, top row icon pair
(type → shield), time range caption, name, "Block" + suggested app icons,
and a circular "+" button bottom-right. Tapping anywhere opens the
@@ -266,8 +266,8 @@ Full-height sheet:
## 4. Behavioral spec
1. **Activation** — a Schedule rule becomes active at `From` on an enabled
day and deactivates at `To` (windows crossing midnight, e.g. 22:0006:00,
must be supported — Deep Sleep preset does this).
day and deactivates at `To` (windows crossing midnight, e.g. 23:0006:30,
must be supported — Lights Out preset does this).
2. **While active** — the rule's app selection is shielded (and, when the
rule's Block Adult Content toggle is on, Screen Time's adult-website
filter is engaged for the same span); blocked apps also