helpButton, openDialog: refactor using hooks and context

This commit is contained in:
Peter Cai 2020-02-20 13:02:40 +08:00
parent 0f6b4e06f1
commit 6c15b51296
No known key found for this signature in database
GPG key ID: 71F5FB4E4F3FD54F
6 changed files with 56 additions and 55 deletions

View file

@ -7,7 +7,6 @@ import * as crypto from "../crypto"
import * as util from "../util" import * as util from "../util"
export default BinaryUpload = -> export default BinaryUpload = ->
[openDialog, renderDialog] = hooks.useDialog()
[encrypt, toggleEncrypt] = hooks.useToggle false [encrypt, toggleEncrypt] = hooks.useToggle false
[encrypting, setEncrypting] = useState false [encrypting, setEncrypting] = useState false
[file, setFile] = useState null [file, setFile] = useState null
@ -15,8 +14,7 @@ export default BinaryUpload = ->
# Paste hook and event # Paste hook and event
clearFile = (status) -> clearFile = (status) ->
setFile null if status == 200 setFile null if status == 200
[doPaste, pasting, progress] = hooks.usePaste openDialog, [doPaste, pasting, progress] = hooks.usePaste useCallback clearFile, []
useCallback clearFile, []
# Dropzone hook and event # Dropzone hook and event
onDrop = (files) -> onDrop = (files) ->
@ -38,7 +36,6 @@ export default BinaryUpload = ->
doUpload = useCallback doUpload, [file, encrypt, doPaste] doUpload = useCallback doUpload, [file, encrypt, doPaste]
<div className="content-pastebin"> <div className="content-pastebin">
{renderDialog()}
<section className="container"> <section className="container">
<div {...getRootProps({className: 'dropzone'})}> <div {...getRootProps({className: 'dropzone'})}>
<input {...getInputProps()} /> <input {...getInputProps()} />
@ -54,7 +51,7 @@ export default BinaryUpload = ->
</aside> </aside>
</section> </section>
<div className="content-buttons"> <div className="content-buttons">
<HelpButton openDialog={openDialog} /> <HelpButton />
<button <button
className="button-blue" className="button-blue"
disabled={pasting} disabled={pasting}

View file

@ -0,0 +1,4 @@
import React from "react"
# The value should be a function `openDialog(msg)`
export default DialogContext = React.createContext null

View file

@ -1,12 +1,12 @@
import React from "react" import React, { useContext, useCallback } from "react"
import DialogContext from "./dialogContext"
import * as util from "../util" import * as util from "../util"
class HelpButton extends React.Component export default HelpButton = ->
constructor: (props) -> openDialog = useContext DialogContext
super props
showHelp: => showHelp = ->
@props.openDialog do => openDialog do ->
<React.Fragment> <React.Fragment>
<p><strong>Angry.Im Pastebin Service</strong><br/> <p><strong>Angry.Im Pastebin Service</strong><br/>
Source code:&nbsp; Source code:&nbsp;
@ -31,13 +31,11 @@ class HelpButton extends React.Component
The decryption will also be done entirely in your browser. Therefore, it is not supported to access encrypted files outside of a modern browser. The decryption will also be done entirely in your browser. Therefore, it is not supported to access encrypted files outside of a modern browser.
</p> </p>
</React.Fragment> </React.Fragment>
showHelp = useCallback showHelp, [openDialog]
render: -> <button
<button className="button-blue"
className="button-blue" onClick={showHelp}
onClick={@showHelp} >
> Help
Help </button>
</button>
export default HelpButton

View file

