diff --git a/package-lock.json b/package-lock.json
index f682d14b5..25e49695c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,6 @@
"version": "1.0.0-alpha1",
"hasInstallScript": true,
"dependencies": {
- "@loadable/component": "^5.15.2",
"@mantine/core": "^5.9.2",
"@mantine/dates": "^5.9.2",
"@mantine/dropzone": "^5.9.2",
@@ -34,6 +33,7 @@
"ky-universal": "^0.11.0",
"lodash": "^4.17.21",
"md5": "^2.3.0",
+ "memoize-one": "^6.0.0",
"nanoid": "^4.0.0",
"node-mpv": "^2.0.0-beta.2",
"react": "^18.2.0",
@@ -55,7 +55,6 @@
},
"devDependencies": {
"@types/electron-localshortcut": "^3.1.0",
- "@types/loadable__component": "^5.13.4",
"@types/lodash": "^4.14.191",
"@types/md5": "^2.3.2",
"@types/node": "18.11.10",
@@ -1665,26 +1664,6 @@
"@jridgewell/sourcemap-codec": "1.4.14"
}
},
- "node_modules/@loadable/component": {
- "version": "5.15.2",
- "resolved": "https://registry.npmjs.org/@loadable/component/-/component-5.15.2.tgz",
- "integrity": "sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==",
- "dependencies": {
- "@babel/runtime": "^7.7.7",
- "hoist-non-react-statics": "^3.3.1",
- "react-is": "^16.12.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/gregberge"
- },
- "peerDependencies": {
- "react": ">=16.3.0"
- }
- },
"node_modules/@malept/cross-spawn-promise": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz",
@@ -2510,15 +2489,6 @@
"@types/node": "*"
}
},
- "node_modules/@types/loadable__component": {
- "version": "5.13.4",
- "resolved": "https://registry.npmjs.org/@types/loadable__component/-/loadable__component-5.13.4.tgz",
- "integrity": "sha512-YhoCCxyuvP2XeZNbHbi8Wb9EMaUJuA2VGHxJffcQYrJKIKSkymJrhbzsf9y4zpTmr5pExAAEh5hbF628PAZ8Dg==",
- "dev": true,
- "dependencies": {
- "@types/react": "*"
- }
- },
"node_modules/@types/lodash": {
"version": "4.14.191",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz",
@@ -10970,9 +10940,9 @@
}
},
"node_modules/memoize-one": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
- "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
+ "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
},
"node_modules/memory-fs": {
"version": "0.2.0",
@@ -12719,6 +12689,11 @@
"react": ">=16.6.0"
}
},
+ "node_modules/react-player/node_modules/memoize-one": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
+ },
"node_modules/react-refresh": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
@@ -12848,6 +12823,11 @@
"react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0"
}
},
+ "node_modules/react-window/node_modules/memoize-one": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
+ },
"node_modules/read-config-file": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.2.0.tgz",
@@ -18469,16 +18449,6 @@
"@jridgewell/sourcemap-codec": "1.4.14"
}
},
- "@loadable/component": {
- "version": "5.15.2",
- "resolved": "https://registry.npmjs.org/@loadable/component/-/component-5.15.2.tgz",
- "integrity": "sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==",
- "requires": {
- "@babel/runtime": "^7.7.7",
- "hoist-non-react-statics": "^3.3.1",
- "react-is": "^16.12.0"
- }
- },
"@malept/cross-spawn-promise": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz",
@@ -19145,15 +19115,6 @@
"@types/node": "*"
}
},
- "@types/loadable__component": {
- "version": "5.13.4",
- "resolved": "https://registry.npmjs.org/@types/loadable__component/-/loadable__component-5.13.4.tgz",
- "integrity": "sha512-YhoCCxyuvP2XeZNbHbi8Wb9EMaUJuA2VGHxJffcQYrJKIKSkymJrhbzsf9y4zpTmr5pExAAEh5hbF628PAZ8Dg==",
- "dev": true,
- "requires": {
- "@types/react": "*"
- }
- },
"@types/lodash": {
"version": "4.14.191",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz",
@@ -25446,9 +25407,9 @@
}
},
"memoize-one": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
- "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
+ "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
},
"memory-fs": {
"version": "0.2.0",
@@ -26709,6 +26670,13 @@
"memoize-one": "^5.1.1",
"prop-types": "^15.7.2",
"react-fast-compare": "^3.0.1"
+ },
+ "dependencies": {
+ "memoize-one": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
+ }
}
},
"react-refresh": {
@@ -26781,6 +26749,13 @@
"requires": {
"@babel/runtime": "^7.0.0",
"memoize-one": ">=3.1.1 <6"
+ },
+ "dependencies": {
+ "memoize-one": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
+ "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="
+ }
}
},
"react-window-infinite-loader": {
diff --git a/package.json b/package.json
index adba48c3f..287910734 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,6 @@
},
"devDependencies": {
"@types/electron-localshortcut": "^3.1.0",
- "@types/loadable__component": "^5.13.4",
"@types/lodash": "^4.14.191",
"@types/md5": "^2.3.2",
"@types/node": "18.11.10",
@@ -78,7 +77,6 @@
"vitest": "0.25.3"
},
"dependencies": {
- "@loadable/component": "^5.15.2",
"@mantine/core": "^5.9.2",
"@mantine/dates": "^5.9.2",
"@mantine/dropzone": "^5.9.2",
@@ -103,6 +101,7 @@
"ky-universal": "^0.11.0",
"lodash": "^4.17.21",
"md5": "^2.3.0",
+ "memoize-one": "^6.0.0",
"nanoid": "^4.0.0",
"node-mpv": "^2.0.0-beta.2",
"react": "^18.2.0",
diff --git a/packages/renderer/src/features/action-required/index.ts b/packages/renderer/src/features/action-required/index.ts
index 1dc40eec3..285f182b1 100644
--- a/packages/renderer/src/features/action-required/index.ts
+++ b/packages/renderer/src/features/action-required/index.ts
@@ -1,3 +1 @@
-export * from './routes/action-required-route';
-export * from './routes/invalid-route';
export * from './components/error-fallback';
diff --git a/packages/renderer/src/features/action-required/routes/action-required-route.tsx b/packages/renderer/src/features/action-required/routes/action-required-route.tsx
index d907b1721..fd24e6fe9 100644
--- a/packages/renderer/src/features/action-required/routes/action-required-route.tsx
+++ b/packages/renderer/src/features/action-required/routes/action-required-route.tsx
@@ -13,7 +13,7 @@ import { AppRoute } from '/@/router/routes';
import { useCurrentServer } from '/@/store';
import { localSettings } from '#preload';
-export const ActionRequiredRoute = () => {
+const ActionRequiredRoute = () => {
const currentServer = useCurrentServer();
const [isMpvRequired, setIsMpvRequired] = useState(false);
const isServerRequired = !currentServer;
@@ -94,3 +94,5 @@ export const ActionRequiredRoute = () => {
);
};
+
+export default ActionRequiredRoute;
diff --git a/packages/renderer/src/features/action-required/routes/invalid-route.tsx b/packages/renderer/src/features/action-required/routes/invalid-route.tsx
index 26834864a..a1a36dab2 100644
--- a/packages/renderer/src/features/action-required/routes/invalid-route.tsx
+++ b/packages/renderer/src/features/action-required/routes/invalid-route.tsx
@@ -4,7 +4,7 @@ import { useLocation, useNavigate } from 'react-router-dom';
import { Button, Text } from '/@/components';
import { AnimatedPage } from '/@/features/shared';
-export const InvalidRoute = () => {
+const InvalidRoute = () => {
const navigate = useNavigate();
const location = useLocation();
@@ -34,3 +34,5 @@ export const InvalidRoute = () => {
);
};
+
+export default InvalidRoute;
diff --git a/packages/renderer/src/features/albums/index.ts b/packages/renderer/src/features/albums/index.ts
index ca8d89bc9..630d1ddb6 100644
--- a/packages/renderer/src/features/albums/index.ts
+++ b/packages/renderer/src/features/albums/index.ts
@@ -1,3 +1,2 @@
export * from './queries/album-detail-query';
export * from './queries/album-list-query';
-export * from './routes/album-list-route';
diff --git a/packages/renderer/src/features/albums/routes/album-list-route.tsx b/packages/renderer/src/features/albums/routes/album-list-route.tsx
index 0899b4cac..67bfda727 100644
--- a/packages/renderer/src/features/albums/routes/album-list-route.tsx
+++ b/packages/renderer/src/features/albums/routes/album-list-route.tsx
@@ -32,37 +32,7 @@ import { NDAlbumListSort } from '/@/api/navidrome.types';
import { controller } from '/@/api/controller';
import { ndNormalize } from '/@/api/navidrome.api';
-const FILTERS = {
- jellyfin: [
- { name: 'Album Artist', value: JFAlbumListSort.NAME },
- { name: 'Community Rating', value: JFAlbumListSort.RATING },
- { name: 'Critic Rating', value: JFAlbumListSort.CRITIC_RATING },
- { name: 'Name', value: JFAlbumListSort.NAME },
- { name: 'Random', value: JFAlbumListSort.RANDOM },
- { name: 'Recently Added', value: JFAlbumListSort.RECENTLY_ADDED },
- { name: 'Release Date', value: JFAlbumListSort.RELEASE_DATE },
- ],
- navidrome: [
- { name: 'Album Artist', value: NDAlbumListSort.ALBUM_ARTIST },
- { name: 'Artist', value: NDAlbumListSort.ARTIST },
- { name: 'Duration', value: NDAlbumListSort.DURATION },
- { name: 'Name', value: NDAlbumListSort.NAME },
- { name: 'Play Count', value: NDAlbumListSort.PLAY_COUNT },
- { name: 'Random', value: NDAlbumListSort.RANDOM },
- { name: 'Rating', value: NDAlbumListSort.RATING },
- { name: 'Recently Added', value: NDAlbumListSort.RECENTLY_ADDED },
- { name: 'Song Count', value: NDAlbumListSort.SONG_COUNT },
- { name: 'Starred', value: NDAlbumListSort.STARRED },
- { name: 'Year', value: NDAlbumListSort.YEAR },
- ],
-};
-
-const ORDER = [
- { name: 'Ascending', value: SortOrder.ASC },
- { name: 'Descending', value: SortOrder.DESC },
-];
-
-export const AlbumListRoute = () => {
+const AlbumListRoute = () => {
const queryClient = useQueryClient();
const server = useCurrentServer();
const { setPage } = useAppStoreActions();
@@ -465,3 +435,5 @@ export const AlbumListRoute = () => {
);
};
+
+export default AlbumListRoute;
diff --git a/packages/renderer/src/features/dashboard/routes/DashboardRoute.tsx b/packages/renderer/src/features/dashboard/routes/DashboardRoute.tsx
index b0a1a89bc..bb605fad3 100644
--- a/packages/renderer/src/features/dashboard/routes/DashboardRoute.tsx
+++ b/packages/renderer/src/features/dashboard/routes/DashboardRoute.tsx
@@ -1,3 +1,5 @@
-export const DashboardRoute = () => {
+const DashboardRoute = () => {
return <>>;
};
+
+export default DashboardRoute;
diff --git a/packages/renderer/src/features/now-playing/index.ts b/packages/renderer/src/features/now-playing/index.ts
index 1b2e6520e..b3e1696b2 100644
--- a/packages/renderer/src/features/now-playing/index.ts
+++ b/packages/renderer/src/features/now-playing/index.ts
@@ -1,2 +1 @@
-export * from './routes/now-playing-route';
export * from './components/play-queue';
diff --git a/packages/renderer/src/features/now-playing/routes/now-playing-route.tsx b/packages/renderer/src/features/now-playing/routes/now-playing-route.tsx
index cdf71ba21..8c915d015 100644
--- a/packages/renderer/src/features/now-playing/routes/now-playing-route.tsx
+++ b/packages/renderer/src/features/now-playing/routes/now-playing-route.tsx
@@ -1,7 +1,6 @@
import { Box } from '@mantine/core';
import styled from 'styled-components';
import { PlayQueue } from '/@/features/now-playing/components/play-queue';
-import { AnimatedPage } from '/@/features/shared';
const QueueContainer = styled(Box)`
position: relative;
@@ -9,12 +8,12 @@ const QueueContainer = styled(Box)`
height: 100%;
`;
-export const NowPlayingRoute = () => {
+const NowPlayingRoute = () => {
return (
-
-
-
-
-
+
+
+
);
};
+
+export default NowPlayingRoute;
diff --git a/packages/renderer/src/router/app-router.tsx b/packages/renderer/src/router/app-router.tsx
index c87cdf11f..6c7a149c5 100644
--- a/packages/renderer/src/router/app-router.tsx
+++ b/packages/renderer/src/router/app-router.tsx
@@ -1,79 +1,80 @@
-import loadable from '@loadable/component';
+import { lazy, Suspense } from 'react';
import {
Route,
- createBrowserRouter,
createRoutesFromElements,
RouterProvider,
+ createHashRouter,
} from 'react-router-dom';
import { DefaultLayout } from '/@/layouts';
import { AppOutlet } from '/@/router/app-outlet';
import { AppRoute } from './routes';
import { RouteErrorBoundary } from '/@/features/action-required';
+import { TitlebarOutlet } from '/@/router/titlebar-outlet';
-const DashboardRoute = loadable(() => import('/@/features/dashboard'), {
- resolveComponent: (components) => components.DashboardRoute,
-});
+const DashboardRoute = lazy(() => import('/@/features/dashboard/routes/DashboardRoute'));
-const NowPlayingRoute = loadable(() => import('/@/features/now-playing'), {
- resolveComponent: (components) => components.NowPlayingRoute,
-});
+const NowPlayingRoute = lazy(() => import('/@/features/now-playing/routes/now-playing-route'));
-const AlbumListRoute = loadable(() => import('/@/features/albums'), {
- resolveComponent: (components) => components.AlbumListRoute,
-});
+const AlbumListRoute = lazy(() => import('/@/features/albums/routes/album-list-route'));
-const ActionRequiredRoute = loadable(() => import('/@/features/action-required'), {
- resolveComponent: (components) => components.ActionRequiredRoute,
-});
+const ActionRequiredRoute = lazy(
+ () => import('/@/features/action-required/routes/action-required-route'),
+);
-const InvalidRoute = loadable(() => import('/@/features/action-required'), {
- resolveComponent: (components) => components.InvalidRoute,
-});
+const InvalidRoute = lazy(() => import('/@/features/action-required/routes/invalid-route'));
export const AppRouter = () => {
- const router = createBrowserRouter(
+ const router = createHashRouter(
createRoutesFromElements(
<>
- }
- errorElement={}
- >
- }>
- }
- />
- }
- path={AppRoute.HOME}
- />
- }
- path={AppRoute.NOW_PLAYING}
- />
- }
- path={AppRoute.LIBRARY_ALBUMS}
- />
- >}
- path={AppRoute.LIBRARY_ARTISTS}
- />
- }
- path="*"
- />
+ }>
+ }
+ errorElement={}
+ >
+ }>
+ }
+ />
+ }
+ path={AppRoute.HOME}
+ />
+ }
+ path={AppRoute.NOW_PLAYING}
+ />
+ }
+ path={AppRoute.LIBRARY_ALBUMS}
+ />
+ >}
+ path={AppRoute.LIBRARY_ARTISTS}
+ />
+ }
+ path="*"
+ />
+
- }>
- }
- path={AppRoute.ACTION_REQUIRED}
- />
+ }>
+ }>
+ }
+ path={AppRoute.ACTION_REQUIRED}
+ />
+
>,
),
);
- return ;
+ return (
+ >}>
+
+
+ );
};
diff --git a/packages/renderer/src/router/titlebar-outlet.tsx b/packages/renderer/src/router/titlebar-outlet.tsx
new file mode 100644
index 000000000..947253cb0
--- /dev/null
+++ b/packages/renderer/src/router/titlebar-outlet.tsx
@@ -0,0 +1,24 @@
+import { Outlet } from 'react-router';
+import styled from 'styled-components';
+import { Titlebar } from '/@/features/titlebar/components/titlebar';
+
+const TitlebarContainer = styled.header`
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 5000;
+ height: 2.5rem;
+ background: var(--titlebar-bg);
+ -webkit-app-region: drag;
+`;
+
+export const TitlebarOutlet = () => {
+ return (
+ <>
+
+
+
+
+ >
+ );
+};