1
0
Fork 0
mirror of https://github.com/kou029w/quot.git synced 2025-03-10 08:25:19 +00:00

Compare commits

..

No commits in common. "86afc69f5665e4a537c11f9c1b51933f56a07113" and "cd012683057af51529e2a8d8d2b1b00f0a814d65" have entirely different histories.

7 changed files with 36 additions and 122 deletions

View file

@ -1,7 +1,7 @@
header { header {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-evenly; justify-content: space-evenly
} }
a[href^="/"] { a[href^="/"] {

View file

@ -1,21 +1,14 @@
import type Pages from "../protocol/pages";
import "./editor.css"; import "./editor.css";
export default (props: { export default () => (
id: number;
onUpdatePage: (content: Pages.RequestContentPage) => void;
}) => {
return (
<textarea <textarea
id={String(props.id)}
class="editor" class="editor"
autofocus autofocus
onInput={(e) => { onInput={(e) => {
const text = e.currentTarget.value; e.currentTarget.setAttribute(
const lines = text.split("\n"); "rows",
props.onUpdatePage({ id: props.id, title: lines[0] ?? "", text }); String(Math.max(2, e.currentTarget.value.split("\n").length))
e.currentTarget.setAttribute("rows", String(Math.max(2, lines.length))); );
}} }}
></textarea> ></textarea>
); );
};

View file

@ -1,18 +0,0 @@
function beforeunload() {
function listener(e: BeforeUnloadEvent) {
e.preventDefault();
e.returnValue = "";
}
function block() {
window.addEventListener("beforeunload", listener);
}
function unblock() {
window.removeEventListener("beforeunload", listener);
}
return { block, unblock };
}
export default beforeunload;

View file

@ -1,21 +0,0 @@
function throttle<Fn extends (...args: any[]) => any>(
fn: Fn,
ms: number
): (...args: Parameters<Fn>) => void {
let throttledFn = () => undefined;
let throttled: boolean = false;
return (...args: Parameters<Fn>): void => {
throttledFn = () => fn(...args);
if (throttled) return;
setTimeout(() => {
throttledFn();
throttled = false;
}, ms);
throttled = true;
};
}
export default throttle;

View file

@ -1,12 +1,19 @@
import { createResource } from "solid-js"; import { createResource } from "solid-js";
import type Pages from "../protocol/pages";
async function fetchPages(): Promise<Pages.Response> { type PagesResponse = Array<{
id: number;
title: string;
text: string;
created: string;
updated: string;
}>;
async function fetchPages(): Promise<PagesResponse> {
const res = await fetch( const res = await fetch(
new URL("/pages?order=updated.desc", import.meta.env.QUOT_API_URL) new URL("/pages?order=updated.desc", import.meta.env.QUOT_API_URL)
); );
const data = (await res.json()) as Pages.Response; const data = await res.json();
return data; return data as PagesResponse;
} }
export default () => { export default () => {

View file

@ -1,55 +1,28 @@
import { createResource } from "solid-js"; import { createResource } from "solid-js";
import type Pages from "../protocol/pages";
import Editor from "../components/editor"; import Editor from "../components/editor";
import beforeunload from "../helpers/beforeunload";
import throttle from "../helpers/throttle";
const intervalMs = 333; type PageResponse = {
const { block, unblock } = beforeunload(); id: number;
title: string;
text: string;
created: string;
updated: string;
};
async function updatePage( async function fetchPage(id: number): Promise<PageResponse> {
id: number,
content: Pages.RequestContentPage
): Promise<boolean> {
const res = await fetch(
new URL(`/pages?id=eq.${id}`, import.meta.env.QUOT_API_URL),
{
method: "PUT",
headers: { "content-type": "application/json" },
body: JSON.stringify(content),
}
);
return res.ok;
}
async function fetchPage(id: number): Promise<Pages.RequestContentPage> {
const res = await fetch( const res = await fetch(
new URL(`/pages?id=eq.${id}`, import.meta.env.QUOT_API_URL) new URL(`/pages?id=eq.${id}`, import.meta.env.QUOT_API_URL)
); );
const data = (await res.json()) as Pages.Response; const [data] = await res.json();
return data[0]!; return data as PageResponse;
} }
export default (props: { id: number }) => { export default (props: { id: number }) => {
const [page, { refetch }] = createResource(props.id, fetchPage); const [page] = createResource(props.id, fetchPage);
const throttledUpdate = throttle(
async (id: number, content: Pages.RequestContentPage) => {
if (await updatePage(id, content)) {
unblock();
refetch();
}
},
intervalMs
);
function onUpdatePage(content: Pages.RequestContentPage) {
block();
throttledUpdate(props.id, content);
}
return ( return (
<main> <main>
<Editor id={props.id} onUpdatePage={onUpdatePage} /> <Editor />
<pre>{() => JSON.stringify(page(), null, " ")}</pre> <pre>{() => JSON.stringify(page(), null, " ")}</pre>
</main> </main>
); );

View file

@ -1,20 +0,0 @@
namespace Pages {
export type RequestContentPage = {
id?: number;
title: string;
text: string;
};
export type ResponsePage = {
id: number;
title: string;
text: string;
created: string;
updated: string;
};
export type RequestContent = Array<RequestContentPage>;
export type Response = Array<ResponsePage>;
}
export default Pages;