fix(webapp): stabilize time-sensitive UI renders
This commit is contained in:
@@ -49,6 +49,7 @@ export function DashboardAgentHeader({
|
||||
onClose: () => void;
|
||||
}) {
|
||||
const [isHistoryOpen, setHistoryOpen] = useState(false);
|
||||
const [historyOpenedAt, setHistoryOpenedAt] = useState<number | null>(null);
|
||||
const [pendingDelete, setPendingDelete] = useState<DashboardAgentChat | null>(null);
|
||||
|
||||
return (
|
||||
@@ -57,7 +58,10 @@ export function DashboardAgentHeader({
|
||||
open={isHistoryOpen}
|
||||
onOpenChange={(open) => {
|
||||
setHistoryOpen(open);
|
||||
if (open) onOpenHistory();
|
||||
if (open) {
|
||||
setHistoryOpenedAt(Date.now());
|
||||
onOpenHistory();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<PopoverArrowTrigger
|
||||
@@ -74,19 +78,22 @@ export function DashboardAgentHeader({
|
||||
className="w-72 max-w-(--radix-popover-content-available-width) p-0"
|
||||
align="start"
|
||||
>
|
||||
<DashboardAgentHistoryMenu
|
||||
chats={chats}
|
||||
currentChatId={currentChatId}
|
||||
thinkingChatId={thinkingChatId}
|
||||
onSelect={(chatId) => {
|
||||
setHistoryOpen(false);
|
||||
onSelectChat(chatId);
|
||||
}}
|
||||
onRequestDelete={(chat) => {
|
||||
setHistoryOpen(false);
|
||||
setPendingDelete(chat);
|
||||
}}
|
||||
/>
|
||||
{historyOpenedAt === null ? null : (
|
||||
<DashboardAgentHistoryMenu
|
||||
chats={chats}
|
||||
currentChatId={currentChatId}
|
||||
thinkingChatId={thinkingChatId}
|
||||
now={historyOpenedAt}
|
||||
onSelect={(chatId) => {
|
||||
setHistoryOpen(false);
|
||||
onSelectChat(chatId);
|
||||
}}
|
||||
onRequestDelete={(chat) => {
|
||||
setHistoryOpen(false);
|
||||
setPendingDelete(chat);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
|
||||
@@ -80,17 +80,17 @@ export function DashboardAgentHistoryMenu({
|
||||
chats,
|
||||
currentChatId,
|
||||
thinkingChatId,
|
||||
now,
|
||||
onSelect,
|
||||
onRequestDelete,
|
||||
}: {
|
||||
chats: DashboardAgentChat[];
|
||||
currentChatId: string;
|
||||
thinkingChatId?: string | null;
|
||||
now: number;
|
||||
onSelect: (chatId: string) => void;
|
||||
onRequestDelete: (chat: DashboardAgentChat) => void;
|
||||
}) {
|
||||
const now = Date.now();
|
||||
|
||||
return (
|
||||
<div className="max-h-80 overflow-y-auto p-1.5 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-surface-control">
|
||||
{chats.length === 0 ? (
|
||||
|
||||
+4
-2
@@ -252,7 +252,9 @@ function CompleteDateTimeWaitpointForm({
|
||||
const project = useProject();
|
||||
const environment = useEnvironment();
|
||||
|
||||
const timeToComplete = waitpoint.completedAfter.getTime() - Date.now();
|
||||
// oxlint-disable-next-line react/react-compiler -- This form intentionally snapshots wall-clock time for its deadline UI.
|
||||
const now = Date.now();
|
||||
const timeToComplete = waitpoint.completedAfter.getTime() - now;
|
||||
if (timeToComplete < 0) {
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
@@ -286,7 +288,7 @@ function CompleteDateTimeWaitpointForm({
|
||||
<div className="flex items-center gap-1">
|
||||
<AnimatedHourglassIcon
|
||||
className="text-dimmed-dimmed size-4"
|
||||
delay={(waitpoint.completedAfter.getMilliseconds() - Date.now()) / 1000}
|
||||
delay={(waitpoint.completedAfter.getMilliseconds() - now) / 1000}
|
||||
/>
|
||||
<span className="mt-0.5 ">
|
||||
<LiveCountdown endTime={waitpoint.completedAfter} />
|
||||
|
||||
Reference in New Issue
Block a user