fix transition between pages by using a custom LinkButton

by replacing everything with a `<Redirect/>` on switching, it produces a
short blink while the new page appears. But we cannot just use `<Link/>`
because an `<a>` cannot be "disabled". Wrapping `Link` around `button`
is invalid HTML5.

Instead, hack together a custom component for the job.
This commit is contained in:
Peter Cai 2020-02-19 19:17:57 +08:00
parent 3169a7825f
commit 2b42e19ecb
No known key found for this signature in database
GPG key ID: 71F5FB4E4F3FD54F
5 changed files with 45 additions and 24 deletions

View file

@ -1,6 +1,6 @@
import React from "react" import React from "react"
import { Redirect } from "react-router-dom"
import Dropzone from "react-dropzone" import Dropzone from "react-dropzone"
import LinkButton from "./util/linkButton"
import * as crypto from "../crypto" import * as crypto from "../crypto"
import * as util from "../util" import * as util from "../util"
@ -11,7 +11,6 @@ class BinaryUpload extends React.Component
file: null file: null
uploading: false uploading: false
progress: 0 progress: 0
switchToText: false
encrypt: false encrypt: false
encrypting: false encrypting: false
@ -70,9 +69,6 @@ class BinaryUpload extends React.Component
{ encrypt: not state.encrypt } { encrypt: not state.encrypt }
render: -> render: ->
if @state.switchToText
return <Redirect to="/paste/text" />
<div className="content-pastebin"> <div className="content-pastebin">
<Dropzone onDrop={@onDrop}> <Dropzone onDrop={@onDrop}>
{({getRootProps, getInputProps}) => {({getRootProps, getInputProps}) =>
@ -100,13 +96,13 @@ class BinaryUpload extends React.Component
> >
{ "Encrypt: " + if @state.encrypt then "ON" else "OFF" } { "Encrypt: " + if @state.encrypt then "ON" else "OFF" }
</button> </button>
<button <LinkButton
className="button-blue" className="button-blue"
disabled={@state.uploading} disabled={@state.uploading}
onClick={(ev) => @setState { switchToText: true }} to="/paste/text"
> >
Text Mode Text Mode
</button> </LinkButton>
<button <button
className="button-blue" className="button-blue"
disabled={@state.uploading or not @state.file} disabled={@state.uploading or not @state.file}

View file

@ -1,6 +1,6 @@
import React from "react" import React from "react"
import { Redirect } from "react-router-dom"
import hljs from "highlight.js" import hljs from "highlight.js"
import LinkButton from "./util/linkButton"
MAX_HIGHLIGHT_LENGTH = 10 * 1024 # 10 KiB MAX_HIGHLIGHT_LENGTH = 10 * 1024 # 10 KiB
@ -9,7 +9,6 @@ class CodeViewer extends React.Component
super props super props
@state = @state =
code: "Loading..." code: "Loading..."
switchToHome: false
highlight: true highlight: true
componentDidMount: -> componentDidMount: ->
@ -42,12 +41,13 @@ class CodeViewer extends React.Component
} }
</div> </div>
<div className="content-buttons"> <div className="content-buttons">
<button <LinkButton
className="button-blue" className="button-blue"
onClick={(ev) => @setState { switchToHome: true }} push
to="/paste/text"
> >
New Paste New Paste
</button> </LinkButton>
</div> </div>
</div> </div>

View file

@ -1,5 +1,5 @@
import React from "react" import React from "react"
import { Link } from "react-router-dom" import LinkButton from "./util/linkButton"
import * as crypto from "../crypto" import * as crypto from "../crypto"
import * as util from "../util" import * as util from "../util"
@ -119,12 +119,13 @@ class FileDecrypter extends React.Component
</a> </a>
} }
<br/> <br/>
<Link <LinkButton
className="button-blue" className="button-blue"
push
to="/paste/text" to="/paste/text"
> >
Home Home
</Link> </LinkButton>
</div> </div>
}</div> }</div>

View file

@ -1,5 +1,5 @@
import React from "react" import React from "react"
import { Redirect } from "react-router-dom" import LinkButton from "./util/linkButton"
import ContentEditable from "./util/contentEditable" import ContentEditable from "./util/contentEditable"
class Pastebin extends React.Component class Pastebin extends React.Component
@ -9,7 +9,6 @@ class Pastebin extends React.Component
text: "" text: ""
pasting: false pasting: false
highlight: false # Make this false by default to avoid blocking highlight: false # Make this false by default to avoid blocking
switchToUpload: false
onEditTextUpdate: (ev) => onEditTextUpdate: (ev) =>
console.log ev.target.value console.log ev.target.value
@ -54,9 +53,6 @@ class Pastebin extends React.Component
pasting: false pasting: false
render: -> render: ->
if @state.switchToUpload
return <Redirect to="/paste/binary" />
<div className="content-pastebin"> <div className="content-pastebin">
<ContentEditable <ContentEditable
className="content-pastebin-edit" className="content-pastebin-edit"
@ -72,13 +68,13 @@ class Pastebin extends React.Component
> >
Highlight: {if @state.highlight then 'ON' else 'OFF'} Highlight: {if @state.highlight then 'ON' else 'OFF'}
</button> </button>
<button <LinkButton
className="button-blue" className="button-blue"
disabled={@state.pasting} disabled={@state.pasting}
onClick={(ev) => @setState { switchToUpload: true }} to="/paste/binary"
> >
File Upload File Upload
</button> </LinkButton>
<button <button
className="button-blue" className="button-blue"
disabled={@state.pasting} disabled={@state.pasting}

View file

@ -0,0 +1,28 @@
import React from "react"
import { Redirect } from "react-router-dom"
# A replacement of react Link that uses a button
class LinkButton extends React.Component
constructor: (props) ->
super props
@state =
switch: false
render: ->
# We cannot just replace the button with a <Redirect/> when we switch
# because it will cause visual breaks where the button disappears for
# a short while before the actual switch happens.
# Use <ins> as a dumb wrapper because it does not actually create
# an element around our tags.
# (the semantics of <ins> is "inserted content", but this seems
# to be the only sane solution here)
# <https://stackoverflow.com/questions/14162035/how-to-wrap-arbitrary-html-with-a-wrapper-without-breaking-markup>
<ins>
<button {...@props} onClick={(e) => @setState { switch: true }}/>
{
@state.switch and
<Redirect {...@props} />
}
</ins>
export default LinkButton