@ -2,6 +2,7 @@ import React, { useState } from "react"
import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom" import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom"
import { AnimatedSwitch, spring } from 'react-router-transition' import { AnimatedSwitch, spring } from 'react-router-transition'
import * as hooks from "./hooks" import * as hooks from "./hooks"
import DialogContext from "./dialogContext"
import Pastebin from "./pastebin" import Pastebin from "./pastebin"
import BinaryUpload from "./binaryUpload" import BinaryUpload from "./binaryUpload"
import FileViewerDispatcher from "./fileViewerDispatcher" import FileViewerDispatcher from "./fileViewerDispatcher"
@ -32,33 +33,35 @@ export default Home = ->
<div className="content-wrapper"> <div className="content-wrapper">
<div className="content"> <div className="content">
<Router> <DialogContext.Provider value={openDialog}>
<AnimatedSwitch <Router>
atEnter={atEnter} <AnimatedSwitch
atLeave={atLeave} atEnter={atEnter}
atActive={atActive} atLeave={atLeave}
mapStyles={mapStyles} atActive={atActive}
className="switch-wrapper" mapStyles={mapStyles}
> className="switch-wrapper"
<Redirect exact from="/" to="/paste/text" /> >
{ <Redirect exact from="/" to="/paste/text" />
# Use `render` instead of `component` to prevent re-rendering the child {
# when parent is re-rendered (however this prevents passing match props) # Use `render` instead of `component` to prevent re-rendering the child
} # when parent is re-rendered (however this prevents passing match props)
<Route }
exact path="/paste/text" <Route
render={() => <Pastebin openDialog={openDialog}/>} exact path="/paste/text"
/> render={() => <Pastebin />}
<Route />
exact path="/paste/binary" <Route
render={() => <BinaryUpload openDialog={openDialog}/>} exact path="/paste/binary"
/> render={() => <BinaryUpload />}
<Route />
path="/paste/:id" <Route
component={FileViewerDispatcher} path="/paste/:id"
/> component={FileViewerDispatcher}
</AnimatedSwitch> />
</Router> </AnimatedSwitch>
</Router>
</DialogContext.Provider>
</div> </div>
{renderDialog()} {renderDialog()}
</div> </div>

View file

@ -1,5 +1,6 @@
import React, { useState, useCallback, useEffect } from "react" import React, { useState, useCallback, useEffect, useContext } from "react"
import ReactModal from "react-modal" import ReactModal from "react-modal"
import DialogContext from "./dialogContext"
# Simple abstraction for a toggling state # Simple abstraction for a toggling state
export useToggle = (defVal) -> export useToggle = (defVal) ->
@ -73,7 +74,8 @@ export useXhrProgress = ->
] ]
# Handles shared file-uploading logic between text / binary pasting # Handles shared file-uploading logic between text / binary pasting
export usePaste = (openDialog, callback) -> export usePaste = (callback) ->
openDialog = useContext DialogContext
[pasting, setPasting] = useState false [pasting, setPasting] = useState false
[progress, _, beginXHR] = useXhrProgress() [progress, _, beginXHR] = useXhrProgress()

View file

@ -1,19 +1,17 @@
import React, { useState, useCallback } from "react" import React, { useState, useCallback, useContext } from "react"
import * as hooks from "./hooks" import * as hooks from "./hooks"
import HelpButton from "./helpButton" import HelpButton from "./helpButton"
import LinkButton from "./util/linkButton" import LinkButton from "./util/linkButton"
import ContentEditable from "./util/contentEditable" import ContentEditable from "./util/contentEditable"
export default Pastebin = -> export default Pastebin = ->
[openDialog, renderDialog] = hooks.useDialog()
[highlight, toggleHighlight] = hooks.useToggle false [highlight, toggleHighlight] = hooks.useToggle false
[text, setText] = useState "" [text, setText] = useState ""
# Paste hook and events # Paste hook and events
clearText = (status) -> clearText = (status) ->
setText "" if status == 200 setText "" if status == 200
[doPaste, pasting, _] = hooks.usePaste openDialog, [doPaste, pasting, _] = hooks.usePaste useCallback clearText, []
useCallback clearText, []
onEditTextUpdate = (ev) -> onEditTextUpdate = (ev) ->
setText ev.target.value setText ev.target.value
@ -28,7 +26,6 @@ export default Pastebin = ->
paste = useCallback paste, [text, doPaste] paste = useCallback paste, [text, doPaste]
<div className="content-pastebin"> <div className="content-pastebin">
{renderDialog()}
<ContentEditable <ContentEditable
className="content-pastebin-edit" className="content-pastebin-edit"
onUpdate={onEditTextUpdate} onUpdate={onEditTextUpdate}
@ -37,7 +34,7 @@ export default Pastebin = ->
plainText plainText
/> />
<div className="content-buttons"> <div className="content-buttons">
<HelpButton openDialog={openDialog} /> <HelpButton />
<button <button
className="button-blue" className="button-blue"
onClick={toggleHighlight} onClick={toggleHighlight}