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:
parent
3169a7825f
commit
2b42e19ecb
|
@ -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}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
|
|
28
src/web/util/linkButton.coffee
Normal file
28
src/web/util/linkButton.coffee
Normal 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
|
Loading…
Reference in a new issue