diff --git a/src/components/WorldLink.svelte b/src/components/WorldLink.svelte new file mode 100644 index 0000000..204997a --- /dev/null +++ b/src/components/WorldLink.svelte @@ -0,0 +1,18 @@ + + +{$title || world.room} diff --git a/src/lib/getTitle.js b/src/lib/getTitle.js new file mode 100644 index 0000000..1af3fac --- /dev/null +++ b/src/lib/getTitle.js @@ -0,0 +1,26 @@ +import { yDocToProsemirrorJSON } from "y-prosemirror"; +import { Node } from "prosemirror-model"; +import { schema } from "../editor/schema"; + +/** + * @param {import("yjs").Doc} ydoc + * @param {string} name + * @returns {string=} + */ +export function getTitle(ydoc, name) { + const json = yDocToProsemirrorJSON(ydoc, name); + const node = Node.fromJSON(schema, json); + /** @type {any} */ + let titleNode = null; + node.descendants((node) => { + if (titleNode) return false; + if (node.type.name === "heading" && node.attrs.level === 1) { + titleNode = node; + return false; + } + }); + if (titleNode) { + // prettier-ignore + return /** @type {Node} */(titleNode).textContent; + } +} diff --git a/src/lib/titleStore.js b/src/lib/titleStore.js new file mode 100644 index 0000000..012c180 --- /dev/null +++ b/src/lib/titleStore.js @@ -0,0 +1,32 @@ +import { getTitle } from "./getTitle.js"; +import { makeYdocStore } from "./makeYdocStore"; + +/** + * @param {import("yjs").Doc} ydoc + * @param {string} id + * @returns {import("svelte/store").Readable} + */ +export function titleStore(ydoc, id) { + /** @type {(() => void) | null } */ + let observer = null; + /** @type {import("yjs").AbstractType | null} */ + let y = null; + + /** @type {string|null} */ + let title = null; + + return makeYdocStore( + (_, __, ydoc) => { + const setTitle = () => (title = getTitle(ydoc, id) || null); + if (!y) { + setTitle(); + y = ydoc.getXmlFragment(id); + observer = setTitle; + y.observeDeep(observer); + } + + return title; + }, + () => observer && y?.unobserveDeep(observer) + )(ydoc); +} diff --git a/src/lib/worldStorage.ts b/src/lib/worldStorage.ts index cc9770d..c4662df 100644 --- a/src/lib/worldStorage.ts +++ b/src/lib/worldStorage.ts @@ -1,11 +1,16 @@ -import type { WorldIdentifier } from "./doc"; +import { getWorldY, type WorldIdentifier } from "./doc"; const localStorageKey = "schreiben-worlds"; export function loadWorlds(): Promise { let json = localStorage.getItem(localStorageKey); if (!json) json = "[]"; - return Promise.resolve(JSON.parse(json)); + const worlds = JSON.parse(json); + for (const world of worlds) { + // empezar a cargar el Ydoc + getWorldY(world); + } + return Promise.resolve(worlds); } export async function writeWorlds( diff --git a/src/views/ChooseWorld.svelte b/src/views/ChooseWorld.svelte index e7e949a..a314486 100644 --- a/src/views/ChooseWorld.svelte +++ b/src/views/ChooseWorld.svelte @@ -2,6 +2,7 @@ import { inject } from "regexparam"; import { loadWorlds } from "../lib/worldStorage"; import { routes } from "../lib/routes"; + import WorldLink from "../components/WorldLink.svelte"; const worldsPromise = loadWorlds(); @@ -13,12 +14,7 @@