From 055e59d8969073612550fd20cb4c68bbe68f9786 Mon Sep 17 00:00:00 2001 From: Lang <7system7@gmail.com> Date: Mon, 13 Apr 2026 21:09:27 +0200 Subject: [PATCH] new: usr: registered users have avatars next to the timer #4 --- assets/css/mineseeker/_timer.scss | 30 +++++++++++++++++++ .../js/mine-seeker/components/GameTimer.jsx | 16 +++++++++- .../hooks/useServerCommunication.jsx | 4 +++ assets/js/mine-seeker/utils/constants.jsx | 1 + src/Util/TopicManager.php | 19 +++++++++--- 5 files changed, 65 insertions(+), 5 deletions(-) diff --git a/assets/css/mineseeker/_timer.scss b/assets/css/mineseeker/_timer.scss index fbf07f1..9fac241 100644 --- a/assets/css/mineseeker/_timer.scss +++ b/assets/css/mineseeker/_timer.scss @@ -49,6 +49,36 @@ box-shadow: 0 0 16px rgba(35, 111, 135, 0.75), 0 0 5px rgba(149, 207, 245, 0.5); } +#mine-wrapper .game-timer .timer-avatar { + width: 26px; + height: 26px; + border-radius: 50%; + overflow: hidden; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + font-size: 10px; + font-weight: bold; + font-family: 'Rajdhani', sans-serif; + background: rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.15); +} + +#mine-wrapper .game-timer .timer-avatar__img { + width: 100%; + height: 100%; + object-fit: cover; +} + +#mine-wrapper .game-timer.red-timer .timer-avatar__initials { + color: rgba(246, 125, 82, 0.85); +} + +#mine-wrapper .game-timer.blue-timer .timer-avatar__initials { + color: rgba(149, 207, 245, 0.85); +} + #mine-wrapper .game-timer .timer-icon { font-size: 15px; opacity: 0.7; diff --git a/assets/js/mine-seeker/components/GameTimer.jsx b/assets/js/mine-seeker/components/GameTimer.jsx index 80bc87a..46bf5c1 100644 --- a/assets/js/mine-seeker/components/GameTimer.jsx +++ b/assets/js/mine-seeker/components/GameTimer.jsx @@ -10,8 +10,20 @@ import React, { useEffect, useRef, useState } from 'react'; import { useGame } from '@mine-contexts'; +const renderAvatar = player => { + if (!player.registered) return null; + return ( +
+ {player.avatar + ? {player.name} + : {player.name.slice(0, 2).toUpperCase()} + } +
+ ); +}; + const GameTimer = () => { - const { overlay, connectionLost, endRef, activePlayer, webPlayer } = useGame(); + const { overlay, connectionLost, endRef, activePlayer, red, blue } = useGame(); const [redTime, setRedTime] = useState(0); const [blueTime, setBlueTime] = useState(0); const [isRunning, setIsRunning] = useState(false); @@ -151,10 +163,12 @@ const GameTimer = () => { return (
+ {renderAvatar(red)} {formatTime(redTime)}
+ {renderAvatar(blue)} {formatTime(blueTime)}
diff --git a/assets/js/mine-seeker/hooks/useServerCommunication.jsx b/assets/js/mine-seeker/hooks/useServerCommunication.jsx index 3e926c2..d52763f 100644 --- a/assets/js/mine-seeker/hooks/useServerCommunication.jsx +++ b/assets/js/mine-seeker/hooks/useServerCommunication.jsx @@ -90,10 +90,14 @@ const useServerCommunication = (gameAssoc, gameInherited, isEnvDev) => { syncRed(p => ({ ...p, name: payload.users.red || payload.users.redAnon || p.name, + registered: !!payload.users.red, + avatar: payload.users.redAvatar ?? null, })); syncBlue(p => ({ ...p, name: payload.users.blue || payload.users.blueAnon || p.name, + registered: !!payload.users.blue, + avatar: payload.users.blueAvatar ?? null, desc: 'blue' === webPlayerRef.current ? DESC.you : DESC.buddy, active: true, })); diff --git a/assets/js/mine-seeker/utils/constants.jsx b/assets/js/mine-seeker/utils/constants.jsx index c36cff1..a6d1fc7 100644 --- a/assets/js/mine-seeker/utils/constants.jsx +++ b/assets/js/mine-seeker/utils/constants.jsx @@ -36,6 +36,7 @@ export const IMAGES = { export const PLAYER_DEF = { name: '...', desc: '', active: false, mines: 0, haveBomb: true, enabledBomb: true, + registered: false, avatar: null, }; export const DESC = { diff --git a/src/Util/TopicManager.php b/src/Util/TopicManager.php index 09f6af3..f3caf04 100644 --- a/src/Util/TopicManager.php +++ b/src/Util/TopicManager.php @@ -18,6 +18,7 @@ use App\Entity\User; use App\Interfaces\TopicManagerInterface; use App\Repository\PlayedGameRepository; use App\Repository\UserRepository; +use Liip\ImagineBundle\Imagine\Cache\CacheManager; use DateTimeInterface; use DateTime; use Doctrine\ORM\EntityManagerInterface; @@ -47,6 +48,7 @@ readonly class TopicManager implements TopicManagerInterface private LoggerInterface $logger, private PlayedGameRepository $playedGameRepository, private UserRepository $userRepository, + private CacheManager $cacheManager, ) { } @@ -516,11 +518,20 @@ readonly class TopicManager implements TopicManagerInterface private function getUserCollection(PlayedGame $playedGame): array { + $redUser = $playedGame->getRed(); + $blueUser = $playedGame->getBlue(); + return [ - 'red' => null !== $playedGame->getRed() ? $playedGame->getRed()->getUsername() : '', - 'blue' => null !== $playedGame->getBlue() ? $playedGame->getBlue()->getUsername() : '', - 'redAnon' => null !== $playedGame->getRedAnon() ? $playedGame->getRedAnon()->getUserName() : '', - 'blueAnon' => null !== $playedGame->getBlueAnon() ? $playedGame->getBlueAnon()->getUserName() : '', + 'red' => null !== $redUser ? $redUser->getUsername() : '', + 'blue' => null !== $blueUser ? $blueUser->getUsername() : '', + 'redAnon' => null !== $playedGame->getRedAnon() ? $playedGame->getRedAnon()->getUserName() : '', + 'blueAnon' => null !== $playedGame->getBlueAnon() ? $playedGame->getBlueAnon()->getUserName() : '', + 'redAvatar' => null !== $redUser && null !== $redUser->getAvatarPath() + ? $this->cacheManager->generateUrl($redUser->getAvatarPath(), 'avatar_thumb') + : null, + 'blueAvatar' => null !== $blueUser && null !== $blueUser->getAvatarPath() + ? $this->cacheManager->generateUrl($blueUser->getAvatarPath(), 'avatar_thumb') + : null, ]; }