From 81e9c0b2ffa3939d79454091d5cb6181b23e0e13 Mon Sep 17 00:00:00 2001 From: ykisana Date: Mon, 12 Oct 2026 20:08:48 -0600 Subject: [PATCH] fix: expiry conflict --- NormalMonitor/NormalMonitor.swift | 21 ++++++++++--------- NormalTests/Shared/ShieldExclusionTests.swift | 15 +++++++++++++ Shared/SharedDTO.swift | 2 +- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/NormalMonitor/NormalMonitor.swift b/NormalMonitor/NormalMonitor.swift index dc258b0..19ae551 100644 --- a/NormalMonitor/NormalMonitor.swift +++ b/NormalMonitor/NormalMonitor.swift @@ -75,16 +75,17 @@ final class NormalMonitor: DeviceActivityMonitor { else { return } let domains = gatedDomains(dto.customDomains) + let allowing = activeSchedules(shouldBlock: false) if dto.isGroupUnblock { guard !sharedStore.isMainTimedUnblockActive() else { sharedStore.removeTimedUnblock(id: dto.id) return } - store.unionShields(with: selection) - store.unionFilterDomains(domains) + store.unionShields(with: allowing.applied(to: selection)) + store.unionFilterDomains(allowing.applied(to: domains)) } else { - store.replaceShields(with: selection) - store.replaceFilterDomains(domains) + store.replaceShields(with: allowing.applied(to: selection)) + store.replaceFilterDomains(allowing.applied(to: domains)) if dto.blockAllPreventsAppDelete == true { store.application.denyAppRemoval = true } @@ -121,7 +122,7 @@ final class NormalMonitor: DeviceActivityMonitor { else { return } let domains = gatedDomains(schedule.customDomains) - let stillActive = otherActiveSchedules(like: schedule) + let stillActive = activeSchedules(shouldBlock: schedule.shouldBlock, excluding: schedule.id) if schedule.shouldBlock { store.subtractShields(with: stillActive.applied(to: selection)) store.subtractFilterDomains(stillActive.applied(to: domains)) @@ -137,15 +138,15 @@ final class NormalMonitor: DeviceActivityMonitor { .groupUnblocks(sharedStore.loadTimedUnblocks(), at: .now) } - private func otherActiveSchedules(like schedule: ScheduleDTO) -> ShieldExclusion { + private func activeSchedules(shouldBlock: Bool, excluding excludedID: UUID? = nil) -> ShieldExclusion { let monitored = Set(DeviceActivityCenter().activities.map(\.rawValue)) return .activeSchedules( sharedStore.loadSchedules(), - shouldBlock: schedule.shouldBlock, + shouldBlock: shouldBlock, at: .now, - excluding: schedule.id - ) { other in - monitored.contains(SharedConstants.scheduleActivityName(for: other.id)) + excluding: excludedID + ) { schedule in + monitored.contains(SharedConstants.scheduleActivityName(for: schedule.id)) } } diff --git a/NormalTests/Shared/ShieldExclusionTests.swift b/NormalTests/Shared/ShieldExclusionTests.swift index 7da9538..148d69d 100644 --- a/NormalTests/Shared/ShieldExclusionTests.swift +++ b/NormalTests/Shared/ShieldExclusionTests.swift @@ -122,4 +122,19 @@ struct ShieldExclusionTests { let remaining = groups.union(schedules).applied(to: TokenFixtures.selection(apps: [1, 2, 3])) #expect(remaining.applicationTokens == [TokenFixtures.app(3)]) } + + @Test func withoutExclusionIncludesEveryActiveScheduleOfKind() throws { + let lunch = try schedule(apps: [1], domains: ["a.com"], shouldBlock: false) + let work = try schedule(apps: [2]) + + let allowing = ShieldExclusion.activeSchedules( + [lunch, work], + shouldBlock: false, + at: noonWednesday, + calendar: cal + ) { _ in true } + + #expect(allowing.applied(to: TokenFixtures.selection(apps: [1, 2])).applicationTokens == [TokenFixtures.app(2)]) + #expect(allowing.applied(to: ["a.com", "b.com"]) == ["b.com"]) + } } diff --git a/Shared/SharedDTO.swift b/Shared/SharedDTO.swift index 82f094c..5319298 100644 --- a/Shared/SharedDTO.swift +++ b/Shared/SharedDTO.swift @@ -174,7 +174,7 @@ nonisolated struct ShieldExclusion { _ schedules: [ScheduleDTO], shouldBlock: Bool, at date: Date, - excluding excludedID: UUID, + excluding excludedID: UUID? = nil, calendar: Calendar = .current, isEnabled: (ScheduleDTO) -> Bool ) -> ShieldExclusion {