summaryrefslogtreecommitdiff
path: root/DomainDig/DomainDigIntents.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-07-17 00:27:45 -0500
committerChristian Cleberg <[email protected]>2026-07-17 00:31:57 -0500
commitd3a27d06809e6744c092f9bed4bf0537843d0210 (patch)
tree1527e935e11561dda4bc8c6cfaabdb92db5be95c /DomainDig/DomainDigIntents.swift
parent685f84ad0a8d2dc7b62125d5d9c3a50b75ae2468 (diff)
downloaddomain-dig-d3a27d06809e6744c092f9bed4bf0537843d0210.tar.gz
domain-dig-d3a27d06809e6744c092f9bed4bf0537843d0210.tar.bz2
domain-dig-d3a27d06809e6744c092f9bed4bf0537843d0210.zip
Complete v4.5.0: Run Sweep intent, detail deep link, and portfolio widget
Finishes the v4.5.0 "Home Screen & Shortcuts reach" scope that the tag shipped partially: - Add RunSweepIntent (opens the app and runs refreshAllTrackedDomains via the in-process router) and expose it in DomainDigShortcuts. - Extend the domaindig:// scheme with `sweep` and `domain` (detail) actions; route .detail to present TrackedDomainDetailView and .sweep to refresh the watchlist. Move DomainDigDeepLink into Shared/ so the widget can build links. - Add a WidgetKit extension (DomainDigWidgetExtension) with small/medium/large Portfolio widgets showing health counts, per-domain status, and certificate countdowns; tapping a domain deep-links into its detail. - Share portfolio state via an App Group (group.net.cleberg.DomainDig): the app writes a DomainDigWidgetData snapshot on launch/foreground and on watchlist changes and reloads timelines; the widget reads the same store.
Diffstat (limited to 'DomainDig/DomainDigIntents.swift')
-rw-r--r--DomainDig/DomainDigIntents.swift78
1 files changed, 27 insertions, 51 deletions
diff --git a/DomainDig/DomainDigIntents.swift b/DomainDig/DomainDigIntents.swift
index 44a1dc4..c0c73cc 100644
--- a/DomainDig/DomainDigIntents.swift
+++ b/DomainDig/DomainDigIntents.swift
@@ -124,6 +124,24 @@ struct AddToWatchlistIntent: AppIntent {
}
}
+/// App Intent that opens DomainDig and re-inspects every tracked domain. It runs
+/// through the existing view-model batch path (`refreshAllTrackedDomains`), which
+/// enforces the batch feature gate and surfaces the paywall when needed.
+struct RunSweepIntent: AppIntent {
+ static var title: LocalizedStringResource = "Run Watchlist Sweep"
+ static var description = IntentDescription(
+ "Open DomainDig and re-inspect every domain on your watchlist."
+ )
+
+ static var openAppWhenRun = true
+
+ @MainActor
+ func perform() async throws -> some IntentResult {
+ DomainDigIntentRouter.shared.pendingAction = .sweep
+ return .result()
+ }
+}
+
/// In-process hand-off from an `openAppWhenRun` intent to the running SwiftUI
/// layer. `RootTabView` observes `pendingAction` and performs it.
@MainActor
@@ -134,57 +152,6 @@ final class DomainDigIntentRouter {
private init() {}
}
-/// Shared builder/parser for the `domaindig://` URL scheme, used by both the
-/// intents (to open the app) and the app (to route incoming links).
-enum DomainDigDeepLink {
- static let scheme = "domaindig"
-
- enum Action: Equatable {
- case inspect(String)
- case watch(String)
-
- var host: String {
- switch self {
- case .inspect: return "inspect"
- case .watch: return "watch"
- }
- }
-
- var domain: String {
- switch self {
- case let .inspect(domain), let .watch(domain): return domain
- }
- }
- }
-
- static func url(for action: Action) -> URL {
- var components = URLComponents()
- components.scheme = scheme
- components.host = action.host
- components.queryItems = [URLQueryItem(name: "domain", value: action.domain)]
- // The scheme and host are fixed and the domain is percent-encoded by
- // URLComponents, so this is always a valid URL.
- return components.url!
- }
-
- static func action(from url: URL) -> Action? {
- guard url.scheme == scheme else { return nil }
-
- let domain = URLComponents(url: url, resolvingAgainstBaseURL: false)?
- .queryItems?
- .first { $0.name == "domain" }?
- .value?
- .trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
- guard !domain.isEmpty else { return nil }
-
- switch url.host() {
- case "inspect": return .inspect(domain)
- case "watch": return .watch(domain)
- default: return nil
- }
- }
-}
-
/// Exposes DomainDig intents to Spotlight and Siri with invocation phrases.
struct DomainDigShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
@@ -206,5 +173,14 @@ struct DomainDigShortcuts: AppShortcutsProvider {
shortTitle: "Add to Watchlist",
systemImageName: "plus.circle"
)
+ AppShortcut(
+ intent: RunSweepIntent(),
+ phrases: [
+ "Run a sweep with \(.applicationName)",
+ "Sweep my \(.applicationName) watchlist"
+ ],
+ shortTitle: "Run Sweep",
+ systemImageName: "arrow.trianglehead.2.clockwise"
+ )
}
}