codeViewer: refactor to use hooks
This commit is contained in:
parent
e3e3445b93
commit
17d6add3dc
|
@ -1,54 +1,43 @@
|
|||
import React from "react"
|
||||
import React, { useState } from "react"
|
||||
import hljs from "highlight.js"
|
||||
import * as hooks from "./hooks"
|
||||
import LinkButton from "./util/linkButton"
|
||||
|
||||
MAX_HIGHLIGHT_LENGTH = 10 * 1024 # 10 KiB
|
||||
|
||||
class CodeViewer extends React.Component
|
||||
constructor: (props) ->
|
||||
super props
|
||||
@state =
|
||||
code: "Loading..."
|
||||
highlight: true
|
||||
export default CodeViewer = (props) ->
|
||||
[code, setCode] = useState "Loading..."
|
||||
[highlight, setHighlight] = useState true
|
||||
|
||||
componentDidMount: ->
|
||||
resp = await fetch "/paste/#{@props.id}?original"
|
||||
# Fetch the content on first mount (and after first render)
|
||||
hooks.useFetchContent props.id, (meta, resp) ->
|
||||
resp = await resp.text()
|
||||
if resp.length < MAX_HIGHLIGHT_LENGTH
|
||||
resp = hljs.highlightAuto(resp).value
|
||||
if meta.length < MAX_HIGHLIGHT_LENGTH
|
||||
setCode hljs.highlightAuto(resp).value
|
||||
else
|
||||
@setState
|
||||
highlight: false
|
||||
setHighlight false
|
||||
setCode resp
|
||||
|
||||
@setState
|
||||
code: resp
|
||||
|
||||
render: ->
|
||||
if @state.switchToHome
|
||||
return <Redirect push to="/paste/text" />
|
||||
|
||||
<div className="content-pastebin">
|
||||
<div
|
||||
className="content-code-viewer"
|
||||
>
|
||||
{
|
||||
if @state.highlight
|
||||
<pre
|
||||
dangerouslySetInnerHTML={{__html: @state.code}}
|
||||
/>
|
||||
else
|
||||
<pre>{@state.code}</pre>
|
||||
}
|
||||
</div>
|
||||
<div className="content-buttons">
|
||||
<LinkButton
|
||||
className="button-blue"
|
||||
push
|
||||
to="/paste/text"
|
||||
>
|
||||
New Paste
|
||||
</LinkButton>
|
||||
</div>
|
||||
<div className="content-pastebin">
|
||||
<div
|
||||
className="content-code-viewer"
|
||||
>
|
||||
{
|
||||
if highlight
|
||||
<pre
|
||||
dangerouslySetInnerHTML={{__html: code}}
|
||||
/>
|
||||
else
|
||||
<pre>{code}</pre>
|
||||
}
|
||||
</div>
|
||||
|
||||
export default CodeViewer
|
||||
<div className="content-buttons">
|
||||
<LinkButton
|
||||
className="button-blue"
|
||||
push
|
||||
to="/paste/text"
|
||||
>
|
||||
New Paste
|
||||
</LinkButton>
|
||||
</div>
|
||||
</div>
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useCallback } from "react"
|
||||
import React, { useState, useCallback, useEffect } from "react"
|
||||
import ReactModal from "react-modal"
|
||||
|
||||
# Simple abstraction for a toggling state
|
||||
|
@ -90,4 +90,32 @@ export usePaste = (openDialog, callback) ->
|
|||
useCallback(doPaste, [openDialog, callback]),
|
||||
pasting,
|
||||
progress
|
||||
]
|
||||
]
|
||||
|
||||
# An effect that fetches the original pasted content,
|
||||
# and then fires a callback that handles metadata and the response body
|
||||
# it also stores the meta into a state and returns it every time
|
||||
# this hook gets called, so callbacks are not necessary
|
||||
# and if callback is not present, then the response body
|
||||
# would simply be thrown away
|
||||
export useFetchContent = (id, callback) ->
|
||||
[meta, setMeta] = useState null
|
||||
|
||||
doFetch = ->
|
||||
resp = await fetch "/paste/#{id}?original"
|
||||
length = resp.headers.get 'content-length'
|
||||
mime = resp.headers.get 'content-type'
|
||||
[_, name] = resp.headers.get 'content-disposition'
|
||||
.split 'filename*='
|
||||
newMeta =
|
||||
name: name
|
||||
mime: mime
|
||||
length: length
|
||||
setMeta newMeta
|
||||
# We have to pass newMeta to callback because
|
||||
# the callback will not be aware of the meta update
|
||||
callback newMeta, resp if callback
|
||||
|
||||
# Run the effect once on mount
|
||||
useEffect doFetch, []
|
||||
meta
|
Loading…
Reference in New Issue