import * as decoding from "lib0/decoding";
import * as encoding from "lib0/encoding";
import * as awarenessProtocol from "y-protocols/awareness";
import * as syncProtocol from "y-protocols/sync";
import * as Y from "yjs";
import {
CLOSE_DOWNGRADED,
CLOSE_REAUTH,
CLOSE_REVOKED,
EDITOR_WS_PROTOCOL,
FILES_MAP,
MESSAGE_AWARENESS,
MESSAGE_SYNC,
textKey,
} from "../lib/editor-protocol";
import type { ClientControl, FileMeta, RoomControl } from "../lib/editor-protocol";
export type RoomEvents = {
onControl(message: RoomControl): void;
onState(state: "connecting" | "online" | "offline" | "revoked"): void;
/** Asked for a fresh token after the current one expired or write access changed. */
refreshToken(): Promise<string>;
};
const MIN_BACKOFF_MS = 500;
const MAX_BACKOFF_MS = 10_000;
const OPEN_TIMEOUT_MS = 15_000;
/**
* Yjs client for the EditorRoom: one Y.Doc for the whole branch, y-protocols sync and awareness over a
* single WebSocket, reconnecting with backoff. Edits made while offline merge on reconnect (CRDT).
*/
export class RoomClient {
readonly doc = new Y.Doc();
readonly awareness = new awarenessProtocol.Awareness(this.doc);
readonly files: Y.Map<FileMeta> = this.doc.getMap<FileMeta>(FILES_MAP);
writable = false;
head = "";
private socket: WebSocket | null = null;
private backoff = MIN_BACKOFF_MS;