diff --git a/src/web/codeViewer.coffee b/src/web/codeViewer.coffee index 6f17fc0..767dae1 100644 --- a/src/web/codeViewer.coffee +++ b/src/web/codeViewer.coffee @@ -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 - -
-
- { - if @state.highlight -
-          else
-            
{@state.code}
- } -
-
- - New Paste - -
+
+
+ { + if highlight +
+        else
+          
{code}
+ }
- -export default CodeViewer \ No newline at end of file +
+ + New Paste + +
+
\ No newline at end of file diff --git a/src/web/hooks.coffee b/src/web/hooks.coffee index e88cdb2..25b484c 100644 --- a/src/web/hooks.coffee +++ b/src/web/hooks.coffee @@ -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 - ] \ No newline at end of file + ] + +# 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 \ No newline at end of file