From aa12b94a0116c9c30203b6201d4b82c568d7b39b Mon Sep 17 00:00:00 2001 From: Gnarwhal Date: Mon, 23 Sep 2024 18:23:19 +0000 Subject: [PATCH 1/8] Better error pages --- src/app/[...file]/components/content.tsx | 23 +++++++++++-------- .../components/types/error/content_type.tsx | 4 +++- .../components/types/error/error.css.ts | 18 +++++++++++++++ .../components/types/error/error.tsx | 13 +++++++++++ .../components/types/error/network.tsx | 5 +++- .../components/types/error/status.tsx | 23 +++++++++++++++++++ 6 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 src/app/[...file]/components/types/error/error.css.ts create mode 100644 src/app/[...file]/components/types/error/error.tsx create mode 100644 src/app/[...file]/components/types/error/status.tsx diff --git a/src/app/[...file]/components/content.tsx b/src/app/[...file]/components/content.tsx index b2a2118..986ed39 100644 --- a/src/app/[...file]/components/content.tsx +++ b/src/app/[...file]/components/content.tsx @@ -2,8 +2,9 @@ import { useState, useEffect } from 'react' -import NetworkError from './types/error/network'; import ContentTypeError from './types/error/content_type'; +import NetworkError from './types/error/network'; +import StatusError from './types/error/status'; import ImageContent from './types/image'; import MarkdownContent from './types/markdown'; import Terminal from './types/terminal'; @@ -86,17 +87,21 @@ export default function Content({ src }: { src: string}) { if (content == undefined) { const result = fetch(src) .then(response => { - for (const type of recognized_types) { - if (is_type(response, type)) { - const emitted = type.emit(); - if (emitted != undefined) { - result.then(emitted.postprocess); - return emitted.process(response); + if (response.status < 400) { + for (const type of recognized_types) { + if (is_type(response, type)) { + const emitted = type.emit(); + if (emitted != undefined) { + result.then(emitted.postprocess); + return emitted.process(response); + } + return; } - return; } + set_content(); + } else { + set_content(); } - set_content(); }) .catch(err => { set_content(); diff --git a/src/app/[...file]/components/types/error/content_type.tsx b/src/app/[...file]/components/types/error/content_type.tsx index 84c9b29..7c50ccd 100644 --- a/src/app/[...file]/components/types/error/content_type.tsx +++ b/src/app/[...file]/components/types/error/content_type.tsx @@ -1,3 +1,5 @@ +import Error from './error' + export default function ContentTypeError({ content_type }: { content_type: string }) { - return

{`Unrecognised MIME type: ${content_type}`}

+ return {`Unrecognised MIME type: ${content_type}`} } diff --git a/src/app/[...file]/components/types/error/error.css.ts b/src/app/[...file]/components/types/error/error.css.ts new file mode 100644 index 0000000..f8d9a10 --- /dev/null +++ b/src/app/[...file]/components/types/error/error.css.ts @@ -0,0 +1,18 @@ +import { style } from '@vanilla-extract/css' + +export const error = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + width: '100%', + height: 'max-content', +}); + +export const message = style({ + fontSize: '2em', +}); + +export const sad = style({ + margin: '0em', + fontSize: '3em', +}) diff --git a/src/app/[...file]/components/types/error/error.tsx b/src/app/[...file]/components/types/error/error.tsx new file mode 100644 index 0000000..f00e2bf --- /dev/null +++ b/src/app/[...file]/components/types/error/error.tsx @@ -0,0 +1,13 @@ +import * as style from './error.css' + +const faces = [ + "(•́︵•̀)", + "(╥﹏╥)", +] + +export default function Error({ children }: { children }) { + return
+

{children}

+

{faces[Math.floor(Math.random() * faces.length)]}

+
+} diff --git a/src/app/[...file]/components/types/error/network.tsx b/src/app/[...file]/components/types/error/network.tsx index f8efcb9..e8b044c 100644 --- a/src/app/[...file]/components/types/error/network.tsx +++ b/src/app/[...file]/components/types/error/network.tsx @@ -1,3 +1,6 @@ +import Error from './error' + export default function NetworkError({ err }: { err: string }) { - return

{`Error: ${err}`}

; + console.err(err); + return Network Error; } diff --git a/src/app/[...file]/components/types/error/status.tsx b/src/app/[...file]/components/types/error/status.tsx new file mode 100644 index 0000000..977a3ba --- /dev/null +++ b/src/app/[...file]/components/types/error/status.tsx @@ -0,0 +1,23 @@ +import Error from './error' + +const statuses = { + [400]: "Bad Request", + [401]: "Unauthorized", + [402]: "Payment Required", + [403]: "Forbidden", + [404]: "Not Found", + [405]: "Method Not Allowed", + [500]: "Internal Server Error", + [501]: "Not Implemented", + [502]: "Bad Gateway", + [503]: "Service Unavailable", + [504]: "Gateway Timeout", + [505]: "HTTP Version Not Supported" +} +export default function StatusError({ status }: { status: number }) { + if (status in statuses) { + return {`${status} ${statuses[status as keyof typeof statuses]}`} + } else { + return {status} + } +} From d25edc1cb85d7c768fcc3bb31553345968f97876 Mon Sep 17 00:00:00 2001 From: Gnarwhal Date: Mon, 23 Sep 2024 18:59:55 +0000 Subject: [PATCH 2/8] Better loading (and some other misc cleanup) --- src/app/[...file]/components/content.tsx | 3 +- src/app/[...file]/components/copy.css.ts | 28 ++++++++--------- src/app/[...file]/components/loading.css.ts | 35 +++++++++++++++++++++ src/app/[...file]/components/loading.tsx | 9 ++++++ src/app/page.tsx | 1 - 5 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 src/app/[...file]/components/loading.css.ts create mode 100644 src/app/[...file]/components/loading.tsx diff --git a/src/app/[...file]/components/content.tsx b/src/app/[...file]/components/content.tsx index 986ed39..fd95921 100644 --- a/src/app/[...file]/components/content.tsx +++ b/src/app/[...file]/components/content.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react' +import Loading from './loading'; import ContentTypeError from './types/error/content_type'; import NetworkError from './types/error/network'; import StatusError from './types/error/status'; @@ -109,5 +110,5 @@ export default function Content({ src }: { src: string}) { } }); - return content ??

Loading...

; + return content ?? ; } diff --git a/src/app/[...file]/components/copy.css.ts b/src/app/[...file]/components/copy.css.ts index 9207e53..c6d8f84 100644 --- a/src/app/[...file]/components/copy.css.ts +++ b/src/app/[...file]/components/copy.css.ts @@ -10,20 +10,20 @@ export const copy = style({ }); export const copy_button = style({ - display: 'flex', - margin: 0, - border: 'none', - padding: 0, - outline: 'inherit', - fontFamily: 'monospace', - fontSize: '1.1em', - lineHeight: '2em', - color: 'inherit', - whiteSpace: 'pre-wrap', - transition: 'background-color 0.35s', - background: 'none', - width: 'max-content', - height: '100%', + display: 'flex', + margin: 0, + border: 'none', + padding: 0, + outline: 'inherit', + fontFamily: 'monospace', + fontSize: '1.1em', + lineHeight: '2em', + color: 'inherit', + whiteSpace: 'pre-wrap', + transition: 'background-color 0.35s', + background: 'none', + width: 'max-content', + height: '100%', ':hover': { backgroundColor: colors.background2, }, diff --git a/src/app/[...file]/components/loading.css.ts b/src/app/[...file]/components/loading.css.ts new file mode 100644 index 0000000..33f4ae6 --- /dev/null +++ b/src/app/[...file]/components/loading.css.ts @@ -0,0 +1,35 @@ +import { keyframes, style } from '@vanilla-extract/css'; + +import * as colors from '../../colors.css'; + +export const loading_squares = style({ + display: 'flex', + justifyContent: 'center', + width: '100%', + marginTop: '4em', + height: 'max-content', +}); + +const animation = keyframes({ + '0%': { backgroundColor: colors.background2 }, + '50%': { backgroundColor: colors.foreground }, + '100%': { backgroundColor: colors.background2 }, +}); + +export const square = style({ + margin: '0 1em', + width: '1em', + height: '1em', + backgroundColor: colors.background2, + animationName: animation, + animationDuration: '2s', + animationIterationCount: 'infinite', +}); + +export const loading = [0, 1, 2, 3, 4].map(index => + style([square, { + animationDelay: `${0.2 * index}s` + }]) +); + + diff --git a/src/app/[...file]/components/loading.tsx b/src/app/[...file]/components/loading.tsx new file mode 100644 index 0000000..730c431 --- /dev/null +++ b/src/app/[...file]/components/loading.tsx @@ -0,0 +1,9 @@ +import * as style from './loading.css'; + +export default function Loading() { + return ( +
+ {style.loading.map((style, index) =>
)} +
+ ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 0d40e07..69d19c4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,7 +2,6 @@ import * as style from './page.css'; export default function App() { const supports_repointing = process.env.ENABLE_REPOINTING == 'true'; - console.log(supports_repointing); return (
From a7d55d94a4b3d01d201beafca8188fc57d9e27e8 Mon Sep 17 00:00:00 2001 From: Gnarwhal Date: Mon, 23 Sep 2024 19:04:51 +0000 Subject: [PATCH 3/8] Cleanup README.md --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d5bbb3e..108539c 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,12 @@ Motto presents files from a static file server in a more friendly way ### Configuration -- `ROOT_URL=(url)` - the static file server instance to get files from -- `ENABLE_REPOINTING=(true|default:false)` - enable [repointing](#Repointing) +Configuration is done through environment variables in `.env.local` + +| Variable | type | default | description | +|--------------------|---------|---------|---------------------------------------------------| +| `ROOT_URL` | string | N/A | the static file server instance to get files from | +|`ENABLE_REPOINTING` | boolean | `false` | enable [repointing](#Repointing) | ### Repointing From 8ec4c959846a46c0ccde8e6f9b305ef343b61be0 Mon Sep 17 00:00:00 2001 From: Gnarwhal Date: Mon, 23 Sep 2024 19:16:08 +0000 Subject: [PATCH 4/8] Make copy text monospace --- src/app/[...file]/components/copy.css.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/[...file]/components/copy.css.ts b/src/app/[...file]/components/copy.css.ts index c6d8f84..884b659 100644 --- a/src/app/[...file]/components/copy.css.ts +++ b/src/app/[...file]/components/copy.css.ts @@ -79,7 +79,9 @@ export const copied_image_light = style([copy_image, { export const copy_text = style({ - margin: 0, + margin: 0, marginLeft: '1em', - width: 'max-content', + width: 'max-content', + fontFamily: 'monospace', + fontSize: '1.2em', }); From bf6709e2fd7f005e7aad776e4bd6cc7bb3a2400b Mon Sep 17 00:00:00 2001 From: Gnarwhal Date: Mon, 23 Sep 2024 18:23:19 +0000 Subject: [PATCH 5/8] Better error pages --- src/app/[...file]/components/content.tsx | 23 +++++++++++-------- .../components/types/error/content_type.tsx | 4 +++- .../components/types/error/error.css.ts | 18 +++++++++++++++ .../components/types/error/error.tsx | 13 +++++++++++ .../components/types/error/network.tsx | 5 +++- .../components/types/error/status.tsx | 23 +++++++++++++++++++ 6 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 src/app/[...file]/components/types/error/error.css.ts create mode 100644 src/app/[...file]/components/types/error/error.tsx create mode 100644 src/app/[...file]/components/types/error/status.tsx diff --git a/src/app/[...file]/components/content.tsx b/src/app/[...file]/components/content.tsx index b2a2118..986ed39 100644 --- a/src/app/[...file]/components/content.tsx +++ b/src/app/[...file]/components/content.tsx @@ -2,8 +2,9 @@ import { useState, useEffect } from 'react' -import NetworkError from './types/error/network'; import ContentTypeError from './types/error/content_type'; +import NetworkError from './types/error/network'; +import StatusError from './types/error/status'; import ImageContent from './types/image'; import MarkdownContent from './types/markdown'; import Terminal from './types/terminal'; @@ -86,17 +87,21 @@ export default function Content({ src }: { src: string}) { if (content == undefined) { const result = fetch(src) .then(response => { - for (const type of recognized_types) { - if (is_type(response, type)) { - const emitted = type.emit(); - if (emitted != undefined) { - result.then(emitted.postprocess); - return emitted.process(response); + if (response.status < 400) { + for (const type of recognized_types) { + if (is_type(response, type)) { + const emitted = type.emit(); + if (emitted != undefined) { + result.then(emitted.postprocess); + return emitted.process(response); + } + return; } - return; } + set_content(); + } else { + set_content(); } - set_content(); }) .catch(err => { set_content(); diff --git a/src/app/[...file]/components/types/error/content_type.tsx b/src/app/[...file]/components/types/error/content_type.tsx index 84c9b29..7c50ccd 100644 --- a/src/app/[...file]/components/types/error/content_type.tsx +++ b/src/app/[...file]/components/types/error/content_type.tsx @@ -1,3 +1,5 @@ +import Error from './error' + export default function ContentTypeError({ content_type }: { content_type: string }) { - return

{`Unrecognised MIME type: ${content_type}`}

+ return {`Unrecognised MIME type: ${content_type}`} } diff --git a/src/app/[...file]/components/types/error/error.css.ts b/src/app/[...file]/components/types/error/error.css.ts new file mode 100644 index 0000000..f8d9a10 --- /dev/null +++ b/src/app/[...file]/components/types/error/error.css.ts @@ -0,0 +1,18 @@ +import { style } from '@vanilla-extract/css' + +export const error = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + width: '100%', + height: 'max-content', +}); + +export const message = style({ + fontSize: '2em', +}); + +export const sad = style({ + margin: '0em', + fontSize: '3em', +}) diff --git a/src/app/[...file]/components/types/error/error.tsx b/src/app/[...file]/components/types/error/error.tsx new file mode 100644 index 0000000..90bd2cd --- /dev/null +++ b/src/app/[...file]/components/types/error/error.tsx @@ -0,0 +1,13 @@ +import * as style from './error.css' + +const faces = [ + "(•́︵•̀)", + "(╥﹏╥)", +] + +export default function Error({ children }: { children: React.ReactNode }) { + return
+

{children}

+

{faces[Math.floor(Math.random() * faces.length)]}

+
+} diff --git a/src/app/[...file]/components/types/error/network.tsx b/src/app/[...file]/components/types/error/network.tsx index f8efcb9..376c755 100644 --- a/src/app/[...file]/components/types/error/network.tsx +++ b/src/app/[...file]/components/types/error/network.tsx @@ -1,3 +1,6 @@ +import Error from './error' + export default function NetworkError({ err }: { err: string }) { - return

{`Error: ${err}`}

; + console.error(err); + return Network Error; } diff --git a/src/app/[...file]/components/types/error/status.tsx b/src/app/[...file]/components/types/error/status.tsx new file mode 100644 index 0000000..977a3ba --- /dev/null +++ b/src/app/[...file]/components/types/error/status.tsx @@ -0,0 +1,23 @@ +import Error from './error' + +const statuses = { + [400]: "Bad Request", + [401]: "Unauthorized", + [402]: "Payment Required", + [403]: "Forbidden", + [404]: "Not Found", + [405]: "Method Not Allowed", + [500]: "Internal Server Error", + [501]: "Not Implemented", + [502]: "Bad Gateway", + [503]: "Service Unavailable", + [504]: "Gateway Timeout", + [505]: "HTTP Version Not Supported" +} +export default function StatusError({ status }: { status: number }) { + if (status in statuses) { + return {`${status} ${statuses[status as keyof typeof statuses]}`} + } else { + return {status} + } +} From 3eb11d3aebe3e63b47dc620b2620106994468f7b Mon Sep 17 00:00:00 2001 From: Gnarwhal Date: Mon, 23 Sep 2024 18:59:55 +0000 Subject: [PATCH 6/8] Better loading (and some other misc cleanup) --- src/app/[...file]/components/content.tsx | 3 +- src/app/[...file]/components/copy.css.ts | 28 ++++++++--------- src/app/[...file]/components/loading.css.ts | 35 +++++++++++++++++++++ src/app/[...file]/components/loading.tsx | 9 ++++++ src/app/page.tsx | 1 - 5 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 src/app/[...file]/components/loading.css.ts create mode 100644 src/app/[...file]/components/loading.tsx diff --git a/src/app/[...file]/components/content.tsx b/src/app/[...file]/components/content.tsx index 986ed39..fd95921 100644 --- a/src/app/[...file]/components/content.tsx +++ b/src/app/[...file]/components/content.tsx @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react' +import Loading from './loading'; import ContentTypeError from './types/error/content_type'; import NetworkError from './types/error/network'; import StatusError from './types/error/status'; @@ -109,5 +110,5 @@ export default function Content({ src }: { src: string}) { } }); - return content ??

Loading...

; + return content ?? ; } diff --git a/src/app/[...file]/components/copy.css.ts b/src/app/[...file]/components/copy.css.ts index 9207e53..c6d8f84 100644 --- a/src/app/[...file]/components/copy.css.ts +++ b/src/app/[...file]/components/copy.css.ts @@ -10,20 +10,20 @@ export const copy = style({ }); export const copy_button = style({ - display: 'flex', - margin: 0, - border: 'none', - padding: 0, - outline: 'inherit', - fontFamily: 'monospace', - fontSize: '1.1em', - lineHeight: '2em', - color: 'inherit', - whiteSpace: 'pre-wrap', - transition: 'background-color 0.35s', - background: 'none', - width: 'max-content', - height: '100%', + display: 'flex', + margin: 0, + border: 'none', + padding: 0, + outline: 'inherit', + fontFamily: 'monospace', + fontSize: '1.1em', + lineHeight: '2em', + color: 'inherit', + whiteSpace: 'pre-wrap', + transition: 'background-color 0.35s', + background: 'none', + width: 'max-content', + height: '100%', ':hover': { backgroundColor: colors.background2, }, diff --git a/src/app/[...file]/components/loading.css.ts b/src/app/[...file]/components/loading.css.ts new file mode 100644 index 0000000..33f4ae6 --- /dev/null +++ b/src/app/[...file]/components/loading.css.ts @@ -0,0 +1,35 @@ +import { keyframes, style } from '@vanilla-extract/css'; + +import * as colors from '../../colors.css'; + +export const loading_squares = style({ + display: 'flex', + justifyContent: 'center', + width: '100%', + marginTop: '4em', + height: 'max-content', +}); + +const animation = keyframes({ + '0%': { backgroundColor: colors.background2 }, + '50%': { backgroundColor: colors.foreground }, + '100%': { backgroundColor: colors.background2 }, +}); + +export const square = style({ + margin: '0 1em', + width: '1em', + height: '1em', + backgroundColor: colors.background2, + animationName: animation, + animationDuration: '2s', + animationIterationCount: 'infinite', +}); + +export const loading = [0, 1, 2, 3, 4].map(index => + style([square, { + animationDelay: `${0.2 * index}s` + }]) +); + + diff --git a/src/app/[...file]/components/loading.tsx b/src/app/[...file]/components/loading.tsx new file mode 100644 index 0000000..730c431 --- /dev/null +++ b/src/app/[...file]/components/loading.tsx @@ -0,0 +1,9 @@ +import * as style from './loading.css'; + +export default function Loading() { + return ( +
+ {style.loading.map((style, index) =>
)} +
+ ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 0d40e07..69d19c4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -2,7 +2,6 @@ import * as style from './page.css'; export default function App() { const supports_repointing = process.env.ENABLE_REPOINTING == 'true'; - console.log(supports_repointing); return (
From 9b3f590becbdc24f2eeaab98e395725393dd7984 Mon Sep 17 00:00:00 2001 From: Gnarwhal Date: Mon, 23 Sep 2024 19:04:51 +0000 Subject: [PATCH 7/8] Cleanup README.md --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d5bbb3e..108539c 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,12 @@ Motto presents files from a static file server in a more friendly way ### Configuration -- `ROOT_URL=(url)` - the static file server instance to get files from -- `ENABLE_REPOINTING=(true|default:false)` - enable [repointing](#Repointing) +Configuration is done through environment variables in `.env.local` + +| Variable | type | default | description | +|--------------------|---------|---------|---------------------------------------------------| +| `ROOT_URL` | string | N/A | the static file server instance to get files from | +|`ENABLE_REPOINTING` | boolean | `false` | enable [repointing](#Repointing) | ### Repointing From 6d17d0b954924464c1cdfaabfa23280309c977b1 Mon Sep 17 00:00:00 2001 From: Gnarwhal Date: Mon, 23 Sep 2024 19:16:08 +0000 Subject: [PATCH 8/8] Make copy text monospace --- src/app/[...file]/components/copy.css.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app/[...file]/components/copy.css.ts b/src/app/[...file]/components/copy.css.ts index c6d8f84..884b659 100644 --- a/src/app/[...file]/components/copy.css.ts +++ b/src/app/[...file]/components/copy.css.ts @@ -79,7 +79,9 @@ export const copied_image_light = style([copy_image, { export const copy_text = style({ - margin: 0, + margin: 0, marginLeft: '1em', - width: 'max-content', + width: 'max-content', + fontFamily: 'monospace', + fontSize: '1.2em', });