diff --git a/src/tictactoe/MatchList.tsx b/src/tictactoe/MatchList.tsx new file mode 100644 index 0000000..e83110a --- /dev/null +++ b/src/tictactoe/MatchList.tsx @@ -0,0 +1,55 @@ +import { Match } from "@heroiclabs/nakama-js"; + +interface MatchListProps { + matches: Match[]; +} + +export default function MatchList({ matches }: MatchListProps) { + if (!matches.length) return

No open matches

; + + return ( +
+

Open Matches

+ + + + + + + + + + + + {matches + .filter(m => m.size ?? 0 > 0) + .map((m, index) => ( + + + + + + ))} + +
Sr No.Match IDLabel
{index + 1}{m.match_id}{m.label ?? "-"}
+
+ ); +} + +const th: React.CSSProperties = { + textAlign: "left", + padding: "8px", + background: "#f2f2f2", + borderBottom: "1px solid #ccc", +}; + +const td: React.CSSProperties = { + padding: "8px", + borderBottom: "1px solid #eee", +}; diff --git a/src/tictactoe/TicTacToe.tsx b/src/tictactoe/TicTacToe.tsx index 1981370..04342be 100644 --- a/src/tictactoe/TicTacToe.tsx +++ b/src/tictactoe/TicTacToe.tsx @@ -1,6 +1,8 @@ import { useState, useEffect } from "react"; import { useNakama } from "./providers/NakamaProvider"; +import { Match } from "@heroiclabs/nakama-js"; import Board from "./Board"; +import MatchList from "./MatchList"; export default function TicTacToe() { const [username, setUsername] = useState(""); @@ -11,12 +13,14 @@ export default function TicTacToe() { ]); const [turn, setTurn] = useState(0); const [winner, setWinner] = useState(null); + const [openMatches, setOpenMatches] = useState([]); const { loginOrRegister, joinMatchmaker, onMatchData, sendMatchData, + listOpenMatches, matchId, } = useNakama(); @@ -32,6 +36,25 @@ export default function TicTacToe() { }); }, [onMatchData]); + useEffect(() => { + let active = true; + + async function refreshLoop() { + while (active) { + const matches = await listOpenMatches(); + setOpenMatches(matches); + + await new Promise(res => setTimeout(res, 500)); // 0.5s refresh + } + } + + refreshLoop(); + + return () => { + active = false; + }; + }, [listOpenMatches]); + // ------------------------------------------ // CONNECT // ------------------------------------------ @@ -82,6 +105,9 @@ export default function TicTacToe() { /> + )} diff --git a/src/tictactoe/providers/NakamaProvider.tsx b/src/tictactoe/providers/NakamaProvider.tsx index eeed378..2daab52 100644 --- a/src/tictactoe/providers/NakamaProvider.tsx +++ b/src/tictactoe/providers/NakamaProvider.tsx @@ -3,10 +3,12 @@ import { Session, Socket, MatchmakerTicket, - Match, MatchData, MatchmakerMatched, } from "@heroiclabs/nakama-js"; +// @ts-ignore +import { ApiMatch } from "@heroiclabs/nakama-js/dist/api.gen" + import React, { createContext, useContext, useState } from "react"; function getOrCreateDeviceId(): string { @@ -32,6 +34,7 @@ export interface NakamaContextType { sendMatchData(matchId: string, op: number, data: object): void; onMatchData(cb: (msg: any) => void): void; + listOpenMatches(): Promise; } export const NakamaContext = createContext(null!); @@ -128,6 +131,19 @@ export function NakamaProvider({ children }: { children: React.ReactNode }) { }; } + async function listOpenMatches(): Promise { + if (!session) { + console.warn("[Nakama] listOpenMatches called before login"); + return []; + } + + const result = await client.listMatches(session, 10); + + console.log("[Nakama] Open matches:", result.matches); + + return result.matches ?? []; + } + return ( {children}