Skip to content

fix(musicKitHook, main): handle MusicKit instance re-attachment and SPA navigation#51

Merged
flexiondotorg merged 3 commits intomainfrom
hook
Mar 25, 2026
Merged

fix(musicKitHook, main): handle MusicKit instance re-attachment and SPA navigation#51
flexiondotorg merged 3 commits intomainfrom
hook

Conversation

@flexiondotorg
Copy link
Copy Markdown
Member

Summary

MusicKit instance is replaced on sign out/in cycles, causing playback controls and status updates to fail. Additionally, SPA navigation requires re-injection of the navigation hook to maintain state synchronisation across page transitions.

Changes

  • Extract attachToInstance() method for reusable instance attachment logic
  • Replace boolean guard with identity check (newInstance !== currentInstance) for detection accuracy
  • Add 5-second monitor for instance replacement detection to handle timing variations
  • Pass hookScript to setupNavigationHandlers for injection on in-page navigation events
  • Inject hook on did-navigate-in-page with error handling to maintain state across SPA transitions

Testing

  • Sign out/in cycle (218/218 tests passing)
  • SPA navigation through albums, artists, playlists
  • Extended playback session
  • Discord presence, notifications, MPRIS all functioning correctly

…ise volume state

- Extract listener setup into attachToInstance function for re-use
- Monitor for MusicKit instance replacement every 5 seconds and
  re-attach on change
- Send initial volume state immediately to ensure MPRIS receives actual
  value
- Convert polled volume updates to event-driven with polling fallback
- Clear previous volume polling timer when re-hooking to prevent leaks

Fixes race condition where MusicKit internally recreates instance,
causing event pipeline to silently fail.

Signed-off-by: Martin Wimpress <code@wimpress.io>
- Add hookScript parameter to setupNavigationHandlers function
- Make did-navigate-in-page handler async and inject hookScript before
  navBarScript
- Wrap both script injections in separate try-catch blocks to prevent
  failures from blocking each other
- Improve reliability of hook attachment during single-page app
  navigation

Signed-off-by: Martin Wimpress <code@wimpress.io>
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="assets/musicKitHook.js">

<violation number="1" location="assets/musicKitHook.js:2">
P1: Guard against MusicKit being undefined before calling `MusicKit.getInstance()`; otherwise the hook can throw before the polling loop starts when MusicKit hasn’t loaded yet.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Prevent ReferenceError when hook executes before MusicKit loads by
checking window.MusicKit exists before accessing MusicKit.getInstance().

Signed-off-by: Martin Wimpress <code@wimpress.io>
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Requires human review: This PR modifies core playback synchronization logic and refactors how the MusicKit instance is tracked, which is a critical path for the application's functionality.

@flexiondotorg flexiondotorg merged commit edfaeba into main Mar 25, 2026
12 checks passed
@flexiondotorg flexiondotorg deleted the hook branch March 25, 2026 23:37
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