feat: global media controls in sidebar#238
Draft
pip-owl wants to merge 12 commits intoMultiboxLabs:mainfrom
Draft
feat: global media controls in sidebar#238pip-owl wants to merge 12 commits intoMultiboxLabs:mainfrom
pip-owl wants to merge 12 commits intoMultiboxLabs:mainfrom
Conversation
Add mediaPlayPause, mediaNextTrack, mediaPreviousTrack to FlowTabsAPI. Add mediaTitle, mediaArtist, mediaArtwork, mediaPlaybackState to TabData.
Add mediaTitle, mediaArtist, mediaArtwork, mediaPlaybackState properties. Add updateMediaMetadata() and clearMediaMetadata() methods that diff incoming data and emit 'updated' only when values change. Extend TabContentProperty union with the four new keys.
Add mute/unmute to tab context menu for awake tabs. Add tabs:media-play-pause, tabs:media-next-track, tabs:media-previous-track handlers that use executeJavaScript to control page media. Add media-session:metadata-changed and media-session:metadata-cleared listeners that receive push updates from the preload script.
Include mediaTitle, mediaArtist, mediaArtwork, mediaPlaybackState in serializeTabForRenderer() so the sidebar UI can display them.
Add setupMediaSessionWatcher() that observes navigator.mediaSession for metadata changes via MutationObserver + rAF throttling, with a 5-second fallback poll. Sends IPC messages to main process on change. Add media control methods (play/pause, next, prev) to preload bridge. Only activates on non-flow:// protocols (regular web pages).
Create GlobalMediaControls component with favicon, title/artist display, play/pause, skip, and mute controls. Uses AnimatePresence for smooth show/hide transitions. Derives primary media tab from audible/playing state. Place component in sidebar between UpdateBanner and bottom row.
Contributor
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
… for paused tabs - Add play/pause event listeners (capture phase) in the preload MediaSession watcher so playback state updates immediately when media is toggled - Derive playback state from the actual media element when navigator.mediaSession.playbackState is 'none' - Include paused tabs in usePrimaryMediaTab() priority chain so the card stays visible after pausing, allowing the user to resume playback - Update useMediaTabCount() to also count paused tabs
- Replace single-card design with per-tab MediaCard components so each playing/paused tab gets its own card in the sidebar - Filter out the currently focused tab so the card only appears for background media tabs - Extract MediaCard as a standalone memo'd component with its own state
…y/pause controls - Monkey-patch navigator.mediaSession.setActionHandler() in the preload to capture handler references registered by the page, stored on window.__flowMediaActionHandlers - Update next/prev track IPC handlers to call captured handlers directly instead of dispatching fake KeyboardEvents (which don't trigger MediaSession handlers) - Add MediaSession play/pause action handler fallback for sites that use custom audio pipelines without standard <video>/<audio> elements - Replace requestAnimationFrame with setTimeout for debouncing in the preload watcher (rAF is suspended in background tabs by Chromium) - Derive playback state from media element .paused property as ground truth instead of relying on navigator.mediaSession.playbackState - Send play/pause events immediately (not debounced) for instant UI response - Reduce fallback poll interval from 5s to 3s
Implement new card-based UI with: - Collapsed state: favicon + transport controls in a single row - Expanded state (on hover): title row with favicon, title, close button slides in above the controls row - Stacked card visual effect when multiple media tabs exist - White/dark card backgrounds matching space theme - Close tab button using flow.tabs.closeTab - Max 5 media cards displayed
ce3f35d to
b2cbe93
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
contextBridge.executeInMainWorld()) to watchnavigator.mediaSessionmetadata changes and send them to the main process via IPC — no polling from rendererChanges
design/GLOBAL_MEDIA_CONTROLS.mdtabs.ts,interfaces/browser/tabs.tsmediaTitle,mediaArtist,mediaArtwork,mediaPlaybackStatetoTabData; addedmediaPlayPause/mediaNextTrack/mediaPreviousTracktoFlowTabsAPItab.ts,tabs.ts(IPC),serialization.tsTabclass, IPC handlers for control commands + metadata updates, serialization of new fieldsindex.tssetupMediaSessionWatcher()with MutationObserver + setTimeout throttling + 3s fallback poll + play/pause event listeners; monkey-patchesnavigator.mediaSession.setActionHandler()to capture handler refs for skip track support; media control bridge methodsglobal-media-controls.tsx(new),inner.tsxGlobalMediaControlscomponent with per-tabMediaCardcomponents, AnimatePresence animations, active tab filteringKey Design Decisions
executeJavaScriptnavigator.mediaSession.setActionHandler()is monkey-patched in the preload to capture handler references, allowing skip track/play/pause to call the page's actual handlers directly instead of dispatching fake keyboard eventssetTimeoutfor debouncing because Chromium completely suspendsrequestAnimationFramein background tabs (the exact use case for media controls)<video>/<audio>element's.pausedproperty, notnavigator.mediaSession.playbackState(many sites never update the latter)Notes