perf(desktop): pause hidden-pane timers in agents view, cron sidebar, and floating pet
Partial pick of the surviving renderer hunks from #75395 (perf commit6502e441dplus fixup3fbbc9c1d): gate the 500ms subagent now-ticker and the cron sidebar 1s ticker/run-poll on usePaneVisible, and skip the legacy floating-pet poll while the document is hidden. Dropped hunks (electron/main.ts, vitest.setup.ts/config) intentionally excluded.
This commit is contained in:
parent
7700597a17
commit
52fb96de4b
|
|
@ -1,6 +1,7 @@
|
|||
import { useStore } from '@nanostores/react'
|
||||
import { type ReactNode, useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import { usePaneVisible } from '@/components/pane-shell/pane-visibility'
|
||||
import { useElapsedSeconds } from '@/components/chat/activity-timer'
|
||||
import { ActivityTimerText } from '@/components/chat/activity-timer-text'
|
||||
import { Codicon } from '@/components/ui/codicon'
|
||||
|
|
@ -189,15 +190,17 @@ function SubagentTree({ tree }: { tree: SubagentNode[] }) {
|
|||
const tokens = flat.reduce((sum, n) => sum + (n.inputTokens ?? 0) + (n.outputTokens ?? 0), 0)
|
||||
const cost = flat.reduce((sum, n) => sum + (n.costUsd ?? 0), 0)
|
||||
|
||||
const visible = usePaneVisible()
|
||||
|
||||
useEffect(() => {
|
||||
if (active <= 0 || typeof window === 'undefined') {
|
||||
if (active <= 0 || !visible || typeof window === 'undefined') {
|
||||
return
|
||||
}
|
||||
|
||||
const id = window.setInterval(() => setNowMs(Date.now()), 500)
|
||||
|
||||
return () => window.clearInterval(id)
|
||||
}, [active])
|
||||
}, [active, visible])
|
||||
|
||||
if (tree.length === 0) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { useStore } from '@nanostores/react'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import { usePaneVisible } from '@/components/pane-shell/pane-visibility'
|
||||
|
||||
import { ActionsContextMenu, type MenuKit, renderActionItem } from '@/components/ui/actions-menu'
|
||||
import { Codicon } from '@/components/ui/codicon'
|
||||
import { DisclosureCaret } from '@/components/ui/disclosure-caret'
|
||||
|
|
@ -92,17 +94,19 @@ export function SidebarCronJobsSection({
|
|||
// Rows revealed so far; starts compact, grows in steps via "load more".
|
||||
const [visibleCount, setVisibleCount] = useState(INITIAL_VISIBLE_JOBS)
|
||||
|
||||
const visible = usePaneVisible()
|
||||
|
||||
// One clock for the whole section (rows are pure) so the countdowns tick
|
||||
// without re-rendering the rest of the sidebar. Only runs while expanded.
|
||||
// without re-rendering the rest of the sidebar. Only runs while expanded and visible.
|
||||
useEffect(() => {
|
||||
if (!open) {
|
||||
if (!open || !visible) {
|
||||
return
|
||||
}
|
||||
|
||||
const id = window.setInterval(() => setNowMs(Date.now()), 1000)
|
||||
|
||||
return () => window.clearInterval(id)
|
||||
}, [open])
|
||||
}, [open, visible])
|
||||
|
||||
// Upcoming first (soonest next run), jobs with no next run sink to the bottom,
|
||||
// then alphabetical for stability.
|
||||
|
|
@ -328,6 +332,7 @@ function CronJobSidebarRuns({ jobId, onOpenRun }: { jobId: string; onOpenRun: (s
|
|||
const changeEventsAvailable = useStore($changeEventsAvailable)
|
||||
const cronChangeTick = useStore($cronChangeTick)
|
||||
const [runs, setRuns] = useState<null | SessionInfo[]>(null)
|
||||
const visible = usePaneVisible()
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false
|
||||
|
|
@ -345,11 +350,14 @@ function CronJobSidebarRuns({ jobId, onOpenRun }: { jobId: string; onOpenRun: (s
|
|||
}
|
||||
})
|
||||
|
||||
void load()
|
||||
// Initial load when visible
|
||||
if (visible) {
|
||||
void load()
|
||||
}
|
||||
|
||||
const intervalId = window.setInterval(
|
||||
() => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
if (visible && document.visibilityState === 'visible') {
|
||||
void load()
|
||||
}
|
||||
},
|
||||
|
|
@ -361,7 +369,7 @@ function CronJobSidebarRuns({ jobId, onOpenRun }: { jobId: string; onOpenRun: (s
|
|||
window.clearInterval(intervalId)
|
||||
}
|
||||
// cronChangeTick: a fired run reloads the peek immediately.
|
||||
}, [changeEventsAvailable, cronChangeTick, jobId])
|
||||
}, [changeEventsAvailable, cronChangeTick, jobId, visible])
|
||||
|
||||
return (
|
||||
<div className="mb-1 ml-[1.375rem] flex flex-col gap-px">
|
||||
|
|
|
|||
|
|
@ -214,7 +214,11 @@ export function FloatingPet() {
|
|||
// so no timer. Legacy backend: the historical poll.
|
||||
const timer = changeEventsAvailable
|
||||
? null
|
||||
: window.setInterval(() => void pull(), active ? PET_ACTIVE_REFRESH_MS : PET_POLL_MS)
|
||||
: window.setInterval(() => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
void pull()
|
||||
}
|
||||
}, active ? PET_ACTIVE_REFRESH_MS : PET_POLL_MS)
|
||||
|
||||
return () => {
|
||||
cancelled = true
|
||||
|
|
|
|||
Loading…
Reference in New Issue