useSession.jsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import React, { useContext } from "react";
  2. import {
  3. useItemActions,
  4. useMessage,
  5. useBoardConfig,
  6. useC2C,
  7. } from "react-sync-board";
  8. import SubscribeSessionEvents from "./SubscribeSessionEvents";
  9. import { updateSession, getSession, getGame } from "../utils/api";
  10. export const SessionContext = React.createContext({});
  11. const emtpyBoard = {
  12. items: [],
  13. availableItems: [],
  14. board: {
  15. size: 1000,
  16. scale: 1,
  17. translations: [
  18. {
  19. language: "fr",
  20. name: "Choisissez un jeu",
  21. description: "...",
  22. },
  23. ],
  24. defaultName: "Choose a game",
  25. defaultLanguage: "en",
  26. defaultDescription: "...",
  27. gridSize: 1,
  28. },
  29. };
  30. export const SessionProvider = ({ sessionId, fromGameId, children }) => {
  31. const { setItemList, getItemList } = useItemActions();
  32. const { messages, setMessages } = useMessage();
  33. const [availableItems, setAvailableItems] = React.useState([]);
  34. const [boardConfig, setBoardConfig] = useBoardConfig();
  35. const [sessionLoaded, setSessionLoaded] = React.useState(false);
  36. const [currentGameId, setCurrentGameId] = React.useState(fromGameId);
  37. const { c2c } = useC2C("board");
  38. const loadSession = React.useCallback(async () => {
  39. let sessionData;
  40. // Init session from server
  41. try {
  42. // First from session if exists
  43. sessionData = await getSession(sessionId);
  44. const sessionGameId = sessionData.gameId;
  45. // Update availableItems from original game
  46. if (sessionGameId) {
  47. const { availableItems } = await getGame(sessionGameId);
  48. sessionData.availableItems = availableItems;
  49. setCurrentGameId(sessionGameId);
  50. }
  51. } catch {
  52. if (fromGameId) {
  53. // Then from initial game
  54. sessionData = await getGame(fromGameId);
  55. } else {
  56. // Empty board
  57. sessionData = emtpyBoard;
  58. }
  59. }
  60. return sessionData;
  61. }, [fromGameId, sessionId]);
  62. const setSession = React.useCallback(
  63. async (newData, sync = false) => {
  64. const { availableItems, items, board, messages = [] } = newData;
  65. setAvailableItems(availableItems);
  66. // The filter prevent the empty item bug on reload
  67. setItemList(items.filter((item) => item));
  68. setBoardConfig(board, false);
  69. setMessages(messages);
  70. if (sync) {
  71. // Send loadSession event for other user
  72. c2c.publish("loadSession", newData);
  73. }
  74. setSessionLoaded(true);
  75. },
  76. [c2c, setBoardConfig, setItemList, setMessages]
  77. );
  78. const getCurrentSession = React.useCallback(async () => {
  79. const currentSession = {
  80. items: await getItemList(),
  81. board: boardConfig,
  82. availableItems: availableItems,
  83. messages: messages.slice(-50),
  84. timestamp: Date.now(),
  85. gameId: fromGameId,
  86. };
  87. return currentSession;
  88. }, [availableItems, boardConfig, fromGameId, getItemList, messages]);
  89. const changeGame = React.useCallback(
  90. async (newGameId) => {
  91. const newGame = await getGame(newGameId);
  92. const currentSession = getCurrentSession();
  93. setSession({ ...currentSession, ...newGame }, true);
  94. },
  95. [getCurrentSession, setSession]
  96. );
  97. const saveSession = React.useCallback(async () => {
  98. const currentSession = await getCurrentSession();
  99. if (currentSession.items.length) {
  100. try {
  101. return await updateSession(sessionId, currentSession);
  102. } catch (e) {
  103. console.log(e);
  104. }
  105. }
  106. }, [getCurrentSession, sessionId]);
  107. return (
  108. <SessionContext.Provider
  109. value={{
  110. loadSession,
  111. changeGame,
  112. setSession,
  113. getSession: getCurrentSession,
  114. saveSession,
  115. sessionLoaded,
  116. sessionId,
  117. gameId: currentGameId,
  118. availableItems,
  119. boardConfig,
  120. messages,
  121. }}
  122. >
  123. {children}
  124. <SubscribeSessionEvents
  125. getSession={getCurrentSession}
  126. setSession={setSession}
  127. />
  128. </SessionContext.Provider>
  129. );
  130. };
  131. export const useSession = () => {
  132. return useContext(SessionContext);
  133. };
  134. export default useSession;