resend mediasession on player repeat (#1472)

This commit is contained in:
jeffvli
2026-01-01 20:17:49 -08:00
parent af8470e254
commit aaf840d358
4 changed files with 58 additions and 16 deletions
+5
View File
@@ -11,6 +11,7 @@ export type EventMap = {
MEDIA_NEXT: MediaNextEventPayload;
MEDIA_PREV: MediaPrevEventPayload;
PLAYER_PLAY: PlayerPlayEventPayload;
PLAYER_REPEATED: PlayerRepeatedEventPayload;
PLAYLIST_MOVE_DOWN: PlaylistMoveEventPayload;
PLAYLIST_MOVE_TO_BOTTOM: PlaylistMoveEventPayload;
PLAYLIST_MOVE_TO_TOP: PlaylistMoveEventPayload;
@@ -46,6 +47,10 @@ export type PlayerPlayEventPayload = {
index: number;
};
export type PlayerRepeatedEventPayload = {
index: number;
};
export type PlaylistMoveEventPayload = {
playlistId: string;
sourceIds: string[];
@@ -35,6 +35,7 @@ interface PlayerEventsCallbacks {
onPlayerProgress?: (properties: { timestamp: number }, prev: { timestamp: number }) => void;
onPlayerQueueChange?: (queue: QueueData, prev: QueueData) => void;
onPlayerRepeat?: (properties: { repeat: PlayerRepeat }, prev: { repeat: PlayerRepeat }) => void;
onPlayerRepeated?: (properties: { index: number }) => void;
onPlayerSeek?: (properties: { seconds: number }, prev: { seconds: number }) => void;
onPlayerSeekToTimestamp?: (
properties: { timestamp: number },
@@ -161,6 +162,10 @@ function createPlayerEvents(callbacks: PlayerEventsCallbacks): PlayerEvents {
eventEmitter.on('PLAYER_PLAY', callbacks.onPlayerPlay);
}
if (callbacks.onPlayerRepeated) {
eventEmitter.on('PLAYER_REPEATED', callbacks.onPlayerRepeated);
}
if (callbacks.onQueueRestored) {
eventEmitter.on('QUEUE_RESTORED', callbacks.onQueueRestored);
}
@@ -185,6 +190,9 @@ function createPlayerEvents(callbacks: PlayerEventsCallbacks): PlayerEvents {
if (callbacks.onPlayerPlay) {
eventEmitter.off('PLAYER_PLAY', callbacks.onPlayerPlay);
}
if (callbacks.onPlayerRepeated) {
eventEmitter.off('PLAYER_REPEATED', callbacks.onPlayerRepeated);
}
if (callbacks.onQueueRestored) {
eventEmitter.off('QUEUE_RESTORED', callbacks.onQueueRestored);
}
@@ -1,11 +1,16 @@
import isElectron from 'is-electron';
import { useEffect, useMemo } from 'react';
import { useCallback, useEffect, useMemo } from 'react';
import { getItemImageUrl } from '/@/renderer/components/item-image/item-image';
import { usePlayerEvents } from '/@/renderer/features/player/audio-player/hooks/use-player-events';
import { usePlayer } from '/@/renderer/features/player/context/player-context';
import { usePlaybackSettings, useSettingsStore, useTimestampStoreBase } from '/@/renderer/store';
import { LibraryItem } from '/@/shared/types/domain-types';
import {
usePlaybackSettings,
usePlayerStore,
useSettingsStore,
useTimestampStoreBase,
} from '/@/renderer/store';
import { LibraryItem, QueueSong } from '/@/shared/types/domain-types';
import { PlayerStatus, PlayerType } from '/@/shared/types/types';
const mediaSession = navigator.mediaSession;
@@ -85,6 +90,29 @@ export const useMediaSession = () => {
};
}, [player, skip?.skipBackwardSeconds, skip?.skipForwardSeconds, isMediaSessionEnabled]);
const updateMediaSessionMetadata = useCallback(
(song: QueueSong | undefined) => {
if (!isMediaSessionEnabled || !song) {
return;
}
const imageUrl = getItemImageUrl({
id: song?.imageId || undefined,
imageUrl: song?.imageUrl,
itemType: LibraryItem.SONG,
type: 'itemCard',
});
mediaSession.metadata = new MediaMetadata({
album: song?.album ?? '',
artist: song?.artistName ?? '',
artwork: imageUrl ? [{ src: imageUrl, type: 'image/png' }] : [],
title: song?.name ?? '',
});
},
[isMediaSessionEnabled],
);
usePlayerEvents(
{
onCurrentSongChange: (properties) => {
@@ -92,20 +120,15 @@ export const useMediaSession = () => {
return;
}
const song = properties.song;
const imageUrl = getItemImageUrl({
id: song?.imageId || undefined,
imageUrl: song?.imageUrl,
itemType: LibraryItem.SONG,
type: 'itemCard',
});
updateMediaSessionMetadata(properties.song);
},
onPlayerRepeated: () => {
if (!isMediaSessionEnabled) {
return;
}
mediaSession.metadata = new MediaMetadata({
album: song?.album ?? '',
artist: song?.artistName ?? '',
artwork: imageUrl ? [{ src: imageUrl, type: 'image/png' }] : [],
title: song?.name ?? '',
});
const currentSong = usePlayerStore.getState().getCurrentSong();
updateMediaSessionMetadata(currentSong);
},
onPlayerStatus: (properties) => {
if (!isMediaSessionEnabled) {
+6
View File
@@ -1367,6 +1367,12 @@ export const usePlayerStoreBase = createWithEqualityFn<PlayerState>()(
state.player.status = newStatus;
});
if (repeat === PlayerRepeat.ONE && nextIndex === currentIndex) {
eventEmitter.emit('PLAYER_REPEATED', {
index: nextIndex,
});
}
const nextSong = calculateNextSong(nextIndex, queue.items, repeat);
return {