random food word nicknames!

This commit is contained in:
legop3
2026-01-15 17:26:31 -05:00
parent 2252527d89
commit d4ce6e9092
8 changed files with 321 additions and 48 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -11,8 +11,8 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
<title>Multi Roomba Rover</title>
<script type="module" crossorigin src="/assets/index-uKsdeTeF.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Cmh8Rw7S.css">
<script type="module" crossorigin src="/assets/index-DAR128uo.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BiAFhEoZ.css">
</head>
<body>
<div id="root"></div>
+2
View File
@@ -24,6 +24,7 @@ import HelpOverlay from './components/HelpOverlay.jsx';
import HelpPanel from './components/HelpPanel.jsx';
import SettingsPanel from './components/SettingsPanel.jsx';
import Tabs, { Tab, TabList, TabPanel, TabPanels } from './components/Tabs.jsx';
import useDefaultNickname from './hooks/useDefaultNickname.js';
function useLayoutMode() {
const [mode, setMode] = useState(() => {
@@ -177,6 +178,7 @@ function App() {
}
function AppWithProviders({ layout, isDesktop, fullscreen }) {
useDefaultNickname();
const {
visible: fullscreenVisible,
mode: fullscreenMode,
+107
View File
@@ -0,0 +1,107 @@
aroma
bagel
batter
beans
beer
biscuit
bread
broth
burger
burrito
butter
cake
candy
caramel
caviar
cheese
chili
chimichanga
chocolate
cider
cobbler
cocoa
coffee
cookie
cream
croissant
crumble
cuisine
curd
dessert
dish
drink
eggs
empanada
enchilada
entree
filet
fish
flour
foie gras
food
glaze
grill
hamburger
ice
juice
ketchup
kitchen
lard
liquor
margarine
marinade
mayo
mayonnaise
meat
milk
mousse
muffin
mushroom
noodle
nut
oil
olive
omelette
pan
pasta
paste
pastry
pie
pizza
plate
pot
poutine
pudding
queso
raclette
recipe
rice
salad
salsa
sandwich
sauce
seasoning
skillet
soda
sopapillas
soup
soy
spice
steak
stew
syrup
taco
taquito
tartar
taste
tea
toast
tostada
vinegar
waffle
water
wheat
wine
wok
yeast
yogurt
+49
View File
@@ -0,0 +1,49 @@
import { useEffect, useRef } from 'react';
import { useSettingsNamespace } from '../settings/index.js';
import { useSession } from '../context/SessionContext.jsx';
import wordListText from '../assets/wordlist.txt?raw';
function capitalize(word) {
if (!word) return '';
return word.charAt(0).toUpperCase() + word.slice(1);
}
function pickRandomWord() {
const words = String(wordListText || '')
.split(/\r?\n/)
.map((word) => word.trim())
.filter(Boolean);
if (!words.length) return '';
const selected = words[Math.floor(Math.random() * words.length)] || '';
return selected.trim();
}
export default function useDefaultNickname() {
const { setNickname } = useSession();
const { value, status, save } = useSettingsNamespace('profile', { nickname: '' });
const attemptedRef = useRef(false);
useEffect(() => {
if (status !== 'ready') return;
if (attemptedRef.current) return;
const existing = (value.nickname || '').trim();
if (existing) return;
attemptedRef.current = true;
const generated = capitalize(pickRandomWord()).slice(0, 32);
if (!generated) return;
const applyNickname = async () => {
try {
await setNickname(generated);
} catch (err) {
// Ignore server errors; still persist locally to avoid re-rolling.
} finally {
save({ nickname: generated });
}
};
applyNickname();
}, [save, setNickname, status, value.nickname]);
}
+2
View File
@@ -9,6 +9,7 @@ import { useRoomCameraSnapshots } from '../hooks/useRoomCameraSnapshots.js';
import VideoTile from '../components/VideoTile.jsx';
import ChatPanel from '../components/ChatPanel.jsx';
import AlertFeed from '../components/AlertFeed.jsx';
import useDefaultNickname from '../hooks/useDefaultNickname.js';
const ROTATE_MS = 20000;
@@ -24,6 +25,7 @@ function formatDriverLabel({ roverId, session }) {
function MiniSummaryContent() {
const { session } = useSession();
const spectatorReady = useSpectatorMode();
useDefaultNickname();
const inLockdown = session?.mode === 'lockdown';
const frames = useTelemetryFrames();
const roster = session?.roster ?? [];
+43 -37
View File
@@ -11,6 +11,7 @@ import ChatPanel from '../components/ChatPanel.jsx';
import LogPanel from '../components/LogPanel.jsx';
import RoverRoster from '../components/RoverRoster.jsx';
import AlertFeed from '../components/AlertFeed.jsx';
import useDefaultNickname from '../hooks/useDefaultNickname.js';
function formatDriverLabel({ roverId, session }) {
const activeDriverId = session?.activeDrivers?.[roverId] || null;
@@ -91,9 +92,10 @@ function LogsRow({ className = '' }) {
);
}
export default function SpectatorApp() {
function SpectatorContent() {
const { session } = useSession();
const inLockdown = session?.mode === 'lockdown';
useDefaultNickname();
useSpectatorMode();
const frames = useTelemetryFrames();
const roster = session?.roster ?? [];
@@ -110,48 +112,52 @@ export default function SpectatorApp() {
if (inLockdown) {
return (
<SettingsProvider>
<div className="flex min-h-screen items-center justify-center bg-black text-slate-200">
<div className="surface max-w-md space-y-0.5 p-1 text-center text-sm">
<p className="text-lg font-semibold text-white">Spectate disabled during lockdown.</p>
<p className="text-slate-300">Please wait until the server leaves lockdown to view streams.</p>
</div>
<div className="flex min-h-screen items-center justify-center bg-black text-slate-200">
<div className="surface max-w-md space-y-0.5 p-1 text-center text-sm">
<p className="text-lg font-semibold text-white">Spectate disabled during lockdown.</p>
<p className="text-slate-300">Please wait until the server leaves lockdown to view streams.</p>
</div>
</SettingsProvider>
</div>
);
}
return (
<div className="min-h-screen bg-black text-slate-100 md:h-screen md:overflow-hidden">
<main className="grid min-h-screen grid-cols-1 gap-0.5 p-0.5 md:h-full md:min-h-0 md:grid-cols-[minmax(0,1fr)_18rem] lg:grid-cols-[minmax(0,1fr)_20rem]">
<section className="flex min-h-0 min-w-0 flex-col gap-0.5 md:overflow-y-auto">
<RoverRow
roster={roster}
frames={frames}
snapshotFeeds={snapshotFeeds}
audioSources={audioSources}
session={session}
/>
<SecondaryRow />
</section>
<section className="flex min-h-0 min-w-0 flex-col gap-0.5 md:h-full">
<div className="panel">
<RoverRoster roster={roster} title="Rovers" emptyText="No rovers registered." />
</div>
<div className="min-h-0 min-w-0 flex-1 overflow-hidden">
<UserListPanel hideNicknameForm hideHeader fillHeight className="h-full" />
</div>
<div className="min-h-0 min-w-0 flex-[1.1] overflow-hidden">
<ChatPanel hideInput hideSpectatorNotice fillHeight />
</div>
<div className="min-h-0 min-w-0">
<LogsRow className="h-40 overflow-hidden" />
</div>
</section>
</main>
<AlertFeed />
</div>
);
}
export default function SpectatorApp() {
return (
<SettingsProvider>
<div className="min-h-screen bg-black text-slate-100 md:h-screen md:overflow-hidden">
<main className="grid min-h-screen grid-cols-1 gap-0.5 p-0.5 md:h-full md:min-h-0 md:grid-cols-[minmax(0,1fr)_18rem] lg:grid-cols-[minmax(0,1fr)_20rem]">
<section className="flex min-h-0 min-w-0 flex-col gap-0.5 md:overflow-y-auto">
<RoverRow
roster={roster}
frames={frames}
snapshotFeeds={snapshotFeeds}
audioSources={audioSources}
session={session}
/>
<SecondaryRow />
</section>
<section className="flex min-h-0 min-w-0 flex-col gap-0.5 md:h-full">
<div className="panel">
<RoverRoster roster={roster} title="Rovers" emptyText="No rovers registered." />
</div>
<div className="min-h-0 min-w-0 flex-1 overflow-hidden">
<UserListPanel hideNicknameForm hideHeader fillHeight className="h-full" />
</div>
<div className="min-h-0 min-w-0 flex-[1.1] overflow-hidden">
<ChatPanel hideInput hideSpectatorNotice fillHeight />
</div>
<div className="min-h-0 min-w-0">
<LogsRow className="h-40 overflow-hidden" />
</div>
</section>
</main>
<AlertFeed />
</div>
<SpectatorContent />
</SettingsProvider>
);
}