From 01da1f385ce1f282a522a471d9f11268c50bd3bb Mon Sep 17 00:00:00 2001 From: Sam Maselli Date: Sat, 2 Nov 2024 17:50:58 -0400 Subject: [PATCH 1/4] reziable panels --- client/package-lock.json | 16 ++++ client/package.json | 1 + client/src/menu/game/GameScreen.tsx | 77 ++++++++++++++++--- client/src/menu/game/gameScreen.css | 19 +---- .../menu/game/gameScreenContent/chatMenu.css | 1 - .../game/gameScreenContent/graveyardMenu.css | 3 - .../game/gameScreenContent/playerListMenu.css | 3 - 7 files changed, 86 insertions(+), 34 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 534363413..7dc29175e 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -22,6 +22,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-helmet": "^6.1.0", + "react-resizable-panels": "^2.1.6", "react-scripts": "^5.0.1", "react-virtuoso": "^4.12.0", "typescript": "^4", @@ -14616,6 +14617,15 @@ "node": ">=0.10.0" } }, + "node_modules/react-resizable-panels": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.1.6.tgz", + "integrity": "sha512-oIqo/7pp2TsR+Dp1qZMr1l4RBDV4Zz/0HEG5zxliBJoHqqFnG0MbmFbk+5Q1VMGfPQ4uhXxefunLC1o7v38PDQ==", + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", @@ -28340,6 +28350,12 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" }, + "react-resizable-panels": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.1.6.tgz", + "integrity": "sha512-oIqo/7pp2TsR+Dp1qZMr1l4RBDV4Zz/0HEG5zxliBJoHqqFnG0MbmFbk+5Q1VMGfPQ4uhXxefunLC1o7v38PDQ==", + "requires": {} + }, "react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", diff --git a/client/package.json b/client/package.json index 590b0bdeb..1bd351fee 100644 --- a/client/package.json +++ b/client/package.json @@ -17,6 +17,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-helmet": "^6.1.0", + "react-resizable-panels": "^2.1.6", "react-scripts": "^5.0.1", "react-virtuoso": "^4.12.0", "typescript": "^4", diff --git a/client/src/menu/game/GameScreen.tsx b/client/src/menu/game/GameScreen.tsx index a7c2e66f8..3bd44355d 100644 --- a/client/src/menu/game/GameScreen.tsx +++ b/client/src/menu/game/GameScreen.tsx @@ -17,6 +17,7 @@ import { Button } from "../../components/Button"; import translate from "../../game/lang"; import { roleSpecificMenuType } from "../Settings"; import { useGameState, usePlayerState } from "../../components/useHooks"; +import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; export enum ContentMenu { ChatMenu = "ChatMenu", @@ -202,23 +203,79 @@ export default function GameScreen(): ReactElement { }) const allMenusClosed = menuController.menusOpen().length === 0; + const minSize = 5; return
-
- {menuController.menuOpen(ContentMenu.ChatMenu) && } - {menuController.menuOpen(ContentMenu.PlayerListMenu) && } - {menuController.menuOpen(ContentMenu.WillMenu) && } - {menuController.menuOpen(ContentMenu.RoleSpecificMenu) && } - {menuController.menuOpen(ContentMenu.GraveyardMenu) && } - {menuController.menuOpen(ContentMenu.WikiMenu) && } - {allMenusClosed &&
+ + {menuController.menuOpen(ContentMenu.ChatMenu) && + + + + } + { + menuController.menuOpen(ContentMenu.ChatMenu) && ( + menuController.menuOpen(ContentMenu.PlayerListMenu) || + menuController.menuOpen(ContentMenu.WillMenu) || + menuController.menuOpen(ContentMenu.RoleSpecificMenu) || + menuController.menuOpen(ContentMenu.GraveyardMenu) || + menuController.menuOpen(ContentMenu.WikiMenu) + ) && + } + {menuController.menuOpen(ContentMenu.PlayerListMenu) && + + + + } + { + menuController.menuOpen(ContentMenu.PlayerListMenu) && + (menuController.menuOpen(ContentMenu.WillMenu) || + menuController.menuOpen(ContentMenu.RoleSpecificMenu) || + menuController.menuOpen(ContentMenu.GraveyardMenu) || + menuController.menuOpen(ContentMenu.WikiMenu)) && + } + {menuController.menuOpen(ContentMenu.WillMenu) && + + + + } + { + menuController.menuOpen(ContentMenu.WillMenu) && + (menuController.menuOpen(ContentMenu.RoleSpecificMenu) || + menuController.menuOpen(ContentMenu.GraveyardMenu) || + menuController.menuOpen(ContentMenu.WikiMenu)) && + } + {menuController.menuOpen(ContentMenu.RoleSpecificMenu) && + + + + } + { + menuController.menuOpen(ContentMenu.RoleSpecificMenu) && + (menuController.menuOpen(ContentMenu.GraveyardMenu) || + menuController.menuOpen(ContentMenu.WikiMenu)) && + } + {menuController.menuOpen(ContentMenu.GraveyardMenu) && + + + + } + { + menuController.menuOpen(ContentMenu.GraveyardMenu) && + menuController.menuOpen(ContentMenu.WikiMenu) && + } + {menuController.menuOpen(ContentMenu.WikiMenu) && + + + + } + {allMenusClosed &&
{translate("menu.gameScreen.noContent")} -
} -
+
} +
} diff --git a/client/src/menu/game/gameScreen.css b/client/src/menu/game/gameScreen.css index 30ed3c335..33f58b8eb 100644 --- a/client/src/menu/game/gameScreen.css +++ b/client/src/menu/game/gameScreen.css @@ -19,26 +19,11 @@ } .game-screen .content { - display: flex; - flex-direction: row; - - flex-grow: 1; - flex-shrink: 0; - flex-basis: auto; - height: 1vh; - overflow-x: hidden; } -.game-screen .content > div { - overflow-x: hidden; - resize: horizontal; - +.game-screen .content > div > div{ height: 100%; max-height: 100%; - - max-width: 100%; - width: 15%; - min-width: 10%; background-color: var(--background-color); border: .13rem solid var(--background-border-color); @@ -47,7 +32,7 @@ } @media only screen and (max-width: 600px) { - .game-screen .content > div { + .game-screen .content > div > div { width: 100%; resize: none; } diff --git a/client/src/menu/game/gameScreenContent/chatMenu.css b/client/src/menu/game/gameScreenContent/chatMenu.css index 154aa64c7..834dacc64 100644 --- a/client/src/menu/game/gameScreenContent/chatMenu.css +++ b/client/src/menu/game/gameScreenContent/chatMenu.css @@ -2,7 +2,6 @@ .game-screen .content > .chat-menu { display: flex; flex-direction: column; - width: 60%; } @media only screen and (max-width: 600px) { .game-screen .content > .chat-menu { diff --git a/client/src/menu/game/gameScreenContent/graveyardMenu.css b/client/src/menu/game/gameScreenContent/graveyardMenu.css index c0ca3abb2..3b906f38c 100644 --- a/client/src/menu/game/gameScreenContent/graveyardMenu.css +++ b/client/src/menu/game/gameScreenContent/graveyardMenu.css @@ -1,6 +1,3 @@ -.game-screen .content > .graveyard-menu { - width: 20%; -} @media only screen and (max-width: 600px) { .game-screen .content > .graveyard-menu { width: 100%; diff --git a/client/src/menu/game/gameScreenContent/playerListMenu.css b/client/src/menu/game/gameScreenContent/playerListMenu.css index 6125de6aa..2f5cc7a2e 100644 --- a/client/src/menu/game/gameScreenContent/playerListMenu.css +++ b/client/src/menu/game/gameScreenContent/playerListMenu.css @@ -1,6 +1,3 @@ -.game-screen .content > .player-list-menu { - width: 20%; -} @media only screen and (max-width: 600px) { .game-screen .content > .player-list-menu { width: 100%; From 09a72dc7b2332b21a4c682ce05da60b0662e7519 Mon Sep 17 00:00:00 2001 From: Jack Papel Date: Sun, 1 Dec 2024 17:20:59 -0500 Subject: [PATCH 2/4] Fix resizing and chat menu --- client/src/menu/game/GameScreen.tsx | 82 +++++-------------- .../menu/game/gameScreenContent/chatMenu.css | 2 +- 2 files changed, 21 insertions(+), 63 deletions(-) diff --git a/client/src/menu/game/GameScreen.tsx b/client/src/menu/game/GameScreen.tsx index 3bd44355d..3fef5266a 100644 --- a/client/src/menu/game/GameScreen.tsx +++ b/client/src/menu/game/GameScreen.tsx @@ -27,6 +27,16 @@ export enum ContentMenu { GraveyardMenu = "GraveyardMenu", WikiMenu = "WikiMenu", } + +const MENU_ELEMENTS = { + [ContentMenu.ChatMenu]: ChatMenu, + [ContentMenu.PlayerListMenu]: PlayerListMenu, + [ContentMenu.RoleSpecificMenu]: RoleSpecificMenu, + [ContentMenu.WillMenu]: WillMenu, + [ContentMenu.GraveyardMenu]: GraveyardMenu, + [ContentMenu.WikiMenu]: WikiMenu +} + const ALL_CONTENT_MENUS = Object.values(ContentMenu); export interface MenuController { @@ -203,7 +213,7 @@ export default function GameScreen(): ReactElement { }) const allMenusClosed = menuController.menusOpen().length === 0; - const minSize = 5; + const minSize = 10; return
@@ -211,67 +221,15 @@ export default function GameScreen(): ReactElement {
- {menuController.menuOpen(ContentMenu.ChatMenu) && - - - - } - { - menuController.menuOpen(ContentMenu.ChatMenu) && ( - menuController.menuOpen(ContentMenu.PlayerListMenu) || - menuController.menuOpen(ContentMenu.WillMenu) || - menuController.menuOpen(ContentMenu.RoleSpecificMenu) || - menuController.menuOpen(ContentMenu.GraveyardMenu) || - menuController.menuOpen(ContentMenu.WikiMenu) - ) && - } - {menuController.menuOpen(ContentMenu.PlayerListMenu) && - - - - } - { - menuController.menuOpen(ContentMenu.PlayerListMenu) && - (menuController.menuOpen(ContentMenu.WillMenu) || - menuController.menuOpen(ContentMenu.RoleSpecificMenu) || - menuController.menuOpen(ContentMenu.GraveyardMenu) || - menuController.menuOpen(ContentMenu.WikiMenu)) && - } - {menuController.menuOpen(ContentMenu.WillMenu) && - - - - } - { - menuController.menuOpen(ContentMenu.WillMenu) && - (menuController.menuOpen(ContentMenu.RoleSpecificMenu) || - menuController.menuOpen(ContentMenu.GraveyardMenu) || - menuController.menuOpen(ContentMenu.WikiMenu)) && - } - {menuController.menuOpen(ContentMenu.RoleSpecificMenu) && - - - - } - { - menuController.menuOpen(ContentMenu.RoleSpecificMenu) && - (menuController.menuOpen(ContentMenu.GraveyardMenu) || - menuController.menuOpen(ContentMenu.WikiMenu)) && - } - {menuController.menuOpen(ContentMenu.GraveyardMenu) && - - - - } - { - menuController.menuOpen(ContentMenu.GraveyardMenu) && - menuController.menuOpen(ContentMenu.WikiMenu) && - } - {menuController.menuOpen(ContentMenu.WikiMenu) && - - - - } + {menuController.menusOpen().map((menu, index, menusOpen) => { + const MenuElement = MENU_ELEMENTS[menu]; + return <> + + + + {menusOpen.some((_, i) => i > index) && } + + })} {allMenusClosed &&
{translate("menu.gameScreen.noContent")}
} diff --git a/client/src/menu/game/gameScreenContent/chatMenu.css b/client/src/menu/game/gameScreenContent/chatMenu.css index 834dacc64..efae9d9e5 100644 --- a/client/src/menu/game/gameScreenContent/chatMenu.css +++ b/client/src/menu/game/gameScreenContent/chatMenu.css @@ -1,5 +1,5 @@ -.game-screen .content > .chat-menu { +.game-screen .content .chat-menu { display: flex; flex-direction: column; } From 9f54fd105b109391ca1a1eedf84503f90fb2d822 Mon Sep 17 00:00:00 2001 From: Jack Papel Date: Sun, 1 Dec 2024 17:30:37 -0500 Subject: [PATCH 3/4] Fix Spectator screen --- client/src/menu/game/GameScreen.tsx | 6 ++--- .../menu/spectator/SpectatorGameScreen.tsx | 23 ++++++++++++++----- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/client/src/menu/game/GameScreen.tsx b/client/src/menu/game/GameScreen.tsx index 8d8178f9b..12762485f 100644 --- a/client/src/menu/game/GameScreen.tsx +++ b/client/src/menu/game/GameScreen.tsx @@ -15,10 +15,8 @@ import { WikiArticleLink } from "../../components/WikiArticleLink"; import Icon from "../../components/Icon"; import { Button } from "../../components/Button"; import translate from "../../game/lang"; -import { roleSpecificMenuType } from "../Settings"; -import { useGameState, usePlayerState } from "../../components/useHooks"; -import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; import { useGameState } from "../../components/useHooks"; +import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; export enum ContentMenu { ChatMenu = "ChatMenu", @@ -29,7 +27,7 @@ export enum ContentMenu { WikiMenu = "WikiMenu", } -const MENU_ELEMENTS = { +export const MENU_ELEMENTS = { [ContentMenu.ChatMenu]: ChatMenu, [ContentMenu.PlayerListMenu]: PlayerListMenu, [ContentMenu.RoleSpecificMenu]: AbilityMenu, diff --git a/client/src/menu/spectator/SpectatorGameScreen.tsx b/client/src/menu/spectator/SpectatorGameScreen.tsx index 0ef02e8c1..28f35136c 100644 --- a/client/src/menu/spectator/SpectatorGameScreen.tsx +++ b/client/src/menu/spectator/SpectatorGameScreen.tsx @@ -7,8 +7,10 @@ import ChatMenu from "../game/gameScreenContent/ChatMenu"; import PlayerListMenu from "../game/gameScreenContent/PlayerListMenu"; import GraveyardMenu from "../game/gameScreenContent/GraveyardMenu"; import HeaderMenu from "../game/HeaderMenu"; -import { MenuController, ContentMenu, useMenuController, MenuControllerContext } from "../game/GameScreen"; +import { MenuController, ContentMenu, useMenuController, MenuControllerContext, MENU_ELEMENTS } from "../game/GameScreen"; import { MobileContext } from "../Anchor"; +import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; +import translate from "../../game/lang"; const DEFAULT_START_PHASE_SCREEN_TIME = 3; @@ -63,11 +65,20 @@ export default function SpectatorGameScreen(): ReactElement { {showStartedScreen ? - :
- {contentController.menuOpen(ContentMenu.ChatMenu) && } - {contentController.menuOpen(ContentMenu.PlayerListMenu) && } - {contentController.menuOpen(ContentMenu.GraveyardMenu) && } -
} + : + {contentController.menusOpen().map((menu, index, menusOpen) => { + const MenuElement = MENU_ELEMENTS[menu]; + return <> + + + + {menusOpen.some((_, i) => i > index) && } + + })} + {contentController.menusOpen().length === 0 &&
+ {translate("menu.gameScreen.noContent")} +
} +
}
); From aeb883f6dcca68ba48cfa1a4cd69e8e25bfb6508 Mon Sep 17 00:00:00 2001 From: Sam Maselli Date: Mon, 2 Dec 2024 03:00:38 -0500 Subject: [PATCH 4/4] remove spectator started screen --- .../src/menu/spectator/PhaseStartedScreen.tsx | 89 ------------------- .../menu/spectator/SpectatorGameScreen.tsx | 55 ++++-------- 2 files changed, 15 insertions(+), 129 deletions(-) delete mode 100644 client/src/menu/spectator/PhaseStartedScreen.tsx diff --git a/client/src/menu/spectator/PhaseStartedScreen.tsx b/client/src/menu/spectator/PhaseStartedScreen.tsx deleted file mode 100644 index ac63d7259..000000000 --- a/client/src/menu/spectator/PhaseStartedScreen.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import React, { ReactElement, useMemo } from "react"; -import GAME_MANAGER from "../.."; -import translate from "../../game/lang"; -import StyledText from "../../components/StyledText"; -import { useGameState } from "../../components/useHooks"; -import GraveComponent from "../../components/grave"; -import { FastForwardButton } from "../game/HeaderMenu"; -import Counter from "../../components/Counter"; - - - -export default function PhaseStartedScreen(): ReactElement { - const phaseState = useGameState( - gameState => gameState.phaseState, - ["phase", "playerOnTrial"] - )! - - return
- {(() => { - switch (phaseState.type) { - case "briefing": - return
- {translate("phase."+phaseState.type+".subtitle")} - -
- case "dusk": - case "night": - case "discussion": - return {translate("phase."+phaseState.type+".subtitle")}; - case "nomination": { - const votesRequired = GAME_MANAGER.getVotesRequired()!; - - return
- { - (votesRequired === 1 ? translate("votesRequired.1") : translate("votesRequired", votesRequired)) - + " " + translate("trialsRemaining", phaseState.trialsLeft) - } - - {translate("menu.playerList.player.votes", votesRequired)} - -
- } - case "testimony": - case "judgement": - case "finalWords": - return { - translate("phase."+phaseState.type+".subtitle", GAME_MANAGER.getPlayerNames()[phaseState.playerOnTrial].toString()) - } - case "obituary": - return - } - })()} -
-} - -function ObituaryScreen(): ReactElement { - const graves = useGameState( - gameState => gameState.graves, - ["addGrave"] - )! - - const dayNumber = useGameState( - gameState => gameState.dayNumber, - ["phase"] - )! - - const playerNames = useGameState( - gameState => gameState.players.map(player => player.toString()), - ["gamePlayers"] - )! - - const newGraves = useMemo(() => { - return graves.filter(grave => grave.diedPhase === "night" && grave.dayNumber === dayNumber - 1); - }, [graves, dayNumber]) - - if(newGraves.length === 0) - return ( - {translate("nobodyDiedLastNight")} - ); - return
- {newGraves.map(grave => - - )} -
; -} diff --git a/client/src/menu/spectator/SpectatorGameScreen.tsx b/client/src/menu/spectator/SpectatorGameScreen.tsx index 28f35136c..a518568f9 100644 --- a/client/src/menu/spectator/SpectatorGameScreen.tsx +++ b/client/src/menu/spectator/SpectatorGameScreen.tsx @@ -1,20 +1,12 @@ import React, { ReactElement, useContext } from "react"; import "./spectatorGameScreen.css"; -import PhaseStartedScreen from "./PhaseStartedScreen"; -import { useGameState } from "../../components/useHooks"; import "../game/gameScreen.css" -import ChatMenu from "../game/gameScreenContent/ChatMenu"; -import PlayerListMenu from "../game/gameScreenContent/PlayerListMenu"; -import GraveyardMenu from "../game/gameScreenContent/GraveyardMenu"; import HeaderMenu from "../game/HeaderMenu"; -import { MenuController, ContentMenu, useMenuController, MenuControllerContext, MENU_ELEMENTS } from "../game/GameScreen"; +import { MenuController, useMenuController, MenuControllerContext, MENU_ELEMENTS } from "../game/GameScreen"; import { MobileContext } from "../Anchor"; import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; import translate from "../../game/lang"; - -const DEFAULT_START_PHASE_SCREEN_TIME = 3; - let CONTENT_CONTROLLER: MenuController | undefined; export function getSpectatorScreenContentController(): MenuController | undefined { @@ -28,21 +20,6 @@ type SpectatorContentMenus = { } export default function SpectatorGameScreen(): ReactElement { - const showStartedScreen = useGameState( - gameState => { - if ( - gameState.phaseState.type === "briefing" - || gameState.phaseState.type === "obituary" - ) return true; - - const maxTime = gameState.phaseTimes[gameState.phaseState.type]; - const timePassed = Math.floor(maxTime - gameState.timeLeftMs/1000); - return timePassed < DEFAULT_START_PHASE_SCREEN_TIME; - }, - ["phase", "phaseTimeLeft", "tick"], - true - )! - const mobile = useContext(MobileContext)!; const contentController = useMenuController( @@ -63,22 +40,20 @@ export default function SpectatorGameScreen(): ReactElement {
- {showStartedScreen - ? - : - {contentController.menusOpen().map((menu, index, menusOpen) => { - const MenuElement = MENU_ELEMENTS[menu]; - return <> - - - - {menusOpen.some((_, i) => i > index) && } - - })} - {contentController.menusOpen().length === 0 &&
- {translate("menu.gameScreen.noContent")} -
} -
} + + {contentController.menusOpen().map((menu, index, menusOpen) => { + const MenuElement = MENU_ELEMENTS[menu]; + return <> + + + + {menusOpen.some((_, i) => i > index) && } + + })} + {contentController.menusOpen().length === 0 &&
+ {translate("menu.gameScreen.noContent")} +
} +
);