You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
3.1 KiB
72 lines
3.1 KiB
import {ReactElement, useContext, useEffect, useRef, useState} from "react";
|
|
import {
|
|
CLIENT_ACT,
|
|
CLIENT_REFRESH,
|
|
ClientActCommand,
|
|
ClientGoodbyeAction,
|
|
ClientHelloCommand,
|
|
ClientRefreshCommand, isClientGoodbyeCommand,
|
|
isClientHelloCommand,
|
|
isClientRefreshCommand,
|
|
SendableAction,
|
|
SentAction
|
|
} from "../../../common/src/actions/ClientAction";
|
|
import {DispatchContext} from "./context/DispatchContext";
|
|
import {DOMWebsocketTranslator} from "./DOMWebsocketTranslator";
|
|
import {ServerConnectionState} from "../state/NetworkState";
|
|
import {SERVER_SOCKET_STARTUP, SocketState} from "../../../common/src/actions/ServerAction";
|
|
|
|
export function WebsocketReactAdapter({url, protocols = ["v1.hexmap.deliciousreya.net"], state, specialMessage, pendingMessages, nextID}: {
|
|
url: string,
|
|
protocols?: readonly string[],
|
|
state: ServerConnectionState,
|
|
specialMessage: ClientHelloCommand | ClientRefreshCommand | ClientGoodbyeAction | null,
|
|
pendingMessages: readonly SendableAction[],
|
|
nextID: number
|
|
}): ReactElement {
|
|
const dispatch = useContext(DispatchContext)
|
|
if (dispatch === null) {
|
|
throw Error("What the heck?! No dispatch?! I quit!")
|
|
}
|
|
const connector = useRef(new DOMWebsocketTranslator({
|
|
url,
|
|
protocols,
|
|
onStartup: dispatch,
|
|
onMessage: dispatch,
|
|
onError: dispatch,
|
|
onGoodbye: dispatch,
|
|
}))
|
|
useEffect(() => {
|
|
connector.current.connect();
|
|
dispatch({
|
|
type: SERVER_SOCKET_STARTUP,
|
|
state: SocketState.CONNECTING,
|
|
});
|
|
}, [dispatch])
|
|
const [lastSpecialMessage, setLastSpecialMessage] = useState<ClientHelloCommand | ClientRefreshCommand | ClientGoodbyeAction | null>(null)
|
|
useEffect(() => {
|
|
if (state === ServerConnectionState.CONNECTED && pendingMessages.length > 0) {
|
|
const sentMessages: SentAction[] = pendingMessages.map((action, index) => {
|
|
return {id: index + nextID, action}
|
|
});
|
|
const sentMessage: ClientActCommand = {
|
|
type: CLIENT_ACT,
|
|
actions: sentMessages,
|
|
};
|
|
connector.current.send(sentMessage)
|
|
dispatch(sentMessage)
|
|
}
|
|
}, [nextID, dispatch, pendingMessages, state])
|
|
useEffect(() => {
|
|
if (specialMessage !== null && specialMessage !== lastSpecialMessage) {
|
|
if ((state === ServerConnectionState.AWAITING_HELLO && isClientHelloCommand(specialMessage))
|
|
|| (state === ServerConnectionState.AWAITING_REFRESH && isClientRefreshCommand(specialMessage))) {
|
|
connector.current.send(specialMessage);
|
|
} else if (state === ServerConnectionState.AWAITING_GOODBYE && isClientGoodbyeCommand(specialMessage)) {
|
|
connector.current.close(specialMessage.code, specialMessage.reason)
|
|
}
|
|
setLastSpecialMessage(specialMessage);
|
|
}
|
|
}, [specialMessage, lastSpecialMessage, setLastSpecialMessage, state])
|
|
return <div className="connectionState" onClick={() => dispatch ? dispatch({type: CLIENT_REFRESH}) : null}>{state}</div>
|
|
} |