breadcrumbs con titulo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

esta implementación es muy cursed
This commit is contained in:
Cat /dev/Nulo 2023-08-29 21:47:02 -03:00
parent b316680114
commit 077ea1af56
3 changed files with 73 additions and 3 deletions

View file

@ -1,5 +1,12 @@
import type { Readable } from "svelte/store";
import type { Doc, Transaction } from "yjs";
import {
derived,
type Readable,
type Subscriber,
type Unsubscriber,
} from "svelte/store";
import type { Doc, Transaction, XmlFragment } from "yjs";
import { loadWorlds, worldsStore } from "./worldStorage";
import { getWorldPage, getWorldY } from "./doc";
export function makeYdocStore<T>(
handler: (
@ -32,3 +39,37 @@ export function makeYdocStore<T>(
};
};
}
export function ydocStore(ydoc: Doc): Readable<{
update: Uint8Array | null;
origin: any;
ydoc: Doc;
tr: Transaction | null;
}> {
return {
subscribe(run) {
run({ update: null, ydoc, tr: null, origin: null });
const cb = (update: any, origin: any, ydoc: any, tr: any) =>
run({ update, origin, ydoc, tr });
ydoc.on("update", cb);
return () => {
ydoc.off("update", cb);
};
},
};
}
export function pageStore(
worldId: string,
pageId: string,
): Readable<{ doc: Doc; frag: XmlFragment }> {
return derived([worldsStore], ([$worlds], set) => {
const world = $worlds?.find((w) => w.room === worldId);
if (!world) return;
const ydoc = getWorldY(world);
const ydocS = ydocStore(ydoc.ydoc);
return derived([ydocS], ([{ ydoc }]) => {
return getWorldPage(ydoc, pageId);
}).subscribe((frag) => set({ doc: ydoc.ydoc, frag }));
});
}

View file

@ -1,7 +1,10 @@
import type { Readable, Subscriber } from "svelte/store";
import { getWorldY, type WorldIdentifier } from "./doc";
const localStorageKey = "schreiben-worlds";
let subs: Subscriber<WorldIdentifier[]>[] = [];
export function loadWorlds(): Promise<WorldIdentifier[]> {
let json = localStorage.getItem(localStorageKey);
if (!json) json = "[]";
@ -19,5 +22,14 @@ export async function writeWorlds(
const oldWorlds = await loadWorlds();
const newWorlds = callback(oldWorlds);
localStorage.setItem(localStorageKey, JSON.stringify(newWorlds));
for (const sub of subs) sub(newWorlds);
return newWorlds;
}
export const worldsStore: Readable<WorldIdentifier[]> = {
subscribe(run) {
subs.push(run);
loadWorlds().then(run);
return () => (subs = subs.filter((s) => s !== run));
},
};

View file

@ -7,11 +7,27 @@
import { routes } from "../lib/routes";
import { loadWorlds } from "../lib/worldStorage";
import breadcrumbs from "../lib/breadcrumbs";
import { pageStore } from "../lib/makeYdocStore";
import { derived } from "svelte/store";
import { getTitle } from "../lib/getTitle";
export let worldId: string;
export let pageId: string;
$: pageBreadcrumbs = breadcrumbs.worldStore(worldId);
$: crumbsTitles = derived(
[pageBreadcrumbs],
([crumbs], set: (val: (string | undefined)[]) => void) => {
return derived(
crumbs.map((c) => pageStore(worldId, c)),
(crumbPages) =>
crumbPages.map(
(x, index) =>
x && x.doc && getTitle(x.doc, `page/${crumbs[index]}`),
),
).subscribe(set);
},
);
async function loadDoc(
worldId: string,
@ -63,7 +79,8 @@
<a
href={inject(routes.Page, { worldId, pageId: crumb })}
class="inline-flex items-center py-1 font-normal hover:text-neutral-900 focus:outline-none"
class:active-breadcrumb={crumb === pageId}>{crumb}</a
class:active-breadcrumb={crumb === pageId}
>{$crumbsTitles[index] || crumb}</a
>
</li>
{#if index !== $pageBreadcrumbs.length - 1}