useC2C.jsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import React, { useContext } from "react";
  2. import { useSocket } from "@scripters/use-socket.io";
  3. import { join } from "client2client.io";
  4. import { useTranslation } from "react-i18next";
  5. import Waiter from "../ui/Waiter";
  6. const contextMap = {};
  7. export const C2CProvider = ({ room, channel = "default", children }) => {
  8. const { t } = useTranslation();
  9. const socket = useSocket();
  10. const [joined, setJoined] = React.useState(false);
  11. const [isMaster, setIsMaster] = React.useState(false);
  12. const [c2c, setC2c] = React.useState(null);
  13. const roomRef = React.useRef(null);
  14. const mountedRef = React.useRef(false);
  15. React.useEffect(() => {
  16. mountedRef.current = true;
  17. return () => {
  18. mountedRef.current = false;
  19. };
  20. }, []);
  21. if (!contextMap[channel]) {
  22. contextMap[channel] = React.createContext({
  23. joined: false,
  24. isMaster: false,
  25. });
  26. }
  27. const Context = contextMap[channel];
  28. React.useEffect(() => {
  29. const disconnect = () => {
  30. console.log(`Disconnected from ${channel}…`);
  31. if (!mountedRef.current) return;
  32. setJoined(false);
  33. setIsMaster(false);
  34. };
  35. socket.on("disconnect", disconnect);
  36. return () => {
  37. socket.off("disconnect", disconnect);
  38. };
  39. }, [channel, socket]);
  40. React.useEffect(() => {
  41. // Connect
  42. if (!socket) {
  43. return;
  44. }
  45. if (!socket.connected) {
  46. socket.connect();
  47. }
  48. join({
  49. socket,
  50. room,
  51. onMaster: () => {
  52. console.log(`Is now master on channel ${channel}…`);
  53. if (!mountedRef.current) return;
  54. setIsMaster(true);
  55. },
  56. onJoined: (newRoom) => {
  57. console.log(`Connected on channel ${channel}…`);
  58. roomRef.current = newRoom;
  59. if (!mountedRef.current) return;
  60. setC2c(newRoom);
  61. setJoined(true);
  62. },
  63. });
  64. return () => {
  65. roomRef.current.leave();
  66. };
  67. }, [channel, room, socket]);
  68. if (!joined || !c2c) {
  69. return <Waiter message={t("Waiting for connection…")} />;
  70. }
  71. return (
  72. <Context.Provider value={{ c2c, joined, isMaster, room }}>
  73. {children}
  74. </Context.Provider>
  75. );
  76. };
  77. export const useC2C = (channel = "default") => {
  78. const Context = contextMap[channel];
  79. return useContext(Context);
  80. };
  81. export default useC2C;