mirror of
https://github.com/antebudimir/feishin.git
synced 2026-01-01 02:13:33 +00:00
simplify remote/media session (#632)
This commit is contained in:
parent
d57b4b4b68
commit
110a1a63f0
15 changed files with 236 additions and 230 deletions
|
|
@ -1,5 +1,4 @@
|
|||
import { useCallback } from 'react';
|
||||
import isElectron from 'is-electron';
|
||||
import styled from 'styled-components';
|
||||
import { usePlaybackType, useSettingsStore } from '/@/renderer/store/settings.store';
|
||||
import { PlaybackType } from '/@/renderer/types';
|
||||
|
|
@ -17,6 +16,7 @@ import { CenterControls } from './center-controls';
|
|||
import { LeftControls } from './left-controls';
|
||||
import { RightControls } from './right-controls';
|
||||
import { PlayersRef } from '/@/renderer/features/player/ref/players-ref';
|
||||
import { updateSong } from '/@/renderer/features/player/update-remote-song';
|
||||
|
||||
const PlayerbarContainer = styled.div`
|
||||
width: 100vw;
|
||||
|
|
@ -59,8 +59,6 @@ const CenterGridItem = styled.div`
|
|||
overflow: hidden;
|
||||
`;
|
||||
|
||||
const remote = isElectron() ? window.electron.remote : null;
|
||||
|
||||
export const Playerbar = () => {
|
||||
const playersRef = PlayersRef;
|
||||
const settings = useSettingsStore((state) => state.playback);
|
||||
|
|
@ -75,13 +73,7 @@ export const Playerbar = () => {
|
|||
|
||||
const autoNextFn = useCallback(() => {
|
||||
const playerData = autoNext();
|
||||
|
||||
if (remote) {
|
||||
remote.updateSong({
|
||||
currentTime: 0,
|
||||
song: playerData.current.song,
|
||||
});
|
||||
}
|
||||
updateSong(playerData.current.song);
|
||||
}, [autoNext]);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@ import {
|
|||
import { usePlaybackType } from '/@/renderer/store/settings.store';
|
||||
import { useScrobble } from '/@/renderer/features/player/hooks/use-scrobble';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { QueueSong } from '/@/renderer/api/types';
|
||||
import { toast } from '/@/renderer/components';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { updateSong } from '/@/renderer/features/player/update-remote-song';
|
||||
|
||||
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
|
||||
const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : null;
|
||||
|
|
@ -24,7 +24,7 @@ const ipc = isElectron() ? window.electron.ipc : null;
|
|||
const utils = isElectron() ? window.electron.utils : null;
|
||||
const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null;
|
||||
const remote = isElectron() ? window.electron.remote : null;
|
||||
const mediaSession = !isElectron() || !utils?.isLinux() ? navigator.mediaSession : null;
|
||||
const mediaSession = navigator.mediaSession;
|
||||
|
||||
export const useCenterControls = (args: { playersRef: any }) => {
|
||||
const { t } = useTranslation();
|
||||
|
|
@ -46,6 +46,23 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
|
||||
const { handleScrobbleFromSongRestart, handleScrobbleFromSeek } = useScrobble();
|
||||
|
||||
useEffect(() => {
|
||||
if (mediaSession) {
|
||||
mediaSession.playbackState =
|
||||
playerStatus === PlayerStatus.PLAYING ? 'playing' : 'paused';
|
||||
}
|
||||
|
||||
remote?.updatePlayback(playerStatus);
|
||||
}, [playerStatus]);
|
||||
|
||||
useEffect(() => {
|
||||
remote?.updateRepeat(repeatStatus);
|
||||
}, [repeatStatus]);
|
||||
|
||||
useEffect(() => {
|
||||
remote?.updateShuffle(shuffleStatus !== PlayerShuffle.NONE);
|
||||
}, [shuffleStatus]);
|
||||
|
||||
const resetPlayers = useCallback(() => {
|
||||
if (player1Ref.getInternalPlayer()) {
|
||||
player1Ref.getInternalPlayer().currentTime = 0;
|
||||
|
|
@ -76,61 +93,7 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
|
||||
const isMpvPlayer = isElectron() && playbackType === PlaybackType.LOCAL;
|
||||
|
||||
const mprisUpdateSong = (args?: {
|
||||
currentTime?: number;
|
||||
song?: QueueSong;
|
||||
status?: PlayerStatus;
|
||||
}) => {
|
||||
const { song, currentTime, status } = args || {};
|
||||
|
||||
const time = currentTime || usePlayerStore.getState().current.time;
|
||||
const playStatus = status || usePlayerStore.getState().current.status;
|
||||
const track = song || usePlayerStore.getState().current.song;
|
||||
|
||||
remote?.updateSong({
|
||||
currentTime: time,
|
||||
repeat: usePlayerStore.getState().repeat,
|
||||
shuffle: usePlayerStore.getState().shuffle !== PlayerShuffle.NONE,
|
||||
song: track,
|
||||
status: playStatus,
|
||||
});
|
||||
|
||||
if (mediaSession) {
|
||||
mediaSession.playbackState = playStatus === PlayerStatus.PLAYING ? 'playing' : 'paused';
|
||||
|
||||
let metadata: MediaMetadata;
|
||||
|
||||
if (track) {
|
||||
let artwork: MediaImage[];
|
||||
|
||||
if (track.imageUrl) {
|
||||
const image300 = track.imageUrl
|
||||
?.replace(/&size=\d+/, '&size=300')
|
||||
.replace(/\?width=\d+/, '?width=300')
|
||||
.replace(/&height=\d+/, '&height=300');
|
||||
|
||||
artwork = [{ sizes: '300x300', src: image300, type: 'image/png' }];
|
||||
} else {
|
||||
artwork = [];
|
||||
}
|
||||
|
||||
metadata = new MediaMetadata({
|
||||
album: track.album ?? '',
|
||||
artist: track.artistName,
|
||||
artwork,
|
||||
title: track.name,
|
||||
});
|
||||
} else {
|
||||
metadata = new MediaMetadata();
|
||||
}
|
||||
|
||||
mediaSession.metadata = metadata;
|
||||
}
|
||||
};
|
||||
|
||||
const handlePlay = useCallback(() => {
|
||||
mprisUpdateSong({ status: PlayerStatus.PLAYING });
|
||||
|
||||
if (isMpvPlayer) {
|
||||
mpvPlayer?.volume(usePlayerStore.getState().volume);
|
||||
mpvPlayer!.play();
|
||||
|
|
@ -145,8 +108,6 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
}, [currentPlayerRef, isMpvPlayer, play]);
|
||||
|
||||
const handlePause = useCallback(() => {
|
||||
mprisUpdateSong({ status: PlayerStatus.PAUSED });
|
||||
|
||||
if (isMpvPlayer) {
|
||||
mpvPlayer!.pause();
|
||||
}
|
||||
|
|
@ -155,8 +116,6 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
}, [isMpvPlayer, pause]);
|
||||
|
||||
const handleStop = useCallback(() => {
|
||||
mprisUpdateSong({ status: PlayerStatus.PAUSED });
|
||||
|
||||
if (isMpvPlayer) {
|
||||
mpvPlayer!.pause();
|
||||
mpvPlayer!.seekTo(0);
|
||||
|
|
@ -212,13 +171,13 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
const handleRepeatAll = {
|
||||
local: () => {
|
||||
const playerData = autoNext();
|
||||
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.autoNext(playerData);
|
||||
play();
|
||||
},
|
||||
web: () => {
|
||||
const playerData = autoNext();
|
||||
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING });
|
||||
updateSong(playerData.current.song);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -226,15 +185,12 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
local: () => {
|
||||
if (isLastTrack) {
|
||||
const playerData = setCurrentIndex(0);
|
||||
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PAUSED });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.setQueue(playerData, true);
|
||||
pause();
|
||||
} else {
|
||||
const playerData = autoNext();
|
||||
mprisUpdateSong({
|
||||
song: playerData.current.song,
|
||||
status: PlayerStatus.PLAYING,
|
||||
});
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.autoNext(playerData);
|
||||
play();
|
||||
}
|
||||
|
|
@ -242,14 +198,10 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
web: () => {
|
||||
if (isLastTrack) {
|
||||
resetPlayers();
|
||||
mprisUpdateSong({ status: PlayerStatus.PAUSED });
|
||||
pause();
|
||||
} else {
|
||||
const playerData = autoNext();
|
||||
mprisUpdateSong({
|
||||
song: playerData.current.song,
|
||||
status: PlayerStatus.PLAYING,
|
||||
});
|
||||
updateSong(playerData.current.song);
|
||||
resetPlayers();
|
||||
}
|
||||
},
|
||||
|
|
@ -258,20 +210,15 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
const handleRepeatOne = {
|
||||
local: () => {
|
||||
const playerData = autoNext();
|
||||
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PLAYING });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.autoNext(playerData);
|
||||
play();
|
||||
},
|
||||
web: () => {
|
||||
if (isLastTrack) {
|
||||
mprisUpdateSong({ status: PlayerStatus.PAUSED });
|
||||
resetPlayers();
|
||||
} else {
|
||||
const playerData = autoNext();
|
||||
mprisUpdateSong({
|
||||
song: playerData.current.song,
|
||||
status: PlayerStatus.PLAYING,
|
||||
});
|
||||
autoNext();
|
||||
resetPlayers();
|
||||
}
|
||||
},
|
||||
|
|
@ -309,12 +256,12 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
const handleRepeatAll = {
|
||||
local: () => {
|
||||
const playerData = next();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.setQueue(playerData);
|
||||
},
|
||||
web: () => {
|
||||
const playerData = next();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -322,27 +269,24 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
local: () => {
|
||||
if (isLastTrack) {
|
||||
const playerData = setCurrentIndex(0);
|
||||
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PAUSED });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.setQueue(playerData, true);
|
||||
pause();
|
||||
} else {
|
||||
const playerData = next();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.setQueue(playerData);
|
||||
}
|
||||
},
|
||||
web: () => {
|
||||
if (isLastTrack) {
|
||||
const playerData = setCurrentIndex(0);
|
||||
mprisUpdateSong({
|
||||
song: playerData.current.song,
|
||||
status: PlayerStatus.PAUSED,
|
||||
});
|
||||
updateSong(playerData.current.song);
|
||||
resetPlayers();
|
||||
pause();
|
||||
} else {
|
||||
const playerData = next();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
resetPlayers();
|
||||
}
|
||||
},
|
||||
|
|
@ -352,14 +296,14 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
local: () => {
|
||||
if (!isLastTrack) {
|
||||
const playerData = next();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.setQueue(playerData);
|
||||
}
|
||||
},
|
||||
web: () => {
|
||||
if (!isLastTrack) {
|
||||
const playerData = next();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -413,22 +357,22 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
local: () => {
|
||||
if (!isFirstTrack) {
|
||||
const playerData = previous();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.setQueue(playerData);
|
||||
} else {
|
||||
const playerData = setCurrentIndex(queue.length - 1);
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.setQueue(playerData);
|
||||
}
|
||||
},
|
||||
web: () => {
|
||||
if (isFirstTrack) {
|
||||
const playerData = setCurrentIndex(queue.length - 1);
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
resetPlayers();
|
||||
} else {
|
||||
const playerData = previous();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
resetPlayers();
|
||||
}
|
||||
},
|
||||
|
|
@ -438,26 +382,22 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
local: () => {
|
||||
if (isFirstTrack) {
|
||||
const playerData = setCurrentIndex(0);
|
||||
mprisUpdateSong({ song: playerData.current.song, status: PlayerStatus.PAUSED });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.setQueue(playerData, true);
|
||||
pause();
|
||||
} else {
|
||||
const playerData = previous();
|
||||
mprisUpdateSong({
|
||||
currentTime: usePlayerStore.getState().current.time,
|
||||
song: playerData.current.song,
|
||||
});
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.setQueue(playerData);
|
||||
}
|
||||
},
|
||||
web: () => {
|
||||
if (isFirstTrack) {
|
||||
resetPlayers();
|
||||
mprisUpdateSong({ status: PlayerStatus.PAUSED });
|
||||
pause();
|
||||
} else {
|
||||
const playerData = previous();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
resetPlayers();
|
||||
}
|
||||
},
|
||||
|
|
@ -466,12 +406,12 @@ export const useCenterControls = (args: { playersRef: any }) => {
|
|||
const handleRepeatOne = {
|
||||
local: () => {
|
||||
const playerData = previous();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
mpvPlayer!.setQueue(playerData);
|
||||
},
|
||||
web: () => {
|
||||
const playerData = previous();
|
||||
mprisUpdateSong({ song: playerData.current.song });
|
||||
updateSong(playerData.current.song);
|
||||
resetPlayers();
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,13 +2,7 @@ import { useCallback, useRef } from 'react';
|
|||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useCurrentServer, usePlayerControls, usePlayerStore } from '/@/renderer/store';
|
||||
import { usePlaybackType } from '/@/renderer/store/settings.store';
|
||||
import {
|
||||
PlayQueueAddOptions,
|
||||
Play,
|
||||
PlaybackType,
|
||||
PlayerStatus,
|
||||
PlayerShuffle,
|
||||
} from '/@/renderer/types';
|
||||
import { PlayQueueAddOptions, Play, PlaybackType } from '/@/renderer/types';
|
||||
import { toast } from '/@/renderer/components/toast/index';
|
||||
import isElectron from 'is-electron';
|
||||
import { nanoid } from 'nanoid/non-secure';
|
||||
|
|
@ -30,6 +24,7 @@ import {
|
|||
import { queryKeys } from '/@/renderer/api/query-keys';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PlayersRef } from '/@/renderer/features/player/ref/players-ref';
|
||||
import { updateSong } from '/@/renderer/features/player/update-remote-song';
|
||||
|
||||
const getRootQueryKey = (itemType: LibraryItem, serverId: string) => {
|
||||
let queryKey;
|
||||
|
|
@ -59,7 +54,6 @@ const getRootQueryKey = (itemType: LibraryItem, serverId: string) => {
|
|||
};
|
||||
|
||||
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
|
||||
const remote = isElectron() ? window.electron.remote : null;
|
||||
|
||||
const addToQueue = usePlayerStore.getState().actions.addToQueue;
|
||||
|
||||
|
|
@ -171,6 +165,8 @@ export const useHandlePlayQueueAdd = () => {
|
|||
const hadSong = usePlayerStore.getState().queue.default.length > 0;
|
||||
const playerData = addToQueue({ initialIndex: initialSongIndex, playType, songs });
|
||||
|
||||
updateSong(playerData.current.song);
|
||||
|
||||
if (playbackType === PlaybackType.LOCAL) {
|
||||
mpvPlayer!.volume(usePlayerStore.getState().volume);
|
||||
|
||||
|
|
@ -197,14 +193,6 @@ export const useHandlePlayQueueAdd = () => {
|
|||
play();
|
||||
}
|
||||
|
||||
remote?.updateSong({
|
||||
currentTime: usePlayerStore.getState().current.time,
|
||||
repeat: usePlayerStore.getState().repeat,
|
||||
shuffle: usePlayerStore.getState().shuffle !== PlayerShuffle.NONE,
|
||||
song: playerData.current.song,
|
||||
status: PlayerStatus.PLAYING,
|
||||
});
|
||||
|
||||
return null;
|
||||
},
|
||||
[play, playbackType, queryClient, server, t],
|
||||
|
|
|
|||
39
src/renderer/features/player/update-remote-song.tsx
Normal file
39
src/renderer/features/player/update-remote-song.tsx
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import isElectron from 'is-electron';
|
||||
import { QueueSong } from '/@/renderer/api/types';
|
||||
|
||||
const remote = isElectron() ? window.electron.remote : null;
|
||||
const mediaSession = navigator.mediaSession;
|
||||
|
||||
export const updateSong = (song: QueueSong | undefined) => {
|
||||
if (mediaSession) {
|
||||
let metadata: MediaMetadata;
|
||||
|
||||
if (song?.id) {
|
||||
let artwork: MediaImage[];
|
||||
|
||||
if (song.imageUrl) {
|
||||
const image300 = song.imageUrl
|
||||
?.replace(/&size=\d+/, '&size=300')
|
||||
.replace(/\?width=\d+/, '?width=300')
|
||||
.replace(/&height=\d+/, '&height=300');
|
||||
|
||||
artwork = [{ sizes: '300x300', src: image300, type: 'image/png' }];
|
||||
} else {
|
||||
artwork = [];
|
||||
}
|
||||
|
||||
metadata = new MediaMetadata({
|
||||
album: song.album ?? '',
|
||||
artist: song.artistName,
|
||||
artwork,
|
||||
title: song.name,
|
||||
});
|
||||
} else {
|
||||
metadata = new MediaMetadata();
|
||||
}
|
||||
|
||||
mediaSession.metadata = metadata;
|
||||
}
|
||||
|
||||
remote?.updateSong(song);
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue