mostrar titulo de mundo en index (fixes #3)
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
This commit is contained in:
parent
56d8aca9b0
commit
73381b0dd7
5 changed files with 85 additions and 8 deletions
18
src/components/WorldLink.svelte
Normal file
18
src/components/WorldLink.svelte
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<script>
|
||||||
|
import { inject } from "regexparam";
|
||||||
|
import { getWorldY } from "../lib/doc";
|
||||||
|
import { titleStore } from "../lib/titleStore";
|
||||||
|
import { routes } from "../lib/routes";
|
||||||
|
|
||||||
|
/** @type {import("../lib/doc").WorldIdentifier} */
|
||||||
|
export let world;
|
||||||
|
|
||||||
|
$: title = titleStore(getWorldY(world).ydoc, "page/index");
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<a
|
||||||
|
href={inject(routes.Page, {
|
||||||
|
worldId: world.room,
|
||||||
|
pageId: "index",
|
||||||
|
})}>{$title || world.room}</a
|
||||||
|
>
|
26
src/lib/getTitle.js
Normal file
26
src/lib/getTitle.js
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
32
src/lib/titleStore.js
Normal file
32
src/lib/titleStore.js
Normal file
|
@ -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<string | null>}
|
||||||
|
*/
|
||||||
|
export function titleStore(ydoc, id) {
|
||||||
|
/** @type {(() => void) | null } */
|
||||||
|
let observer = null;
|
||||||
|
/** @type {import("yjs").AbstractType<any> | 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);
|
||||||
|
}
|
|
@ -1,11 +1,16 @@
|
||||||
import type { WorldIdentifier } from "./doc";
|
import { getWorldY, type WorldIdentifier } from "./doc";
|
||||||
|
|
||||||
const localStorageKey = "schreiben-worlds";
|
const localStorageKey = "schreiben-worlds";
|
||||||
|
|
||||||
export function loadWorlds(): Promise<WorldIdentifier[]> {
|
export function loadWorlds(): Promise<WorldIdentifier[]> {
|
||||||
let json = localStorage.getItem(localStorageKey);
|
let json = localStorage.getItem(localStorageKey);
|
||||||
if (!json) json = "[]";
|
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(
|
export async function writeWorlds(
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { inject } from "regexparam";
|
import { inject } from "regexparam";
|
||||||
import { loadWorlds } from "../lib/worldStorage";
|
import { loadWorlds } from "../lib/worldStorage";
|
||||||
import { routes } from "../lib/routes";
|
import { routes } from "../lib/routes";
|
||||||
|
import WorldLink from "../components/WorldLink.svelte";
|
||||||
|
|
||||||
const worldsPromise = loadWorlds();
|
const worldsPromise = loadWorlds();
|
||||||
</script>
|
</script>
|
||||||
|
@ -13,12 +14,7 @@
|
||||||
<ul>
|
<ul>
|
||||||
{#each worlds as world}
|
{#each worlds as world}
|
||||||
<li>
|
<li>
|
||||||
<a
|
<WorldLink {world} />
|
||||||
href={inject(routes.Page, {
|
|
||||||
worldId: world.room,
|
|
||||||
pageId: "index",
|
|
||||||
})}>{world.room}</a
|
|
||||||
>
|
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
<li><a href={routes.CreateWorld}>Crear mundo</a></li>
|
<li><a href={routes.CreateWorld}>Crear mundo</a></li>
|
||||||
|
|
Loading…
Reference in a new issue