From 4bfcc405716bdddbfdd004411fbf53cb1c3cfe66 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Fri, 12 Jun 2026 17:57:54 +0000 Subject: [PATCH] poc multi page --- next/index.html | 21 +++++++ src/backend/server/index.ts | 4 +- src/client/AppNext.tsx | 120 ++++++++++++++++++++++++++++++++++++ src/client/index-next.tsx | 18 ++++++ vite.config.ts | 23 ++++--- 5 files changed, 177 insertions(+), 9 deletions(-) create mode 100644 next/index.html create mode 100644 src/client/AppNext.tsx create mode 100644 src/client/index-next.tsx diff --git a/next/index.html b/next/index.html new file mode 100644 index 00000000..75573f32 --- /dev/null +++ b/next/index.html @@ -0,0 +1,21 @@ + + + + + + + + + + + Multi Scrobbler + + + +
+ + + diff --git a/src/backend/server/index.ts b/src/backend/server/index.ts index 68c4372a..68bc8fe3 100644 --- a/src/backend/server/index.ts +++ b/src/backend/server/index.ts @@ -82,7 +82,9 @@ export const initServer = async (parentLogger: Logger, appLoggerStream: PassThro process.env.USE_HASH_ROUTER = root.get('isSubPath').toString(); } - + app.get(/^\/next$/, (_, res) => { + res.redirect("/next/") + }); const viteExpressOptions: Parameters[0] = { mode: isProd ? 'production' : 'development', diff --git a/src/client/AppNext.tsx b/src/client/AppNext.tsx new file mode 100644 index 00000000..f64473e9 --- /dev/null +++ b/src/client/AppNext.tsx @@ -0,0 +1,120 @@ +import React from 'react'; +import { + createBrowserRouter, + createHashRouter, RouteObject, + RouterProvider, useLocation, +} from "react-router-dom"; +import {connect, ConnectedProps, Provider as ReduxProvider} from 'react-redux' +import './App.css'; +import CopyToClipboard from "./components/CopyToClipboard"; +import ExternalLink from "./components/ExternalLink"; +import {store} from './store'; +import Dashboard from "./dashboard/dashboard"; +import RecentPage from "./recent/RecentPage"; +import ScrobbledPage from "./scrobbled/ScrobbledPage"; +import DeadPage from "./deadLetter/DeadPage"; +import {clientUpdate, sourceUpdate} from "./status/ducks"; +import {useEventSource, useEventSourceListener} from "@react-nano/use-event-source"; +import Version from "./Version"; +import { MSComponentList } from './components/msComponent/MSComponentList'; +import { Provider } from './components/Provider'; + +function NoMatch() { + const location = useLocation(); + + return ( +
+ No page for {location.pathname} exists! +
+ ); +} + +// https://tailwindflex.com/@sienna/copy-code-block +function MissingDocs() { + return ( +
+
Oops! You need to build docs first. Run the following commands to build:
+ + + + $ + + + + + npm run docs:install && npm run docs:build + + + + + + +
+ ); +} + +const routes: RouteObject[] = [ + { + path: "/next", + element: , + }, + { + path: "/docs", + element: + }, + { + path: "*", + element: + } +]; + +const genRouter = () => { + const useHashRouter = __USE_HASH_ROUTER__ === 'true'; + return useHashRouter ? createHashRouter(routes) : createBrowserRouter(routes); +} + +const router = genRouter(); + +// const mapDispatchToProps = (dispatch) => { +// return { +// updateSource: (payload) => dispatch(sourceUpdate(payload)), +// updateClient: (payload) => dispatch(clientUpdate(payload)) +// } +// } + +// const connector = connect(null, mapDispatchToProps); + +// type PropsFromRedux = ConnectedProps; + +// const Global = (props: PropsFromRedux) => { +// const { +// updateSource, +// updateClient +// } = props; + +// const [sourceEventSource, eventSourceStatus] = useEventSource("api/events", false); +// useEventSourceListener(sourceEventSource, ['source', 'client'], evt => { +// const data = JSON.parse(evt.data); +// if(data.from === 'source') { +// updateSource(data); +// } else if(data.from === 'client') { +// updateClient(data); +// } +// }, [updateSource, updateClient]); + +// return ; +// } + +// const ConnectedGlobal = connector(Global); + +function App() { + return ( + + + + ); +} + +export default App; diff --git a/src/client/index-next.tsx b/src/client/index-next.tsx new file mode 100644 index 00000000..1a9a181c --- /dev/null +++ b/src/client/index-next.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import App from './AppNext.js'; +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc.js'; +import relativeTime from 'dayjs/plugin/relativeTime.js'; +dayjs.extend(utc) +dayjs.extend(relativeTime); + +const root = ReactDOM.createRoot( + document.getElementById('root') as HTMLElement +); +root.render( + + + +); diff --git a/vite.config.ts b/vite.config.ts index e3e95429..0b991440 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,20 +2,21 @@ import react from '@vitejs/plugin-react'; import normalizeUrl from "normalize-url"; import { defineConfig } from 'vite'; import tailwindcss from '@tailwindcss/vite' +import { dirname, resolve } from 'node:path' const QUOTES_UNWRAP_REGEX: RegExp = new RegExp(/^"(.*)"$/); export const generateBaseURL = (userUrl: string | undefined): URL => { let cleanUserUrl = userUrl.trim(); - if(QUOTES_UNWRAP_REGEX.test(cleanUserUrl)) { + if (QUOTES_UNWRAP_REGEX.test(cleanUserUrl)) { const results = cleanUserUrl.match(QUOTES_UNWRAP_REGEX); cleanUserUrl = results[1]; } - const base = normalizeUrl(cleanUserUrl, {removeSingleSlash: true}); + const base = normalizeUrl(cleanUserUrl, { removeSingleSlash: true }); const u = new URL(base); - if(u.port === '') { - if(u.protocol === 'https:') { + if (u.port === '') { + if (u.protocol === 'https:') { u.port = '443'; - } else if(userUrl.includes(`${u.hostname}:80`)) { + } else if (userUrl.includes(`${u.hostname}:80`)) { u.port = '80'; } } @@ -24,9 +25,9 @@ export const generateBaseURL = (userUrl: string | undefined): URL => { export default defineConfig(() => { let baseUrlStr = '/'; - if(process.env.BASE_URL !== undefined && process.env.BASE_URL !== '') { + if (process.env.BASE_URL !== undefined && process.env.BASE_URL !== '') { const baseUrl = generateBaseURL(process.env.BASE_URL); - if(baseUrl.pathname !== '/') { + if (baseUrl.pathname !== '/') { baseUrlStr = baseUrl.toString(); } } @@ -48,7 +49,13 @@ export default defineConfig(() => { ], build: { sourcemap: true, - cssCodeSplit: true + cssCodeSplit: true, + rolldownOptions: { + input: { + main: resolve(import.meta.dirname, 'index.html'), + next: resolve(import.meta.dirname, 'next/index.html'), + }, + }, }, define: { "__USE_HASH_ROUTER__": JSON.stringify((process.env.USE_HASH_ROUTER ?? false))