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
diff --git a/src/app/[...file]/components/content.tsx b/src/app/[...file]/components/content.tsx
index b2a2118..fd95921 100644
--- a/src/app/[...file]/components/content.tsx
+++ b/src/app/[...file]/components/content.tsx
@@ -2,8 +2,10 @@
import { useState, useEffect } from 'react'
-import NetworkError from './types/error/network';
+import Loading from './loading';
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 +88,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();
@@ -104,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..884b659 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,
},
@@ -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',
});
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/[...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}
+ }
+}
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 (