From dd3de662326302178baa98e9ba83f414280aa64d Mon Sep 17 00:00:00 2001 From: jeffvli Date: Mon, 24 Oct 2022 22:30:16 -0700 Subject: [PATCH] Update player/shared components --- src/renderer/app.tsx | 62 +++++++++---------- .../virtual-grid/virtual-grid-wrapper.tsx | 2 +- .../features/player/components/Playerbar.tsx | 8 +-- .../features/player/components/Slider.tsx | 2 +- ...CenterControls.tsx => center-controls.tsx} | 36 +++++------ .../{LeftControls.tsx => left-controls.tsx} | 6 +- .../{PlayerButton.tsx => player-button.tsx} | 23 ++++--- .../{RightControls.tsx => right-controls.tsx} | 20 +++--- ...nterControls.ts => use-center-controls.ts} | 18 +++--- ...eueHandler.ts => use-playqueue-handler.ts} | 54 ++++++++-------- ...RightControls.ts => use-right-controls.ts} | 0 src/renderer/features/player/index.ts | 8 +-- .../{AnimatedPage.tsx => animated-page.tsx} | 2 +- .../features/shared/hooks/use-permissions.ts | 22 +++++++ src/renderer/features/shared/index.ts | 2 + .../features/sidebar/components/Sidebar.tsx | 20 +++--- .../{ListItem.tsx => list-item.tsx} | 3 +- src/renderer/features/sidebar/index.ts | 2 +- src/renderer/index.tsx | 4 +- src/renderer/types.ts | 2 +- src/renderer/types/emotion.d.ts | 7 +++ 21 files changed, 164 insertions(+), 139 deletions(-) rename src/renderer/features/player/components/{CenterControls.tsx => center-controls.tsx} (87%) rename src/renderer/features/player/components/{LeftControls.tsx => left-controls.tsx} (91%) rename src/renderer/features/player/components/{PlayerButton.tsx => player-button.tsx} (87%) rename src/renderer/features/player/components/{RightControls.tsx => right-controls.tsx} (78%) rename src/renderer/features/player/hooks/{useCenterControls.ts => use-center-controls.ts} (91%) rename src/renderer/features/player/hooks/{usePlayQueueHandler.ts => use-playqueue-handler.ts} (51%) rename src/renderer/features/player/hooks/{useRightControls.ts => use-right-controls.ts} (100%) rename src/renderer/features/shared/components/{AnimatedPage.tsx => animated-page.tsx} (93%) create mode 100644 src/renderer/features/shared/hooks/use-permissions.ts create mode 100644 src/renderer/features/shared/index.ts rename src/renderer/features/sidebar/components/{ListItem.tsx => list-item.tsx} (92%) create mode 100644 src/renderer/types/emotion.d.ts diff --git a/src/renderer/app.tsx b/src/renderer/app.tsx index a9f62379d..375e55c3e 100644 --- a/src/renderer/app.tsx +++ b/src/renderer/app.tsx @@ -1,20 +1,14 @@ import { ReactNode, useEffect } from 'react'; -import { - DndContext, - MouseSensor, - TouchSensor, - useSensor, - useSensors, -} from '@dnd-kit/core'; import { MantineProvider } from '@mantine/core'; import { useLocalStorage } from '@mantine/hooks'; +import { ModalsProvider } from '@mantine/modals'; +import { NotificationsProvider } from '@mantine/notifications'; import isElectron from 'is-electron'; import { BrowserRouter, HashRouter } from 'react-router-dom'; import { useDefaultSettings } from './features/settings'; -import { AppRouter } from './router/AppRouter'; +import { AppRouter } from './router/app-router'; import './styles/global.scss'; import 'ag-grid-community/styles/ag-grid.css'; -import './styles/ag-grid.scss'; const SelectRouter = ({ children }: { children: ReactNode }) => { if (isElectron()) { @@ -36,27 +30,16 @@ export const App = () => { document.body.setAttribute('data-theme', theme); }, [theme]); - const sensors = useSensors( - useSensor(MouseSensor, { - activationConstraint: { - delay: 200, - tolerance: 100, - }, - }), - useSensor(TouchSensor, { - activationConstraint: { - delay: 500, - tolerance: 10, - }, - }) - ); - return ( { xl: 18, xs: 10, }, - other: {}, spacing: { + lg: 12, + md: 8, + sm: 4, + xl: 16, xs: 2, }, }} > - console.log('drag end')} - onDragStart={() => console.log('drag start')} + - - - - + + + + + + ); }; diff --git a/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx b/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx index 06cc6d5ca..ae917ee48 100644 --- a/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx +++ b/src/renderer/components/virtual-grid/virtual-grid-wrapper.tsx @@ -1,7 +1,7 @@ import { Ref, useMemo } from 'react'; import { FixedSizeList, FixedSizeListProps } from 'react-window'; import { GridCard } from '@/renderer/components/virtual-grid/grid-card'; -import { usePlayQueueHandler } from '@/renderer/features/player/hooks/usePlayQueueHandler'; +import { usePlayQueueHandler } from '@/renderer/features/player/hooks/use-playqueue-handler'; import { CardRow } from '@/renderer/types'; export const VirtualGridWrapper = ({ diff --git a/src/renderer/features/player/components/Playerbar.tsx b/src/renderer/features/player/components/Playerbar.tsx index cb6b33d1b..2687628a5 100644 --- a/src/renderer/features/player/components/Playerbar.tsx +++ b/src/renderer/features/player/components/Playerbar.tsx @@ -1,11 +1,11 @@ import { useRef } from 'react'; -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { PlaybackType } from '../../../../types'; import { AudioPlayer } from '../../../components'; import { usePlayerStore } from '../../../store'; -import { CenterControls } from './CenterControls'; -import { LeftControls } from './LeftControls'; -import { RightControls } from './RightControls'; +import { CenterControls } from './center-controls'; +import { LeftControls } from './left-controls'; +import { RightControls } from './right-controls'; const PlayerbarContainer = styled.div` width: 100%; diff --git a/src/renderer/features/player/components/Slider.tsx b/src/renderer/features/player/components/Slider.tsx index 143f50148..426050d51 100644 --- a/src/renderer/features/player/components/Slider.tsx +++ b/src/renderer/features/player/components/Slider.tsx @@ -1,7 +1,7 @@ import { useMemo, useState } from 'react'; +import styled from '@emotion/styled'; import format from 'format-duration'; import ReactSlider, { ReactSliderProps } from 'react-slider'; -import styled from 'styled-components'; interface SliderProps extends ReactSliderProps { hasTooltip?: boolean; diff --git a/src/renderer/features/player/components/CenterControls.tsx b/src/renderer/features/player/components/center-controls.tsx similarity index 87% rename from src/renderer/features/player/components/CenterControls.tsx rename to src/renderer/features/player/components/center-controls.tsx index d6fc53c69..78012f3ea 100644 --- a/src/renderer/features/player/components/CenterControls.tsx +++ b/src/renderer/features/player/components/center-controls.tsx @@ -1,22 +1,22 @@ import { useEffect, useMemo, useState } from 'react'; +import styled from '@emotion/styled'; import format from 'format-duration'; import { useTranslation } from 'react-i18next'; import { RiPauseLine, RiPlayFill, - RiRewindFill, + RiRepeat2Fill, + RiShuffleFill, RiSkipBackFill, RiSkipForwardFill, - RiSpeedFill, } from 'react-icons/ri'; -import styled from 'styled-components'; import { PlaybackType, PlayerStatus } from '../../../../types'; import { Text } from '../../../components'; import { usePlayerStore } from '../../../store'; import { Font } from '../../../styles'; -import { useCenterControls } from '../hooks/useCenterControls'; -import { PlayerButton } from './PlayerButton'; -import { Slider } from './Slider'; +import { useCenterControls } from '../hooks/use-center-controls'; +import { PlayerButton } from './player-button'; +import { Slider } from './slider'; interface CenterControlsProps { playersRef: any; @@ -67,8 +67,6 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => { handlePlayPause, handlePrevTrack, handleSeekSlider, - handleSkipBackward, - handleSkipForward, } = useCenterControls({ playersRef }); const currentTime = usePlayerStore((state) => state.current.time); @@ -106,16 +104,16 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => { console.log(e)}> } - tooltip={{ label: `${t('player.prev')}` }} + icon={} + tooltip={{ label: `${t('player.shuffle')}` }} variant="secondary" onClick={handlePrevTrack} /> } - tooltip={{ label: `${t('player.skipBack')}` }} + icon={} + tooltip={{ label: `${t('player.previous')}` }} variant="secondary" - onClick={handleSkipBackward} + onClick={handlePrevTrack} /> { variant="main" onClick={handlePlayPause} /> - } - tooltip={{ label: `${t('player.skipForward')}` }} - variant="secondary" - onClick={handleSkipForward} - /> } tooltip={{ label: `${t('player.next')}` }} variant="secondary" onClick={handleNextTrack} /> + } + tooltip={{ label: `${t('player.repeat')}` }} + variant="secondary" + onClick={handleNextTrack} + /> diff --git a/src/renderer/features/player/components/LeftControls.tsx b/src/renderer/features/player/components/left-controls.tsx similarity index 91% rename from src/renderer/features/player/components/LeftControls.tsx rename to src/renderer/features/player/components/left-controls.tsx index c9568ba5b..cc3d9d59c 100644 --- a/src/renderer/features/player/components/LeftControls.tsx +++ b/src/renderer/features/player/components/left-controls.tsx @@ -1,4 +1,4 @@ -import styled from 'styled-components'; +import styled from '@emotion/styled'; import { Text } from '../../../components'; import { usePlayerStore } from '../../../store'; import { Font } from '../../../styles'; @@ -34,7 +34,9 @@ export const LeftControls = () => { return ( - img + {song?.imageUrl && ( + img + )} ` const ButtonMainVariant = css` padding: 0.5rem; - background: var(--playerbar-btn-color); + border: 2px solid var(--playerbar-btn-color); border-radius: 50%; svg { display: flex; - fill: black; - stroke: black; - } - - &:hover { - background: var(--playerbar-btn-color-hover); } &:focus-visible { @@ -109,13 +104,17 @@ export const PlayerButton = ({ }: PlayerButtonProps) => { if (tooltip) { return ( - - + + {icon} - - + + ); } diff --git a/src/renderer/features/player/components/RightControls.tsx b/src/renderer/features/player/components/right-controls.tsx similarity index 78% rename from src/renderer/features/player/components/RightControls.tsx rename to src/renderer/features/player/components/right-controls.tsx index d256b4c82..fa37edfc2 100644 --- a/src/renderer/features/player/components/RightControls.tsx +++ b/src/renderer/features/player/components/right-controls.tsx @@ -1,9 +1,9 @@ +import styled from '@emotion/styled'; import { RiVolumeUpFill, RiVolumeMuteFill } from 'react-icons/ri'; -import styled from 'styled-components'; -import { IconButton } from '../../../components'; import { usePlayerStore } from '../../../store'; -import { useRightControls } from '../hooks/useRightControls'; -import { Slider } from './Slider'; +import { useRightControls } from '../hooks/use-right-controls'; +import { PlayerButton } from './player-button'; +import { Slider } from './slider'; const RightControlsContainer = styled.div` display: flex; @@ -39,23 +39,21 @@ export const RightControls = () => { - + ) : ( - + ) } - size={20} tooltip={{ label: muted ? 'Muted' : volume }} - variant="transparent" + variant="secondary" onClick={handleMute} /> - { }; const handlePlay = useCallback(() => { - if (settings.type === PlaybackType.Local) { + if (settings.type === PlaybackType.LOCAL) { mpvPlayer.play(); } else { currentPlayerRef.getInternalPlayer().play(); @@ -52,7 +52,7 @@ export const useCenterControls = (args: { playersRef: any }) => { }, [currentPlayerRef, play, settings]); const handlePause = useCallback(() => { - if (settings.type === PlaybackType.Local) { + if (settings.type === PlaybackType.LOCAL) { mpvPlayer.pause(); } @@ -60,7 +60,7 @@ export const useCenterControls = (args: { playersRef: any }) => { }, [pause, settings]); const handleStop = () => { - if (settings.type === PlaybackType.Local) { + if (settings.type === PlaybackType.LOCAL) { mpvPlayer.stop(); } else { stopPlayback(); @@ -73,7 +73,7 @@ export const useCenterControls = (args: { playersRef: any }) => { const handleNextTrack = useCallback(() => { const playerData = next(); - if (settings.type === PlaybackType.Local) { + if (settings.type === PlaybackType.LOCAL) { mpvPlayer.setQueue(playerData); mpvPlayer.next(); } else { @@ -86,7 +86,7 @@ export const useCenterControls = (args: { playersRef: any }) => { const handlePrevTrack = useCallback(() => { const playerData = prev(); - if (settings.type === PlaybackType.Local) { + if (settings.type === PlaybackType.LOCAL) { mpvPlayer.setQueue(playerData); mpvPlayer.previous(); } else { @@ -98,7 +98,7 @@ export const useCenterControls = (args: { playersRef: any }) => { const handlePlayPause = useCallback(() => { if (queue) { - if (playerStatus === PlayerStatus.Paused) { + if (playerStatus === PlayerStatus.PAUSED) { return handlePlay(); } @@ -111,7 +111,7 @@ export const useCenterControls = (args: { playersRef: any }) => { const handleSkipBackward = () => { const skipBackwardSec = 5; - if (settings.type === PlaybackType.Local) { + if (settings.type === PlaybackType.LOCAL) { const newTime = currentTime - skipBackwardSec; mpvPlayer.seek(-skipBackwardSec); setCurrentTime(newTime < 0 ? 0 : newTime); @@ -126,7 +126,7 @@ export const useCenterControls = (args: { playersRef: any }) => { const handleSkipForward = () => { const skipForwardSec = 5; - if (settings.type === PlaybackType.Local) { + if (settings.type === PlaybackType.LOCAL) { const newTime = currentTime + skipForwardSec; mpvPlayer.seek(skipForwardSec); setCurrentTime(newTime); @@ -147,7 +147,7 @@ export const useCenterControls = (args: { playersRef: any }) => { (e: number | any) => { setCurrentTime(e); - if (settings.type === PlaybackType.Local) { + if (settings.type === PlaybackType.LOCAL) { mpvPlayer.seekTo(e); } else { currentPlayerRef.seekTo(e); diff --git a/src/renderer/features/player/hooks/usePlayQueueHandler.ts b/src/renderer/features/player/hooks/use-playqueue-handler.ts similarity index 51% rename from src/renderer/features/player/hooks/usePlayQueueHandler.ts rename to src/renderer/features/player/hooks/use-playqueue-handler.ts index 8f43eab5e..75927ac18 100644 --- a/src/renderer/features/player/hooks/usePlayQueueHandler.ts +++ b/src/renderer/features/player/hooks/use-playqueue-handler.ts @@ -1,23 +1,19 @@ +import { api } from '@/renderer/api'; import { Item, Play } from '../../../../types'; -import { albumsApi } from '../../../api/albumsApi'; -import { usePlayerStore } from '../../../store'; -import { - getJellyfinStreamUrl, - getServerFolderAuth, - getSubsonicStreamUrl, -} from '../../../utils'; +import { useAuthStore, usePlayerStore } from '../../../store'; import { mpvPlayer } from '../utils/mpvPlayer'; const getEndpointByItemType = (item: Item) => { switch (item) { case Item.ALBUM: - return albumsApi.getAlbum; + return api.albums.getAlbumDetail; default: - return albumsApi.getAlbum; + return api.albums.getAlbumDetail; } }; export const usePlayQueueHandler = () => { + const serverId = useAuthStore((state) => state.currentServer?.id) || ''; const addToQueue = usePlayerStore((state) => state.addToQueue); const handlePlayQueueAdd = async (options: { @@ -35,36 +31,42 @@ export const usePlayQueueHandler = () => { if (options.byItemType) { const deviceId = localStorage.getItem('device_id'); - const { serverUrl } = JSON.parse( - localStorage.getItem('authentication') || '{}' - ); + // const { state } = JSON.parse( + // localStorage.getItem('authentication') || '{}' + // ); if (deviceId) { const endpoint = getEndpointByItemType(options.byItemType.type); const { data } = await endpoint({ - id: options.byItemType.id, + albumId: options.byItemType.id, + serverId, }); - const songs = data.songs.map((song) => { - const auth = getServerFolderAuth(serverUrl, song.serverFolderId); + const songs = data.songs?.map((song) => { + // const auth = getServerFolderAuth( + // state.serverUrl, + // song.serverFolderId + // ); - if (auth) { - const streamUrl = - auth.type === 'jellyfin' - ? getJellyfinStreamUrl(auth, song, deviceId) - : getSubsonicStreamUrl(auth, song, deviceId); + // if (auth) { + // const streamUrl = + // auth.type === 'jellyfin' + // ? getJellyfinStreamUrl(auth, song, deviceId) + // : getSubsonicStreamUrl(auth, song, deviceId); - return { - ...song, - streamUrl, - }; - } + // return { + // ...song, + // streamUrl, + // }; + // } return song; }); - const playerData = addToQueue(songs, options.play); + const playerData = addToQueue(songs || [], options.play); + + console.log('playerData', playerData); if (options.play === Play.NEXT || options.play === Play.LAST) { mpvPlayer.setQueueNext(playerData); diff --git a/src/renderer/features/player/hooks/useRightControls.ts b/src/renderer/features/player/hooks/use-right-controls.ts similarity index 100% rename from src/renderer/features/player/hooks/useRightControls.ts rename to src/renderer/features/player/hooks/use-right-controls.ts diff --git a/src/renderer/features/player/index.ts b/src/renderer/features/player/index.ts index c092b35d8..bfa9c40b1 100644 --- a/src/renderer/features/player/index.ts +++ b/src/renderer/features/player/index.ts @@ -1,4 +1,4 @@ -export * from './components/CenterControls'; -export * from './components/LeftControls'; -export * from './components/Playerbar'; -export * from './components/Slider'; +export * from './components/center-controls'; +export * from './components/left-controls'; +export * from './components/playerbar'; +export * from './components/slider'; diff --git a/src/renderer/features/shared/components/AnimatedPage.tsx b/src/renderer/features/shared/components/animated-page.tsx similarity index 93% rename from src/renderer/features/shared/components/AnimatedPage.tsx rename to src/renderer/features/shared/components/animated-page.tsx index b84a2a6f7..c1536ab74 100644 --- a/src/renderer/features/shared/components/AnimatedPage.tsx +++ b/src/renderer/features/shared/components/animated-page.tsx @@ -1,6 +1,6 @@ import { ReactNode } from 'react'; +import styled from '@emotion/styled'; import { motion } from 'framer-motion'; -import styled from 'styled-components'; interface AnimatedPageProps { children: ReactNode; diff --git a/src/renderer/features/shared/hooks/use-permissions.ts b/src/renderer/features/shared/hooks/use-permissions.ts new file mode 100644 index 000000000..b0c388304 --- /dev/null +++ b/src/renderer/features/shared/hooks/use-permissions.ts @@ -0,0 +1,22 @@ +import { useMemo } from 'react'; +import { useAuthStore } from '@/renderer/store'; + +export const usePermissions = () => { + const permissions = useAuthStore((state) => state.permissions); + + const permissionSet = useMemo(() => { + const set = { + createServer: permissions.isAdmin, + createServerCredential: true, + createServerUrl: permissions.isAdmin, + deleteServer: permissions.isAdmin, + deleteServerCredential: true, + deleteServerUrl: permissions.isAdmin, + editServer: permissions.isAdmin, + }; + + return set; + }, [permissions]); + + return permissionSet; +}; diff --git a/src/renderer/features/shared/index.ts b/src/renderer/features/shared/index.ts new file mode 100644 index 000000000..1cf0038a1 --- /dev/null +++ b/src/renderer/features/shared/index.ts @@ -0,0 +1,2 @@ +export * from './components/animated-page'; +export * from './hooks/use-permissions'; diff --git a/src/renderer/features/sidebar/components/Sidebar.tsx b/src/renderer/features/sidebar/components/Sidebar.tsx index b02da3fa6..a5a65b978 100644 --- a/src/renderer/features/sidebar/components/Sidebar.tsx +++ b/src/renderer/features/sidebar/components/Sidebar.tsx @@ -1,11 +1,11 @@ +import styled from '@emotion/styled'; import { RiDashboardFill, RiFileList2Fill, - RiSearch2Fill, + RiSearch2Line, } from 'react-icons/ri'; -import styled from 'styled-components'; -import { AppRoute } from '../../../router/utils/routes'; -import { ListItem } from './ListItem'; +import { AppRoute } from '../../../router/routes'; +import { ListItem } from './list-item'; const StyledSidebar = styled.div``; @@ -19,15 +19,15 @@ export const Sidebar = () => { - - - Search + + + Library - - - Your Library + + + Search diff --git a/src/renderer/features/sidebar/components/ListItem.tsx b/src/renderer/features/sidebar/components/list-item.tsx similarity index 92% rename from src/renderer/features/sidebar/components/ListItem.tsx rename to src/renderer/features/sidebar/components/list-item.tsx index 0e3fe0784..8d97ca4d4 100644 --- a/src/renderer/features/sidebar/components/ListItem.tsx +++ b/src/renderer/features/sidebar/components/list-item.tsx @@ -1,7 +1,8 @@ import { ReactNode } from 'react'; +import { css } from '@emotion/react'; +import styled from '@emotion/styled'; import { motion } from 'framer-motion'; import { Link, LinkProps } from 'react-router-dom'; -import styled, { css } from 'styled-components'; import { fontInter } from '../../../styles'; interface ListItemProps { diff --git a/src/renderer/features/sidebar/index.ts b/src/renderer/features/sidebar/index.ts index af7b0814a..4a2c14b85 100644 --- a/src/renderer/features/sidebar/index.ts +++ b/src/renderer/features/sidebar/index.ts @@ -1 +1 @@ -export * from './components/Sidebar'; +export * from './components/sidebar'; diff --git a/src/renderer/index.tsx b/src/renderer/index.tsx index b5f6a3a56..5e10893ea 100644 --- a/src/renderer/index.tsx +++ b/src/renderer/index.tsx @@ -1,9 +1,9 @@ +import { QueryClientProvider } from '@tanstack/react-query'; import { createRoot } from 'react-dom/client'; import { I18nextProvider } from 'react-i18next'; -import { QueryClientProvider } from 'react-query'; +import { queryClient } from '@/renderer/lib/react-query'; import i18n from '../i18n/i18n'; import { App } from './app'; -import { queryClient } from './lib'; const container = document.getElementById('root')!; const root = createRoot(container); diff --git a/src/renderer/types.ts b/src/renderer/types.ts index 23d4e840c..72f59140c 100644 --- a/src/renderer/types.ts +++ b/src/renderer/types.ts @@ -1,4 +1,4 @@ -import { AppRoute } from './router/utils/routes'; +import { AppRoute } from './router/routes'; export interface CardRow { align?: 'left' | 'center' | 'right'; diff --git a/src/renderer/types/emotion.d.ts b/src/renderer/types/emotion.d.ts new file mode 100644 index 000000000..038b592e7 --- /dev/null +++ b/src/renderer/types/emotion.d.ts @@ -0,0 +1,7 @@ +import '@emotion/react'; +import type { MantineTheme } from '@mantine/core'; + +declare module '@emotion/react' { + // eslint-disable-next-line @typescript-eslint/no-empty-interface + export interface GREY extends MantineTheme {} +}