diff --git a/packages/app/config/routes.js b/packages/app/config/routes.js index dcef44ba..91947106 100755 --- a/packages/app/config/routes.js +++ b/packages/app/config/routes.js @@ -14,6 +14,11 @@ export default [ useLayout: "default", public: true, }, + { + path: "/tv/*", + useLayout: "default", + centeredContent: false, + }, { path: "/featured-event/*", useLayout: "default", @@ -31,7 +36,7 @@ export default [ { path: "/music/*", useLayout: "default", - centeredContent: true, + centeredContent: false, }, { path: "/nfc/*", diff --git a/packages/app/package.json b/packages/app/package.json index c3ae0ea1..4b747dad 100755 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -66,6 +66,7 @@ "react-modal-image": "^2.6.0", "react-player": "^2.16.0", "react-rnd": "^10.4.14", + "react-router": "^7.6.2", "react-router-dom": "^6.26.2", "react-transition-group": "^4.4.5", "react-useanimations": "^2.10.0", diff --git a/packages/app/src/App.jsx b/packages/app/src/App.jsx index 68462acc..5e719586 100755 --- a/packages/app/src/App.jsx +++ b/packages/app/src/App.jsx @@ -1,5 +1,8 @@ import React from "react" import { Runtime } from "@ragestudio/vessel" +import * as Router from "@ragestudio/vessel/router" +import routesDeclarations from "@config/routes" + import { Helmet } from "react-helmet" import * as Sentry from "@sentry/browser" import { invoke } from "@tauri-apps/api/tauri" @@ -14,7 +17,6 @@ import DesktopTopBar from "@components/DesktopTopBar" import { ThemeProvider } from "@cores/style/style.core.jsx" import Layout from "./layout" -import * as Router from "./router" import StaticMethods from "./statics/methods" import StaticEvents from "./statics/events" @@ -117,19 +119,21 @@ class ComtyApp extends React.Component { /> - - - {window.__TAURI__ && } - - {this.state.firstInitialized && ( - - )} - - - + + + {window.__TAURI__ && } + + {this.state.firstInitialized && ( + + )} + + ) } diff --git a/packages/app/src/router.jsx b/packages/app/src/router.jsx deleted file mode 100755 index b97d6ab1..00000000 --- a/packages/app/src/router.jsx +++ /dev/null @@ -1,244 +0,0 @@ -import React from "react" -import { BrowserRouter, Route, Routes, useNavigate, useParams } from "react-router-dom" -import { Skeleton } from "antd" -import config from "@config" -import loadable from "@loadable/component" - -import routesDeclaration from "@config/routes" - -const DefaultNotFoundRender = () => { - return
Not found
-} - -const DefaultLoadingRender = () => { - return -} - -const getPagePaths = () => { - let paths = { - ...import.meta.glob("/src/pages/**/[a-z[]*.jsx"), - ...import.meta.glob("/src/pages/**/[a-z[]*.tsx"), - } - - if (app.isMobile) { - paths = { - ...paths, - ...import.meta.glob("/src/pages/**/[a-z[]*.mobile.jsx"), - ...import.meta.glob("/src/pages/**/[a-z[]*.mobile.tsx"), - } - - // find & replace matching non mobile routes with mobile routes - Object.keys(paths).forEach((path) => { - const mobilePath = path.replace(/\.jsx$/, ".mobile.jsx").replace(/\.tsx$/, ".mobile.tsx") - - if (paths[mobilePath]) { - delete paths[path] - } - }) - } - - return paths -} - -const generateRoutes = () => { - let paths = getPagePaths() - - return Object.keys(paths).map((route) => { - let path = route - .replace(/\/src\/pages|index|\.jsx$/g, "") - .replace(/\/src\/pages|index|\.tsx$/g, "") - .replace(/\/src\/pages|index|\.mobile|\.jsx$/g, "") - .replace(/\/src\/pages|index|\.mobile|\.tsx$/g, "") - - path = path.replace(/\[([a-z]+)\]/g, ":$1") - path = path.replace(/\[\.{3}.+\]/, "*").replace(/\[(.+)\]/, ":$1") - - return { - path, - element: paths[route], - } - }) -} - -function findRouteDeclaration(route) { - return routesDeclaration.find((layout) => { - const routePath = layout.path.replace(/\*/g, ".*").replace(/!/g, "^") - - return new RegExp(routePath).test(route) - }) ?? { - path: route, - useLayout: "default", - } -} - -function isAuthenticated() { - return !!app.userData -} - -function handleRouteDeclaration(declaration) { - React.useEffect(() => { - if (declaration) { - // if not authenticated and is not in public route, redirect - if (!isAuthenticated() && !declaration.public && (window.location.pathname !== config.app?.authPath)) { - if (typeof window.app.location.push === "function") { - window.app.location.push(config.app?.authPath ?? "/login") - - app.cores.notifications.new({ - title: "Please login to use this feature.", - duration: 15, - }) - } else { - window.location.href = config.app?.authPath ?? "/login" - } - } else { - if (declaration.useLayout) { - app.layout.set(declaration.useLayout) - } - - if (typeof declaration.centeredContent !== "undefined") { - let finalBool = null - - if (typeof declaration.centeredContent === "boolean") { - finalBool = declaration.centeredContent - } else { - if (app.isMobile) { - finalBool = declaration.centeredContent?.mobile ?? null - } else { - finalBool = declaration.centeredContent?.desktop ?? null - } - } - - app.layout.toggleCenteredContent(finalBool) - } - - if (typeof declaration.useTitle !== "undefined") { - if (typeof declaration.useTitle === "function") { - declaration.useTitle = declaration.useTitle(path, params) - } - - document.title = `${declaration.useTitle} - ${config.app.siteName}` - } else { - document.title = config.app.siteName - } - } - } - }, []) -} - -function generatePageElementWrapper(path, element, props, declaration) { - return React.createElement((props) => { - const params = useParams() - const url = new URL(window.location) - const query = new Proxy(url, { - get: (target, prop) => target.searchParams.get(prop), - }) - - handleRouteDeclaration(declaration) - - return React.createElement( - loadable(element, { - fallback: React.createElement(props.staticRenders?.PageLoad || DefaultLoadingRender), - }), - { - ...props, - ...props, - url: url, - params: params, - query: query, - }) - }) -} - -const NavigationController = (props) => { - if (!app.location) { - app.location = Object() - } - - const navigate = useNavigate() - - async function setLocation(to, state = {}) { - // clean double slashes - to = to.replace(/\/{2,}/g, "/") - - // if state is a number, it's a delay - if (typeof state !== "object") { - state = {} - } - - app.location.last = window.location - - await navigate(to, { - state - }) - - app.eventBus.emit("router.navigate", to, { - state, - }) - - return { - to, - state, - } - } - - async function backLocation() { - return window.history.back() - } - - async function onHistoryChange() { - setTimeout(() => { - app.eventBus.emit("router.navigate", window.location.pathname, { - state: window.location.state, - }) - }, 0) - } - - React.useEffect(() => { - app.location = { - last: window.location, - push: setLocation, - back: backLocation, - } - - window.addEventListener("popstate", onHistoryChange) - - return () => { - window.removeEventListener("popstate", onHistoryChange) - } - }, []) - - return props.children -} - -export const InternalRouter = (props) => { - return - - { - props.children - } - - -} - -export const PageRender = React.memo((props) => { - let routes = generateRoutes() - - return - { - routes.map((route, index) => { - const declaration = findRouteDeclaration(route.path) - - return - }) - } - - -}) \ No newline at end of file diff --git a/packages/app/src/statics/renders.jsx b/packages/app/src/statics/renders.jsx index 91390d8b..8910f4a6 100644 --- a/packages/app/src/statics/renders.jsx +++ b/packages/app/src/statics/renders.jsx @@ -1,14 +1,8 @@ -import { NotFound, RenderError, Crash } from "@components" - +import { NotFound, Crash, Skeleton } from "@components" +import ErrorCatcher from "@components/ErrorCatcher" export default { - PageLoad: () => { - return - }, - NotFound: (props) => { - return - }, - RenderError: (props) => { - return - }, + Loading: Skeleton, + NotFound: NotFound, + RenderError: ErrorCatcher, Crash: Crash.CrashWrapper, }