enprogreso/src/doc.ts

104 lines
3 KiB
TypeScript

import * as Y from "yjs";
import { WebrtcProvider } from "y-webrtc";
import { IndexeddbPersistence } from "y-indexeddb";
import { syncedStore, getYjsDoc } from "@syncedstore/core";
import { svelteSyncedStore } from "@syncedstore/svelte";
import { nanoid } from "nanoid";
import type { MappedTypeDescription } from "@syncedstore/core/types/doc";
export type UserIdentifier = {
room: string;
password: string;
};
type SyncedStoreType = MappedTypeDescription<{
doing: Doing[];
done: Done[];
name: Y.Text;
}>;
export type UserY = {
// ydoc: Y.Doc;
webrtcProvider: WebrtcProvider;
store: SyncedStoreType;
svelteStore: ReturnType<typeof svelteSyncedStore<SyncedStoreType>>;
};
export function createUser(): UserIdentifier {
return {
room: nanoid(),
password: nanoid(),
};
}
export function parseUser(id: string): UserIdentifier {
const [room, password] = id.split(";");
return { room, password };
}
// when creating a webrtc provider for a second time in the same room, it freaks out.
// cache the previous doc and return that instead
let userYCache: { [key: string]: UserY } = {};
window.userYCache = userYCache;
const credsReq = fetch(
"https://nulo.metered.live/api/v1/turn/credentials?apiKey=205de2914a8564e2efa19a7d7f299a95e574"
).then((res) => res.json());
export function getUserY(world: UserIdentifier): UserY {
if (userYCache[world.room]) return userYCache[world.room];
const store = syncedStore({
doing: [] as Doing[],
done: [] as Done[],
name: "text",
});
const svelteStore = svelteSyncedStore(store);
const ydoc = getYjsDoc(store);
const provider = new WebrtcProvider(world.room, ydoc, {
password: world.password,
signaling: [
"wss://webrtc-signaling.schreiben.nulo.ar",
"wss://y-webrtc-eu.fly.dev",
// "wss://signaling.yjs.dev",
// "wss://y-webrtc-signaling-eu.herokuapp.com",
// "wss://y-webrtc-signaling-us.herokuapp.com",
],
});
credsReq.then((iceServers) => {
// change the default for future connections
provider.peerOpts.config = { iceServers };
if (!provider.room?.webrtcConns) return;
// change the configuration in current connections
for (const conn of provider.room?.webrtcConns?.values()) {
const pc: RTCPeerConnection = conn.peer._pc;
pc.setConfiguration({
iceServers,
});
}
});
const idbProvider = new IndexeddbPersistence(world.room, ydoc);
const worldY = { webrtcProvider: provider, store, svelteStore };
userYCache[world.room] = worldY;
return worldY;
}
// export function getWorldPage(ydoc: Y.Doc, pageId: string): Y.XmlFragment {
// return ydoc.getXmlFragment(`page/${pageId}`);
// }
export type Doing = {
description: string;
started: number;
};
export type Done = {
description: string;
started: number;
took: number;
};
// export function getData(userY: UserY) {
// const ydoing: Y.Array<Doing> = userY.ydoc.getArray("doing");
// const ydone: Y.Array<Done> = userY.ydoc.getArray("done");
// const yname: Y.Text = userY.ydoc.getText("name");
// return { ydoing, ydone, yname };
// }