Skip to content

Commit cca9f2e

Browse files
committed
feat: regroup settings and drop footers
Group General settings into Blocking, Unblocking, Websites and Appearance, remove the static section footers, and show Max Daily Limits as a single row with its status. Block Adult Websites moves into Blocking, and the custom websites toggle is relabeled Enable Custom Websites and only shows a footer while it is disabled.
1 parent 601d73f commit cca9f2e

5 files changed

Lines changed: 82 additions & 120 deletions

File tree

‎Normal/Resources/Localizable.xcstrings‎

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
},
9999
"%lld Max Daily Limits" : {
100100
"comment" : "Max Daily Limits row in Settings — title. The argument is the number of Max Daily Limits.",
101+
"extractionState" : "stale",
101102
"localizations" : {
102103
"en" : {
103104
"variations" : {
@@ -276,10 +277,6 @@
276277
},
277278
"Add Shortcuts to your selected apps in Normal so the automation itself can't be easily modified." : {
278279

279-
},
280-
"Adds a section to App Select, allowing you to type custom website domains to block." : {
281-
"comment" : "A footer description for the custom domains section in the general settings view.",
282-
"isCommentAutoGenerated" : true
283280
},
284281
"After %@ of combined use, these stay blocked until %@, even if unblocked with a key. Time already used today counts; if you're already past it, the limit starts at the next reset." : {
285282
"comment" : "A description of how long a usage limit lasts. The argument is the number of minutes.",
@@ -349,6 +346,10 @@
349346
"comment" : "The title of a view that allows users to select which family members have access to their devices.",
350347
"isCommentAutoGenerated" : true
351348
},
349+
"Appearance" : {
350+
"comment" : "A heading for the appearance settings in the settings view.",
351+
"isCommentAutoGenerated" : true
352+
},
352353
"Apple lets you reset a forgotten Screen Time passcode using the Apple ID you registered. If that's your own account, you can bypass the lock yourself. Which is why it's important to use credentials you don't have easy access to." : {
353354
"comment" : "An explanation of why using a dummy Apple ID is important.",
354355
"isCommentAutoGenerated" : true
@@ -403,6 +404,10 @@
403404
},
404405
"Block ${group}" : {
405406

407+
},
408+
"Block Adult Websites" : {
409+
"comment" : "Title of a toggle that allows the user to block adult content on their devices.",
410+
"isCommentAutoGenerated" : true
406411
},
407412
"Block All" : {
408413
"comment" : "A button label that blocks all selected apps.",
@@ -412,10 +417,6 @@
412417
"comment" : "Title of the intent to block all apps.",
413418
"isCommentAutoGenerated" : true
414419
},
415-
"Block Custom Websites" : {
416-
"comment" : "A toggle that lets the user enable or disable blocking of custom website domains.",
417-
"isCommentAutoGenerated" : true
418-
},
419420
"Block Group" : {
420421
"comment" : "Shortcut title for the \"Block Group\" shortcut.",
421422
"isCommentAutoGenerated" : true
@@ -447,8 +448,8 @@
447448
"comment" : "Text displayed in a dialog when all selected apps are blocked.",
448449
"isCommentAutoGenerated" : true
449450
},
450-
"Blocking All Apps" : {
451-
"comment" : "A section header that lists the option to prevent app deletion when blocking all apps.",
451+
"Blocking" : {
452+
"comment" : "A section in the settings view for toggling blocking-related options.",
452453
"isCommentAutoGenerated" : true
453454
},
454455
"Blocks the apps and websites selected in Normal. Unblocking still requires your key." : {
@@ -553,10 +554,6 @@
553554
"comment" : "A section header for custom website domain blocking.",
554555
"isCommentAutoGenerated" : true
555556
},
556-
"Custom domains are currently being blocked. Unblock all apps before disabling this setting." : {
557-
"comment" : "A description of the custom domains section.",
558-
"isCommentAutoGenerated" : true
559-
},
560557
"Default" : {
561558
"comment" : "A label displayed next to a timed unblock duration that is set as the user's default.",
562559
"isCommentAutoGenerated" : true
@@ -573,13 +570,6 @@
573570
"comment" : "A label for the setting that lets the user choose which tab is selected when the app launches.",
574571
"isCommentAutoGenerated" : true
575572
},
576-
"Default Page opens when you launch the app. Hiding the Donate button hides it from the main toolbar." : {
577-
578-
},
579-
"Defaults allow to skip selection steps for faster unblocking. Live Activity shows a Lock Screen and Dynamic Island countdown for timed unblocks, for up to 8 hours." : {
580-
"comment" : "A description of the default settings.",
581-
"isCommentAutoGenerated" : true
582-
},
583573
"Delete" : {
584574
"comment" : "A button label that deletes an app group.",
585575
"isCommentAutoGenerated" : true
@@ -711,6 +701,10 @@
711701
},
712702
"Enable" : {
713703

704+
},
705+
"Enable Custom Websites" : {
706+
"comment" : "A toggle that lets the user enable or disable blocking of custom website domains.",
707+
"isCommentAutoGenerated" : true
714708
},
715709
"Enable location access in Settings to use your current spot. You can still pick anywhere on the map." : {
716710
"comment" : "A message explaining that location access is needed to use the user's current location, and that the user can still pick a location on the map.",
@@ -802,15 +796,15 @@
802796
"comment" : "A bullet point in the \"Pick one option for the passcode and Apple ID\" section of the SettingsBypassGuide view.",
803797
"isCommentAutoGenerated" : true
804798
},
805-
"Hard cap on daily app use" : {
806-
"comment" : "A description of the max daily limit usage.",
807-
"isCommentAutoGenerated" : true
808-
},
809799
"Head to our GitHub repository to get started, check out open issues, or submit a pull request." : {
810800

811801
},
812802
"Here's the technical reason:" : {
813803

804+
},
805+
"Hide Blocked Apps" : {
806+
"comment" : "A toggle that allows users to hide blocked apps.",
807+
"isCommentAutoGenerated" : true
814808
},
815809
"Hide Donate Button" : {
816810
"comment" : "A toggle that hides the donate button in the settings interface.",
@@ -992,10 +986,6 @@
992986
"comment" : "A label for the name field in the \"New Group\" sheet.",
993987
"isCommentAutoGenerated" : true
994988
},
995-
"Navigation & Appearance" : {
996-
"comment" : "A section header that lists navigation and appearance settings.",
997-
"isCommentAutoGenerated" : true
998-
},
999989
"Needs Update" : {
1000990
"comment" : "A label indicating that a group's app selection needs to be updated.",
1001991
"isCommentAutoGenerated" : true
@@ -1187,9 +1177,6 @@
11871177
"Paused by emergency unblock until %@." : {
11881178
"comment" : "Notice on the Max Daily Limits screen after an emergency unblock. The argument is the reset time."
11891179
},
1190-
"Paused until %@" : {
1191-
"comment" : "Max Daily Limits row in Settings — subtitle after an emergency unblock. The argument is the reset time."
1192-
},
11931180
"per month" : {
11941181
"comment" : "A unit of measurement for a monthly donation.",
11951182
"isCommentAutoGenerated" : true
@@ -1272,10 +1259,6 @@
12721259
"Resets At" : {
12731260
"comment" : "Label for the time Max Daily Limits reset each day."
12741261
},
1275-
"Resets at %@" : {
1276-
"comment" : "A description of the next reset time for the usage limits.",
1277-
"isCommentAutoGenerated" : true
1278-
},
12791262
"Resets at %@." : {
12801263
"comment" : "A footer that shows when the limit is paused, or when it resets.",
12811264
"isCommentAutoGenerated" : true
@@ -1580,6 +1563,10 @@
15801563
"comment" : "A footer text that appears when \"Select Apps\" is tapped, explaining that unblocking apps is necessary to edit the selection.",
15811564
"isCommentAutoGenerated" : true
15821565
},
1566+
"Unblock all apps to turn this off." : {
1567+
"comment" : "A footer explaining why the custom websites toggle is disabled while custom domains are blocked.",
1568+
"isCommentAutoGenerated" : true
1569+
},
15831570
"Unblock Durations" : {
15841571
"comment" : "Title of a row that shows the number of unblock durations.",
15851572
"isCommentAutoGenerated" : true
@@ -1664,10 +1651,6 @@
16641651
"comment" : "A welcome message displayed at the top of the onboarding screen.",
16651652
"isCommentAutoGenerated" : true
16661653
},
1667-
"When enabled 'Block All' and prevent app deletion are linked." : {
1668-
"comment" : "A footer for the \"Blocking All Apps\" section, explaining that when \"Block All\" and prevent app deletion are enabled, they are linked.",
1669-
"isCommentAutoGenerated" : true
1670-
},
16711654
"When enabled, apps cannot be uninstalled from this device." : {
16721655
"comment" : "A footer label explaining the purpose of the toggle.",
16731656
"isCommentAutoGenerated" : true

‎Normal/Views/Settings/AdultContentToggleView.swift‎

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,11 @@ struct AdultContentToggleView: View {
55
let defaultKeyType: KeyType?
66

77
var body: some View {
8-
Section {
9-
KeyProtectedToggle(
10-
title: "Block Adult Websites",
11-
isOn: screenTimeService.isAdultContentBlocked,
12-
defaultKeyType: defaultKeyType
13-
) { screenTimeService.setAdultContentBlocked($0) }
8+
KeyProtectedToggle(
9+
title: "Block Adult Websites",
10+
isOn: screenTimeService.isAdultContentBlocked,
11+
defaultKeyType: defaultKeyType
12+
) { screenTimeService.setAdultContentBlocked($0) }
1413
.accessibilityIdentifier("settings.blockAdultContentToggle")
15-
} header: {
16-
Text("Adult Content")
17-
} footer: {
18-
Text("Uses Apple's web content filter to block adult websites in Safari and other apps. Stays on independently of blocking. Turning it off requires a key.")
19-
}
2014
}
2115
}

‎Normal/Views/Settings/GeneralSettingsView.swift‎

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,9 @@ struct GeneralSettingsView: View {
1111

1212
var body: some View {
1313
List {
14-
unblockingSection
1514
blockingSection
16-
UsageSummaryView()
17-
customDomainsSection
18-
AdultContentToggleView(defaultKeyType: settings.defaultKeyType)
19-
HideBlockedAppsToggleView()
15+
unblockingSection
16+
websitesSection
2017
appearanceSection
2118
aboutSection
2219
#if DEBUG
@@ -31,19 +28,19 @@ struct GeneralSettingsView: View {
3128
screenTimeService.hasActiveCustomDomainFilter()
3229
}
3330

34-
private var customDomainsSection: some View {
31+
private var websitesSection: some View {
3532
Section {
3633
Toggle(
37-
"Block Custom Websites",
34+
"Enable Custom Websites",
3835
isOn: Bindable(settings).enableCustomDomains
3936
)
4037
.disabled(hasActiveFilter)
4138
} header: {
42-
Text("Custom Domains")
39+
Text("Websites")
4340
} footer: {
44-
Text(hasActiveFilter
45-
? "Custom domains are currently being blocked. Unblock all apps before disabling this setting."
46-
: "Adds a section to App Select, allowing you to type custom website domains to block.")
41+
if hasActiveFilter {
42+
Text("Unblock all apps to turn this off.")
43+
}
4744
}
4845
}
4946

@@ -88,28 +85,30 @@ struct GeneralSettingsView: View {
8885
"Live Activity",
8986
isOn: Bindable(settings).showTimedUnblockLiveActivity
9087
)
91-
92-
Toggle(
93-
"Skip Block Without Key Confirmation",
94-
isOn: Bindable(settings).skipBlockWithoutKeyConfirmation
95-
)
9688
} header: {
9789
Text("Unblocking")
98-
} footer: {
99-
Text("Defaults allow to skip selection steps for faster unblocking. Live Activity shows a Lock Screen and Dynamic Island countdown for timed unblocks, for up to 8 hours.")
10090
}
10191
}
10292

10393
private var blockingSection: some View {
10494
Section {
95+
UsageSummaryView()
96+
97+
AdultContentToggleView(defaultKeyType: settings.defaultKeyType)
98+
10599
Toggle(
106100
"Prevent App Deletion on Block All",
107101
isOn: Bindable(settings).blockAllPreventsAppDelete
108102
)
103+
104+
Toggle(
105+
"Skip Block Without Key Confirmation",
106+
isOn: Bindable(settings).skipBlockWithoutKeyConfirmation
107+
)
108+
109+
HideBlockedAppsToggleView()
109110
} header: {
110-
Text("Blocking All Apps")
111-
} footer: {
112-
Text("When enabled 'Block All' and prevent app deletion are linked.")
111+
Text("Blocking")
113112
}
114113
}
115114

@@ -132,9 +131,7 @@ struct GeneralSettingsView: View {
132131
isOn: Bindable(settings).hideDonateButton
133132
)
134133
} header: {
135-
Text("Navigation & Appearance")
136-
} footer: {
137-
Text("Default Page opens when you launch the app. Hiding the Donate button hides it from the main toolbar.")
134+
Text("Appearance")
138135
}
139136
}
140137

‎Normal/Views/Settings/HideBlockedAppsToggleView.swift‎

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,14 @@ struct HideBlockedAppsToggleView: View {
44
@Environment(ScreenTimeService.self) private var screenTimeService
55

66
var body: some View {
7-
Section {
8-
Toggle(
9-
"Hide Blocked Apps",
10-
isOn: Binding(
11-
get: { screenTimeService.isHidingBlockedApps },
12-
set: { screenTimeService.setHidingBlockedApps($0) }
13-
)
7+
Toggle(
8+
"Hide Blocked Apps",
9+
isOn: Binding(
10+
get: { screenTimeService.isHidingBlockedApps },
11+
set: { screenTimeService.setHidingBlockedApps($0) }
1412
)
15-
.tint(.accentColor)
16-
.accessibilityIdentifier("settings.hideBlockedAppsToggle")
17-
} header: {
18-
Text("Hidden Apps")
19-
} footer: {
20-
Text("Individually selected apps are removed from the Home Screen, App Library and Search while blocked. Apps blocked through a category or a daily limit stay blocked but remain visible. When unblocked, apps may reappear in the App Library rather than their original Home Screen spot.")
21-
}
13+
)
14+
.tint(.accentColor)
15+
.accessibilityIdentifier("settings.hideBlockedAppsToggle")
2216
}
2317
}

‎Normal/Views/Usage/UsageSummaryView.swift‎

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,36 @@ struct UsageSummaryView: View {
1111
let reachedCount = states.values.filter { $0 == .reached }.count
1212
let worstState = states.values.max() ?? .under
1313

14-
Section("Max Daily Limits") {
15-
NavigationLink {
16-
UsageView()
17-
} label: {
18-
SummaryRow(
19-
systemImage: limits.isEmpty ? "hourglass" : worstState.icon,
20-
tint: limits.isEmpty ? .secondary : worstState.color,
21-
title: title(reachedCount: reachedCount),
22-
subtitle: subtitle(reachedCount: reachedCount, worstState: worstState)
23-
)
14+
NavigationLink {
15+
UsageView()
16+
} label: {
17+
HStack {
18+
Text("Max Daily Limits")
19+
.foregroundStyle(.primary)
20+
Spacer()
21+
status(reachedCount: reachedCount, worstState: worstState)
2422
}
25-
.accessibilityIdentifier("settings.maxDailyLimitsLink")
2623
}
24+
.accessibilityIdentifier("settings.maxDailyLimitsLink")
2725
}
2826

29-
private func title(reachedCount: Int) -> Text {
27+
@ViewBuilder
28+
private func status(reachedCount: Int, worstState: UsageLimitState) -> some View {
3029
if limits.isEmpty {
31-
return Text("No Max Daily Limits")
30+
EmptyView()
31+
} else if usageLimitService.isDayOverridden() {
32+
Text("Paused")
33+
.foregroundStyle(.secondary)
34+
} else if reachedCount > 0 {
35+
Text("\(reachedCount) of \(limits.count) Reached")
36+
.foregroundStyle(worstState.color)
37+
} else if worstState == .warning {
38+
Text(worstState.label)
39+
.foregroundStyle(worstState.color)
40+
} else {
41+
Text("\(limits.count)")
42+
.monospacedDigit()
43+
.foregroundStyle(.secondary)
3244
}
33-
if reachedCount > 0 {
34-
return Text("\(reachedCount) of \(limits.count) Reached")
35-
}
36-
return Text("\(limits.count) Max Daily Limits")
37-
}
38-
39-
private func subtitle(reachedCount: Int, worstState: UsageLimitState) -> Text {
40-
if limits.isEmpty {
41-
return Text("Hard cap on daily app use")
42-
}
43-
let reset = usageLimitService.nextReset().formatted(date: .omitted, time: .shortened)
44-
if usageLimitService.isDayOverridden() {
45-
return Text("Paused until \(reset)")
46-
}
47-
if reachedCount > 0 {
48-
return Text("Resets at \(reset)")
49-
}
50-
return Text(worstState.label)
5145
}
5246
}

0 commit comments

Comments
 (0)