From ef5ef4c90fea2ef4829604a269e498a8cf6bdc45 Mon Sep 17 00:00:00 2001 From: srgooglo Date: Wed, 7 Sep 2022 12:29:06 +0200 Subject: [PATCH] improve router and page transition logic --- packages/app/src/App.jsx | 30 ++++--- packages/app/src/layout/index.jsx | 138 ++++++++++++++++-------------- packages/app/src/router.jsx | 41 ++++++--- 3 files changed, 117 insertions(+), 92 deletions(-) diff --git a/packages/app/src/App.jsx b/packages/app/src/App.jsx index e3f73782..c7eb9a73 100644 --- a/packages/app/src/App.jsx +++ b/packages/app/src/App.jsx @@ -57,7 +57,7 @@ import { NotFound, RenderError, Crash, Settings, Navigation, Login } from "compo import { Icons } from "components/Icons" import Layout from "./layout" -import Router from "./router" +import * as Router from "./router" import "theme/index.less" @@ -423,19 +423,21 @@ class App extends React.Component {
- - - + + + + + } diff --git a/packages/app/src/layout/index.jsx b/packages/app/src/layout/index.jsx index 0ef7a1ad..9b2eac9c 100644 --- a/packages/app/src/layout/index.jsx +++ b/packages/app/src/layout/index.jsx @@ -8,6 +8,8 @@ import Drawer from "./drawer" import Sidedrawer from "./sidedrawer" import BottomBar from "./bottomBar" +import config from "config" + import routes from "schemas/routes" const LayoutRenders = { @@ -15,7 +17,7 @@ const LayoutRenders = { return -
+
{React.cloneElement(props.children, props)}
@@ -31,7 +33,7 @@ const LayoutRenders = { -
+
{React.cloneElement(props.children, props)}
@@ -40,16 +42,70 @@ const LayoutRenders = { } } -export default class Layout extends React.PureComponent { +export default class Layout extends React.Component { progressBar = progressBar.configure({ parent: "html", showSpinner: false }) state = { layoutType: "default", - isOnTransition: false, renderLock: true, renderError: null, } + events = { + "app.initialization.start": () => { + this.setState({ + renderLock: true, + }) + }, + "app.initialization.finish": () => { + this.setState({ + renderLock: false, + }) + }, + "router.transitionStart": () => { + this.progressBar.start() + + if (!app.settings.get("reduceAnimations")) { + // add "fade-transverse-leave" class to `transitionLayer` + document.getElementById("transitionLayer").classList.add("fade-transverse-leave") + } + }, + "router.transitionFinish": () => { + this.progressBar.done() + + if (!app.settings.get("reduceAnimations")) { + // remove "fade-transverse-leave" class to `transitionLayer` + document.getElementById("transitionLayer").classList.remove("fade-transverse-leave") + } + }, + } + + componentDidMount() { + if (window.app.settings.get("forceMobileMode") || window.app.isAppCapacitor() || Math.min(window.screen.width, window.screen.height) < 768 || navigator.userAgent.indexOf("Mobi") > -1) { + window.isMobile = true + + this.setLayout("mobile") + } else { + window.isMobile = false + } + + // register events + Object.keys(this.events).forEach((event) => { + window.app.eventBus.on(event, this.events[event]) + }) + } + + componentWillUnmount() { + // unregister events + Object.keys(this.events).forEach((event) => { + window.app.eventBus.off(event, this.events[event]) + }) + } + + componentDidCatch(info, stack) { + this.setState({ renderError: { info, stack } }) + } + setLayout = (layout) => { if (typeof LayoutRenders[layout] === "function") { return this.setState({ @@ -60,66 +116,8 @@ export default class Layout extends React.PureComponent { return console.error("Layout type not found") } - componentDidMount() { - window.app.eventBus.on("app.initialization.start", () => { - this.setState({ - renderLock: true, - }) - }) - window.app.eventBus.on("app.initialization.finish", () => { - this.setState({ - renderLock: false, - }) - }) - - if (window.app.settings.get("forceMobileMode") || window.app.isAppCapacitor() || Math.min(window.screen.width, window.screen.height) < 768 || navigator.userAgent.indexOf("Mobi") > -1) { - window.isMobile = true - this.setLayout("mobile") - } else { - window.isMobile = false - } - - window.app.eventBus.on("forceMobileMode", (to) => { - if (to) { - window.isMobile = true - this.setLayout("mobile") - } else { - window.isMobile = false - this.setLayout("default") - } - }) - - // this is a hacky one to fix app.setLocation not working on when app not render a router - window.app.setLocation = (location) => { - // update history - window.history.pushState(null, null, location) - - // reload page - window.location.reload() - } - } - - onTransitionStart = () => { - progressBar.start() - - if (!app.settings.get("reduceAnimations")) { - this.setState({ isOnTransition: true }) - } - } - - onTransitionFinish = () => { - progressBar.done() - - if (!app.settings.get("reduceAnimations")) { - this.setState({ isOnTransition: false }) - } - } - - componentDidCatch(info, stack) { - this.setState({ renderError: { info, stack } }) - } - render() { + let layoutType = this.state.layoutType const InitializationComponent = this.props.staticRenders?.Initialization ? React.createElement(this.props.staticRenders.Initialization) : null if (this.state.renderError) { @@ -148,16 +146,24 @@ export default class Layout extends React.PureComponent { /> } } + + if (typeof routeDeclaration.useLayout !== "undefined") { + layoutType = routeDeclaration.useLayout + } + + if (typeof routeDeclaration.webTitleAddition !== "undefined") { + document.title = `${routeDeclaration.webTitleAddition} - ${config.app.siteName}` + } else { + document.title = config.app.siteName + } } const layoutComponentProps = { ...this.props.bindProps, ...this.state, - onTransitionStart: this.onTransitionStart, - onTransitionFinish: this.onTransitionFinish, } - const Layout = LayoutRenders[this.state.layoutType] + const Layout = LayoutRenders[layoutType] return {this.state.renderLock ? InitializationComponent : this.props.children} diff --git a/packages/app/src/router.jsx b/packages/app/src/router.jsx index 82954bcc..41f10cdb 100644 --- a/packages/app/src/router.jsx +++ b/packages/app/src/router.jsx @@ -59,7 +59,7 @@ export function BindContexts(component) { return (props) => React.createElement(component, { ...props, contexts }) } -export const InternalRouter = withRouter((props) => { +export const Router = withRouter((props) => { const defaultTransitionDelay = 150 const forceUpdate = React.useReducer(() => ({}))[1] @@ -69,7 +69,7 @@ export const InternalRouter = withRouter((props) => { props.onTransitionFinish(event) } - window.app.eventBus.emit("transitionDone", event) + window.app.eventBus.emit("router.transitionFinish", event) }) props.history.setLocation = (to, state = {}, delay = 150) => { @@ -92,7 +92,7 @@ export const InternalRouter = withRouter((props) => { props.onTransitionStart(delay) } - window.app.eventBus.emit("transitionStart", delay) + window.app.eventBus.emit("router.transitionStart", delay) setTimeout(() => { props.history.push({ @@ -110,6 +110,26 @@ export const InternalRouter = withRouter((props) => { window.app.setLocation = props.history.setLocation }, []) + const router = { + history: props.history, + lastLocation: props.history.lastLocation, + forceUpdate, + } + + // return children with router in props + return React.cloneElement(props.children, { router }) +}) + +export const InternalRouter = (props) => { + console.log(props) + return + + +} + +export const PageRender = (props) => { + console.log(props) + return {routes.map(({ path, component: Component = React.Fragment }) => ( @@ -127,14 +147,11 @@ export const InternalRouter = withRouter((props) => { -}) - -export const Router = (props) => { - return - - } -export default Router \ No newline at end of file +export default { + routes, + BindContexts, + InternalRouter, + PageRender, +} \ No newline at end of file