mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
spectator nicknames, overseer common issue filtering
This commit is contained in:
@@ -2,29 +2,28 @@
|
||||
// Purpose: Defines the Nickname Form module and the local helpers/components used in this file.
|
||||
// Scope: Keeps behavior unchanged while isolating this concern into a clear, single-responsibility unit.
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useSessionActions, useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useSessionActions } from '../../context/SessionContext.jsx';
|
||||
import { useSettingsNamespace } from '../../settings/index.js';
|
||||
|
||||
export default function NicknameForm({ compact = false }) {
|
||||
const role = useSessionSelector((state) => state.session?.role || null);
|
||||
const { setNickname } = useSessionActions();
|
||||
const { value, save } = useSettingsNamespace('profile', { nickname: '' });
|
||||
const [nicknameInput, setNicknameInput] = useState(value.nickname || '');
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
const canSetNickname = role !== 'spectator';
|
||||
|
||||
useEffect(() => {
|
||||
setNicknameInput(value.nickname || '');
|
||||
}, [value.nickname]);
|
||||
|
||||
async function handleSave(event) {
|
||||
event.preventDefault();
|
||||
if (!canSetNickname) return;
|
||||
const trimmed = (nicknameInput || '').trim().slice(0, 32);
|
||||
if (!trimmed) return;
|
||||
setSaving(true);
|
||||
try {
|
||||
// Nicknames are identity metadata rather than rover-control permission.
|
||||
// Spectator pages use the same socket action and local profile storage as
|
||||
// the driver UI so chat/user-list labels stay consistent across routes.
|
||||
await setNickname(trimmed);
|
||||
save({ nickname: trimmed });
|
||||
} catch (err) {
|
||||
@@ -47,12 +46,11 @@ export default function NicknameForm({ compact = false }) {
|
||||
}}
|
||||
maxLength={32}
|
||||
placeholder="Enter a nickname"
|
||||
disabled={!canSetNickname}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleSave}
|
||||
disabled={!canSetNickname || saving}
|
||||
disabled={saving}
|
||||
className="button-dark h-full shrink-0 whitespace-nowrap px-0.5 py-0 disabled:opacity-50"
|
||||
>
|
||||
{saving ? 'Saving…' : compact ? 'Set' : 'Save'}
|
||||
|
||||
@@ -36,10 +36,8 @@ export default function RawUserPilePanel({
|
||||
fillHeight = false,
|
||||
compact = false,
|
||||
}) {
|
||||
const role = useSessionSelector((state) => state.session?.role || null);
|
||||
const users = useSessionSelector((state) => state.session?.users ?? []);
|
||||
const selfId = useSessionSelector((state) => state.session?.socketId || null);
|
||||
const canSetNickname = role !== 'spectator';
|
||||
|
||||
const sorted = useMemo(
|
||||
() =>
|
||||
@@ -76,7 +74,6 @@ export default function RawUserPilePanel({
|
||||
</div>
|
||||
<SocialButtonsGrid />
|
||||
</div>
|
||||
{!canSetNickname && <p className="text-xs text-slate-500">Spectators cannot set nicknames.</p>}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -56,13 +56,11 @@ export default function UserListPanel({
|
||||
compact = false,
|
||||
showBothTurnsAndUsers = false,
|
||||
}) {
|
||||
const role = useSessionSelector((state) => state.session?.role || null);
|
||||
const users = useSessionSelector((state) => state.session?.users ?? []);
|
||||
const selfId = useSessionSelector((state) => state.session?.socketId || null);
|
||||
const mode = useSessionSelector((state) => state.session?.mode || null);
|
||||
const turnQueues = useSessionSelector((state) => state.session?.turnQueues || {});
|
||||
const roster = useSessionSelector((state) => state.session?.roster || []);
|
||||
const canSetNickname = role !== 'spectator';
|
||||
const isTurnsMode = mode === 'turns';
|
||||
const [turnView, setTurnView] = useState('queues');
|
||||
|
||||
@@ -168,7 +166,6 @@ export default function UserListPanel({
|
||||
</div>
|
||||
<SocialButtonsGrid />
|
||||
</div>
|
||||
{!canSetNickname && <p className="text-xs text-slate-500">Spectators cannot set nicknames.</p>}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { useSession } from '../../context/SessionContext.jsx';
|
||||
import { useSpectatorMode } from '../../hooks/useSpectatorMode.js';
|
||||
import useDefaultNickname from '../../hooks/useDefaultNickname.js';
|
||||
import useUserIdentitySync from '../../hooks/useUserIdentitySync.js';
|
||||
import ChatPanel from '../../components/ChatPanel/index.jsx';
|
||||
import AlertFeed from '../../components/AlertFeed/index.jsx';
|
||||
import GlobalObjectiveBanner from '../../components/GlobalObjectiveBanner/index.jsx';
|
||||
@@ -20,6 +21,11 @@ export default function SpectatorContent() {
|
||||
const { session } = useSession();
|
||||
const inLockdown = session?.mode === 'lockdown';
|
||||
useDefaultNickname();
|
||||
// The spectator route is not rendered through App.jsx, so it must opt into
|
||||
// the same persisted identity heartbeat here. That keeps the existing
|
||||
// cookie-backed identity and saved nickname behavior active without adding a
|
||||
// separate spectator identity path.
|
||||
useUserIdentitySync();
|
||||
useSpectatorMode();
|
||||
const isPortraitLayout = usePortraitLayout();
|
||||
const roster = session?.roster ?? [];
|
||||
|
||||
Reference in New Issue
Block a user