diff options
| author | Christian Cleberg <[email protected]> | 2026-07-24 23:52:39 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-07-25 00:00:29 -0500 |
| commit | 7805888980f6d41bcc881c5d2e6001b2d8e69351 (patch) | |
| tree | 40710d217106a500428ad8f26c3bddd803d17bdb /DomainDig/DomainViewModel.swift | |
| parent | e597cdf5b7084634e300af39b622c8552c9cc5e8 (diff) | |
| download | domain-dig-7805888980f6d41bcc881c5d2e6001b2d8e69351.tar.gz domain-dig-7805888980f6d41bcc881c5d2e6001b2d8e69351.tar.bz2 domain-dig-7805888980f6d41bcc881c5d2e6001b2d8e69351.zip | |
refactor: extract monitoring surface into DomainViewModel+Monitoring (v5 step 4, 2/n)
Second slice of the DomainViewModel decomposition, stacked on the audit split.
- Moves the monitoring configuration surface — notification authorization, the
settings mutators (enabled/scope/interval/adaptive/sensitivity/quiet-hours/
alert filter/alerts/selection), toggleMonitoring, runMonitoringNow, the manual
run, and the per-domain interval/status labels — plus the private
intervalLabel helper into DomainViewModel+Monitoring.swift. Pure move.
- persistMonitoringSettings(...) and sanitizeMonitoringSelection() are promoted
private -> internal: the tracked-domain lifecycle (add/delete/clear) on the
main type calls them too, so they stay put and are now reachable cross-file.
The two visibility drops are the only non-deletion edits to DomainViewModel.
DomainViewModel.swift: 4761 -> 4601 lines. App builds clean; unit suite 58/58.
No project.pbxproj change (DomainDig/ is a synchronized group).
Diffstat (limited to 'DomainDig/DomainViewModel.swift')
| -rw-r--r-- | DomainDig/DomainViewModel.swift | 165 |
1 files changed, 2 insertions, 163 deletions
diff --git a/DomainDig/DomainViewModel.swift b/DomainDig/DomainViewModel.swift index fdf6b84..3814704 100644 --- a/DomainDig/DomainViewModel.swift +++ b/DomainDig/DomainViewModel.swift @@ -1100,167 +1100,6 @@ final class DomainViewModel { await refreshMonitoringAuthorizationStatus() } - func refreshMonitoringAuthorizationStatus() async { - let settings = await UNUserNotificationCenter.current().notificationSettings() - monitoringNotificationStatus = settings.authorizationStatus - } - - func setMonitoringEnabled(_ isEnabled: Bool) { - guard !isEnabled || FeatureAccessService.hasAccess(to: .automatedMonitoring) else { - monitoringSettings.isEnabled = false - upgradePrompt = FeatureAccessService.upgradePrompt(for: .automatedMonitoring) - return - } - - monitoringSettings.isEnabled = isEnabled - persistMonitoringSettings(localActivationConfirmed: isEnabled) - monitoringStatusMessage = DomainMonitoringScheduler.shared.syncSchedule() - } - - func setMonitoringScope(_ scope: MonitoringScope) { - monitoringSettings.scope = scope - persistMonitoringSettings(localActivationConfirmed: monitoringSettings.isEnabled) - } - - func setMonitoringBaseInterval(_ baseInterval: MonitoringBaseInterval) { - guard FeatureAccessService.hasAccess(to: .automatedMonitoring) else { - upgradePrompt = FeatureAccessService.upgradePrompt(for: .automatedMonitoring) - return - } - monitoringSettings.baseInterval = baseInterval.interval - persistMonitoringSettings(localActivationConfirmed: monitoringSettings.isEnabled) - monitoringStatusMessage = DomainMonitoringScheduler.shared.syncSchedule() - } - - func setMonitoringAdaptiveEnabled(_ isEnabled: Bool) { - guard FeatureAccessService.hasAccess(to: .automatedMonitoring) else { - upgradePrompt = FeatureAccessService.upgradePrompt(for: .automatedMonitoring) - return - } - monitoringSettings.adaptiveEnabled = isEnabled - persistMonitoringSettings(localActivationConfirmed: monitoringSettings.isEnabled) - monitoringStatusMessage = DomainMonitoringScheduler.shared.syncSchedule() - } - - func setMonitoringSensitivity(_ sensitivity: MonitoringSensitivity) { - guard FeatureAccessService.hasAccess(to: .automatedMonitoring) else { - upgradePrompt = FeatureAccessService.upgradePrompt(for: .automatedMonitoring) - return - } - monitoringSettings.sensitivity = sensitivity - persistMonitoringSettings(localActivationConfirmed: monitoringSettings.isEnabled) - monitoringStatusMessage = DomainMonitoringScheduler.shared.syncSchedule() - } - - func setMonitoringQuietHours(startHour: Int, endHour: Int, isEnabled: Bool) { - guard FeatureAccessService.hasAccess(to: .automatedMonitoring) else { - upgradePrompt = FeatureAccessService.upgradePrompt(for: .automatedMonitoring) - return - } - monitoringSettings.quietHours = isEnabled ? QuietHours(startHour: startHour, endHour: endHour) : nil - persistMonitoringSettings(localActivationConfirmed: monitoringSettings.isEnabled) - } - - func setMonitoringAlertFilter(_ filter: MonitoringAlertFilter) { - guard FeatureAccessService.hasAccess(to: .localAlerts) else { - monitoringSettings.alertsEnabled = false - upgradePrompt = FeatureAccessService.upgradePrompt(for: .localAlerts) - return - } - monitoringSettings.alertFilter = filter - persistMonitoringSettings(localActivationConfirmed: monitoringSettings.isEnabled) - } - - func setMonitoringAlertsEnabled(_ isEnabled: Bool) { - guard !isEnabled || FeatureAccessService.hasAccess(to: .localAlerts) else { - monitoringSettings.alertsEnabled = false - upgradePrompt = FeatureAccessService.upgradePrompt(for: .localAlerts) - return - } - monitoringSettings.alertsEnabled = isEnabled - persistMonitoringSettings(localActivationConfirmed: monitoringSettings.isEnabled) - } - - func setMonitoringSelection(for trackedDomain: TrackedDomain, isSelected: Bool) { - if isSelected { - if !monitoringSettings.selectedDomainIDs.contains(trackedDomain.id) { - monitoringSettings.selectedDomainIDs.append(trackedDomain.id) - } - } else { - monitoringSettings.selectedDomainIDs.removeAll { $0 == trackedDomain.id } - } - persistMonitoringSettings(localActivationConfirmed: monitoringSettings.isEnabled) - } - - func toggleMonitoring(for trackedDomain: TrackedDomain) { - guard canEdit(trackedDomain) else { return } - guard FeatureAccessService.hasAccess(to: .automatedMonitoring) else { - upgradePrompt = FeatureAccessService.upgradePrompt(for: .automatedMonitoring) - return - } - guard let index = trackedDomains.firstIndex(where: { $0.id == trackedDomain.id }) else { return } - trackedDomains[index].monitoringEnabled.toggle() - trackedDomains[index].updatedAt = Date() - MonitoringStorage.saveTrackedDomains(trackedDomains) - CloudSyncService.shared.scheduleSyncIfNeeded() - sanitizeMonitoringSelection() - } - - func requestMonitoringNotificationAuthorization() async { - let granted = await LocalNotificationService.shared.requestAuthorizationIfNeeded() - monitoringSettings.alertsEnabled = granted - persistMonitoringSettings(localActivationConfirmed: monitoringSettings.isEnabled) - await refreshMonitoringAuthorizationStatus() - } - - func runMonitoringNow() { - guard FeatureAccessService.hasAccess(to: .automatedMonitoring) else { - upgradePrompt = FeatureAccessService.upgradePrompt(for: .automatedMonitoring) - return - } - guard !monitoringRunInProgress else { return } - - monitoringRunInProgress = true - monitoringStatusMessage = nil - - Task { [weak self] in - guard let self else { return } - let outcome = await DomainMonitoringService.shared.performMonitoring( - trigger: .manual, - requireEnabledSetting: false - ) - await MainActor.run { - self.refreshMonitoringState() - self.monitoringRunInProgress = false - self.monitoringStatusMessage = outcome.message - } - } - } - - func monitoringIntervalLabel(for trackedDomain: TrackedDomain) -> String { - let state = DomainMonitoringScheduler.normalizedMonitoringState(for: trackedDomain, settings: monitoringSettings) - return Self.intervalLabel(for: state.currentInterval) - } - - func monitoringStatusLabel(for trackedDomain: TrackedDomain) -> String { - let state = trackedDomain.monitoringState - if let lastChangeDate = state.lastChangeDate, - Date().timeIntervalSince(lastChangeDate) <= 6 * 60 * 60 { - return "Recently Changed" - } - if state.consecutiveStableChecks >= 2 { - return "Stable" - } - return trackedDomain.monitoringEnabled ? "Active" : "Paused" - } - - private static func intervalLabel(for interval: TimeInterval) -> String { - let formatter = DateComponentsFormatter() - formatter.allowedUnits = interval < 3600 ? [.minute] : [.hour, .minute] - formatter.unitsStyle = .full - return formatter.string(from: interval) ?? "Unknown" - } - func rerunLookup(from entry: HistoryEntry, useSnapshotResolver: Bool) { if useSnapshotResolver { UserDefaults.standard.set(entry.resolverURLString, forKey: DNSResolverOption.userDefaultsKey) @@ -2590,13 +2429,13 @@ final class DomainViewModel { return existingMax + 1 } - private func persistMonitoringSettings(localActivationConfirmed: Bool = false) { + func persistMonitoringSettings(localActivationConfirmed: Bool = false) { monitoringSettings = MonitoringStorage.sanitizeSettings(monitoringSettings, trackedDomains: trackedDomains) MonitoringStorage.saveSettings(monitoringSettings) CloudSyncService.shared.markMonitoringSettingsChanged(localActivationConfirmed: localActivationConfirmed) } - private func sanitizeMonitoringSelection() { + func sanitizeMonitoringSelection() { monitoringSettings = MonitoringStorage.sanitizeSettings(monitoringSettings, trackedDomains: trackedDomains) MonitoringStorage.saveSettings(monitoringSettings) CloudSyncService.shared.markMonitoringSettingsChanged(localActivationConfirmed: false) |
