aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/App/App.tsx18
-rw-r--r--src/components/Content/Content.tsx19
-rw-r--r--src/components/Frames/Frames.tsx3
-rw-r--r--src/components/RequestList/RequestList.tsx4
-rw-r--r--src/components/RequestSummary/RequestSummary.tsx3
-rw-r--r--src/contexts/DarkMode.tsx41
-rw-r--r--src/contexts/Settings.tsx65
-rw-r--r--src/index.scss1
-rw-r--r--src/index.tsx6
-rw-r--r--src/types.ts4
10 files changed, 94 insertions, 70 deletions
diff --git a/src/components/App/App.tsx b/src/components/App/App.tsx
index ad36add..85119e6 100644
--- a/src/components/App/App.tsx
+++ b/src/components/App/App.tsx
@@ -1,25 +1,19 @@
1import * as React from "react"; 1import * as React from "react";
2import { ReactElement, useContext, useEffect, useMemo, useState } from "react"; 2import { ReactElement, useContext, useEffect } from "react";
3import useRequests from "~/hooks/useRequests";
4 3
5import styles from "~/components/App/App.module.scss"; 4import styles from "~/components/App/App.module.scss";
6import RequestDetails from "~/components/RequestDetails/RequestDetails"; 5import RequestDetails from "~/components/RequestDetails/RequestDetails";
7import { getHost } from "~/utils";
8import { Container, Nav, Navbar, NavDropdown } from "react-bootstrap"; 6import { Container, Nav, Navbar, NavDropdown } from "react-bootstrap";
9import classNames from "classnames"; 7import classNames from "classnames";
10import Sliders from "~/components/Icons/Sliders"; 8import Sliders from "~/components/Icons/Sliders";
11import Sun from "~/components/Icons/Sun"; 9import Sun from "~/components/Icons/Sun";
12import Moon from "~/components/Icons/Moon"; 10import Moon from "~/components/Icons/Moon";
13import Trash from "~/components/Icons/Trash"; 11import Trash from "~/components/Icons/Trash";
14import { DarkModeContext } from "~/contexts/DarkMode"; 12import { SettingsContext } from "~/contexts/Settings";
15import RequestList from "~/components/RequestList/RequestList"; 13import RequestList from "~/components/RequestList/RequestList";
16import { Call, ReadyState } from "~/types"; 14import { ReadyState } from "~/types";
17import { ConnectionContext } from "~/contexts/Connection"; 15import { ConnectionContext } from "~/contexts/Connection";
18 16
19interface Config {
20 url: string;
21}
22
23interface SettingsMenu { 17interface SettingsMenu {
24 icon: ReactElement; 18 icon: ReactElement;
25 label: string; 19 label: string;
@@ -48,8 +42,8 @@ const statusTextMap: ReadyStateMap = {
48}; 42};
49 43
50export default function App() { 44export default function App() {
51 const { darkMode, toggle } = useContext(DarkModeContext); 45 const { darkMode, setSetting } = useContext(SettingsContext);
52 const { config, selectedCall, setSelectedCall, readyState, clear } = 46 const { config, setSelectedCall, readyState, clear } =
53 useContext(ConnectionContext); 47 useContext(ConnectionContext);
54 48
55 useEffect(() => { 49 useEffect(() => {
@@ -59,7 +53,7 @@ export default function App() {
59 53
60 const settingsMenu: (SettingsMenu | null)[] = [ 54 const settingsMenu: (SettingsMenu | null)[] = [
61 { 55 {
62 onClick: toggle, 56 onClick: () => setSetting("darkMode", !darkMode),
63 icon: darkMode ? <Sun /> : <Moon />, 57 icon: darkMode ? <Sun /> : <Moon />,
64 label: darkMode ? "Light mode" : "Dark mode", 58 label: darkMode ? "Light mode" : "Dark mode",
65 }, 59 },
diff --git a/src/components/Content/Content.tsx b/src/components/Content/Content.tsx
index e670376..94fca32 100644
--- a/src/components/Content/Content.tsx
+++ b/src/components/Content/Content.tsx
@@ -4,7 +4,7 @@ import { Headers, RequestPayload, ResponsePayload } from "~hooks/useRequests";
4import ReactJson from "react-json-view"; 4import ReactJson from "react-json-view";
5import styles from "~/components/Content/Content.module.scss"; 5import styles from "~/components/Content/Content.module.scss";
6import { Button, Col, Container, Row } from "react-bootstrap"; 6import { Button, Col, Container, Row } from "react-bootstrap";
7import { DarkModeContext } from "~/contexts/DarkMode"; 7import { SettingsContext } from "~/contexts/Settings";
8 8
9function getHeader( 9function getHeader(
10 headers: Headers, 10 headers: Headers,
@@ -80,14 +80,14 @@ export default function Content({
80} 80}
81 81
82function ContentBody({ data, raw = false }: Omit<ContentProps, "setRaw">) { 82function ContentBody({ data, raw = false }: Omit<ContentProps, "setRaw">) {
83 const { darkMode } = useContext(DarkModeContext); 83 const { darkMode } = useContext(SettingsContext);
84 const contentType = useMemo(() => { 84 const contentType = useMemo(() => {
85 if (raw) { 85 if (raw) {
86 return ""; 86 return "";
87 } 87 }
88 88
89 const type = getHeader(data.headers, "content-type"); 89 const type = getHeader(data.headers, "content-type");
90 return type.toLowerCase().split(";")[0]; 90 return type?.toLowerCase().split(";")[0];
91 }, [data, raw]); 91 }, [data, raw]);
92 92
93 if (raw) { 93 if (raw) {
@@ -98,7 +98,10 @@ function ContentBody({ data, raw = false }: Omit<ContentProps, "setRaw">) {
98 ); 98 );
99 } 99 }
100 100
101 if (["application/pdf", "text/html"].includes(contentType)) { 101 if (
102 contentType !== undefined &&
103 ["application/pdf", "text/html"].includes(contentType)
104 ) {
102 return ( 105 return (
103 <iframe 106 <iframe
104 className="bg-white" 107 className="bg-white"
@@ -110,7 +113,7 @@ function ContentBody({ data, raw = false }: Omit<ContentProps, "setRaw">) {
110 ); 113 );
111 } 114 }
112 115
113 if (contentType.startsWith("application/json")) { 116 if (contentType?.startsWith("application/json")) {
114 return ( 117 return (
115 <ReactJson 118 <ReactJson
116 src={JSON.parse(atob(data.body))} 119 src={JSON.parse(atob(data.body))}
@@ -125,15 +128,15 @@ function ContentBody({ data, raw = false }: Omit<ContentProps, "setRaw">) {
125 ); 128 );
126 } 129 }
127 130
128 if (contentType.startsWith("audio")) { 131 if (contentType?.startsWith("audio")) {
129 return <audio src={`data:${contentType};base64,${data.body}`} />; 132 return <audio src={`data:${contentType};base64,${data.body}`} />;
130 } 133 }
131 134
132 if (contentType.startsWith("video")) { 135 if (contentType?.startsWith("video")) {
133 return <video src={`data:${contentType};base64,${data.body}`} />; 136 return <video src={`data:${contentType};base64,${data.body}`} />;
134 } 137 }
135 138
136 if (contentType.startsWith("image")) { 139 if (contentType?.startsWith("image")) {
137 return <img src={`data:${contentType};base64,${data.body}`} alt="" />; 140 return <img src={`data:${contentType};base64,${data.body}`} alt="" />;
138 } 141 }
139 142
diff --git a/src/components/Frames/Frames.tsx b/src/components/Frames/Frames.tsx
index 83c4c96..1d31d92 100644
--- a/src/components/Frames/Frames.tsx
+++ b/src/components/Frames/Frames.tsx
@@ -5,7 +5,7 @@ import classNames from "classnames";
5import styles from "./Frames.module.scss"; 5import styles from "./Frames.module.scss";
6import dayjs from "dayjs"; 6import dayjs from "dayjs";
7import ReactJson from "react-json-view"; 7import ReactJson from "react-json-view";
8import { DarkModeContext } from "~/contexts/DarkMode"; 8import { SettingsContext } from "~/contexts/Settings";
9 9
10function isJson(data: any): boolean { 10function isJson(data: any): boolean {
11 try { 11 try {
@@ -23,7 +23,6 @@ interface FramesProps {
23export default function Frames({ 23export default function Frames({
24 frames, 24 frames,
25}: PropsWithChildren<FramesProps>): JSX.Element { 25}: PropsWithChildren<FramesProps>): JSX.Element {
26 const { darkMode } = useContext(DarkModeContext);
27 return ( 26 return (
28 <ListGroup variant="flush" as="ul" className={"flex-grow-1"}> 27 <ListGroup variant="flush" as="ul" className={"flex-grow-1"}>
29 {frames.length > 0 ? ( 28 {frames.length > 0 ? (
diff --git a/src/components/RequestList/RequestList.tsx b/src/components/RequestList/RequestList.tsx
index 82a6b21..8217229 100644
--- a/src/components/RequestList/RequestList.tsx
+++ b/src/components/RequestList/RequestList.tsx
@@ -12,7 +12,7 @@ import styles from "~/components/RequestList/RequestList.module.scss";
12import RequestSummary from "~/components/RequestSummary/RequestSummary"; 12import RequestSummary from "~/components/RequestSummary/RequestSummary";
13import * as React from "react"; 13import * as React from "react";
14import { useCallback, useContext, useEffect, useMemo, useState } from "react"; 14import { useCallback, useContext, useEffect, useMemo, useState } from "react";
15import { DarkModeContext } from "~/contexts/DarkMode"; 15import { SettingsContext } from "~/contexts/Settings";
16import Filter from "~/components/Icons/Filter"; 16import Filter from "~/components/Icons/Filter";
17import { Call, Method } from "~/types"; 17import { Call, Method } from "~/types";
18import { ConnectionContext } from "~/contexts/Connection"; 18import { ConnectionContext } from "~/contexts/Connection";
@@ -22,7 +22,7 @@ type EnabledMethods = {
22}; 22};
23 23
24export default function RequestList() { 24export default function RequestList() {
25 const { darkMode } = useContext(DarkModeContext); 25 const { darkMode } = useContext(SettingsContext);
26 const { 26 const {
27 calls: requests, 27 calls: requests,
28 selectedCall, 28 selectedCall,
diff --git a/src/components/RequestSummary/RequestSummary.tsx b/src/components/RequestSummary/RequestSummary.tsx
index 4e97676..64ff475 100644
--- a/src/components/RequestSummary/RequestSummary.tsx
+++ b/src/components/RequestSummary/RequestSummary.tsx
@@ -4,10 +4,11 @@ import classNames from "classnames";
4 4
5import { Badge, Col, Row } from "react-bootstrap"; 5import { Badge, Col, Row } from "react-bootstrap";
6import dayjs from "dayjs"; 6import dayjs from "dayjs";
7import { Call } from "~/types";
7 8
8interface RequestSummaryProps { 9interface RequestSummaryProps {
9 selected?: boolean; 10 selected?: boolean;
10 requestResponse: Calls; 11 requestResponse: Call;
11 showTime?: boolean; 12 showTime?: boolean;
12} 13}
13 14
diff --git a/src/contexts/DarkMode.tsx b/src/contexts/DarkMode.tsx
deleted file mode 100644
index fd536b2..0000000
--- a/src/contexts/DarkMode.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
1import * as React from "react";
2import {
3 Context,
4 createContext,
5 PropsWithChildren,
6 useEffect,
7 useMemo,
8 useState,
9} from "react";
10import { ThemeConfig } from "bootstrap-darkmode";
11
12interface DarkModeApi {
13 darkMode: boolean;
14 toggle: () => void;
15}
16
17export const DarkModeContext = createContext<Partial<DarkModeApi>>(
18 {}
19) as Context<DarkModeApi>;
20
21export default function DarkModeProvider({ children }: PropsWithChildren<any>) {
22 const themeConfig = useMemo(() => new ThemeConfig(), []);
23 const [darkMode, setDarkMode] = useState(
24 () => themeConfig.getTheme() === "dark"
25 );
26
27 useEffect(() => {
28 themeConfig.setTheme(darkMode ? "dark" : "light");
29 }, [darkMode]);
30
31 return (
32 <DarkModeContext.Provider
33 value={{
34 darkMode,
35 toggle: () => setDarkMode((dm) => !dm),
36 }}
37 >
38 {children}
39 </DarkModeContext.Provider>
40 );
41}
diff --git a/src/contexts/Settings.tsx b/src/contexts/Settings.tsx
new file mode 100644
index 0000000..2bbebcc
--- /dev/null
+++ b/src/contexts/Settings.tsx
@@ -0,0 +1,65 @@
1import * as React from "react";
2import {
3 Context,
4 createContext,
5 PropsWithChildren,
6 useCallback,
7 useEffect,
8 useState,
9} from "react";
10import { Settings } from "~/types";
11
12interface SettingsApi {
13 darkMode: boolean;
14 setSetting: (key: keyof Settings, value: any) => void;
15}
16
17export const SettingsContext = createContext<Partial<SettingsApi>>(
18 {}
19) as Context<SettingsApi>;
20
21export default function SettingsProvider({ children }: PropsWithChildren<any>) {
22 // const themeConfig = useMemo(() => new ThemeConfig(), []);
23 const [settings, setSettings] = useState<Settings>(() => {
24 const stored = localStorage.getItem("settings");
25
26 if (stored) {
27 return JSON.parse(stored);
28 }
29
30 return {
31 darkMode:
32 window.matchMedia &&
33 window.matchMedia("(prefers-color-scheme: dark)").matches,
34 };
35 });
36
37 const setSetting = useCallback(
38 (key: keyof Settings, value: any) => {
39 const newSetting = {
40 ...settings,
41 [key]: value,
42 };
43 setSettings(newSetting);
44 localStorage.setItem("settings", JSON.stringify(newSetting));
45 },
46 [settings]
47 );
48
49 useEffect(() => {
50 document
51 .querySelector("html")
52 ?.setAttribute("data-bs-theme", settings.darkMode ? "dark" : "light");
53 }, [settings.darkMode]);
54
55 return (
56 <SettingsContext.Provider
57 value={{
58 darkMode: settings.darkMode,
59 setSetting,
60 }}
61 >
62 {children}
63 </SettingsContext.Provider>
64 );
65}
diff --git a/src/index.scss b/src/index.scss
index 1572e11..23e87b0 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -1,6 +1,5 @@
1@import "../node_modules/bootstrap/scss/bootstrap"; 1@import "../node_modules/bootstrap/scss/bootstrap";
2@import "../node_modules/bootstrap-icons/font/bootstrap-icons"; 2@import "../node_modules/bootstrap-icons/font/bootstrap-icons";
3@import "../node_modules/bootstrap-darkmode/scss/darktheme";
4 3
5* { 4* {
6 box-sizing: border-box; 5 box-sizing: border-box;
diff --git a/src/index.tsx b/src/index.tsx
index a2c18e3..c1a4211 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -3,7 +3,7 @@ import * as ReactDOM from "react-dom";
3import App from "~/components/App/App"; 3import App from "~/components/App/App";
4 4
5import "~/index.scss"; 5import "~/index.scss";
6import DarkModeProvider from "./contexts/DarkMode"; 6import SettingsProvider from "./contexts/Settings";
7 7
8import dayjs from "dayjs"; 8import dayjs from "dayjs";
9import localizedFormat from "dayjs/plugin/localizedFormat"; 9import localizedFormat from "dayjs/plugin/localizedFormat";
@@ -11,10 +11,10 @@ import ConnectionProvider from "~/contexts/Connection";
11dayjs.extend(localizedFormat); 11dayjs.extend(localizedFormat);
12 12
13ReactDOM.render( 13ReactDOM.render(
14 <DarkModeProvider> 14 <SettingsProvider>
15 <ConnectionProvider> 15 <ConnectionProvider>
16 <App /> 16 <App />
17 </ConnectionProvider> 17 </ConnectionProvider>
18 </DarkModeProvider>, 18 </SettingsProvider>,
19 document.getElementById("root") 19 document.getElementById("root")
20); 20);
diff --git a/src/types.ts b/src/types.ts
index 0e11bee..122fcf3 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,3 +1,7 @@
1export interface Settings {
2 darkMode: boolean;
3}
4
1export type Headers = [string, string][]; 5export type Headers = [string, string][];
2export type Method = 6export type Method =
3 | "GET" 7 | "GET"