mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
tiny toasts!
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -11,8 +11,8 @@
|
|||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||||
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
|
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
|
||||||
<title>Multi Roomba Rover</title>
|
<title>Multi Roomba Rover</title>
|
||||||
<script type="module" crossorigin src="/assets/index-DAR128uo.js"></script>
|
<script type="module" crossorigin src="/assets/index-D-77ZqXZ.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-BiAFhEoZ.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-Cc3cNOzE.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from 'react';
|
|||||||
import { useSession } from '../context/SessionContext.jsx';
|
import { useSession } from '../context/SessionContext.jsx';
|
||||||
import ChatMessageRow from './ChatMessageRow.jsx';
|
import ChatMessageRow from './ChatMessageRow.jsx';
|
||||||
|
|
||||||
const LIFETIME_MS = 5000;
|
const LIFETIME_MS = 3000;
|
||||||
const DEFAULT_COLOR = '#2196f3';
|
const DEFAULT_COLOR = '#2196f3';
|
||||||
|
|
||||||
function buildKey(alert) {
|
function buildKey(alert) {
|
||||||
@@ -14,7 +14,7 @@ function buildKey(alert) {
|
|||||||
export default function AlertFeed() {
|
export default function AlertFeed() {
|
||||||
const { alerts } = useSession();
|
const { alerts } = useSession();
|
||||||
const [now, setNow] = useState(() => Date.now());
|
const [now, setNow] = useState(() => Date.now());
|
||||||
const latest = useMemo(() => alerts.slice(-5).map((alert) => ({ alert, key: buildKey(alert) })), [alerts]);
|
const latest = useMemo(() => alerts.slice(-3).map((alert) => ({ alert, key: buildKey(alert) })), [alerts]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!latest.length) return undefined;
|
if (!latest.length) return undefined;
|
||||||
@@ -57,15 +57,18 @@ function AlertToast({ alert }) {
|
|||||||
return <ChatMessageRow message={alert.payload} />;
|
return <ChatMessageRow message={alert.payload} />;
|
||||||
}
|
}
|
||||||
const rgb = hexToRgb(alert.color) || hexToRgb(DEFAULT_COLOR);
|
const rgb = hexToRgb(alert.color) || hexToRgb(DEFAULT_COLOR);
|
||||||
const backgroundColor = rgb ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.25)` : 'rgba(33, 150, 243, 0.25)';
|
const backgroundColor = rgb ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.18)` : 'rgba(33, 150, 243, 0.18)';
|
||||||
const borderColor = rgb ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.7)` : 'rgba(33, 150, 243, 0.7)';
|
const borderColor = rgb ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.45)` : 'rgba(33, 150, 243, 0.45)';
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="pointer-events-auto px-0.5 py-0.5 text-[0.85rem] text-slate-100"
|
className="pointer-events-auto max-w-[80vw] rounded-full border px-2 py-0.5 text-[0.7rem] leading-tight text-slate-100 shadow-sm shadow-black/30"
|
||||||
style={{ backgroundColor, border: `1px solid ${borderColor}` }}
|
style={{ backgroundColor, border: `1px solid ${borderColor}` }}
|
||||||
>
|
>
|
||||||
<p className="text-xs text-slate-200">{alert.title || 'Alert'}</p>
|
<p className="truncate text-slate-100">
|
||||||
<p className="text-sm text-white">{alert.message}</p>
|
<span className="text-slate-300">{alert.title || 'Alert'}</span>
|
||||||
|
<span className="text-slate-500"> · </span>
|
||||||
|
<span className="text-white">{alert.message}</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -710,6 +710,7 @@ function HudChatInput({ compact = false }) {
|
|||||||
const [draft, setDraft] = useState('');
|
const [draft, setDraft] = useState('');
|
||||||
const [sending, setSending] = useState(false);
|
const [sending, setSending] = useState(false);
|
||||||
const canChat = session?.role !== 'spectator';
|
const canChat = session?.role !== 'spectator';
|
||||||
|
const hideHudChat = session?.role === 'spectator';
|
||||||
const currentRoverId = session?.assignment?.roverId || null;
|
const currentRoverId = session?.assignment?.roverId || null;
|
||||||
const rover = useMemo(
|
const rover = useMemo(
|
||||||
() => session?.roster?.find((entry) => String(entry.id) === String(currentRoverId)) || null,
|
() => session?.roster?.find((entry) => String(entry.id) === String(currentRoverId)) || null,
|
||||||
@@ -756,6 +757,8 @@ function HudChatInput({ compact = false }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hideHudChat) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSend} className={containerClass}>
|
<form onSubmit={handleSend} className={containerClass}>
|
||||||
<input
|
<input
|
||||||
|
|||||||
Reference in New Issue
Block a user