Show live online-players count on the home screen
- OnlineService.getOnlineCount(); mock random-walks a believable number, SignalrService reads GET /api/stats/online (server tracks hub connections) - Home screen badge with pulsing dot, polls every 8s, localized digits Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -12,10 +12,12 @@ import {
|
||||
Users,
|
||||
Wifi,
|
||||
} from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useGameStore } from "@/lib/game-store";
|
||||
import { useSessionStore } from "@/lib/session-store";
|
||||
import { useUIStore, type Screen } from "@/lib/ui-store";
|
||||
import { useI18n } from "@/lib/i18n";
|
||||
import { getService } from "@/lib/online/service";
|
||||
import { sound } from "@/lib/sound";
|
||||
import { SUIT_SYMBOL } from "@/lib/hokm/types";
|
||||
import { TopBar } from "./online/TopBar";
|
||||
@@ -64,6 +66,7 @@ export function HomeScreen() {
|
||||
{t("app.title")}
|
||||
</h1>
|
||||
<p className="text-cream/60 mt-1 text-sm">{t("app.subtitle")}</p>
|
||||
<OnlinePlayers />
|
||||
</motion.div>
|
||||
|
||||
{/* primary actions */}
|
||||
@@ -191,6 +194,41 @@ function Tile({
|
||||
);
|
||||
}
|
||||
|
||||
function OnlinePlayers() {
|
||||
const { t, locale } = useI18n();
|
||||
const [count, setCount] = useState<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let alive = true;
|
||||
const tick = async () => {
|
||||
try {
|
||||
const n = await getService().getOnlineCount();
|
||||
if (alive) setCount(n);
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
};
|
||||
tick();
|
||||
const id = setInterval(tick, 8000);
|
||||
return () => {
|
||||
alive = false;
|
||||
clearInterval(id);
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (count == null) return null;
|
||||
const n = new Intl.NumberFormat(locale === "fa" ? "fa-IR" : "en-US").format(count);
|
||||
return (
|
||||
<div className="mt-3 inline-flex items-center gap-2 glass rounded-full px-3 py-1.5">
|
||||
<span className="relative flex size-2.5">
|
||||
<span className="absolute inline-flex h-full w-full rounded-full bg-teal-400 opacity-70 animate-ping" />
|
||||
<span className="relative inline-flex size-2.5 rounded-full bg-teal-400" />
|
||||
</span>
|
||||
<span className="text-xs text-cream/85">{t("home.onlineCount", { n })}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function FloatingSuits() {
|
||||
const suits = Object.values(SUIT_SYMBOL);
|
||||
const items = Array.from({ length: 8 }, (_, i) => ({
|
||||
|
||||
Reference in New Issue
Block a user