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:
@@ -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 {
|
struct RulePresetSection: Identifiable, Hashable, Sendable {
|
||||||
let id: String
|
let id: String
|
||||||
let title: String
|
let title: String
|
||||||
@@ -31,20 +31,20 @@ struct RulePresetSection: Identifiable, Hashable, Sendable {
|
|||||||
|
|
||||||
static let all: [RulePresetSection] = [
|
static let all: [RulePresetSection] = [
|
||||||
RulePresetSection(
|
RulePresetSection(
|
||||||
id: "productivity",
|
id: "focus",
|
||||||
title: "Get More Done",
|
title: "Focus Time",
|
||||||
subtitle: "Maximize your productivity while staying sane.",
|
subtitle: "Protect your deep-work hours.",
|
||||||
presets: [
|
presets: [
|
||||||
RulePreset(
|
RulePreset(
|
||||||
id: "work-time", name: "Work Time",
|
id: "morning-focus", name: "Morning Focus",
|
||||||
startMinutes: 9 * 60, endMinutes: 17 * 60, days: Weekday.weekdays,
|
startMinutes: 8 * 60, endMinutes: 11 * 60 + 30, days: Weekday.weekdays,
|
||||||
symbolName: "briefcase.fill",
|
symbolName: "sunrise.fill",
|
||||||
gradientTop: Color(red: 0.16, green: 0.27, blue: 0.22),
|
gradientTop: Color(red: 0.33, green: 0.23, blue: 0.13),
|
||||||
gradientBottom: Color(red: 0.05, green: 0.10, blue: 0.08)
|
gradientBottom: Color(red: 0.12, green: 0.07, blue: 0.03)
|
||||||
),
|
),
|
||||||
RulePreset(
|
RulePreset(
|
||||||
id: "laser-focus", name: "Laser Focus",
|
id: "deep-work", name: "Deep Work",
|
||||||
startMinutes: 14 * 60, endMinutes: 18 * 60, days: Weekday.weekdays,
|
startMinutes: 13 * 60 + 30, endMinutes: 16 * 60, days: Weekday.weekdays,
|
||||||
symbolName: "scope",
|
symbolName: "scope",
|
||||||
gradientTop: Color(red: 0.13, green: 0.20, blue: 0.33),
|
gradientTop: Color(red: 0.13, green: 0.20, blue: 0.33),
|
||||||
gradientBottom: Color(red: 0.04, green: 0.06, blue: 0.12)
|
gradientBottom: Color(red: 0.04, green: 0.06, blue: 0.12)
|
||||||
@@ -52,20 +52,20 @@ struct RulePresetSection: Identifiable, Hashable, Sendable {
|
|||||||
]
|
]
|
||||||
),
|
),
|
||||||
RulePresetSection(
|
RulePresetSection(
|
||||||
id: "sleep",
|
id: "rest",
|
||||||
title: "Sleep, Relax and Reset",
|
title: "Rest & Recharge",
|
||||||
subtitle: "Sleep better, rise refreshed.",
|
subtitle: "Wind the day down on schedule.",
|
||||||
presets: [
|
presets: [
|
||||||
RulePreset(
|
RulePreset(
|
||||||
id: "wind-down", name: "Wind Down",
|
id: "evening-reset", name: "Evening Reset",
|
||||||
startMinutes: 20 * 60, endMinutes: 22 * 60, days: Weekday.everyDay,
|
startMinutes: 21 * 60, endMinutes: 23 * 60, days: Weekday.everyDay,
|
||||||
symbolName: "moon.haze.fill",
|
symbolName: "moon.haze.fill",
|
||||||
gradientTop: Color(red: 0.25, green: 0.18, blue: 0.33),
|
gradientTop: Color(red: 0.25, green: 0.18, blue: 0.33),
|
||||||
gradientBottom: Color(red: 0.08, green: 0.05, blue: 0.12)
|
gradientBottom: Color(red: 0.08, green: 0.05, blue: 0.12)
|
||||||
),
|
),
|
||||||
RulePreset(
|
RulePreset(
|
||||||
id: "deep-sleep", name: "Deep Sleep",
|
id: "lights-out", name: "Lights Out",
|
||||||
startMinutes: 22 * 60, endMinutes: 6 * 60, days: Weekday.everyDay,
|
startMinutes: 23 * 60, endMinutes: 6 * 60 + 30, days: Weekday.everyDay,
|
||||||
symbolName: "moon.zzz.fill",
|
symbolName: "moon.zzz.fill",
|
||||||
gradientTop: Color(red: 0.10, green: 0.13, blue: 0.30),
|
gradientTop: Color(red: 0.10, green: 0.13, blue: 0.30),
|
||||||
gradientBottom: Color(red: 0.02, green: 0.03, blue: 0.10)
|
gradientBottom: Color(red: 0.02, green: 0.03, blue: 0.10)
|
||||||
@@ -73,21 +73,21 @@ struct RulePresetSection: Identifiable, Hashable, Sendable {
|
|||||||
]
|
]
|
||||||
),
|
),
|
||||||
RulePresetSection(
|
RulePresetSection(
|
||||||
id: "habits",
|
id: "balance",
|
||||||
title: "Build Healthy Habits",
|
title: "Healthy Balance",
|
||||||
subtitle: "Spend time on important things.",
|
subtitle: "Make room for what matters.",
|
||||||
presets: [
|
presets: [
|
||||||
RulePreset(
|
RulePreset(
|
||||||
id: "reading-time", name: "Reading Time",
|
id: "family-dinner", name: "Family Dinner",
|
||||||
startMinutes: 19 * 60 + 45, endMinutes: 20 * 60 + 45, days: Weekday.everyDay,
|
startMinutes: 18 * 60, endMinutes: 19 * 60 + 30, days: Weekday.everyDay,
|
||||||
symbolName: "book.fill",
|
symbolName: "fork.knife",
|
||||||
gradientTop: Color(red: 0.33, green: 0.23, blue: 0.13),
|
gradientTop: Color(red: 0.16, green: 0.27, blue: 0.22),
|
||||||
gradientBottom: Color(red: 0.12, green: 0.07, blue: 0.03)
|
gradientBottom: Color(red: 0.05, green: 0.10, blue: 0.08)
|
||||||
),
|
),
|
||||||
RulePreset(
|
RulePreset(
|
||||||
id: "gym-time", name: "Gym Time",
|
id: "screen-free-sunday", name: "Screen-Free Sunday",
|
||||||
startMinutes: 17 * 60 + 30, endMinutes: 18 * 60 + 30, days: Weekday.everyDay,
|
startMinutes: 9 * 60, endMinutes: 20 * 60, days: [.sunday],
|
||||||
symbolName: "figure.run",
|
symbolName: "leaf.fill",
|
||||||
gradientTop: Color(red: 0.13, green: 0.30, blue: 0.30),
|
gradientTop: Color(red: 0.13, green: 0.30, blue: 0.30),
|
||||||
gradientBottom: Color(red: 0.03, green: 0.10, blue: 0.10)
|
gradientBottom: Color(red: 0.03, green: 0.10, blue: 0.10)
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -177,12 +177,12 @@ struct RuleDraftTests {
|
|||||||
let preset = try #require(
|
let preset = try #require(
|
||||||
RulePresetSection.all
|
RulePresetSection.all
|
||||||
.flatMap(\.presets)
|
.flatMap(\.presets)
|
||||||
.first { $0.id == "deep-sleep" }
|
.first { $0.id == "lights-out" }
|
||||||
)
|
)
|
||||||
let draft = RuleDraft(preset: preset)
|
let draft = RuleDraft(preset: preset)
|
||||||
#expect(draft.name == "Deep Sleep")
|
#expect(draft.name == "Lights Out")
|
||||||
#expect(draft.scheduleConfig.startMinutes == 22 * 60)
|
#expect(draft.scheduleConfig.startMinutes == 23 * 60)
|
||||||
#expect(draft.scheduleConfig.endMinutes == 6 * 60)
|
#expect(draft.scheduleConfig.endMinutes == 6 * 60 + 30)
|
||||||
#expect(draft.kind == .schedule)
|
#expect(draft.kind == .schedule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ final class RuleCreationUITests: XCTestCase {
|
|||||||
app.goToRulesTab()
|
app.goToRulesTab()
|
||||||
app.buttons["newRuleButton"].waitToAppear().tap()
|
app.buttons["newRuleButton"].waitToAppear().tap()
|
||||||
|
|
||||||
app.buttons["preset-work-time"].waitToAppear().tap()
|
app.buttons["preset-morning-focus"].waitToAppear().tap()
|
||||||
XCTAssertEqual(app.staticTexts["ruleEditorTitle"].waitToAppear().label, "Work Time")
|
XCTAssertEqual(app.staticTexts["ruleEditorTitle"].waitToAppear().label, "Morning Focus")
|
||||||
|
|
||||||
app.buttons["commitRuleButton"].waitToAppear().tap()
|
app.buttons["commitRuleButton"].waitToAppear().tap()
|
||||||
app.buttons["ruleCard-Work Time"].waitToAppear()
|
app.buttons["ruleCard-Morning Focus"].waitToAppear()
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRenameRuleInEditor() throws {
|
func testRenameRuleInEditor() throws {
|
||||||
@@ -190,8 +190,8 @@ final class RuleCreationUITests: XCTestCase {
|
|||||||
app.buttons["ruleKind-schedule"].waitToAppear()
|
app.buttons["ruleKind-schedule"].waitToAppear()
|
||||||
XCTAssertTrue(app.buttons["ruleKind-timeLimit"].exists)
|
XCTAssertTrue(app.buttons["ruleKind-timeLimit"].exists)
|
||||||
XCTAssertTrue(app.buttons["ruleKind-openLimit"].exists)
|
XCTAssertTrue(app.buttons["ruleKind-openLimit"].exists)
|
||||||
XCTAssertTrue(app.staticTexts["Get More Done"].exists)
|
XCTAssertTrue(app.staticTexts["Focus Time"].exists)
|
||||||
XCTAssertTrue(app.buttons["preset-work-time"].exists)
|
XCTAssertTrue(app.buttons["preset-morning-focus"].exists)
|
||||||
XCTAssertTrue(app.buttons["preset-laser-focus"].exists)
|
XCTAssertTrue(app.buttons["preset-deep-work"].exists)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ offered, presented on the "New Rule" sheet:
|
|||||||
|
|
||||||
**Common attributes** — present for *every* rule kind:
|
**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
|
- **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** *(OpenAppLock refinement)* — each rule points to exactly one
|
||||||
**App List**: a named, reusable selection of apps/categories/websites stored
|
**App List**: a named, reusable selection of apps/categories/websites stored
|
||||||
@@ -145,15 +145,15 @@ Presented from "+ New". Full-height sheet, scrollable.
|
|||||||
defaults.
|
defaults.
|
||||||
- **Preset gallery** — vertically scrolling sections, each with a bold header
|
- **Preset gallery** — vertically scrolling sections, each with a bold header
|
||||||
+ grey subtitle, containing a 2-up grid of photo-backed preset cards:
|
+ grey subtitle, containing a 2-up grid of photo-backed preset cards:
|
||||||
- **Get More Done** — "Maximize your productivity while staying sane."
|
- **Focus Time** — "Protect your deep-work hours."
|
||||||
- Work Time (Schedule 09:00–17:00, Block, weekdays)
|
- Morning Focus (Schedule 08:00–11:30, Block, weekdays)
|
||||||
- Laser Focus (Schedule 14:00–18:00, Block)
|
- Deep Work (Schedule 13:30–16:00, Block, weekdays)
|
||||||
- **Sleep, Relax and Reset** — "Sleep better, rise refreshed."
|
- **Rest & Recharge** — "Wind the day down on schedule."
|
||||||
- Wind Down (Schedule 20:00–22:00, Block)
|
- Evening Reset (Schedule 21:00–23:00, Block)
|
||||||
- Deep Sleep (Schedule 22:00–06:00, Block)
|
- Lights Out (Schedule 23:00–06:30, Block)
|
||||||
- **Build Healthy Habits** — "Spend time on important things."
|
- **Healthy Balance** — "Make room for what matters."
|
||||||
- Reading Time (Schedule ~19:45–20:45, Block)
|
- Family Dinner (Schedule 18:00–19:30, Block)
|
||||||
- Gym Time (Schedule 17:30–18:30, Block)
|
- Screen-Free Sunday (Schedule 09:00–20:00, Block, Sundays)
|
||||||
- **Preset card** anatomy: full-bleed background photo, top row icon pair
|
- **Preset card** anatomy: full-bleed background photo, top row icon pair
|
||||||
(type → shield), time range caption, name, "Block" + suggested app icons,
|
(type → shield), time range caption, name, "Block" + suggested app icons,
|
||||||
and a circular "+" button bottom-right. Tapping anywhere opens the
|
and a circular "+" button bottom-right. Tapping anywhere opens the
|
||||||
@@ -266,8 +266,8 @@ Full-height sheet:
|
|||||||
## 4. Behavioral spec
|
## 4. Behavioral spec
|
||||||
|
|
||||||
1. **Activation** — a Schedule rule becomes active at `From` on an enabled
|
1. **Activation** — a Schedule rule becomes active at `From` on an enabled
|
||||||
day and deactivates at `To` (windows crossing midnight, e.g. 22:00–06:00,
|
day and deactivates at `To` (windows crossing midnight, e.g. 23:00–06:30,
|
||||||
must be supported — Deep Sleep preset does this).
|
must be supported — Lights Out preset does this).
|
||||||
2. **While active** — the rule's app selection is shielded (and, when the
|
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
|
rule's Block Adult Content toggle is on, Screen Time's adult-website
|
||||||
filter is engaged for the same span); blocked apps also
|
filter is engaged for the same span); blocked apps also
|
||||||
|
|||||||
Reference in New Issue
Block a user