guesstimate/client/src/hooks/use-server-sync.ts

57 lines
1.4 KiB
TypeScript

import { Project } from "../models/project";
import { usePrevious } from "./use-previous";
import * as jsonpatch from 'fast-json-patch';
import { useEffect, useState } from "preact/hooks";
import { Operation } from "fast-json-patch";
export interface ServerSyncOptions {
baseUrl: string
}
export const defaultOptions = {
baseUrl: `ws://${window.location.host}/ws`,
}
export function useServerSync(project: Project, options: ServerSyncOptions = defaultOptions) {
options = Object.assign({}, defaultOptions, options);
const [ conn, setConn ] = useState<WebSocket>(() => {
const conn = new WebSocket(`${options.baseUrl}/${project.id}`);
conn.onerror = (evt: Event) => {
console.error(evt);
};
conn.onopen = (evt: Event) => {
console.log('ws connection opened');
};
return conn;
});
const [ ops, setOps ] = useState<Operation[][]>([]);
useEffect(() => {
return () => {
if (!conn) return;
console.log('closing ws');
conn.close();
conn.onerror = null;
conn.onopen = null;
};
}, []);
useEffect(() => {
conn.send(JSON.stringify(ops));
setOps([]);
}, [ops.length > 0]);
let previousProject: Project|any = usePrevious(project);
if (!previousProject) previousProject = {};
const newOps = jsonpatch.compare(previousProject, project);
if (ops.length === 0) return;
setOps(ops => [...ops, newOps]);
}