Skip to content

fix(#312): deep linking for widgets, custom URLs, and Universal Links#313

Merged
cassio-rossi merged 3 commits into
release/v5from
fix/widget-deeplink-scenedelegate
Jul 21, 2026
Merged

fix(#312): deep linking for widgets, custom URLs, and Universal Links#313
cassio-rossi merged 3 commits into
release/v5from
fix/widget-deeplink-scenedelegate

Conversation

@cassio-rossi

@cassio-rossi cassio-rossi commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Fixes deep linking end-to-end for MacMagazine post URLs. Covers three entry points under #312: widget taps, custom URLs, and Universal Links (web links opening the app instead of Safari).

Problem

  1. Tapping any widget opened the app but nothing happened, on every widget size.
  2. Tapping a macmagazine.com.br post link in Safari/Messages/Mail opened the browser, never the app.

Root cause

The app runs on the UIKit scene lifecycle (AppDelegate installs a SceneDelegate that hosts SceneView in a UIHostingController; the @main WindowGroup is EmptyView()). Under a UISceneDelegate, SwiftUI's .onOpenURL never fires, and SceneDelegate handled only shortcut items — so widget URLs were dropped. Separately, the app declared no Associated Domains and handled no browsing-web NSUserActivity, so it could not claim its own web URLs.

Fix

  • Widget / custom URL: SceneDelegate now handles scene(_:openURLContexts:) (warm) and connectionOptions.urlContexts (cold).
  • Universal Links: SceneDelegate handles scene(_:continue:) (warm) and connectionOptions.userActivities (cold), filtering for NSUserActivityTypeBrowsingWeb.
  • All sources funnel into MainViewModel.openDeepLink(_:source:), which sets deepLinkPostURL and tracks analytics per source (widget vs universal_link). Reuses the existing DeepLinkNewsDetailViewMMWebView path — no new routing.
  • Added com.apple.developer.associated-domains (apex + www) to debug and release entitlements.
  • Added a ready-to-host reference AASA file under Support/AssociatedDomains/ (Team ID A5VW9QUF9L), scoped to /post/* so only article URLs open the app.

Verification

  • ✅ Build succeeded (iPhone 17 simulator — "iPhone 17 Pro" is not installed on this machine).
  • ✅ SwiftLint --strict on all changed Swift files — 0 violations.
  • ✅ AASA JSON validated.
  • ⚠️ Test suite not run (UNVERIFIED): changed types live in the main app target, which has no test coverage; no new test target created (per decision to ship with manual verification).
  • 📱 Manual check needed: tap each widget size (cold + warm launch); once the AASA is live, tap a /post/* link and confirm it opens the article in-app.

Required outside this repo (server / portal)

  1. Host Support/AssociatedDomains/apple-app-site-association at https://macmagazine.com.br/.well-known/apple-app-site-association (and www) — HTTPS, application/json, no redirect, no extension. See the README in that folder.
  2. Enable Associated Domains on the com.brit.macmagazine App ID and regenerate provisioning profiles (device/TestFlight signing; simulator doesn't enforce it).

Notes / deviations

  • No develop branch exists — branch is based on release/v5; PR targets release/v5.
  • Left as-is by request: on medium/large widgets, WidgetView stamps a container-wide .widgetURL(content.first?.url) under .accessibilityElement(children: .combine), which limits VoiceOver users to only the first post.

🤖 Generated with Claude Code

cassio-rossi and others added 3 commits July 21, 2026 20:09
Widget taps opened the app but nothing happened, on every widget size.
The app uses the UIKit scene lifecycle (AppDelegate configures a
SceneDelegate that hosts SceneView in a UIHostingController), so
SwiftUI's .onOpenURL never fires — incoming URLs are delivered to the
scene delegate instead. SceneDelegate handled only shortcut items, so
the post URL was dropped.

Handle URLs in SceneDelegate for both cold launch (connectionOptions
.urlContexts) and warm launch (scene(_:openURLContexts:)), routing them
into MainViewModel.openDeepLink, which sets deepLinkPostURL and tracks
the existing widget deep-link analytics.

Co-Authored-By: Claude <noreply@anthropic.com>
Tapping a macmagazine.com.br link in Safari or another app opened the
browser instead of the app. The app declared no Associated Domains and
handled no browsing-web user activity, so it could not claim its URLs.

- Add com.apple.developer.associated-domains (apex + www) to the debug
  and release entitlements.
- Handle Universal Links in SceneDelegate for cold launch
  (connectionOptions.userActivities) and warm launch
  (scene(_:continue:)), routing the webpageURL into openDeepLink.
- Parameterize MainViewModel.openDeepLink with a source so universal
  links track distinctly from widget opens.

Which URLs open the app (/post/*) is gated server-side by the AASA
file; the app trusts that classification and reuses the existing
DeepLinkNewsDetailView path to render the post.

Co-Authored-By: Claude <noreply@anthropic.com>
Ready-to-host apple-app-site-association (Team ID A5VW9QUF9L, appID
A5VW9QUF9L.com.brit.macmagazine) scoped to /post/* only, plus a README
documenting the hosting requirements for macmagazine.com.br and www.

Co-Authored-By: Claude <noreply@anthropic.com>
@cassio-rossi cassio-rossi changed the title fix(#312): route widget deep links through SceneDelegate fix(#312): deep linking for widgets, custom URLs, and Universal Links Jul 21, 2026
@cassio-rossi
cassio-rossi merged commit 2675a51 into release/v5 Jul 21, 2026
2 checks passed
@cassio-rossi
cassio-rossi deleted the fix/widget-deeplink-scenedelegate branch July 21, 2026 20:07
cassio-rossi added a commit that referenced this pull request Jul 21, 2026
Rebuilt against the merged release/v5 tree (2828 nodes, 5293 edges,
200 communities). Transient AST cache and dated snapshots left untracked.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant