From 7b8d015fa6f227572013b00b8b88814d118a589c Mon Sep 17 00:00:00 2001 From: ykisana Date: Sun, 15 Nov 2026 04:20:24 -0600 Subject: [PATCH] feat: allow adding websites while blocked --- Normal/Resources/Localizable.xcstrings | 8 ++--- .../Components/CustomDomainsEditor.swift | 12 +++---- Normal/Shared/Components/FooterMessage.swift | 2 +- Normal/Views/AppSelect/AppSelectView.swift | 3 +- NormalUITests/NormalUITests.swift | 31 ++++++++++++++++--- 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/Normal/Resources/Localizable.xcstrings b/Normal/Resources/Localizable.xcstrings index 1534282..6762e36 100644 --- a/Normal/Resources/Localizable.xcstrings +++ b/Normal/Resources/Localizable.xcstrings @@ -1614,14 +1614,14 @@ "comment" : "Message displayed at the bottom of the screen in a `SafeAreaInset` modifier, when the user is blocked from deleting keys.", "isCommentAutoGenerated" : true }, - "Unblock all apps to edit custom domains." : { - "comment" : "A footer text displayed below the list of custom domains, explaining that unblocking all apps is necessary to edit the list.", - "isCommentAutoGenerated" : true - }, "Unblock all apps to edit selection." : { "comment" : "A footer text that appears when \"Select Apps\" is tapped, explaining that unblocking apps is necessary to edit the selection.", "isCommentAutoGenerated" : true }, + "Unblock all apps to remove custom domains." : { + "comment" : "A footer text displayed below the list of custom domains, explaining that unblocking all apps is necessary to remove domains from the list.", + "isCommentAutoGenerated" : true + }, "Unblock all apps to turn this off." : { "comment" : "A footer explaining why the custom websites toggle is disabled while custom domains are blocked.", "isCommentAutoGenerated" : true diff --git a/Normal/Shared/Components/CustomDomainsEditor.swift b/Normal/Shared/Components/CustomDomainsEditor.swift index ece79b2..17264c1 100644 --- a/Normal/Shared/Components/CustomDomainsEditor.swift +++ b/Normal/Shared/Components/CustomDomainsEditor.swift @@ -4,7 +4,7 @@ struct CustomDomainsEditor: View { @Binding var domains: [String] var otherItemCount: Int = 0 - var isEditable: Bool = true + var canRemove: Bool = true @State private var input = "" @State private var message: FieldMessage? @@ -24,9 +24,7 @@ struct CustomDomainsEditor: View { var body: some View { Form { - if isEditable { - inputSection - } + inputSection if !domains.isEmpty { domainsSection } @@ -34,7 +32,7 @@ struct CustomDomainsEditor: View { .navigationTitle("Custom Domains") .navigationBarTitleDisplayMode(.inline) .safeAreaInset(edge: .bottom) { - if !isEditable { + if !canRemove { FooterMessage(text: BlockedMessage.customDomains) } } @@ -77,7 +75,7 @@ struct CustomDomainsEditor: View { HStack { Label(domain, systemImage: "globe") .lineLimit(1) - if isEditable { + if canRemove { Spacer() deleteButton(domain) } @@ -127,7 +125,7 @@ struct CustomDomainsEditor: View { } private var deleteAction: ((IndexSet) -> Void)? { - guard isEditable else { return nil } + guard canRemove else { return nil } return { offsets in domains.remove(atOffsets: offsets) show(nil) diff --git a/Normal/Shared/Components/FooterMessage.swift b/Normal/Shared/Components/FooterMessage.swift index 1cdbc06..d69a302 100644 --- a/Normal/Shared/Components/FooterMessage.swift +++ b/Normal/Shared/Components/FooterMessage.swift @@ -16,5 +16,5 @@ enum BlockedMessage { static let groups: LocalizedStringKey = "Unblock all apps to add or edit groups." static let schedules: LocalizedStringKey = "Unblock all apps to add or edit schedules." static let keys: LocalizedStringKey = "Unblock all apps to add or delete keys." - static let customDomains: LocalizedStringKey = "Unblock all apps to edit custom domains." + static let customDomains: LocalizedStringKey = "Unblock all apps to remove custom domains." } diff --git a/Normal/Views/AppSelect/AppSelectView.swift b/Normal/Views/AppSelect/AppSelectView.swift index 66a0117..d2c38a9 100644 --- a/Normal/Views/AppSelect/AppSelectView.swift +++ b/Normal/Views/AppSelect/AppSelectView.swift @@ -74,11 +74,10 @@ struct AppSelectView: View { CustomDomainsEditor( domains: $customDomains, otherItemCount: selection.count, - isEditable: !isBlocked + canRemove: !isBlocked ) } label: { CountRow(title: "Custom Domains", count: customDomains.count) - .opacity(isBlocked ? DS.Opacity.dim : 1) } .accessibilityIdentifier("appSelect.customDomainsLink") } diff --git a/NormalUITests/NormalUITests.swift b/NormalUITests/NormalUITests.swift index 4a59bb6..7b9f13b 100644 --- a/NormalUITests/NormalUITests.swift +++ b/NormalUITests/NormalUITests.swift @@ -219,8 +219,12 @@ final class NormalUITests: XCTestCase { } @MainActor - func testCustomDomainsEditorIsReadOnlyWhileBlocked() { - let app = launch(["-uiTestMode", "-uiTestSkipOnboarding", "-uiTestCustomDomains", "-uiTestStartBlocked"]) + func testCustomDomainsEditorAddsButDoesNotRemoveWhileBlocked() { + let app = launch([ + "-uiTestMode", "-uiTestSkipOnboarding", "-uiTestCustomDomains", "-uiTestWebsitesOnly", "-uiTestStartBlocked", + ]) + require(app.buttons["home.unblockAll"], "The seeded website should start blocked") + XCTAssertFalse(app.buttons["home.blockAll"].exists, "Everything selected should already be blocked") let appSelectTab = app.mainTab("App Select") require(appSelectTab, "App Select tab should be reachable") @@ -230,11 +234,28 @@ final class NormalUITests: XCTestCase { require(link, "Custom Domains row should remain visible while blocked") link.tap() + require(app.staticTexts["example.com"], "The blocked website should be listed") XCTAssertFalse( - app.textFields["customDomains.field"].waitForExistence(timeout: 3), - "Add field should be hidden while apps are blocked" + app.buttons["customDomains.delete.example.com"].exists, + "Websites can't be removed while blocked" ) - XCTAssertFalse(app.buttons["customDomains.addButton"].exists, "Add button should be hidden while blocked") + + let field = app.textFields["customDomains.field"] + require(field, "Websites can be added while blocked") + field.tap() + field.typeText("reddit.com") + app.buttons["customDomains.addButton"].tap() + + require(app.staticTexts["reddit.com"], "Added website should appear in the list") + XCTAssertFalse( + app.buttons["customDomains.delete.reddit.com"].exists, + "A website added while blocked can't be removed either" + ) + + app.navigationBars.buttons.element(boundBy: 0).tap() + require(link, "Going back should return to App Select") + app.mainTab("Home").tap() + require(app.buttons["home.blockAll"], "The added website stays unblocked until Block All is tapped") } @MainActor