Skip to content

Commit

Permalink
cleanup UserValue, LobbyValue
Browse files Browse the repository at this point in the history
  • Loading branch information
salvoilmiosi committed Oct 26, 2024
1 parent 9e7d5e1 commit 4b17149
Show file tree
Hide file tree
Showing 11 changed files with 47 additions and 75 deletions.
2 changes: 1 addition & 1 deletion src/Components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function Header({ scene, settings, connection }: HeaderProps) {
const handleLeaveLobby = () => connection.sendMessage({ lobby_leave: {}});
const handleReturnLobby = () => connection.sendMessage({ lobby_return: {}});

const myUser = scene.type === 'lobby' ? scene.lobbyState.users.find(user => user.id === scene.lobbyState.myUserId) : undefined;
const myUser = scene.type === 'lobby' ? scene.lobbyState.users.find(user => user.user_id === scene.lobbyState.myUserId) : undefined;
const isSpectator = myUser?.flags.includes('spectator') ?? false;
const handleToggleSpectate = () => connection.sendMessage({ user_spectate: !isSpectator });

Expand Down
4 changes: 2 additions & 2 deletions src/Components/LobbyChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default function LobbyChat({ connection, lobbyState: { myUserId, users, c
};

const transformChatArg = useMemo(() => createUnionDispatch<LobbyChatArg, string>({
user: user_id => clipUsername(getUser(users, user_id).name),
user: user_id => clipUsername(getUser(users, user_id).username),
integer: value => value.toString(),
string: value => value
}), [users]);
Expand All @@ -87,7 +87,7 @@ export default function LobbyChat({ connection, lobbyState: { myUserId, users, c
}
} else {
const pClass = props.user_id === myUserId ? 'text-right' : '';
return <p className={pClass}><span className='username'>{clipUsername(getUser(users, props.user_id).name)}</span> : {props.message}</p>;
return <p className={pClass}><span className='username'>{clipUsername(getUser(users, props.user_id).username)}</span> : {props.message}</p>;
}
}, [users, myUserId, transformChatArg]);

Expand Down
37 changes: 13 additions & 24 deletions src/Model/SceneState.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { Id } from "../Scenes/Game/Model/GameTable";
import { GameOptions } from "../Scenes/Game/Model/GameUpdate";
import { UserValue } from "../Scenes/Lobby/LobbyUser";
import { LobbyValue } from "../Scenes/WaitingArea/LobbyElement";
import { createUnionReducer } from "../Utils/UnionUtils";
import { ChatMessage, Empty, LobbyEntered, LobbyId, LobbyUpdate, LobbyUserUpdate, UserId } from "./ServerMessage";
import { ChatMessage, Empty, LobbyEntered, LobbyId, LobbyValue, UserId, UserValue } from "./ServerMessage";

export interface LobbyState {
lobbyId: LobbyId;
Expand All @@ -23,7 +20,7 @@ export function newLobbyState(lobbyId: LobbyId, myUserId: UserId): LobbyState {
export function isLobbyOwner(lobby: LobbyState) {
for (const user of lobby.users) {
if (!user.flags.includes('disconnected')) {
return user.id === lobby.myUserId;
return user.user_id === lobby.myUserId;
}
}
return false;
Expand All @@ -49,10 +46,10 @@ export type SceneUpdate =
{ gotoLobby: LobbyEntered } |
{ gotoGame: Empty } |
{ setError: ErrorState | null } |
{ updateLobbies: LobbyUpdate } |
{ updateLobbies: LobbyValue } |
{ removeLobby: LobbyId } |
{ setGameOptions: GameOptions } |
{ updateLobbyUser: LobbyUserUpdate } |
{ updateLobbyUser: UserValue } |
{ addLobbyChatMessage: ChatMessage };

export function defaultCurrentScene(sessionId?: number): SceneState {
Expand All @@ -63,25 +60,17 @@ export function defaultCurrentScene(sessionId?: number): SceneState {
}
}

function handleListUpdate<T extends Id>(values: T[], newValue: T): T[] {
function handleListUpdate<T, U>(values: T[], newValue: T, getId: (value: T) => U): T[] {
let copy = values.slice();
const index = copy.findIndex(value => value.id === newValue.id);
const index = copy.findIndex(value => getId(value) === getId(newValue));
if (index >= 0) {
copy[index] = { ...copy[index], ...newValue };
copy[index] = newValue;
} else {
copy.push(newValue);
}
return copy;
}

function newLobbyValue({ lobby_id, name, num_players, num_spectators, max_players, secure, state }: LobbyUpdate): LobbyValue {
return { id: lobby_id, name, num_players, num_spectators, max_players, secure, state };
}

function newUserValue({ user_id, username, propic, flags, lifetime }: LobbyUserUpdate): UserValue {
return { id: user_id, name: username, propic, flags, lifetime };
}

export const sceneReducer = createUnionReducer<SceneState, SceneUpdate>({
gotoHome() {
return { type: 'home' };
Expand All @@ -98,7 +87,7 @@ export const sceneReducer = createUnionReducer<SceneState, SceneUpdate>({
lobbyName: name,
gameOptions: options,
lobbyState: 'lobbyState' in this
? { ...this.lobbyState, users: this.lobbyState.users.filter(user => user.id >= 0) }
? { ...this.lobbyState, users: this.lobbyState.users.filter(user => user.user_id >= 0) }
: newLobbyState(lobby_id, user_id)
};
},
Expand All @@ -111,29 +100,29 @@ export const sceneReducer = createUnionReducer<SceneState, SceneUpdate>({
setError(error) {
return { ...this, error: error ?? undefined };
},
updateLobbies(update) {
updateLobbies(value) {
if (this.type !== 'waiting_area') {
throw new Error('Invalid scene type for updateLobbies: ' + this.type);
}
return { ...this, lobbies: handleListUpdate(this.lobbies, newLobbyValue(update)) };
return { ...this, lobbies: handleListUpdate(this.lobbies, value, lobby => lobby.lobby_id) };
},
removeLobby(lobby_id) {
if (this.type !== 'waiting_area') {
throw new Error('Invalid scene type for removeLobby: ' + this.type);
}
return { ...this, lobbies: this.lobbies.filter(lobby => lobby.id !== lobby_id) };
return { ...this, lobbies: this.lobbies.filter(lobby => lobby.lobby_id !== lobby_id) };
},
setGameOptions(gameOptions) {
if (this.type !== 'lobby') {
throw new Error('Invalid scene type for setGameOptions: ' + this.type);
}
return { ...this, gameOptions };
},
updateLobbyUser(update) {
updateLobbyUser(value) {
if (this.type !== 'lobby' && this.type !== 'game') {
throw new Error('Invalid scene type for updateLobbyUser: ' + this.type);
}
return { ...this, lobbyState: { ...this.lobbyState, users: handleListUpdate(this.lobbyState.users, newUserValue(update)) }};
return { ...this, lobbyState: { ...this.lobbyState, users: handleListUpdate(this.lobbyState.users, value, value => value.user_id) }};
},
addLobbyChatMessage(message) {
if (this.type !== 'lobby' && this.type !== 'game') {
Expand Down
8 changes: 4 additions & 4 deletions src/Model/ServerMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface ClientAccepted {

export type LobbyStateEnum = 'waiting' | 'playing' | 'finished';

export interface LobbyUpdate {
export interface LobbyValue {
lobby_id: LobbyId;
name: string;
num_players: number;
Expand All @@ -37,7 +37,7 @@ export type LobbyChatFlag = 'is_read' | 'translated';

export type LobbyUserFlag = 'disconnected' | 'spectator' | 'muted';

export interface LobbyUserUpdate {
export interface UserValue {
user_id: UserId;
username: string;
propic: string | null;
Expand All @@ -61,11 +61,11 @@ export type ServerMessage =
{ping: Empty} |
{client_accepted: ClientAccepted} |
{lobby_error: string} |
{lobby_update: LobbyUpdate} |
{lobby_update: LobbyValue} |
{lobby_entered: LobbyEntered} |
{lobby_game_options: GameOptions} |
{lobby_removed: LobbyRemoved} |
{lobby_user_update: LobbyUserUpdate} |
{lobby_user_update: UserValue} |
{lobby_kick: Empty} |
{lobby_chat: ChatMessage} |
{game_update: GameUpdate} |
Expand Down
2 changes: 1 addition & 1 deletion src/Scenes/Game/GameStringComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function PlayerNameView({ id }: PlayerNameProps) {

const player = getPlayer(table, id);
const user = getUser(users, player.user_id);
const username = clipUsername(user.name);
const username = clipUsername(user.username);

return <span className="player-name">{username}</span>;
}
Expand Down
8 changes: 4 additions & 4 deletions src/Scenes/Game/GameUsersView.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useContext, useMemo } from "react";
import { UserId } from "../../Model/ServerMessage";
import { UserId, UserValue } from "../../Model/ServerMessage";
import useCloseOnLoseFocus from "../../Utils/UseCloseOnLoseFocus";
import { getUser, LobbyContext } from "../Lobby/Lobby";
import LobbyUser, { UserValue } from "../Lobby/LobbyUser";
import LobbyUser from "../Lobby/LobbyUser";
import { GameStateContext } from "./GameScene";
import { isPlayerDead, isPlayerGhost } from "./Model/Filters";
import { Player } from "./Model/GameTable";
Expand Down Expand Up @@ -43,7 +43,7 @@ function GameUserPlayer({ player, user, myUserId }: GameUserProps) {
</div>;
}, [player]);

return <LobbyUser align='horizontal' user={user} isSelf={myUserId === user.id}>
return <LobbyUser align='horizontal' user={user} isSelf={myUserId === user.user_id}>
{ playerIcons }
</LobbyUser>;
}
Expand All @@ -68,7 +68,7 @@ export default function GameUsersView() {
}

return players.map(([user, player]) =>
<GameUserPlayer key={user.id} player={player} user={user} myUserId={myUserId} />
<GameUserPlayer key={user.user_id} player={player} user={user} myUserId={myUserId} />
);
}, [users, myUserId, table.players]);

Expand Down
3 changes: 2 additions & 1 deletion src/Scenes/Game/PlayerView.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { CSSProperties, Ref, RefObject, useContext, useImperativeHandle, useRef } from "react";
import Button from "../../Components/Button";
import getLabel from "../../Locale/GetLabel";
import { UserValue } from "../../Model/ServerMessage";
import { getDivRect, Rect } from "../../Utils/Rect";
import { useMapRef } from "../../Utils/UseMapRef";
import LobbyUser, { UserValue } from "../Lobby/LobbyUser";
import LobbyUser from "../Lobby/LobbyUser";
import { GameStateContext } from "./GameScene";
import { PocketType } from "./Model/CardEnums";
import { PlayerRef, PocketRef } from "./Model/CardTracker";
Expand Down
8 changes: 4 additions & 4 deletions src/Scenes/Lobby/Lobby.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import useEvent from 'react-use-event-hook';
import Button from '../../Components/Button';
import getLabel from '../../Locale/GetLabel';
import { LobbyState, isLobbyOwner, newLobbyState } from '../../Model/SceneState';
import { UserId } from '../../Model/ServerMessage';
import { UserId, UserValue } from '../../Model/ServerMessage';
import { BangConnection } from '../../Model/UseBangConnection';
import { GameOptions } from '../Game/Model/GameUpdate';
import GameOptionsEditor from './GameOptionsEditor';
import LobbyUser, { UserValue } from './LobbyUser';
import LobbyUser from './LobbyUser';

export function getUser(users: UserValue[], id: UserId): UserValue {
const user = users.find(user => user.id === id);
const user = users.find(user => user.user_id === id);
if (!user) {
throw new Error('cannot find user ' + id);
}
Expand Down Expand Up @@ -44,7 +44,7 @@ export default function LobbyScene({ gameOptions, setGameOptions, connection, lo
if (user.flags.includes('disconnected')) {
return [];
}
return <LobbyUser align='vertical' key={user.id} user={user} isSelf={user.id === lobbyState.myUserId} />;
return <LobbyUser align='vertical' key={user.user_id} user={user} isSelf={user.user_id === lobbyState.myUserId} />;
})}
</div>
</div>
Expand Down
28 changes: 10 additions & 18 deletions src/Scenes/Lobby/LobbyUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,10 @@ import { ReactNode } from "react";
import TimerWidget from "../../Components/TimerWidget";
import getLabel from "../../Locale/GetLabel";
import Env from "../../Model/Env";
import { LobbyUserFlag, Milliseconds, UserId } from "../../Model/ServerMessage";
import { UserValue } from "../../Model/ServerMessage";
import "./Style/LobbyUser.css";
import defaultUserPropic from "/media/icon_default_user.png";

export interface UserValue {
id: UserId;
name: string;
propic: string | null;
flags: LobbyUserFlag[];
lifetime: Milliseconds;
}

export interface LobbyUserProps {
user: UserValue;
isSelf?: boolean;
Expand All @@ -23,9 +15,9 @@ export interface LobbyUserProps {

export const DEFAULT_USER_PROPIC = defaultUserPropic;

export function getPropic(user: UserValue) {
if (user.propic) {
return `${Env.bangImageUrl}/${user.propic}`;
export function getPropicUrl(propic: string | null) {
if (propic) {
return `${Env.bangImageUrl}/${propic}`;
}
return DEFAULT_USER_PROPIC;
}
Expand All @@ -34,17 +26,17 @@ export function clipUsername(username: string): string {
return username.length !== 0 ? username : getLabel('ui', 'USERNAME_EMPTY');
}

export default function LobbyUser({ isSelf, user, align, children }: LobbyUserProps) {
const timerWidget = user && user.lifetime > 0 && <TimerWidget duration={user.lifetime} />;
const isSpectator = user && user.flags.includes('spectator');
const isDisconnected = user && user.flags.includes('disconnected');
export default function LobbyUser({ user: { username, propic, flags, lifetime}, isSelf, align, children }: LobbyUserProps) {
const timerWidget = lifetime > 0 && <TimerWidget duration={lifetime} />;
const isSpectator = flags.includes('spectator');
const isDisconnected = flags.includes('disconnected');
return (
<div className={`lobby-user ${isDisconnected ? 'lobby-user-disconnected ' : ''}${align === 'vertical' ? 'flex-col' : 'flex-row'}`}>
<div className='lobby-user-inner'>
<img src={getPropic(user)} alt="" />
<img src={getPropicUrl(propic)} alt="" />
</div>
<div className='lobby-username'>
<span className={isSelf ? 'lobby-username-self' : ''}>{clipUsername(user.name)}</span>
<span className={isSelf ? 'lobby-username-self' : ''}>{clipUsername(username)}</span>
{ isDisconnected ? <div className="mx-1 align-middle player-icon icon-disconnected"/>
: isSpectator ? <div className="mx-1 align-middle player-icon icon-spectator"/>
: null }
Expand Down
16 changes: 3 additions & 13 deletions src/Scenes/WaitingArea/LobbyElement.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
import Button from "../../Components/Button";
import getLabel from "../../Locale/GetLabel";
import { LobbyId } from "../../Model/ServerMessage";

export interface LobbyValue {
id: LobbyId;
name: string;
num_players: number;
num_spectators: number;
max_players: number;
secure: boolean;
state: string;
}
import { LobbyId, LobbyValue } from "../../Model/ServerMessage";

export interface LobbyElementProps {
lobby: LobbyValue;
onClickJoin: (lobby_id: LobbyId, secure: boolean) => void;
}

function LobbyElement({ lobby: { id, name, num_players, num_spectators, max_players, secure, state }, onClickJoin }: LobbyElementProps) {
function LobbyElement({ lobby: { lobby_id, name, num_players, num_spectators, max_players, secure, state }, onClickJoin }: LobbyElementProps) {
const numPlayersStatus = `${num_players}/${max_players}` + (num_spectators > 0 ? `+${num_spectators}` : '');
return (
<div className="lobby-element">
<div id='lobby-name'>{name}</div>
<div id='num-players'>{numPlayersStatus}</div>
<div id='lobby-state'>{getLabel('LobbyState', state)}</div>
<div id='lobby-button-join'><Button color='green' onClick={() => onClickJoin(id, secure)}>
<div id='lobby-button-join'><Button color='green' onClick={() => onClickJoin(lobby_id, secure)}>
{getLabel('ui', 'BUTTON_JOIN')}{secure && <div className='lobby-secure-icon' />}
</Button></div>
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/Scenes/WaitingArea/WaitingArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import BangLogo from "../../Components/BangLogo";
import Button from "../../Components/Button";
import getLabel from "../../Locale/GetLabel";
import AppSettings, { MAX_LOBBY_NAME_LENGTH } from "../../Model/AppSettings";
import { LobbyId } from "../../Model/ServerMessage";
import { LobbyId, LobbyValue } from "../../Model/ServerMessage";
import { BangConnection } from "../../Model/UseBangConnection";
import LobbyElement, { LobbyValue } from "./LobbyElement";
import LobbyElement from "./LobbyElement";
import './Style/WaitingArea.css';

export interface WaitingAreaProps {
Expand Down Expand Up @@ -81,7 +81,7 @@ function WaitingArea({ lobbies, connection, settings }: WaitingAreaProps) {
</form>
<div className='lobby-list'>
{lobbies.map((lobby) => (
<LobbyElement key={lobby.id} lobby={lobby} onClickJoin={handleClickJoin} />
<LobbyElement key={lobby.lobby_id} lobby={lobby} onClickJoin={handleClickJoin} />
))}
</div>
</div>
Expand Down

0 comments on commit 4b17149

Please sign in to comment.