diff options
| author | 2021-12-30 09:51:00 +0100 | |
|---|---|---|
| committer | 2022-01-11 00:00:22 +0100 | |
| commit | bcb77d979d817e1e609adb4d007bbbcc3f61efbd (patch) | |
| tree | 093c5a2914ee0f6e1ec559b3b98725190fee7285 /src/components/Content/Content.tsx | |
| download | client-bcb77d979d817e1e609adb4d007bbbcc3f61efbd.tar.gz client-bcb77d979d817e1e609adb4d007bbbcc3f61efbd.tar.bz2 client-bcb77d979d817e1e609adb4d007bbbcc3f61efbd.zip | |
Prepare for githubv1.0.0
Diffstat (limited to 'src/components/Content/Content.tsx')
| -rw-r--r-- | src/components/Content/Content.tsx | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/src/components/Content/Content.tsx b/src/components/Content/Content.tsx new file mode 100644 index 0000000..a7b5949 --- /dev/null +++ b/src/components/Content/Content.tsx | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | import styles from "~components/Details/Details.module.scss"; | ||
| 2 | import * as React from "react"; | ||
| 3 | import classNames from "classnames"; | ||
| 4 | import {RequestPayload, ResponsePayload} from "~hooks/useRequests"; | ||
| 5 | import { | ||
| 6 | Dispatch, | ||
| 7 | forwardRef, SetStateAction, | ||
| 8 | useEffect, | ||
| 9 | useImperativeHandle, | ||
| 10 | useMemo, | ||
| 11 | useRef, | ||
| 12 | useState | ||
| 13 | } from "react"; | ||
| 14 | import ReactJson from 'react-json-view'; | ||
| 15 | import styles from './Content.module.scss'; | ||
| 16 | |||
| 17 | interface ContentProps { | ||
| 18 | data: RequestPayload | ResponsePayload | ||
| 19 | setRaw: Dispatch<SetStateAction<boolean>> | ||
| 20 | raw?: boolean | ||
| 21 | } | ||
| 22 | |||
| 23 | export default function Content({ raw, setRaw, ...props }: ContentProps): JSX.Element { | ||
| 24 | return ( | ||
| 25 | <div className={styles.content}> | ||
| 26 | <div className={styles.header}> | ||
| 27 | <input id='raw' type='checkbox' checked={raw} onChange={() => setRaw(!raw)}/> | ||
| 28 | <label htmlFor='raw'>Raw</label> | ||
| 29 | </div> | ||
| 30 | <div className={styles.body}> | ||
| 31 | {(() => { | ||
| 32 | try { | ||
| 33 | return ContentBody({ ...props, raw }) | ||
| 34 | } catch { | ||
| 35 | return ( | ||
| 36 | <div className={styles.renderError}> | ||
| 37 | <p>Body could not be rendered</p> | ||
| 38 | <a onClick={() => setRaw(true)}>View raw</a> | ||
| 39 | </div> | ||
| 40 | ) | ||
| 41 | } | ||
| 42 | })()} | ||
| 43 | </div> | ||
| 44 | </div> | ||
| 45 | ) | ||
| 46 | }; | ||
| 47 | |||
| 48 | function ContentBody({ data, raw = false }: Omit<ContentProps, 'setRaw'>) { | ||
| 49 | const contentType = useMemo(() => { | ||
| 50 | if (raw) { | ||
| 51 | return ''; | ||
| 52 | } | ||
| 53 | |||
| 54 | const [_, type] = ( | ||
| 55 | Object | ||
| 56 | .entries(data.headers) | ||
| 57 | .find(([key]) => key.toLowerCase() === 'content-type') | ||
| 58 | ); | ||
| 59 | |||
| 60 | return type.toLowerCase().split(';')[0]; | ||
| 61 | }, [data, raw]); | ||
| 62 | |||
| 63 | if (raw) { | ||
| 64 | return <pre>{atob(data.body)}</pre> | ||
| 65 | } | ||
| 66 | |||
| 67 | if (['application/pdf', 'text/html'].includes(contentType)) { | ||
| 68 | return <iframe | ||
| 69 | src={`data:${contentType};base64,${data.body}`} | ||
| 70 | srcDoc={contentType === 'text/html' ? atob(data.body) : undefined} | ||
| 71 | loading='lazy' | ||
| 72 | sandbox='' | ||
| 73 | /> | ||
| 74 | } | ||
| 75 | |||
| 76 | if (contentType.startsWith('application/json')) { | ||
| 77 | return <ReactJson | ||
| 78 | src={JSON.parse(atob(data.body))} | ||
| 79 | style={{ | ||
| 80 | padding: '1em', | ||
| 81 | width: '100%', | ||
| 82 | height: '100%', | ||
| 83 | }} | ||
| 84 | /> | ||
| 85 | } | ||
| 86 | |||
| 87 | if (contentType.startsWith('audio')) { | ||
| 88 | return <audio src={`data:${contentType};base64,${data.body}`} /> | ||
| 89 | } | ||
| 90 | |||
| 91 | if (contentType.startsWith('video')) { | ||
| 92 | return <video src={`data:${contentType};base64,${data.body}`} /> | ||
| 93 | } | ||
| 94 | |||
| 95 | if (contentType.startsWith('image')) { | ||
| 96 | return <img src={`data:${contentType};base64,${data.body}`} alt=''/> | ||
| 97 | } | ||
| 98 | |||
| 99 | throw new Error('Not Rendered'); | ||
| 100 | }; | ||
