mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-15 07:54:18 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b16e57710b | |||
| 931e96b9d1 | |||
| c27b86d2b2 | |||
| b3cf73836d | |||
| 1b15c73db0 | |||
| 4e53030e8d | |||
| 22b798812e |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "feishin",
|
"name": "feishin",
|
||||||
"version": "0.21.1",
|
"version": "0.21.2",
|
||||||
"description": "A modern self-hosted music player.",
|
"description": "A modern self-hosted music player.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"subsonic",
|
"subsonic",
|
||||||
|
|||||||
@@ -39,17 +39,21 @@ interface CenterControlsProps {
|
|||||||
export const CenterControls = ({ playersRef }: CenterControlsProps) => {
|
export const CenterControls = ({ playersRef }: CenterControlsProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
const [isSeeking, setIsSeeking] = useState(false);
|
||||||
const currentSong = useCurrentSong();
|
const currentSong = useCurrentSong();
|
||||||
const skip = useSettingsStore((state) => state.general.skipButtons);
|
const skip = useSettingsStore((state) => state.general.skipButtons);
|
||||||
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
const buttonSize = useSettingsStore((state) => state.general.buttonSize);
|
||||||
|
const playbackType = usePlaybackType();
|
||||||
const player1 = playersRef?.current?.player1;
|
const player1 = playersRef?.current?.player1;
|
||||||
const player2 = playersRef?.current?.player2;
|
const player2 = playersRef?.current?.player2;
|
||||||
const status = useCurrentStatus();
|
const status = useCurrentStatus();
|
||||||
|
const player = useCurrentPlayer();
|
||||||
|
const setCurrentTime = useSetCurrentTime();
|
||||||
const repeat = useRepeatStatus();
|
const repeat = useRepeatStatus();
|
||||||
const shuffle = useShuffleStatus();
|
const shuffle = useShuffleStatus();
|
||||||
const { bindings } = useHotkeySettings();
|
const { bindings } = useHotkeySettings();
|
||||||
|
const { showTimeRemaining } = useAppStore();
|
||||||
|
const { setShowTimeRemaining } = useAppStoreActions();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
handleNextTrack,
|
handleNextTrack,
|
||||||
@@ -66,6 +70,32 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
|
|||||||
} = useCenterControls({ playersRef });
|
} = useCenterControls({ playersRef });
|
||||||
const handlePlayQueueAdd = usePlayQueueAdd();
|
const handlePlayQueueAdd = usePlayQueueAdd();
|
||||||
|
|
||||||
|
const songDuration = currentSong?.duration ? currentSong.duration / 1000 : 0;
|
||||||
|
const currentTime = useCurrentTime();
|
||||||
|
const currentPlayerRef = player === 1 ? player1 : player2;
|
||||||
|
const formattedDuration = formatDuration(songDuration * 1000 || 0);
|
||||||
|
const formattedTimeRemaining = formatDuration((currentTime - songDuration) * 1000 || 0);
|
||||||
|
const formattedTime = formatDuration(currentTime * 1000 || 0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let interval: ReturnType<typeof setInterval>;
|
||||||
|
|
||||||
|
if (status === PlayerStatus.PLAYING && !isSeeking) {
|
||||||
|
if (!isElectron() || playbackType === PlaybackType.WEB) {
|
||||||
|
// Update twice a second for slightly better performance
|
||||||
|
interval = setInterval(() => {
|
||||||
|
if (currentPlayerRef) {
|
||||||
|
setCurrentTime(currentPlayerRef.getCurrentTime());
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}, [currentPlayerRef, isSeeking, setCurrentTime, playbackType, status]);
|
||||||
|
|
||||||
|
const [seekValue, setSeekValue] = useState(0);
|
||||||
|
|
||||||
useHotkeys([
|
useHotkeys([
|
||||||
[bindings.playPause.isGlobal ? '' : bindings.playPause.hotkey, handlePlayPause],
|
[bindings.playPause.isGlobal ? '' : bindings.playPause.hotkey, handlePlayPause],
|
||||||
[bindings.play.isGlobal ? '' : bindings.play.hotkey, handlePlay],
|
[bindings.play.isGlobal ? '' : bindings.play.hotkey, handlePlay],
|
||||||
@@ -237,60 +267,6 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<PlayerSeekSlider
|
|
||||||
handleSeekSlider={handleSeekSlider}
|
|
||||||
player1={player1}
|
|
||||||
player2={player2}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const PlayerSeekSlider = ({
|
|
||||||
handleSeekSlider,
|
|
||||||
player1,
|
|
||||||
player2,
|
|
||||||
}: {
|
|
||||||
handleSeekSlider: (e: any | number) => void;
|
|
||||||
player1: any;
|
|
||||||
player2: any;
|
|
||||||
}) => {
|
|
||||||
const player = useCurrentPlayer();
|
|
||||||
const playbackType = usePlaybackType();
|
|
||||||
const setCurrentTime = useSetCurrentTime();
|
|
||||||
const status = useCurrentStatus();
|
|
||||||
|
|
||||||
const currentSong = useCurrentSong();
|
|
||||||
const songDuration = currentSong?.duration ? currentSong.duration / 1000 : 0;
|
|
||||||
const currentTime = useCurrentTime();
|
|
||||||
const currentPlayerRef = player === 1 ? player1 : player2;
|
|
||||||
const [isSeeking, setIsSeeking] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
let interval: ReturnType<typeof setInterval>;
|
|
||||||
|
|
||||||
if (status === PlayerStatus.PLAYING && !isSeeking) {
|
|
||||||
if (!isElectron() || playbackType === PlaybackType.WEB) {
|
|
||||||
// Update twice a second for slightly better performance
|
|
||||||
interval = setInterval(() => {
|
|
||||||
if (currentPlayerRef) {
|
|
||||||
setCurrentTime(currentPlayerRef.getCurrentTime());
|
|
||||||
}
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
|
||||||
}, [currentPlayerRef, isSeeking, setCurrentTime, playbackType, status]);
|
|
||||||
|
|
||||||
const { showTimeRemaining } = useAppStore();
|
|
||||||
const { setShowTimeRemaining } = useAppStoreActions();
|
|
||||||
const formattedDuration = formatDuration(songDuration * 1000 || 0);
|
|
||||||
const formattedTimeRemaining = formatDuration((currentTime - songDuration) * 1000 || 0);
|
|
||||||
const formattedTime = formatDuration(currentTime * 1000 || 0);
|
|
||||||
const [seekValue, setSeekValue] = useState(0);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.sliderContainer}>
|
<div className={styles.sliderContainer}>
|
||||||
<div className={styles.sliderValueWrapper}>
|
<div className={styles.sliderValueWrapper}>
|
||||||
<Text
|
<Text
|
||||||
@@ -342,5 +318,6 @@ const PlayerSeekSlider = ({
|
|||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ import {
|
|||||||
import { usePlaybackSettings, useSettingsStoreActions } from '/@/renderer/store/settings.store';
|
import { usePlaybackSettings, useSettingsStoreActions } from '/@/renderer/store/settings.store';
|
||||||
import { Switch } from '/@/shared/components/switch/switch';
|
import { Switch } from '/@/shared/components/switch/switch';
|
||||||
|
|
||||||
const isWindows = window.api.utils.isWindows();
|
const isWindows = isElectron() ? window.api.utils.isWindows() : null;
|
||||||
const isDesktop = isElectron();
|
const isDesktop = isElectron();
|
||||||
|
const ipc = isElectron() ? window.api.ipc : null;
|
||||||
|
|
||||||
export const MediaSessionSettings = () => {
|
export const MediaSessionSettings = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -19,7 +20,7 @@ export const MediaSessionSettings = () => {
|
|||||||
function handleMediaSessionChange() {
|
function handleMediaSessionChange() {
|
||||||
const current = mediaSession;
|
const current = mediaSession;
|
||||||
toggleMediaSession();
|
toggleMediaSession();
|
||||||
window.api.ipc.send('settings-set', { property: 'mediaSession', value: !current });
|
ipc?.send('settings-set', { property: 'mediaSession', value: !current });
|
||||||
}
|
}
|
||||||
|
|
||||||
const mediaSessionOptions: SettingOption[] = [
|
const mediaSessionOptions: SettingOption[] = [
|
||||||
@@ -35,7 +36,7 @@ export const MediaSessionSettings = () => {
|
|||||||
context: 'description',
|
context: 'description',
|
||||||
postProcess: 'sentenceCase',
|
postProcess: 'sentenceCase',
|
||||||
}),
|
}),
|
||||||
isHidden: isDesktop && !isWindows,
|
isHidden: !isWindows || !isDesktop,
|
||||||
note: t('common.restartRequired', { postProcess: 'sentenceCase' }),
|
note: t('common.restartRequired', { postProcess: 'sentenceCase' }),
|
||||||
title: t('setting.mediaSession', { postProcess: 'sentenceCase' }),
|
title: t('setting.mediaSession', { postProcess: 'sentenceCase' }),
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user