Rebasely Beta: data may be purged

examples/live-notes Public

TypeScript · 72 lines · 2.3 KiB · at bd4f325

// The editor page: a textarea bound to one note over a WebSocket. The note id comes from the// URL fragment, so /#groceries edits the note "groceries".import { Session, moveCaret } from "./session.ts";import type { ServerMessage } from "../src/protocol.ts";const NOTE_ID = /^[A-Za-z0-9_-]{1,64}$/;const area = document.querySelector<HTMLTextAreaElement>("#note")!;const status = document.querySelector<HTMLElement>("#status")!;const title = document.querySelector<HTMLElement>("#title")!;function noteId(): string {  const id = decodeURIComponent(location.hash.slice(1));  return NOTE_ID.test(id) ? id : "scratch";}let socket: WebSocket | null = null;let retry = 0;function connect(): void {  const id = noteId();  title.textContent = id;  document.title = `${id} · live-notes`;  area.disabled = true;  status.textContent = "Connecting";  const scheme = location.protocol === "https:" ? "wss" : "ws";  const ws = new WebSocket(`${scheme}://${location.host}/notes/${encodeURIComponent(id)}/ws`);  const session = new Session((msg) => ws.send(JSON.stringify(msg)));  socket = ws;  ws.addEventListener("message", (event) => {    const msg = JSON.parse(String(event.data)) as ServerMessage;    const { selectionStart, selectionEnd } = area;    const applied = session.receive(msg);    if (applied === "reset") {      area.value = session.text;      area.disabled = false;      area.focus();      retry = 0;      status.textContent = msg.type === "snapshot" && msg.reason ? `Edit undone: ${msg.reason}` : `Version ${session.version}`;    } else if (applied) {      area.value = session.text;      area.setSelectionRange(moveCaret(selectionStart, applied), moveCaret(selectionEnd, applied));    }    if (msg.type !== "snapshot") status.textContent = session.pending ? "Saving" : `Version ${session.version}`;  });  area.oninput = () => {    session.edit(area.value);    status.textContent = "Saving";  };  ws.addEventListener("close", () => {    if (socket !== ws) return;    area.disabled = true;    // Back off to at most 10 seconds between attempts.    const wait = Math.min(10_000, 500 * 2 ** retry++);    status.textContent = "Offline, reconnecting";    setTimeout(connect, wait);  });}window.addEventListener("hashchange", () => {  const old = socket;  socket = null;  old?.close();  connect();});connect();