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 (
-
+ {song?.imageUrl && (
+
+ )}
`
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 {}
+}