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>
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
# OpenAppLock — "Rules" Feature Spec (derived from Opal screen recording)
|
||||
# OpenAppLock — "Rules" Feature Spec
|
||||
|
||||
Source: `ScreenRecording_06-12-2026 11-26-19_1.MP4` (iPhone, 4:29). The rules feature
|
||||
appears roughly between 1:00–3:00 of the recording, on Opal's "My Apps" tab.
|
||||
This spec describes what was observed, then maps it onto an implementation plan
|
||||
for OpenAppLock.
|
||||
This spec describes OpenAppLock's recurring app-blocking **rules** feature: the
|
||||
behavior the app implements, then how it maps onto the native iOS presentation
|
||||
(see §6).
|
||||
|
||||
---
|
||||
|
||||
@@ -11,13 +10,13 @@ for OpenAppLock.
|
||||
|
||||
A **Rule** is a recurring, automated app-blocking policy. Unlike a one-off
|
||||
block/timer session, a rule re-arms itself on a schedule. Three rule types are
|
||||
offered (Opal's "New Rule" sheet):
|
||||
offered, presented on the "New Rule" sheet:
|
||||
|
||||
| Type | Icon | Example shown | Semantics |
|
||||
|------|------|---------------|-----------|
|
||||
| **Schedule** | calendar grid | "e.g. 9-5, Daily" | Block selected apps during a daily time window on chosen days |
|
||||
| **Time Limit** | hourglass | "e.g. 45m/day" | After N minutes of cumulative use of selected apps per day, block them until a reset point |
|
||||
| **Open Limit** | padlock | "e.g. 5 opens/day" | After N opens of selected apps per day, block them (not demoed in video; inferred from card) |
|
||||
| **Open Limit** | padlock | "e.g. 5 opens/day" | After N opens of selected apps per day, block them |
|
||||
|
||||
**Common attributes** — present for *every* rule kind:
|
||||
|
||||
@@ -28,7 +27,7 @@ offered (Opal's "New Rule" sheet):
|
||||
independently of any rule. When editing a rule the user picks an existing
|
||||
list or creates a new one; editing a list affects every rule that uses it.
|
||||
Deleting a list detaches it from its rules (they fall back to "no apps").
|
||||
- **Hard Mode** — boolean, PRO-gated in Opal; subtitle "No unblocks allowed". When off, the rule detail shows "Unblocks allowed: Yes"
|
||||
- **Hard Mode** — boolean; subtitle "No unblocks allowed". When off, the rule detail shows "Unblocks allowed: Yes"
|
||||
- **Enabled/disabled** — a rule can be disabled without deleting ("Disable Rule")
|
||||
|
||||
**Per-kind options** — each kind carries only the options that make sense for
|
||||
@@ -87,10 +86,10 @@ Dark theme throughout (near-black background, very dark green tint).
|
||||
2. **Blocked Apps** — section header; horizontal row of currently-blocked app
|
||||
icons. Each icon has a lock badge overlay and a teal/green rounded-rect
|
||||
outline; caption "Unblock" under the icon. Tapping unblocks (with friction
|
||||
if hard mode — not demoed).
|
||||
if hard mode).
|
||||
*(OpenAppLock)* Time/Open Limit rules whose budget is spent for the day
|
||||
also appear here, blocked until midnight.
|
||||
3. **Usage** *(OpenAppLock addition — not in the Opal video)* — a section
|
||||
3. **Usage** *(OpenAppLock addition)* — a section
|
||||
showing live tracking for every enabled Time/Open Limit rule scheduled today
|
||||
**that is not currently blocking**. Each row leads its subtitle with the rule
|
||||
**type** so the kind is clear without relying on the icon:
|
||||
@@ -175,8 +174,7 @@ Sections (each an inset rounded group with a small icon + caption header):
|
||||
1. **📅 During this time**
|
||||
- Rows `From` / `To` with right-aligned time + stepper chevrons (`09:00 ⌃⌄`).
|
||||
- A dotted vertical line with ●/○ endpoints visually links From → To.
|
||||
- Tapping a row expands an inline wheel time picker (24h, demoed changing
|
||||
From 22:00 → 23:00).
|
||||
- Tapping a row expands an inline wheel time picker (24h).
|
||||
2. **On these days:** — trailing summary label ("Weekdays"/"Weekends"/custom);
|
||||
row of 7 circular toggles `S M T W T F S`; selected = filled white circle
|
||||
with black letter, unselected = dark circle.
|
||||
@@ -188,8 +186,8 @@ Sections (each an inset rounded group with a small icon + caption header):
|
||||
blocked" / "Only these apps are allowed" accordingly.
|
||||
4. **Hard Mode** `⚡PRO` badge — subtitle "No unblocks allowed"; trailing
|
||||
toggle.
|
||||
5. **Block Adult Content** *(OpenAppLock addition — not in the Opal video;
|
||||
**Schedule rules only**)* — subtitle "Filter adult websites while this rule
|
||||
5. **Block Adult Content** *(OpenAppLock addition; **Schedule rules only**)* —
|
||||
subtitle "Filter adult websites while this rule
|
||||
is active"; trailing toggle. Maps to Screen Time's web-content filter
|
||||
(`ManagedSettingsStore.webContent.blockedByFilter = .auto(...)`), applied
|
||||
and cleared together with the rule's shield. Surfaces in the rule detail
|
||||
@@ -217,7 +215,7 @@ Same chrome (back / title / rename). Sections:
|
||||
|
||||
### 3.6 Rule Editor — Open Limit type
|
||||
|
||||
Not demoed beyond its card. Spec by analogy: "When I open [apps]" /
|
||||
Spec by analogy with the other editors: "When I open [apps]" /
|
||||
"More than `N opens ⌃⌄` (Daily)" / day picker / "Then block until …" /
|
||||
Hard Mode / Hold to Commit. *(No Block Adult Content toggle — Schedule-only.)*
|
||||
|
||||
@@ -243,11 +241,10 @@ Full-height sheet:
|
||||
letting users add arbitrary domains.
|
||||
- Footer: "**N Apps Selected**" caption + white pill "**Save**" (+ "Cancel").
|
||||
|
||||
> Implementation note: Opal ships its own app categorization. On iOS, third
|
||||
> parties cannot enumerate installed apps; the system-sanctioned route is
|
||||
> `FamilyActivityPicker` (FamilyControls), which provides its own
|
||||
> category/app/website UI and returns opaque tokens. **v1 of OpenAppLock should
|
||||
> embed `FamilyActivityPicker`** instead of cloning Opal's custom picker.
|
||||
> Implementation note: On iOS, third parties cannot enumerate installed apps;
|
||||
> the system-sanctioned route is `FamilyActivityPicker` (FamilyControls), which
|
||||
> provides its own category/app/website UI and returns opaque tokens. **v1 of
|
||||
> OpenAppLock embeds `FamilyActivityPicker`** rather than a custom app picker.
|
||||
>
|
||||
> **App Lists (OpenAppLock):** the selection itself lives on a reusable
|
||||
> **App List** (`@Model AppList`: name + encoded `FamilyActivitySelection`).
|
||||
@@ -305,11 +302,11 @@ Full-height sheet:
|
||||
(which lists only rules whose budget is exhausted); it shows under "Usage"
|
||||
with its remaining opens.
|
||||
5. **Disable vs delete** — "Disable Rule" pauses scheduling but keeps the
|
||||
rule (card presumably shows disabled state). No delete flow was shown;
|
||||
add delete via swipe/long-press or a button in the editor.
|
||||
rule (the card shows a disabled state). Delete is offered from the rule
|
||||
editor's actions menu.
|
||||
6. **Commit friction** — creating/committing a rule uses press-and-hold
|
||||
("Hold to Commit"), echoing Opal's philosophy that *starting* a commitment
|
||||
should be deliberate. Editing uses a plain "Done".
|
||||
("Hold to Commit"), making the *start* of a commitment deliberate. Editing
|
||||
uses a plain "Done".
|
||||
7. **Live countdowns** — "Starts in 22h" / "6h left" update over time
|
||||
(minute granularity is fine).
|
||||
8. **Overlapping rules — strictest enforcement wins.** When several rules
|
||||
@@ -503,20 +500,20 @@ Xh", "Xh left") is **derived**, not stored.
|
||||
- All shared logic lives in `Shared/` (notably `LimitEnforcement`), unit
|
||||
tested from the app test target.
|
||||
|
||||
### 5.6 Out of scope (seen in video, not part of "rules")
|
||||
### 5.6 Out of scope (not part of "rules")
|
||||
|
||||
- Onboarding flow, paywall ("You know Opal works. Make it permanent."),
|
||||
Home tab gem/score UI, Timer tab (one-off focus sessions, "Leave Early?"
|
||||
friction screen), notification nudges ("Complete Your Setup").
|
||||
- Onboarding flow, paywall, Home tab gem/score UI, Timer tab (one-off focus
|
||||
sessions, "Leave Early?" friction screen), notification nudges ("Complete
|
||||
Your Setup").
|
||||
|
||||
---
|
||||
|
||||
## 6. Native UI re-skin (current presentation)
|
||||
|
||||
OpenAppLock has since replaced the Opal-style custom presentation with the bare
|
||||
OpenAppLock has since replaced its custom themed presentation with the bare
|
||||
iOS design language, keeping the backend (models, logic, services), the
|
||||
flows, and the accessibility identifiers intact. Sections 1–5 remain as the
|
||||
reference for *what* the feature does; presentation now maps as follows.
|
||||
spec for *what* the feature does; presentation now maps as follows.
|
||||
|
||||
After onboarding the app is a three-tab `TabView` (`MainTabView`), each tab its
|
||||
own `NavigationStack`:
|
||||
|
||||
Reference in New Issue
Block a user