diff options
| author | 2022-02-12 11:33:52 +0100 | |
|---|---|---|
| committer | 2022-02-12 11:33:52 +0100 | |
| commit | 871a85d9343cf49646d13dc455c062efadcb959a (patch) | |
| tree | 7d36b14b237719901d71d58c88f74b87b875ee61 /src/components/Content | |
| parent | 7c48533571e9f9d3731a59433a56cc8d6e008123 (diff) | |
| download | client-871a85d9343cf49646d13dc455c062efadcb959a.tar.gz client-871a85d9343cf49646d13dc455c062efadcb959a.tar.bz2 client-871a85d9343cf49646d13dc455c062efadcb959a.zip | |
Beatified codev1.3.0
Diffstat (limited to 'src/components/Content')
| -rw-r--r-- | src/components/Content/Content.tsx | 167 |
1 files changed, 94 insertions, 73 deletions
diff --git a/src/components/Content/Content.tsx b/src/components/Content/Content.tsx index c7a5f58..56a802f 100644 --- a/src/components/Content/Content.tsx +++ b/src/components/Content/Content.tsx | |||
| @@ -1,120 +1,141 @@ | |||
| 1 | import * as React from "react"; | 1 | import * as React from "react"; |
| 2 | import {Dispatch, SetStateAction, useContext, useMemo} from "react"; | 2 | import { Dispatch, SetStateAction, useContext, useMemo } from "react"; |
| 3 | import {RequestPayload, ResponsePayload, Headers} from "~hooks/useRequests"; | 3 | import { RequestPayload, ResponsePayload, Headers } from "~hooks/useRequests"; |
| 4 | import ReactJson from 'react-json-view'; | 4 | import ReactJson from "react-json-view"; |
| 5 | import styles from './Content.module.scss'; | 5 | import styles from "./Content.module.scss"; |
| 6 | import {Button, Col, Container, Row} from "react-bootstrap"; | 6 | import { Button, Col, Container, Row } from "react-bootstrap"; |
| 7 | import {DarkModeContext} from "../../contexts/DarkMode"; | 7 | import { DarkModeContext } from "../../contexts/DarkMode"; |
| 8 | 8 | ||
| 9 | function getHeader(headers: Headers, key: string, unit?: string): string | null { | 9 | function getHeader( |
| 10 | headers: Headers, | ||
| 11 | key: string, | ||
| 12 | unit?: string | ||
| 13 | ): string | null { | ||
| 10 | try { | 14 | try { |
| 11 | const [_, value] = headers.find(([headerKey]) => headerKey.toLowerCase() === key.toLowerCase()) | 15 | const [_, value] = headers.find( |
| 12 | return unit !== undefined | 16 | ([headerKey]) => headerKey.toLowerCase() === key.toLowerCase() |
| 13 | ? `${value}${unit}` | 17 | ); |
| 14 | : value | 18 | return unit !== undefined ? `${value}${unit}` : value; |
| 15 | } catch { | 19 | } catch { |
| 16 | return null; | 20 | return null; |
| 17 | } | 21 | } |
| 18 | } | 22 | } |
| 19 | 23 | ||
| 20 | interface ContentProps { | 24 | interface ContentProps { |
| 21 | data: RequestPayload | ResponsePayload | 25 | data: RequestPayload | ResponsePayload; |
| 22 | setRaw: Dispatch<SetStateAction<boolean>> | 26 | setRaw: Dispatch<SetStateAction<boolean>>; |
| 23 | raw?: boolean | 27 | raw?: boolean; |
| 24 | } | 28 | } |
| 25 | 29 | ||
| 26 | export default function Content({ raw, setRaw, data }: ContentProps): JSX.Element { | 30 | export default function Content({ |
| 31 | raw, | ||
| 32 | setRaw, | ||
| 33 | data, | ||
| 34 | }: ContentProps): JSX.Element { | ||
| 27 | return ( | 35 | return ( |
| 28 | <div className={styles.content}> | 36 | <div className={styles.content}> |
| 29 | <Container fluid className="border-bottom"> | 37 | <Container fluid className="border-bottom"> |
| 30 | <Row className="py-3"> | 38 | <Row className="py-3"> |
| 31 | <Col className="form-check form-switch ms-3"> | 39 | <Col className="form-check form-switch ms-3"> |
| 32 | <input className="form-check-input" id='raw' type='checkbox' checked={raw} role="switch" onChange={() => setRaw(!raw)}/> | 40 | <input |
| 33 | <label htmlFor='raw' className="form-check-label">Raw</label> | 41 | className="form-check-input" |
| 34 | </Col> | 42 | id="raw" |
| 43 | type="checkbox" | ||
| 44 | checked={raw} | ||
| 45 | role="switch" | ||
| 46 | onChange={() => setRaw(!raw)} | ||
| 47 | /> | ||
| 48 | <label htmlFor="raw" className="form-check-label"> | ||
| 49 | Raw | ||
| 50 | </label> | ||
| 51 | </Col> | ||
| 35 | <Col xs="auto"> | 52 | <Col xs="auto"> |
| 36 | { | 53 | {[ |
| 37 | [ | 54 | getHeader(data.headers, "content-length", "bytes"), |
| 38 | getHeader(data.headers, 'content-length', 'bytes'), | 55 | getHeader(data.headers, "content-type"), |
| 39 | getHeader(data.headers, 'content-type'), | 56 | ] |
| 40 | ].filter(x => x !== null).join('; ') | 57 | .filter((x) => x !== null) |
| 41 | } | 58 | .join("; ")} |
| 42 | </Col> | 59 | </Col> |
| 43 | </Row> | 60 | </Row> |
| 44 | </Container> | 61 | </Container> |
| 45 | <Row className={styles.body}> | 62 | <Row className={styles.body}> |
| 46 | {(() => { | 63 | {(() => { |
| 47 | try { | 64 | try { |
| 48 | return ContentBody({ data, raw }) | 65 | return ContentBody({ data, raw }); |
| 49 | } catch { | 66 | } catch { |
| 50 | return ( | 67 | return ( |
| 51 | <div className={styles.renderError}> | 68 | <div className={styles.renderError}> |
| 52 | <p>Body could not be rendered</p> | 69 | <p>Body could not be rendered</p> |
| 53 | <Button variant="link" onClick={() => setRaw(true)}>View raw</Button> | 70 | <Button variant="link" onClick={() => setRaw(true)}> |
| 71 | View raw | ||
| 72 | </Button> | ||
| 54 | </div> | 73 | </div> |
| 55 | ) | 74 | ); |
| 56 | } | 75 | } |
| 57 | })()} | 76 | })()} |
| 58 | </Row> | 77 | </Row> |
| 59 | </div > | 78 | </div> |
| 60 | ) | 79 | ); |
| 61 | }; | 80 | } |
| 62 | |||
| 63 | function ContentBody({ data, raw = false }: Omit<ContentProps, 'setRaw'>) { | ||
| 64 | const { darkMode } = useContext(DarkModeContext); | ||
| 65 | const contentType = useMemo(() => { | ||
| 66 | if (raw) { | ||
| 67 | return ''; | ||
| 68 | } | ||
| 69 | |||
| 70 | const type = getHeader(data.headers, 'content-type'); | ||
| 71 | return type.toLowerCase().split(';')[0]; | ||
| 72 | }, [data, raw]); | ||
| 73 | 81 | ||
| 82 | function ContentBody({ data, raw = false }: Omit<ContentProps, "setRaw">) { | ||
| 83 | const { darkMode } = useContext(DarkModeContext); | ||
| 84 | const contentType = useMemo(() => { | ||
| 74 | if (raw) { | 85 | if (raw) { |
| 75 | return ( | 86 | return ""; |
| 76 | <pre className="mb-0"> | ||
| 77 | <code> | ||
| 78 | {atob(data.body)} | ||
| 79 | </code> | ||
| 80 | </pre> | ||
| 81 | ) | ||
| 82 | } | 87 | } |
| 83 | 88 | ||
| 84 | if (['application/pdf', 'text/html'].includes(contentType)) { | 89 | const type = getHeader(data.headers, "content-type"); |
| 85 | return <iframe | 90 | return type.toLowerCase().split(";")[0]; |
| 91 | }, [data, raw]); | ||
| 92 | |||
| 93 | if (raw) { | ||
| 94 | return ( | ||
| 95 | <pre className="mb-0"> | ||
| 96 | <code>{atob(data.body)}</code> | ||
| 97 | </pre> | ||
| 98 | ); | ||
| 99 | } | ||
| 100 | |||
| 101 | if (["application/pdf", "text/html"].includes(contentType)) { | ||
| 102 | return ( | ||
| 103 | <iframe | ||
| 86 | className="bg-white" | 104 | className="bg-white" |
| 87 | src={`data:${contentType};base64,${data.body}`} | 105 | src={`data:${contentType};base64,${data.body}`} |
| 88 | srcDoc={contentType === 'text/html' ? atob(data.body) : undefined} | 106 | srcDoc={contentType === "text/html" ? atob(data.body) : undefined} |
| 89 | loading='lazy' | 107 | loading="lazy" |
| 90 | sandbox='' | 108 | sandbox="" |
| 91 | /> | 109 | /> |
| 92 | } | 110 | ); |
| 111 | } | ||
| 93 | 112 | ||
| 94 | if (contentType.startsWith('application/json')) { | 113 | if (contentType.startsWith("application/json")) { |
| 95 | return <ReactJson | 114 | return ( |
| 115 | <ReactJson | ||
| 96 | src={JSON.parse(atob(data.body))} | 116 | src={JSON.parse(atob(data.body))} |
| 97 | theme={darkMode ? "monokai" : undefined} | 117 | theme={darkMode ? "monokai" : undefined} |
| 98 | style={{ | 118 | style={{ |
| 99 | padding: '1em', | 119 | padding: "1em", |
| 100 | width: '100%', | 120 | width: "100%", |
| 101 | height: '100%', | 121 | height: "100%", |
| 102 | overflowY: 'auto', | 122 | overflowY: "auto", |
| 103 | }} | 123 | }} |
| 104 | /> | 124 | /> |
| 105 | } | 125 | ); |
| 126 | } | ||
| 106 | 127 | ||
| 107 | if (contentType.startsWith('audio')) { | 128 | if (contentType.startsWith("audio")) { |
| 108 | return <audio src={`data:${contentType};base64,${data.body}`} /> | 129 | return <audio src={`data:${contentType};base64,${data.body}`} />; |
| 109 | } | 130 | } |
| 110 | 131 | ||
| 111 | if (contentType.startsWith('video')) { | 132 | if (contentType.startsWith("video")) { |
| 112 | return <video src={`data:${contentType};base64,${data.body}`} /> | 133 | return <video src={`data:${contentType};base64,${data.body}`} />; |
| 113 | } | 134 | } |
| 114 | 135 | ||
| 115 | if (contentType.startsWith('image')) { | 136 | if (contentType.startsWith("image")) { |
| 116 | return <img src={`data:${contentType};base64,${data.body}`} alt=''/> | 137 | return <img src={`data:${contentType};base64,${data.body}`} alt="" />; |
| 117 | } | 138 | } |
| 118 | 139 | ||
