104 lines
3 KiB
TypeScript
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 };
|
|
// }
|