Skip to content

Add applenugs:// deep-link handler (show / track / video)#2

Merged
tsvb merged 1 commit into
mainfrom
deep-link-handler
Jun 29, 2026
Merged

Add applenugs:// deep-link handler (show / track / video)#2
tsvb merged 1 commit into
mainfrom
deep-link-handler

Conversation

@tsvb

@tsvb tsvb commented Jun 29, 2026

Copy link
Copy Markdown
Owner

What

Implements the app side of the goose-almanac deep-link contract:

applenugs://show/<date>?artist=Goose[&venue=][&song=&set=&pos=][&media=audio|video]

A deep link resolves an artist + date to a nugs container, navigates to it, and starts playback:

  • show link → plays from the top
  • track link (&song=) → jumps to the matched track
  • video link (&media=video) → opens the auto-playing video detail

Registers the applenugs scheme only — nugsnet stays OAuth-only/unregistered to avoid clashing with the official nugs.net app.

How

  • Core/DeepLink.swift — pure, unit-tested parser + DeepLinkMatch fuzzy matching (normalize / venue / best-track-index / zero-pad date). No I/O.
  • Core/DeepLinkRouter.swift@MainActor resolver. Audio: bounded paging of artistShows + catalog-search fallback. Video: bounded paging of the per-artist list (no video search exists), date-only match.
  • AppModel — serialized deep-link channel (receiveDeepLink / handleDeepLink): a chained deepLinkTask ensures two links — or a link racing the post-login drain — can't interleave their navigate+play steps. A pendingDeepLink slot (last-wins) is replayed after login/bootstrap.
  • AppleNugsApp.onOpenURL wired non-destructively (existing .frame / UITest modifiers untouched). RootView — drains the pending link once .loggedIn.
  • project.yml — registers the scheme and adds a standalone, host-free AppleNugsTests unit-test target (bundle.unit-test); DeepLink.swift is compiled into the bundle directly so logic tests run without launching the app.

Review & fixes

After implementation, a multi-agent adversarial review surfaced 8 genuine defects (others dismissed as false positives). All fixed:

  • venue mismatch now falls through to search instead of autoplaying the wrong show on a two-show day
  • serialized handling prevents interleaved navigate/play
  • fetch-before-navigate (no stranded empty detail on fetch failure)
  • best-track-index prefers the longest contained title for segue links
  • audio resolution paginates (was first-page-only)
  • onOpenURL TOCTOU re-check + re-stash
  • zero-pad-tolerant date comparison

Testing

  • 19 unit tests (parser + matchers), host-free, ~10ms.
  • Clean build under SWIFT_STRICT_CONCURRENCY=complete, 0 warnings from new code.
  • Verified end-to-end against a real applenugs:// URL with a logged-in session (ad-hoc-signed test build).

Notes

  • Auto-play on arrival is intentional (the user came from a "Listen"/"Watch" link).
  • AppleNugs.xcodeproj is generated (xcodegen generate), per existing repo convention.

🤖 Generated with Claude Code

…lay)

Implements the app side of the goose-almanac deep-link contract:
  applenugs://show/<date>?artist=Goose[&venue=][&song=&set=&pos=][&media=audio|video]

- DeepLink.swift: pure, unit-tested parser + DeepLinkMatch fuzzy matching
  (normalize / venue / best-track-index), plus zero-pad date normalization.
- DeepLinkRouter.swift: resolves artist+date to a nugs container and
  navigates + starts playback; track links start at the matched track, show
  links play from the top, video opens the auto-playing video detail. Audio
  resolution pages the artist's shows (bounded) and falls back to catalog
  search; video pages the per-artist list (no search exists for video).
- AppModel: serialized deep-link channel (receiveDeepLink/handleDeepLink) so
  two links — or a link racing the post-login drain — can't interleave their
  navigate+play steps; pending-link slot replayed after login/bootstrap.
- AppleNugsApp: .onOpenURL wired non-destructively (existing .frame / UITest
  modifiers untouched). RootView: drains the pending link once .loggedIn.
- project.yml: registers the `applenugs` scheme only (not `nugsnet`, which
  stays OAuth-only) and adds a standalone host-free AppleNugsTests unit-test
  target (DeepLink.swift compiled in directly, no app launch on test runs).

Review corrections folded in: venue mismatch falls through to search instead
of guessing; fetch-before-navigate; best-track-index prefers the longest
contained title for segue links; date comparison is zero-pad tolerant.

19 unit tests; clean build under SWIFT_STRICT_CONCURRENCY=complete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tsvb
tsvb merged commit d439b8d into main Jun 29, 2026
1 check passed
@tsvb
tsvb deleted the deep-link-handler branch June 29, 2026 18:43
tsvb pushed a commit that referenced this pull request Jul 3, 2026
Reconciles PR #2 with the iOS port: single host-free AppleNugsTests
target carrying both suites (DeepLink parser + downloads/webcast logic;
34 tests green), deep-link wiring follows AppleNugsApp/RootView into
AppleNugs/macOS/, and the iOS target inherits the pure parser/router in
shared Core for future adoption. Both targets verified green from fresh
derived data.

Co-Authored-By: Claude Fable 5 <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