summaryrefslogtreecommitdiffstats
path: root/src/components/Content/Content.tsx
diff options
context:
space:
mode:
authorGravatar Tom van der Lee <tom@vanderlee.io>2021-12-30 09:51:00 +0100
committerGravatar Tom van der Lee <tom@vanderlee.io>2022-01-11 00:00:22 +0100
commitbcb77d979d817e1e609adb4d007bbbcc3f61efbd (patch)
tree093c5a2914ee0f6e1ec559b3b98725190fee7285 /src/components/Content/Content.tsx
downloadclient-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.tsx100
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 @@
1import styles from "~components/Details/Details.module.scss";
2import * as React from "react";
3import classNames from "classnames";
4import {RequestPayload, ResponsePayload} from "~hooks/useRequests";
5import {
6 Dispatch,
7 forwardRef, SetStateAction,
8 useEffect,
9 useImperativeHandle,
10 useMemo,
11 useRef,
12 useState
13} from "react";
14import ReactJson from 'react-json-view';
15import styles from './Content.module.scss';
16
17interface ContentProps {
18 data: RequestPayload | ResponsePayload
19 setRaw: Dispatch<SetStateAction<boolean>>
20 raw?: boolean
21}
22
23export 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
48function 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};