57 lines
1.4 KiB
TypeScript
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]);
|
|
} |