Skip to content

Commit 66b6353

Browse files
committed
simple lobby state
1 parent 815d672 commit 66b6353

File tree

4 files changed

+97
-72
lines changed

4 files changed

+97
-72
lines changed

src/main/client/src/feature/lobby/Lobby.jsx

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,14 @@ import {
3131
} from "./ActiveGames.jsx"
3232
import {
3333
useAuthStore,
34-
useLobbyStore,
3534
} from "src/store.js"
35+
import {
36+
checkNewGameOpen,
37+
setNewGameOpen,
38+
handleLobbyClick,
39+
closeLobbyPopup,
40+
initialState,
41+
} from "./lobbyState.js"
3642
import {
3743
CgClose,
3844
} from "react-icons/cg"
@@ -46,10 +52,8 @@ const detailData = [
4652
]
4753

4854
export function Lobby() {
49-
let isNewGameOpen = useLobbyStore(state => state.isNewGameOpen())
50-
let setNewGameOpen = useLobbyStore(state => state.setNewGameOpen)
51-
let handleLobbyClick = useLobbyStore(state => state.handleLobbyClick)
52-
let closeLobbyPopup = useLobbyStore(state => state.closeLobbyPopup)
55+
let [lobbyState, setLobbyState] = useState(initialState())
56+
let isNewGameOpen = checkNewGameOpen(lobbyState)
5357
let [detail, setDetail] = useState("open")
5458
let stompClient = useContext(StompContext)
5559
let navigate = useNavigate()
@@ -69,8 +73,8 @@ export function Lobby() {
6973
navigate(base + "/game/" + game.id)
7074
sub.unsubscribe()
7175
})
72-
closeLobbyPopup()
73-
}), [auth.token, navigate, stompClient, closeLobbyPopup])
76+
setLobbyState(closeLobbyPopup(lobbyState))
77+
}), [auth.token, navigate, stompClient, lobbyState])
7478
let onStartEdit = useCallback((d) => doTry(async () => {
7579
let response = await tfetch("/api/start_edit", {
7680
method: "POST",
@@ -83,13 +87,15 @@ export function Lobby() {
8387
navigate(base + "/game/" + response.id)
8488
}), [auth, navigate])
8589
return (
86-
<div onClick={handleLobbyClick} className="h-full">
90+
<div onClick={(event) => setLobbyState(handleLobbyClick(lobbyState, event))} className="h-full">
8791
<div className={twJoin(
8892
"mt-2 py-2 pr-4 gap-x-1",
8993
isNewGameOpen && "",
9094
!isNewGameOpen && "border-transparent",
9195
)}>
9296
<NewGameDialog
97+
lobbyState={lobbyState}
98+
setLobbyState={setLobbyState}
9399
newGameRef={newGameRef}
94100
onNewGame={onNewGame}
95101
onStartEdit={onStartEdit} />
@@ -99,7 +105,7 @@ export function Lobby() {
99105
!isNewGameOpen && "hover:border-sky-700",
100106
)}
101107
onClick={(event) => {
102-
setNewGameOpen(newGameRef.current)
108+
setLobbyState(setNewGameOpen(lobbyState, newGameRef.current))
103109
stopPropagation(event)
104110
}}>
105111
New Game
@@ -108,7 +114,7 @@ export function Lobby() {
108114
<div className="mt-2 grid gap-x-4 grid-cols-[max-content_auto]">
109115
<DetailNavigation detail={detail} setDetail={setDetail} />
110116
{detail === "open" && (
111-
<OpenGames />
117+
<OpenGames lobbyState={lobbyState} setLobbyState={setLobbyState} />
112118
)}
113119
{detail === "active" && (
114120
<ActiveGames />
@@ -119,12 +125,11 @@ export function Lobby() {
119125
)
120126
}
121127

122-
function NewGameDialog({onNewGame, onStartEdit, newGameRef}) {
128+
function NewGameDialog({lobbyState, setLobbyState, onNewGame, onStartEdit, newGameRef}) {
123129
let dimRef = useRef(9)
124130
let timeRef = useRef(10)
125131
let [edit, setEdit] = useState(false)
126-
let closeLobbyPopup = useLobbyStore(state => state.closeLobbyPopup)
127-
let isNewGameOpen = useLobbyStore(state => state.isNewGameOpen())
132+
let isNewGameOpen = checkNewGameOpen(lobbyState)
128133
return (
129134
<form onSubmit={(e) => {
130135
e.preventDefault()
@@ -141,7 +146,7 @@ function NewGameDialog({onNewGame, onStartEdit, newGameRef}) {
141146
"absolute ml-40 bg-slate-800 border-2 border-slate-600 rounded-lg z-10 px-3 py-2",
142147
)}>
143148
<div className="absolute top-1 right-1">
144-
<button onClick={closeLobbyPopup} className="text-stone-100 hover:text-stone-300">
149+
<button onClick={() => setLobbyState(closeLobbyPopup(lobbyState))} className="text-stone-100 hover:text-stone-300">
145150
<IconContext.Provider value={{ size: "1.25em" }}>
146151
<CgClose />
147152
</IconContext.Provider>

src/main/client/src/feature/lobby/OpenGames.jsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,17 @@ import {
3434
doTry,
3535
stopPropagation,
3636
} from "src/util.js"
37+
import {
38+
getAcceptDialog,
39+
setAcceptDialogOpen,
40+
} from "./lobbyState.js"
3741
import {
3842
useAuthStore,
39-
useLobbyStore,
4043
} from "src/store.js"
4144

42-
export function OpenGames() {
45+
export function OpenGames({lobbyState, setLobbyState}) {
4346
let [openGames, setOpenGames] = useState([])
44-
let acceptDialog = useLobbyStore(state => state.getAcceptDialog())
45-
let setAcceptDialogOpen = useLobbyStore(state => state.setAcceptDialogOpen)
47+
let acceptDialog = getAcceptDialog(lobbyState)
4648
let stompClient = useContext(StompContext)
4749
let navigate = useNavigate()
4850
let auth = useAuthStore(state => state.auth)
@@ -90,13 +92,14 @@ export function OpenGames() {
9092
if (acceptDialog) {
9193
return
9294
}
93-
setAcceptDialogOpen(acceptDialogRef.current, acceptableGame)
95+
setLobbyState(setAcceptDialogOpen(lobbyState, acceptDialogRef.current, acceptableGame))
9496
stopPropagation(event)
9597
}}
9698
key={game.id} />
9799
))}
98100
</div>
99101
<AcceptDialog
102+
acceptDialog={acceptDialog}
100103
onAccept={onAccept}
101104
acceptDialogRef={acceptDialogRef}
102105
/>
@@ -140,8 +143,7 @@ function OpenGame({game, onClick}) {
140143
)
141144
}
142145

143-
function AcceptDialog({onAccept, acceptDialogRef}) {
144-
let acceptDialog = useLobbyStore(state => state.getAcceptDialog())
146+
function AcceptDialog({onAccept, acceptDialog, acceptDialogRef}) {
145147
let acceptableGame = acceptDialog?.data
146148
let [isFlip, setFlip] = useState(false)
147149
let [handi, setHandi] = useState(1)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
export function initialState() {
2+
return {
3+
stack: [],
4+
}
5+
}
6+
7+
function setOpen(state, el, kind, data) {
8+
if (!el) {
9+
return state
10+
}
11+
if (state.stack.some(obj => obj.kind === kind)) {
12+
return state
13+
}
14+
return {
15+
stack: [...state.stack, {
16+
kind: kind,
17+
el: el,
18+
data: data,
19+
}],
20+
}
21+
}
22+
23+
export function checkNewGameOpen({stack}) {
24+
return stack.some(obj => obj.kind === "newgame")
25+
}
26+
27+
export function setNewGameOpen(state, el) {
28+
return setOpen(state, el, "newgame")
29+
}
30+
31+
export function getAcceptDialog({stack}) {
32+
let result = stack.filter(obj => obj.kind === "accept")
33+
if (!result.length) {
34+
return undefined
35+
}
36+
return result[0]
37+
}
38+
39+
export function setAcceptDialogOpen(state, el, data) {
40+
return setOpen(state, el, "accept", data)
41+
}
42+
43+
export function closeLobbyPopup(state) {
44+
if (!state.stack.length) {
45+
return state
46+
}
47+
let newStack = [...state.stack]
48+
newStack.pop()
49+
return {
50+
stack: newStack,
51+
}
52+
}
53+
54+
export function handleLobbyClick(state, event) {
55+
if (!state.stack.length) {
56+
return state
57+
}
58+
let {clientX, clientY} = event
59+
let {el} = state.stack[state.stack.length - 1]
60+
let {left, right, top, bottom} = el.getBoundingClientRect()
61+
if (clientX <= right && clientX >= left && clientY <= bottom && clientY >= top) {
62+
return state
63+
}
64+
let newStack = [...state.stack]
65+
newStack.pop()
66+
return {
67+
stack: newStack,
68+
}
69+
}

src/main/client/src/store.js

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -52,54 +52,3 @@ export const useTimeoutStore = create(set => ({
5252
draft.timeout = timeout
5353
}), true),
5454
}))
55-
56-
export const useLobbyStore = create((set, get) => ({
57-
stack: [],
58-
isNewGameOpen: () => {
59-
return get().stack.some(obj => obj.kind === "newgame")
60-
},
61-
setOpen: (el, kind, data) => set(produce(draft => {
62-
if (!el) {
63-
return
64-
}
65-
if (get().stack.some(obj => obj.kind === kind)) {
66-
return
67-
}
68-
draft.stack = [...get().stack, {
69-
kind: kind,
70-
el: el,
71-
data: data,
72-
}]
73-
}), true),
74-
setNewGameOpen: (el) => get().setOpen(el, "newgame"),
75-
getAcceptDialog: () => {
76-
let result = get().stack.filter(obj => obj.kind === "accept")
77-
if (!result.length) {
78-
return undefined
79-
}
80-
return result[0]
81-
},
82-
setAcceptDialogOpen: (el, data) => get().setOpen(el, "accept", data),
83-
closeLobbyPopup: () => set(produce(draft => {
84-
if (!get().stack.length) {
85-
return
86-
}
87-
let newStack = [...get().stack]
88-
newStack.pop()
89-
draft.stack = newStack
90-
}), true),
91-
handleLobbyClick: (event) => set(produce(draft => {
92-
if (!get().stack.length) {
93-
return
94-
}
95-
let {clientX, clientY} = event
96-
let {el} = get().stack[get().stack.length - 1]
97-
let {left, right, top, bottom} = el.getBoundingClientRect()
98-
if (clientX <= right && clientX >= left && clientY <= bottom && clientY >= top) {
99-
return
100-
}
101-
let newStack = [...get().stack]
102-
newStack.pop()
103-
draft.stack = newStack
104-
}), true),
105-
}))

0 commit comments

Comments
 (0)