From 129c33fa12298390246e92cb935cc795635d7784 Mon Sep 17 00:00:00 2001 From: Maciej Matuszewski Date: Wed, 12 Dec 2018 13:58:03 +0100 Subject: [PATCH] Add basic history handling (#288) (#309) * Add basic history handling (#288) * Move history management to Compress component * Remove unused pathname property from history * Rename history listener functions * Use history.back instead of history.replace * Support going forward in history. Persist last selected file in runtime * Add netlify redirects file * Use 301 status code for redirect * Cleanup _redirects file * Use 200 status code for redirects * Simplify onPopState function * Always redirect to 301 with url rewrite * Remove redundant history function * Remove file check on render. Call openEditor synchronously * Use pushState only if user is on the initial screen. Mount history listener in constructor * Simplify openEditor condition * Update early return condition * Rolling abstractions back into the main component --- _redirects.ejs | 2 ++ src/components/App/index.tsx | 32 +++++++++++++++++++++++++------- webpack.config.js | 5 +++++ 3 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 _redirects.ejs diff --git a/_redirects.ejs b/_redirects.ejs new file mode 100644 index 00000000..66fd124c --- /dev/null +++ b/_redirects.ejs @@ -0,0 +1,2 @@ +/index.html / 301 +/* /index.html 301 \ No newline at end of file diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index a0477733..f30ddc7c 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -9,6 +9,8 @@ import '../../lib/SnackBar'; import Intro from '../intro'; import '../custom-els/LoadingSpinner'; +const ROUTE_EDITOR = '/editor'; + const compressPromise = import( /* webpackChunkName: "main-app" */ '../compress', @@ -18,15 +20,21 @@ const offlinerPromise = import( '../../lib/offliner', ); +function back() { + window.history.back(); +} + interface Props {} interface State { file?: File | Fileish; + isEditorOpen: Boolean; Compress?: typeof import('../compress').default; } export default class App extends Component { state: State = { + isEditorOpen: false, file: undefined, Compress: undefined, }; @@ -53,17 +61,20 @@ export default class App extends Component { window.STATE = this.state; }; } + + window.addEventListener('popstate', this.onPopState); } @bind - private onFileDrop(event: FileDropEvent) { - const { file } = event; + private onFileDrop({ file }: FileDropEvent) { if (!file) return; + this.openEditor(); this.setState({ file }); } @bind private onIntroPickFile(file: File | Fileish) { + this.openEditor(); this.setState({ file }); } @@ -74,18 +85,25 @@ export default class App extends Component { } @bind - private onBack() { - this.setState({ file: undefined }); + private onPopState() { + this.setState({ isEditorOpen: location.pathname === ROUTE_EDITOR }); } - render({}: Props, { file, Compress }: State) { + @bind + private openEditor() { + if (this.state.isEditorOpen) return; + history.pushState(null, '', ROUTE_EDITOR); + this.setState({ isEditorOpen: true }); + } + + render({}: Props, { file, isEditorOpen, Compress }: State) { return (
- {(!file) + {!isEditorOpen ? : (Compress) - ? + ? : } diff --git a/webpack.config.js b/webpack.config.js index c4511162..fe52f705 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -251,6 +251,11 @@ module.exports = async function (_, env) { filename: '_headers', }), + isProd && new AssetTemplatePlugin({ + template: path.join(__dirname, '_redirects.ejs'), + filename: '_redirects', + }), + new ScriptExtHtmlPlugin({ inline: ['first'] }),