mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 18:44:16 +00:00
improve router and page transition logic
This commit is contained in:
parent
1c534a3946
commit
ef5ef4c90f
@ -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 {
|
||||
</Helmet>
|
||||
<antd.ConfigProvider>
|
||||
<div className="backgroundDecorator" />
|
||||
<Layout
|
||||
user={this.state.user}
|
||||
staticRenders={App.staticRenders}
|
||||
bindProps={{
|
||||
staticRenders: App.staticRenders,
|
||||
user: this.state.user,
|
||||
session: this.state.session,
|
||||
sessionController: this.sessionController,
|
||||
userController: this.userController,
|
||||
}}
|
||||
>
|
||||
<Router />
|
||||
</Layout>
|
||||
<Router.InternalRouter>
|
||||
<Layout
|
||||
user={this.state.user}
|
||||
staticRenders={App.staticRenders}
|
||||
bindProps={{
|
||||
staticRenders: App.staticRenders,
|
||||
user: this.state.user,
|
||||
session: this.state.session,
|
||||
sessionController: this.sessionController,
|
||||
userController: this.userController,
|
||||
}}
|
||||
>
|
||||
<Router.PageRender />
|
||||
</Layout>
|
||||
</Router.InternalRouter>
|
||||
</antd.ConfigProvider>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
@ -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 <antd.Layout className={classnames("app_layout", ["mobile"])} style={{ height: "100%" }}>
|
||||
<antd.Layout className="content_layout">
|
||||
<antd.Layout.Content className={classnames("layout_page", ...props.layoutPageModesClassnames ?? [])}>
|
||||
<div className={classnames("fade-transverse-active", { "fade-transverse-leave": props.isOnTransition })}>
|
||||
<div id="transitionLayer" className="fade-transverse-active">
|
||||
{React.cloneElement(props.children, props)}
|
||||
</div>
|
||||
</antd.Layout.Content>
|
||||
@ -31,7 +33,7 @@ const LayoutRenders = {
|
||||
<Sidedrawer />
|
||||
<antd.Layout className="content_layout">
|
||||
<antd.Layout.Content className={classnames("layout_page", ...props.layoutPageModesClassnames ?? [])}>
|
||||
<div className={classnames("fade-transverse-active", { "fade-transverse-leave": props.isOnTransition })}>
|
||||
<div id="transitionLayer" className="fade-transverse-active">
|
||||
{React.cloneElement(props.children, props)}
|
||||
</div>
|
||||
</antd.Layout.Content>
|
||||
@ -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 <Layout {...layoutComponentProps}>
|
||||
{this.state.renderLock ? InitializationComponent : this.props.children}
|
||||
|
@ -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 <BrowserRouter>
|
||||
<Router {...props} />
|
||||
</BrowserRouter>
|
||||
}
|
||||
|
||||
export const PageRender = (props) => {
|
||||
console.log(props)
|
||||
|
||||
return <React.Suspense fallback={props.staticRenders?.PageLoad ? React.createElement(props.staticRenders?.PageLoad) : "Loading..."}>
|
||||
<Switch>
|
||||
{routes.map(({ path, component: Component = React.Fragment }) => (
|
||||
@ -127,14 +147,11 @@ export const InternalRouter = withRouter((props) => {
|
||||
<Route path="*" component={props.staticRenders?.NotFound ?? NotFoundRender} />
|
||||
</Switch>
|
||||
</React.Suspense>
|
||||
})
|
||||
|
||||
export const Router = (props) => {
|
||||
return <BrowserRouter>
|
||||
<InternalRouter
|
||||
{...props}
|
||||
/>
|
||||
</BrowserRouter>
|
||||
}
|
||||
|
||||
export default Router
|
||||
export default {
|
||||
routes,
|
||||
BindContexts,
|
||||
InternalRouter,
|
||||
PageRender,
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user