Browse Source

split seek/status to player slice

master
jeffvli 3 years ago
parent
commit
12e3ae3735
  1. 4
      src/components/card/Card.tsx
  2. 2
      src/components/library/AlbumView.tsx
  3. 2
      src/components/library/ArtistView.tsx
  4. 5
      src/components/player/NowPlayingView.tsx
  5. 17
      src/components/player/Player.tsx
  6. 19
      src/components/player/PlayerBar.tsx
  7. 2
      src/components/starred/StarredView.tsx
  8. 29
      src/components/viewtypes/ListViewTable.tsx
  9. 7
      src/main.dev.js
  10. 63
      src/redux/playQueueSlice.ts
  11. 67
      src/redux/playerSlice.ts

4
src/components/card/Card.tsx

@ -21,6 +21,7 @@ import {
Overlay,
HoverControlButton,
} from './styled';
import { setStatus } from '../../redux/playerSlice';
const Card = ({
onClick,
@ -48,18 +49,21 @@ const Card = ({
if (playClick.type === 'playlist') {
const res = await getPlaylist(playClick.id);
dispatch(setPlayQueue(res.entry));
dispatch(setStatus('PLAYING'));
dispatch(fixPlayer2Index());
}
if (playClick.type === 'album') {
const res = await getAlbum(playClick.id);
dispatch(setPlayQueue(res.song));
dispatch(setStatus('PLAYING'));
dispatch(fixPlayer2Index());
}
if (playClick.type === 'artist') {
const res = await getAlbum(playClick.id);
dispatch(setPlayQueue(res.song));
dispatch(setStatus('PLAYING'));
dispatch(fixPlayer2Index());
}
};

2
src/components/library/AlbumView.tsx

@ -27,6 +27,7 @@ import ListViewType from '../viewtypes/ListViewType';
import Loader from '../loader/Loader';
import GenericPageHeader from '../layout/GenericPageHeader';
import { TagLink } from './styled';
import { setStatus } from '../../redux/playerSlice';
interface AlbumParams {
id: string;
@ -73,6 +74,7 @@ const AlbumView = () => {
dispatch(clearSelected());
dispatch(setPlayQueue(newPlayQueue));
dispatch(setStatus('PLAYING'));
dispatch(fixPlayer2Index());
};

2
src/components/library/ArtistView.tsx

@ -28,6 +28,7 @@ import Loader from '../loader/Loader';
import GenericPageHeader from '../layout/GenericPageHeader';
import CustomTooltip from '../shared/CustomTooltip';
import { TagLink } from './styled';
import { setStatus } from '../../redux/playerSlice';
interface ArtistParams {
id: string;
@ -85,6 +86,7 @@ const ArtistView = () => {
dispatch(clearSelected());
dispatch(setPlayQueue(newPlayQueue));
dispatch(setStatus('PLAYING'));
dispatch(fixPlayer2Index());
};

5
src/components/player/NowPlayingView.tsx

@ -22,6 +22,7 @@ import GenericPage from '../layout/GenericPage';
import GenericPageHeader from '../layout/GenericPageHeader';
import ListViewType from '../viewtypes/ListViewType';
import Loader from '../loader/Loader';
import { resetPlayer, setStatus } from '../../redux/playerSlice';
const NowPlayingView = () => {
const tableRef = useRef<any>();
@ -77,8 +78,10 @@ const NowPlayingView = () => {
dispatch(setPlayerVolume({ player: 2, volume: 0 }));
dispatch(clearSelected());
dispatch(resetPlayer());
dispatch(setPlayerIndex(rowData));
dispatch(fixPlayer2Index());
dispatch(setStatus('PLAYING'));
};
if (!playQueue) {
@ -114,6 +117,8 @@ const NowPlayingView = () => {
<Button
onClick={() => {
dispatch(clearPlayQueue());
dispatch(resetPlayer());
dispatch(setStatus('PAUSED'));
}}
>
Clear queue

17
src/components/player/Player.tsx

@ -17,13 +17,13 @@ import {
incrementPlayerIndex,
setCurrentPlayer,
setPlayerVolume,
setCurrentSeek,
setIsFading,
setAutoIncremented,
resetPlayer,
resetPlayQueue,
fixPlayer2Index,
setCurrentIndex,
} from '../../redux/playQueueSlice';
import { resetPlayer, setCurrentSeek } from '../../redux/playerSlice';
import cacheSong from '../shared/cacheSong';
const Player = ({ children }: any, ref: any) => {
@ -31,6 +31,7 @@ const Player = ({ children }: any, ref: any) => {
const player2Ref = useRef<any>();
const dispatch = useAppDispatch();
const playQueue = useAppSelector((state) => state.playQueue);
const player = useAppSelector((state) => state.player);
const cacheSongs = settings.getSync('cacheSongs');
const [title, setTitle] = useState('');
@ -44,7 +45,7 @@ const Player = ({ children }: any, ref: any) => {
}));
useEffect(() => {
if (playQueue.status === 'PLAYING') {
if (player.status === 'PLAYING') {
if (playQueue.currentPlayer === 1) {
try {
player1Ref.current.audioEl.current.play();
@ -62,7 +63,7 @@ const Player = ({ children }: any, ref: any) => {
player1Ref.current.audioEl.current.pause();
player2Ref.current.audioEl.current.pause();
}
}, [playQueue.currentPlayer, playQueue.status]);
}, [playQueue.currentPlayer, player.status]);
const handleListen1 = () => {
const fadeDuration = Number(settings.getSync('fadeDuration')) || 0;
@ -188,6 +189,7 @@ const Player = ({ children }: any, ref: any) => {
playQueue.repeat === 'none' &&
playQueue.player1.index > playQueue.player2.index
) {
dispatch(resetPlayQueue());
dispatch(resetPlayer());
dispatch(fixPlayer2Index());
setTimeout(() => {
@ -196,6 +198,7 @@ const Player = ({ children }: any, ref: any) => {
}, 200);
} else {
if (!playQueue.autoIncremented) {
dispatch(resetPlayer());
dispatch(incrementCurrentIndex('none'));
dispatch(setCurrentIndex(playQueue.entry[playQueue.player2.index]));
dispatch(setAutoIncremented(true));
@ -225,6 +228,7 @@ const Player = ({ children }: any, ref: any) => {
playQueue.repeat === 'none' &&
playQueue.player2.index > playQueue.player1.index
) {
dispatch(resetPlayQueue());
dispatch(resetPlayer());
dispatch(fixPlayer2Index());
setTimeout(() => {
@ -233,6 +237,7 @@ const Player = ({ children }: any, ref: any) => {
}, 200);
} else {
if (!playQueue.autoIncremented) {
dispatch(resetPlayer());
dispatch(incrementCurrentIndex('none'));
dispatch(setCurrentIndex(playQueue.entry[playQueue.player1.index]));
dispatch(setAutoIncremented(true));
@ -275,7 +280,7 @@ const Player = ({ children }: any, ref: any) => {
useEffect(() => {
const playStatus =
playQueue.status !== 'PLAYING' && playQueue.entry.length > 0
player.status !== 'PLAYING' && playQueue.entry.length > 0
? '(Paused)'
: '';
const songTitle = playQueue.entry[playQueue.currentIndex]?.title
@ -285,7 +290,7 @@ const Player = ({ children }: any, ref: any) => {
: 'sonixd';
setTitle(`${playStatus} ${songTitle}`);
}, [playQueue.currentIndex, playQueue.entry, playQueue.status]);
}, [playQueue.currentIndex, playQueue.entry, player.status]);
return (
<>

19
src/components/player/PlayerBar.tsx

@ -17,12 +17,12 @@ import {
decrementCurrentIndex,
setVolume,
setPlayerVolume,
setStatus,
fixPlayer2Index,
toggleRepeat,
toggleDisplayQueue,
setStar,
} from '../../redux/playQueueSlice';
import { setStatus, resetPlayer } from '../../redux/playerSlice';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import Player from './Player';
import CustomTooltip from '../shared/CustomTooltip';
@ -37,6 +37,7 @@ const keyCodes = {
const PlayerBar = () => {
const queryClient = useQueryClient();
const playQueue = useAppSelector((state) => state.playQueue);
const player = useAppSelector((state) => state.player);
const dispatch = useAppDispatch();
const [seek, setSeek] = useState(0);
const [isDragging, setIsDragging] = useState(false);
@ -51,8 +52,8 @@ const PlayerBar = () => {
const history = useHistory();
useEffect(() => {
setSeek(playQueue.currentSeek);
}, [playQueue.currentSeek]);
setSeek(player.currentSeek);
}, [player.currentSeek]);
useEffect(() => {
if (isDragging) {
@ -70,16 +71,18 @@ const PlayerBar = () => {
}, [isDragging, manualSeek, playQueue.currentPlayer]);
const handleClickNext = () => {
dispatch(resetPlayer());
dispatch(incrementCurrentIndex('usingHotkey'));
};
const handleClickPrevious = () => {
dispatch(resetPlayer());
dispatch(decrementCurrentIndex('usingHotkey'));
dispatch(fixPlayer2Index());
};
const handleClickPlayPause = () => {
dispatch(setStatus(playQueue.status === 'PLAYING' ? 'PAUSED' : 'PLAYING'));
dispatch(setStatus(player.status === 'PLAYING' ? 'PAUSED' : 'PLAYING'));
};
const handleVolumeSlider = (e: number) => {
@ -395,13 +398,11 @@ const PlayerBar = () => {
<PlayerControlIcon
tabIndex={0}
icon={
playQueue.status === 'PLAYING'
? 'pause-circle'
: 'play-circle'
player.status === 'PLAYING' ? 'pause-circle' : 'play-circle'
}
spin={
playQueue.currentSeekable <= playQueue.currentSeek &&
playQueue.status === 'PLAYING'
player.currentSeekable <= player.currentSeek &&
player.status === 'PLAYING'
}
size="3x"
onClick={handleClickPlayPause}

2
src/components/starred/StarredView.tsx

@ -18,6 +18,7 @@ import GenericPageHeader from '../layout/GenericPageHeader';
import Loader from '../loader/Loader';
import ListViewType from '../viewtypes/ListViewType';
import GridViewType from '../viewtypes/GridViewType';
import { setStatus } from '../../redux/playerSlice';
const StarredView = () => {
const dispatch = useAppDispatch();
@ -80,6 +81,7 @@ const StarredView = () => {
const newPlayQueue = data.song.slice([e.index], data.song.length);
dispatch(clearSelected());
dispatch(setPlayQueue(newPlayQueue));
dispatch(setStatus('PLAYING'));
dispatch(fixPlayer2Index());
};

29
src/components/viewtypes/ListViewTable.tsx

@ -112,7 +112,10 @@ const ListViewTable = ({
})
}
className={
rowData.id === playQueue?.currentSongId ? 'active' : ''
rowData.id === playQueue?.currentSongId &&
playQueue.currentIndex === rowIndex
? 'active'
: ''
}
style={
multiSelect?.selected.find(
@ -149,7 +152,10 @@ const ListViewTable = ({
})
}
className={
rowData.id === playQueue?.currentSongId ? 'active' : ''
rowData.id === playQueue?.currentSongId &&
playQueue.currentIndex === rowIndex
? 'active'
: ''
}
style={
multiSelect?.selected.find(
@ -258,11 +264,6 @@ const ListViewTable = ({
<RsuiteLinkButton
subtitle="true"
appearance="link"
className={
rowData.id === playQueue?.currentSongId
? 'active'
: ''
}
onClick={() => {
history.push(
`/library/artist/${rowData.artistId}`
@ -355,7 +356,12 @@ const ListViewTable = ({
})
}
className={
rowData.id === playQueue?.currentSongId ? 'active' : ''
rowData.id === playQueue?.currentSongId &&
(column.dataKey === 'title' ||
column.dataKey === 'name') &&
playQueue.currentIndex === rowIndex
? 'active'
: ''
}
style={
multiSelect?.selected.find(
@ -382,11 +388,6 @@ const ListViewTable = ({
column.dataKey === 'artist' ? (
<RsuiteLinkButton
appearance="link"
className={
rowData.id === playQueue?.currentSongId
? 'active'
: ''
}
onClick={() => {
if (column.dataKey === 'album') {
history.push(`/library/album/${rowData.albumId}`);
@ -414,7 +415,7 @@ const ListViewTable = ({
size="lg"
fixedWidth
style={{
color: rowData?.starred ? '#1179ac' : undefined,
color: rowData?.starred ? '#1179ac' : '#E8EAEF',
cursor: 'pointer',
}}
onClick={() => handleFavorite(rowData)}

7
src/main.dev.js

@ -20,11 +20,10 @@ import {
triggerAlias,
replayActionMain,
} from 'electron-redux';
import playerReducer from './redux/playerSlice';
import playerReducer, { resetPlayer, setStatus } from './redux/playerSlice';
import playQueueReducer, {
decrementCurrentIndex,
incrementCurrentIndex,
setStatus,
fixPlayer2Index,
} from './redux/playQueueSlice';
import multiSelectReducer from './redux/multiSelectSlice';
@ -112,7 +111,7 @@ const createWindow = async () => {
globalShortcut.register('MediaPlayPause', () => {
const storeValues = store.getState();
if (storeValues.playQueue.entry.length >= 1) {
if (storeValues.playQueue.status === 'PAUSED') {
if (storeValues.player.status === 'PAUSED') {
store.dispatch(setStatus('PLAYING'));
} else {
store.dispatch(setStatus('PAUSED'));
@ -123,6 +122,7 @@ const createWindow = async () => {
globalShortcut.register('MediaNextTrack', () => {
const storeValues = store.getState();
if (storeValues.playQueue.entry.length >= 1) {
store.dispatch(resetPlayer());
store.dispatch(incrementCurrentIndex('usingHotkey'));
}
});
@ -130,6 +130,7 @@ const createWindow = async () => {
globalShortcut.register('MediaPreviousTrack', () => {
const storeValues = store.getState();
if (storeValues.playQueue.entry.length >= 1) {
store.dispatch(resetPlayer());
store.dispatch(decrementCurrentIndex('usingHotkey'));
store.dispatch(fixPlayer2Index());
}

63
src/redux/playQueueSlice.ts

@ -30,14 +30,6 @@ interface Entry {
}
export interface PlayQueue {
status: string;
currentIndex: number;
currentSongId: string;
currentPlayer: number;
currentSeek: number;
currentSeekable: number;
isFading: boolean;
autoIncremented: boolean;
player1: {
index: number;
volume: number;
@ -46,6 +38,11 @@ export interface PlayQueue {
index: number;
volume: number;
};
currentIndex: number;
currentSongId: string;
currentPlayer: number;
isFading: boolean;
autoIncremented: boolean;
volume: number;
isLoading: boolean;
repeat: string;
@ -55,14 +52,6 @@ export interface PlayQueue {
}
const initialState: PlayQueue = {
status: 'PAUSED',
currentIndex: 0,
currentSongId: '',
currentPlayer: 1,
currentSeek: 0,
currentSeekable: 0,
isFading: false,
autoIncremented: false,
player1: {
index: 0,
volume: 0.5,
@ -71,6 +60,11 @@ const initialState: PlayQueue = {
index: 1,
volume: 0,
},
currentIndex: 0,
currentSongId: '',
currentPlayer: 1,
isFading: false,
autoIncremented: false,
volume: 0.5,
isLoading: false,
repeat: 'none',
@ -79,17 +73,11 @@ const initialState: PlayQueue = {
entry: [],
};
// TODO: Needs refactoring due to rapid experimental changes to add gapless playback
const resetPlayerDefaults = (state: PlayQueue) => {
state.currentSeek = 0;
state.currentSeekable = 0;
state.isFading = false;
state.currentIndex = 0;
state.currentSongId = '';
state.currentPlayer = 1;
state.currentSeek = 0;
state.currentSeekable = 0;
state.player1.index = 0;
state.player1.volume = state.volume;
state.player2.index = 0;
@ -100,16 +88,9 @@ const playQueueSlice = createSlice({
name: 'nowPlaying',
initialState,
reducers: {
resetPlayer: (state) => {
resetPlayQueue: (state) => {
resetPlayerDefaults(state);
state.currentSongId = state.entry[0].id;
state.status = 'PAUSED';
},
setStatus: (state, action: PayloadAction<string>) => {
if (state.entry.length >= 1) {
state.status = action.payload;
}
},
setAutoIncremented: (state, action: PayloadAction<boolean>) => {
@ -151,14 +132,6 @@ const playQueueSlice = createSlice({
state.volume = action.payload;
},
setCurrentSeek: (
state,
action: PayloadAction<{ seek: number; seekable: number }>
) => {
state.currentSeek = action.payload.seek;
state.currentSeekable = action.payload.seekable;
},
setCurrentPlayer: (state, action: PayloadAction<number>) => {
if (action.payload === 1) {
state.currentPlayer = 1;
@ -169,8 +142,6 @@ const playQueueSlice = createSlice({
incrementCurrentIndex: (state, action: PayloadAction<string>) => {
if (state.entry.length >= 1) {
state.currentSeek = 0;
state.currentSeekable = 0;
if (state.currentIndex < state.entry.length - 1) {
state.currentIndex += 1;
if (action.payload === 'usingHotkey') {
@ -242,8 +213,6 @@ const playQueueSlice = createSlice({
(track) => track.id === action.payload.id
);
state.currentSeek = 0;
state.currentSeekable = 0;
state.isFading = false;
state.player1.index = findIndex;
state.player1.volume = state.volume;
@ -271,8 +240,6 @@ const playQueueSlice = createSlice({
decrementCurrentIndex: (state, action: PayloadAction<string>) => {
if (state.entry.length >= 1) {
state.currentSeek = 0;
state.currentSeekable = 0;
if (state.currentIndex > 0) {
state.currentIndex -= 1;
if (action.payload === 'usingHotkey') {
@ -316,9 +283,6 @@ const playQueueSlice = createSlice({
state.entry = [];
resetPlayerDefaults(state);
if (state.status !== 'PLAYING') {
state.status = 'PLAYING';
}
state.currentSongId = action.payload[0].id;
action.payload.map((entry: any) => state.entry.push(entry));
},
@ -329,7 +293,6 @@ const playQueueSlice = createSlice({
clearPlayQueue: (state) => {
state.entry = [];
state.status = 'PAUSED';
resetPlayerDefaults(state);
},
@ -423,16 +386,14 @@ export const {
moveUp,
moveDown,
setCurrentPlayer,
setStatus,
setPlayerVolume,
setVolume,
setCurrentSeek,
setIsFading,
setAutoIncremented,
toggleRepeat,
toggleShuffle,
toggleDisplayQueue,
resetPlayer,
resetPlayQueue,
setStar,
} = playQueueSlice.actions;
export default playQueueSlice.reducer;

67
src/redux/playerSlice.ts

@ -1,64 +1,39 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface Player {
url?: string;
playStatus?: string;
playFromPosition?: number;
volume?: number;
isLoading?: boolean;
status: string;
currentSeek: number;
currentSeekable: number;
}
const initialState: Player = {
url: '',
playStatus: 'STOPPED',
playFromPosition: 0,
volume: 100,
isLoading: false,
status: 'PAUSED',
currentSeek: 0,
currentSeekable: 0,
};
const playerSlice = createSlice({
name: 'player',
initialState,
reducers: {
togglePlayback: (state, action: PayloadAction<Player>) => {
if (state.playStatus === 'PAUSED' || state.playStatus === 'STOPPED') {
state.playStatus = 'PLAYING';
} else {
state.playStatus = 'PAUSED';
}
state.url = action.payload.url!;
},
startPlayback: (state: any, action: PayloadAction<Player>) => {
state.url = action.payload.url;
state.playStatus = 'PLAYING';
state.playFromPosition = 0;
},
stopPlayback: (state) => {
state.playStatus = 'STOPPED';
resetPlayer: (state) => {
state.currentSeek = 0;
state.currentSeekable = 0;
},
pausePlayback: (state) => {
state.playStatus = 'PAUSED';
},
resetPlayback: () => initialState,
setIsLoading: (state: any, action: PayloadAction<Player>) => {
state.isLoading = action.payload.isLoading;
},
setVolume: (state, action: PayloadAction<Player>) => {
state.volume = action.payload.volume!;
setStatus: (state, action: PayloadAction<string>) => {
state.status = action.payload;
},
setPlayFromPosition: (state, action: PayloadAction<Player>) => {
state.playFromPosition = action.payload.playFromPosition!;
setCurrentSeek: (
state,
action: PayloadAction<{ seek: number; seekable: number }>
) => {
state.currentSeek = action.payload.seek;
state.currentSeekable = action.payload.seekable;
},
},
});
export const {
togglePlayback,
startPlayback,
stopPlayback,
pausePlayback,
resetPlayback,
setIsLoading,
setVolume,
setPlayFromPosition,
} = playerSlice.actions;
export const { setStatus, setCurrentSeek, resetPlayer } = playerSlice.actions;
export default playerSlice.reducer;

Loading…
Cancel
Save