mirror of
https://github.com/outline/outline.git
synced 2026-06-27 02:04:23 +03:00
107 lines
2.8 KiB
JavaScript
107 lines
2.8 KiB
JavaScript
// @flow
|
|
import * as React from "react";
|
|
import * as Y from "yjs";
|
|
import { SocketContext } from "components/SocketProvider";
|
|
import useStores from "hooks/useStores";
|
|
import { WebsocketProvider } from "multiplayer/WebsocketProvider";
|
|
|
|
type Props = {
|
|
children: ({
|
|
provider: ?WebsocketProvider,
|
|
isReconnecting: boolean,
|
|
isConnected: boolean,
|
|
doc: Y.Doc,
|
|
}) => React.Node,
|
|
isMultiplayer: boolean,
|
|
documentId: string,
|
|
userId?: string,
|
|
};
|
|
|
|
export default function SocketPresence(props: Props) {
|
|
const { presence } = useStores();
|
|
const context = React.useContext(SocketContext);
|
|
const [isConnected, setConnected] = React.useState(
|
|
context ? context.connected : false
|
|
);
|
|
const [isReconnecting, setReconnecting] = React.useState(false);
|
|
const [doc] = React.useState(() =>
|
|
props.isMultiplayer ? new Y.Doc() : undefined
|
|
);
|
|
const [provider] = React.useState(() =>
|
|
props.isMultiplayer && props.userId
|
|
? new WebsocketProvider(context, props.documentId, props.userId, doc)
|
|
: undefined
|
|
);
|
|
|
|
React.useEffect(() => {
|
|
return () => {
|
|
console.log("destroy");
|
|
provider.destroy();
|
|
};
|
|
}, []);
|
|
|
|
const awareness = provider && provider.awareness;
|
|
React.useEffect(() => {
|
|
const onUpdate = () => {
|
|
presence.updateFromAwareness(props.documentId, awareness);
|
|
};
|
|
|
|
if (awareness) {
|
|
awareness.on("update", onUpdate);
|
|
}
|
|
|
|
return () => {
|
|
if (awareness) {
|
|
awareness.off("update", onUpdate);
|
|
}
|
|
};
|
|
}, [presence, props.documentId, awareness]);
|
|
|
|
React.useEffect(() => {
|
|
console.log("useEffect", context);
|
|
if (!context) return;
|
|
|
|
const emitJoin = () => {
|
|
if (!context) return;
|
|
context.emit("join", { documentId: props.documentId });
|
|
};
|
|
|
|
const updateStatus = () => {
|
|
setConnected(context.connected);
|
|
};
|
|
|
|
const reconnectingStopped = () => {
|
|
setReconnecting(false);
|
|
};
|
|
|
|
context.on("connect", updateStatus);
|
|
context.on("disconnect", updateStatus);
|
|
context.on("reconnect", reconnectingStopped);
|
|
context.on("reconnect_attempt", setReconnecting);
|
|
context.on("reconnect_failed", reconnectingStopped);
|
|
context.on("authenticated", emitJoin);
|
|
|
|
if (context.authenticated) {
|
|
emitJoin();
|
|
}
|
|
|
|
return () => {
|
|
if (!context) return;
|
|
context.emit("leave", { documentId: props.documentId });
|
|
context.off("authenticated", emitJoin);
|
|
context.off("connect", updateStatus);
|
|
context.off("disconnect", updateStatus);
|
|
context.off("reconnect", reconnectingStopped);
|
|
context.off("reconnect_attempt", setReconnecting);
|
|
context.off("reconnect_failed", reconnectingStopped);
|
|
};
|
|
}, [context, props.documentId, props.userId]);
|
|
|
|
return props.children({
|
|
isConnected,
|
|
isReconnecting,
|
|
provider,
|
|
doc,
|
|
});
|
|
}
|