mirror of
https://github.com/stablyai/orca.git
synced 2026-11-14 01:47:24 +00:00
refactor(renderer): spell out logical assignments React Compiler can't lower yet (#39339)
React Compiler skips any function containing `??=`, `||=` or `&&=`. Rewrite
the statement-position ones whose target re-reads without side effects
(identifiers and plain member chains) as the equivalent `if`:
a ??= b -> if (a == null) { a = b }
a ||= b -> if (!a) { a = b }
a &&= b -> if (a) { a = b }
21 files; 25 fewer bailouts and 12 more compiled functions in the
compiler-compat baseline.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
@@ -77,10 +77,8 @@
|
||||
1 src/renderer/src/components/crash-report/CrashReportDialog.tsx
|
||||
1 src/renderer/src/components/crash-report/CrashReportDialogSurface.tsx
|
||||
3 src/renderer/src/components/crash-report/use-crash-report-copy.ts
|
||||
1 src/renderer/src/components/dashboard-popout/useDashboardSnapshot.ts
|
||||
2 src/renderer/src/components/dashboard/useAgentBucketCounts.ts
|
||||
1 src/renderer/src/components/dashboard/useAgentBucketCounts.ts
|
||||
1 src/renderer/src/components/dashboard/useLiveDashboardSnapshot.ts
|
||||
1 src/renderer/src/components/dashboard/useRetainedAgents.ts
|
||||
2 src/renderer/src/components/diff-comments/DiffCommentCard.tsx
|
||||
5 src/renderer/src/components/diff-comments/DiffCommentPopover.tsx
|
||||
2 src/renderer/src/components/diff-comments/diff-comment-draft-zone.ts
|
||||
@@ -137,7 +135,6 @@
|
||||
1 src/renderer/src/components/editor/rich-markdown/review/useRichMarkdownReviewData.ts
|
||||
1 src/renderer/src/components/editor/rich-markdown/review/useRichMarkdownReviewRailController.ts
|
||||
12 src/renderer/src/components/editor/rich-markdown/tables/RichMarkdownTableControls.tsx
|
||||
2 src/renderer/src/components/editor/rich-markdown/tables/use-rich-markdown-table-control-target.ts
|
||||
2 src/renderer/src/components/editor/use-editor-group-file-drop-owner.ts
|
||||
1 src/renderer/src/components/editor/use-monaco-content-sync-bridge.ts
|
||||
1 src/renderer/src/components/editor/use-monaco-editor-mount.ts
|
||||
@@ -165,8 +162,7 @@
|
||||
1 src/renderer/src/components/feature-wall/WorkbenchTerminalSplitMenu.tsx
|
||||
1 src/renderer/src/components/feature-wall/agents-orchestration/OrchestrationPage.tsx
|
||||
2 src/renderer/src/components/feature-wall/agents-orchestration/UsageAccountsCard.tsx
|
||||
1 src/renderer/src/components/feature-wall/use-feature-wall-session-depth.ts
|
||||
3 src/renderer/src/components/feature-wall/use-feature-wall-tour-telemetry.ts
|
||||
2 src/renderer/src/components/feature-wall/use-feature-wall-tour-telemetry.ts
|
||||
3 src/renderer/src/components/feature-wall/useAiCommitPrSettings.ts
|
||||
1 src/renderer/src/components/floating-terminal/FloatingTerminalIconContextMenu.tsx
|
||||
3 src/renderer/src/components/floating-terminal/FloatingTerminalToggleButton.tsx
|
||||
@@ -211,9 +207,8 @@
|
||||
2 src/renderer/src/components/mobile/use-mobile-page-paired-devices.ts
|
||||
1 src/renderer/src/components/mobile/use-mobile-pairing-generation.ts
|
||||
1 src/renderer/src/components/native-chat-restart-runtimes.ts
|
||||
1 src/renderer/src/components/native-chat-resume-on-restart-store.ts
|
||||
1 src/renderer/src/components/native-chat/AddToChatMenu.tsx
|
||||
2 src/renderer/src/components/native-chat/NativeChatAccountUsageCard.tsx
|
||||
1 src/renderer/src/components/native-chat/NativeChatAccountUsageCard.tsx
|
||||
6 src/renderer/src/components/native-chat/NativeChatAutocompleteMenus.tsx
|
||||
1 src/renderer/src/components/native-chat/NativeChatComposerField.tsx
|
||||
2 src/renderer/src/components/native-chat/NativeChatComposerToolbar.tsx
|
||||
@@ -237,21 +232,19 @@
|
||||
8 src/renderer/src/components/native-chat/use-native-chat-composer-attachments.ts
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-composer-keydown.ts
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-context-clear-floor.ts
|
||||
3 src/renderer/src/components/native-chat/use-native-chat-find-matches.ts
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-find.ts
|
||||
6 src/renderer/src/components/native-chat/use-native-chat-fork.ts
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-hand-off.tsx
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-history-retention.ts
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-launch-prompt-delivery-notice.ts
|
||||
3 src/renderer/src/components/native-chat/use-native-chat-live-session.ts
|
||||
4 src/renderer/src/components/native-chat/use-native-chat-message-rail.ts
|
||||
2 src/renderer/src/components/native-chat/use-native-chat-live-session.ts
|
||||
3 src/renderer/src/components/native-chat/use-native-chat-message-rail.ts
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-mobile-hold-notice.ts
|
||||
2 src/renderer/src/components/native-chat/use-native-chat-paste-lifetime.ts
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-pending-delivery.ts
|
||||
2 src/renderer/src/components/native-chat/use-native-chat-provisional-launch.ts
|
||||
2 src/renderer/src/components/native-chat/use-native-chat-resolved-path-attachments.ts
|
||||
4 src/renderer/src/components/native-chat/use-native-chat-retained-session.ts
|
||||
2 src/renderer/src/components/native-chat/use-native-chat-selected-history.ts
|
||||
3 src/renderer/src/components/native-chat/use-native-chat-retained-session.ts
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-selected-history.ts
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-session-context-actions.tsx
|
||||
1 src/renderer/src/components/native-chat/use-native-chat-session-option-command.ts
|
||||
2 src/renderer/src/components/native-chat/use-native-chat-skills.ts
|
||||
@@ -278,7 +271,6 @@
|
||||
2 src/renderer/src/components/onboarding/AgentStep.tsx
|
||||
2 src/renderer/src/components/onboarding/NotificationStep.tsx
|
||||
8 src/renderer/src/components/onboarding/OnboardingFlow.tsx
|
||||
1 src/renderer/src/components/onboarding/OnboardingInlineCommandTerminal.tsx
|
||||
3 src/renderer/src/components/onboarding/OnboardingLanguageSwitcher.tsx
|
||||
1 src/renderer/src/components/onboarding/ThemeLookCarousel.tsx
|
||||
1 src/renderer/src/components/onboarding/ThemeLookGallery.tsx
|
||||
@@ -295,7 +287,6 @@
|
||||
3 src/renderer/src/components/plugins/dialogs/PluginMarketplaceSourceDialog.tsx
|
||||
1 src/renderer/src/components/plugins/frames/use-plugin-frame-entry.ts
|
||||
1 src/renderer/src/components/plugins/frames/use-plugin-frame-host.ts
|
||||
1 src/renderer/src/components/plugins/frames/use-plugin-panel-theme-revision.ts
|
||||
4 src/renderer/src/components/plugins/list/PluginsSettingsSection.tsx
|
||||
1 src/renderer/src/components/plugins/page/PluginContributionActionCommand.tsx
|
||||
2 src/renderer/src/components/plugins/state/use-plugin-catalog.ts
|
||||
@@ -303,7 +294,7 @@
|
||||
1 src/renderer/src/components/plugins/state/use-plugin-install-action.ts
|
||||
2 src/renderer/src/components/plugins/state/use-plugin-marketplace-lifecycle.ts
|
||||
1 src/renderer/src/components/plugins/state/use-plugin-settings-writes.ts
|
||||
3 src/renderer/src/components/ports/WorkspacePortScanner.tsx
|
||||
1 src/renderer/src/components/ports/WorkspacePortScanner.tsx
|
||||
2 src/renderer/src/components/provider-accounts/AntigravityChatAuthForm.tsx
|
||||
1 src/renderer/src/components/pull-request-page/checks/tab.tsx
|
||||
2 src/renderer/src/components/pull-request-page/comments/composer.tsx
|
||||
@@ -360,7 +351,6 @@
|
||||
1 src/renderer/src/components/right-sidebar/hosted-review/provider-actions/HostedReviewActions.tsx
|
||||
6 src/renderer/src/components/right-sidebar/hosted-review/provider-actions/use-hosted-review-actions.ts
|
||||
2 src/renderer/src/components/right-sidebar/hosted-review/provider-actions/use-ready-hosted-review-action.ts
|
||||
1 src/renderer/src/components/right-sidebar/plugin-panels/declarative/use-plugin-declarative-tree.ts
|
||||
1 src/renderer/src/components/right-sidebar/source-control/ai/text-generation-dialog-form.tsx
|
||||
1 src/renderer/src/components/right-sidebar/source-control/ai/text-generation-dialog.tsx
|
||||
1 src/renderer/src/components/right-sidebar/source-control/ai/use-conflict-recovery-composer.ts
|
||||
@@ -389,7 +379,6 @@
|
||||
1 src/renderer/src/components/right-sidebar/source-control/review/use-hosted-review-provider-hint.ts
|
||||
1 src/renderer/src/components/right-sidebar/source-control/sync/git-history-panel.tsx
|
||||
1 src/renderer/src/components/right-sidebar/source-control/sync/git-status-file-watch-refresh.ts
|
||||
1 src/renderer/src/components/right-sidebar/source-control/sync/git-status-push-signal-refresh.ts
|
||||
1 src/renderer/src/components/right-sidebar/source-control/sync/use-branch-compare.ts
|
||||
1 src/renderer/src/components/right-sidebar/source-control/sync/use-conflict-abort.ts
|
||||
1 src/renderer/src/components/right-sidebar/source-control/sync/use-remote-action-runner.ts
|
||||
@@ -572,7 +561,7 @@
|
||||
1 src/renderer/src/components/status-bar/RuntimeHostStatusRow.tsx
|
||||
2 src/renderer/src/components/status-bar/SshTargetStatusRow.tsx
|
||||
1 src/renderer/src/components/status-bar/icons.tsx
|
||||
4 src/renderer/src/components/status-bar/status-bar-density.ts
|
||||
3 src/renderer/src/components/status-bar/status-bar-density.ts
|
||||
2 src/renderer/src/components/status-bar/use-codex-switcher-controller.ts
|
||||
1 src/renderer/src/components/status-bar/use-owner-usage-rate-limits.ts
|
||||
1 src/renderer/src/components/status-bar/use-provider-account-list.ts
|
||||
@@ -687,7 +676,6 @@
|
||||
2 src/renderer/src/components/workspace-cleanup/use-workspace-cleanup-git-evidence.ts
|
||||
1 src/renderer/src/components/workspace-cleanup/workspace-cleanup-candidate-list.tsx
|
||||
2 src/renderer/src/components/workspace-emoji/useWorkspaceEmojiShortcodeInput.ts
|
||||
1 src/renderer/src/components/workspace-space/SpaceWindowStatePublisher.tsx
|
||||
1 src/renderer/src/components/worktree-jump/use-worktree-jump-palette-list-entries.ts
|
||||
1 src/renderer/src/components/worktree-jump/use-worktree-jump-palette-local-state.ts
|
||||
1 src/renderer/src/components/worktree-jump/use-worktree-jump-palette-open-tabs.ts
|
||||
|
||||
@@ -50,7 +50,9 @@ export function useDashboardSnapshot(): DashboardSnapshot {
|
||||
clearTimeout(topologyRefreshTimer)
|
||||
}
|
||||
const now = Date.now()
|
||||
topologyRefreshStartedAt ??= now
|
||||
if (topologyRefreshStartedAt == null) {
|
||||
topologyRefreshStartedAt = now
|
||||
}
|
||||
const remainingMaxWait = Math.max(
|
||||
0,
|
||||
TOPOLOGY_REFRESH_MAX_WAIT_MS - (now - topologyRefreshStartedAt)
|
||||
|
||||
@@ -117,7 +117,9 @@ export function useAgentBucketCounts(): AgentBucketCounts {
|
||||
const state = useAppStore(selectAgentBucketCountState)
|
||||
// Cache per worktree so status/title churn in one workspace does not rebuild every row pipeline.
|
||||
const cacheRef = useRef<ReturnType<typeof createDashboardBucketCountsCache>>(undefined!)
|
||||
cacheRef.current ??= createDashboardBucketCountsCache()
|
||||
if (cacheRef.current == null) {
|
||||
cacheRef.current = createDashboardBucketCountsCache()
|
||||
}
|
||||
return useMemo(() => {
|
||||
// Freshness follows agentStatusEpoch in state; read the clock when that generation invalidates the memo, not as a dependency.
|
||||
// oxlint-disable-next-line react/purity -- wall time is sampled per epoch tick, as explained above.
|
||||
|
||||
@@ -138,7 +138,9 @@ export function useRetainedAgentsSync(): void {
|
||||
TerminalTab,
|
||||
TerminalTab
|
||||
> | null>(null)
|
||||
tabTopologyProjectionRef.current ??= createRetainedAgentsTabTopologyProjection()
|
||||
if (tabTopologyProjectionRef.current == null) {
|
||||
tabTopologyProjectionRef.current = createRetainedAgentsTabTopologyProjection()
|
||||
}
|
||||
const retainAgents = useAppStore((s) => s.retainAgents)
|
||||
const pruneRetainedAgents = useAppStore((s) => s.pruneRetainedAgents)
|
||||
const clearRetentionSuppressedPaneKeys = useAppStore((s) => s.clearRetentionSuppressedPaneKeys)
|
||||
|
||||
+9
-5
@@ -97,7 +97,9 @@ export function useRichMarkdownTableControlTarget(
|
||||
if (cell && editorDom.contains(cell)) {
|
||||
activate(cell)
|
||||
pendingPointerRef.current = { cell, x: event.clientX, y: event.clientY }
|
||||
pointerFrameRef.current ??= window.requestAnimationFrame(flushPointer)
|
||||
if (pointerFrameRef.current == null) {
|
||||
pointerFrameRef.current = window.requestAnimationFrame(flushPointer)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (
|
||||
@@ -133,10 +135,12 @@ export function useRichMarkdownTableControlTarget(
|
||||
}
|
||||
let layoutFrame: number | null = null
|
||||
const update = (): void => {
|
||||
layoutFrame ??= window.requestAnimationFrame(() => {
|
||||
layoutFrame = null
|
||||
setLayoutVersion((version) => version + 1)
|
||||
})
|
||||
if (layoutFrame == null) {
|
||||
layoutFrame = window.requestAnimationFrame(() => {
|
||||
layoutFrame = null
|
||||
setLayoutVersion((version) => version + 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
const observer = new ResizeObserver(update)
|
||||
observer.observe(table)
|
||||
|
||||
@@ -48,12 +48,14 @@ export function useFeatureWallSessionDepth(
|
||||
visitedReviewSteps: Set<ReviewStepId>
|
||||
lastGroupId: FeatureWallWorkflowId | null
|
||||
}>(undefined!)
|
||||
sessionDepthRef.current ??= {
|
||||
visitedWorkflows: new Set(),
|
||||
visitedAgentSteps: new Set(),
|
||||
visitedWorkbenchSteps: new Set(),
|
||||
visitedReviewSteps: new Set(),
|
||||
lastGroupId: null
|
||||
if (sessionDepthRef.current == null) {
|
||||
sessionDepthRef.current = {
|
||||
visitedWorkflows: new Set(),
|
||||
visitedAgentSteps: new Set(),
|
||||
visitedWorkbenchSteps: new Set(),
|
||||
visitedReviewSteps: new Set(),
|
||||
lastGroupId: null
|
||||
}
|
||||
}
|
||||
|
||||
const getTourDepthSummary = useCallback((): FeatureWallTourDepthSummary => {
|
||||
|
||||
@@ -78,7 +78,9 @@ export function useFeatureWallTourTelemetry(args: {
|
||||
}): { markExitAction: (exitAction: FeatureWallExitAction) => void } {
|
||||
const { isOpen, source, getDepthSummary } = args
|
||||
const telemetryRef = useRef<FeatureWallTourTelemetryState>(undefined!)
|
||||
telemetryRef.current ??= createFeatureWallTourTelemetryState()
|
||||
if (telemetryRef.current == null) {
|
||||
telemetryRef.current = createFeatureWallTourTelemetryState()
|
||||
}
|
||||
const sourceRef = useRef(source)
|
||||
const getDepthSummaryRef = useRef(getDepthSummary)
|
||||
// Refresh payload refs before open/close effects and unmount cleanup can emit.
|
||||
|
||||
@@ -26,7 +26,9 @@ export function useNativeChatRestartOffer(enabled: boolean, store = localNativeC
|
||||
const settingsLoaded = useAppStore((state) => state.settings !== null)
|
||||
useEffect(() => {
|
||||
if (enabled && settingsLoaded && store.target.kind === 'local') {
|
||||
launch ??= loadLaunchOffer(store).finally(markNativeChatLaunchResumeDecided)
|
||||
if (launch == null) {
|
||||
launch = loadLaunchOffer(store).finally(markNativeChatLaunchResumeDecided)
|
||||
}
|
||||
}
|
||||
}, [enabled, settingsLoaded, store])
|
||||
return useSyncExternalStore(
|
||||
|
||||
@@ -186,9 +186,11 @@ function ChatUsageReset({
|
||||
if (busy || !result.reset) {
|
||||
return
|
||||
}
|
||||
attempt.current ??= {
|
||||
idempotencyKey: createBrowserUuid(),
|
||||
expectedScope: result.reset.expectedScope
|
||||
if (attempt.current == null) {
|
||||
attempt.current = {
|
||||
idempotencyKey: createBrowserUuid(),
|
||||
expectedScope: result.reset.expectedScope
|
||||
}
|
||||
}
|
||||
setBusy(true)
|
||||
setFailed(false)
|
||||
|
||||
@@ -220,15 +220,21 @@ export function useNativeChatFindMatches({
|
||||
Array.from(record.removedNodes).some((node) => holdsMatch(node, matchNodesRef.current))
|
||||
)
|
||||
if (now) {
|
||||
frame ??= requestAnimationFrame(runSearch)
|
||||
if (frame == null) {
|
||||
frame = requestAnimationFrame(runSearch)
|
||||
}
|
||||
} else {
|
||||
timer ??= setTimeout(runSearch, TEXT_GROWTH_SEARCH_DELAY_MS)
|
||||
if (timer == null) {
|
||||
timer = setTimeout(runSearch, TEXT_GROWTH_SEARCH_DELAY_MS)
|
||||
}
|
||||
}
|
||||
})
|
||||
// A disclosure opens with a height animation (not a mutation): what it cut off at first shows at its end.
|
||||
const onAnimationEnd = (event: Event): void => {
|
||||
if (event.target instanceof Node && column?.contains(event.target)) {
|
||||
frame ??= requestAnimationFrame(runSearch)
|
||||
if (frame == null) {
|
||||
frame = requestAnimationFrame(runSearch)
|
||||
}
|
||||
}
|
||||
}
|
||||
root.addEventListener('animationend', onAnimationEnd)
|
||||
|
||||
@@ -53,7 +53,9 @@ export function useNativeChatHistoryRetention({
|
||||
const leaveEnd = useCallback(() => {
|
||||
cancelTrim()
|
||||
transition('browsing')
|
||||
release.current ??= retainHistory?.() ?? null
|
||||
if (release.current == null) {
|
||||
release.current = retainHistory?.() ?? null
|
||||
}
|
||||
}, [retainHistory, cancelTrim, transition])
|
||||
const returnToEnd = useCallback(
|
||||
(reason?: 'send') => {
|
||||
|
||||
@@ -71,7 +71,9 @@ export function useNativeChatLiveSession(
|
||||
const [appended, setAppended] = useState<NativeChatMessage[]>([])
|
||||
// Cache the id index so each frame costs O(incoming), not O(existing).
|
||||
const appendMergerRef = useRef<ReturnType<typeof createNativeChatMerger>>(undefined!)
|
||||
appendMergerRef.current ??= createNativeChatMerger(NATIVE_CHAT_SOURCE_PRIORITY)
|
||||
if (appendMergerRef.current == null) {
|
||||
appendMergerRef.current = createNativeChatMerger(NATIVE_CHAT_SOURCE_PRIORITY)
|
||||
}
|
||||
|
||||
const [hookState, hookStateStartedAt, hookHasWorkingSubagents] = useNativeChatHookStatus(paneKey)
|
||||
|
||||
|
||||
@@ -92,7 +92,9 @@ export function useNativeChatMessageRail({
|
||||
const slotIndex = previousItemsRef.current.find((item) => item.id === clicked.id)?.slotIndex
|
||||
const row = virtualItemsRef.current.find((item) => item.index === slotIndex)
|
||||
if (row && row.end > top && row.start < top + element.clientHeight) {
|
||||
clicked.offset ??= row.start - top
|
||||
if (clicked.offset == null) {
|
||||
clicked.offset = row.start - top
|
||||
}
|
||||
if (Math.abs(row.start - top - clicked.offset) <= ALIGN_ARRIVED_PX) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ export function useNativeChatRetainedSession(
|
||||
])
|
||||
const activeIdentityRef = useRef(identity)
|
||||
const retentionRef = useRef<ReturnType<typeof createNativeChatTranscriptRetention>>(undefined!)
|
||||
retentionRef.current ??= createNativeChatTranscriptRetention()
|
||||
if (retentionRef.current == null) {
|
||||
retentionRef.current = createNativeChatTranscriptRetention()
|
||||
}
|
||||
const sessionMatchesIdentity = activeIdentityRef.current === identity
|
||||
const readPhase = sessionMatchesIdentity ? session.readPhase : 'loading'
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ export function useNativeChatSelectedHistory({
|
||||
return false
|
||||
}
|
||||
setSelectedSource(sourceKey)
|
||||
release.current ??= retainHistory?.() ?? null
|
||||
if (release.current == null) {
|
||||
release.current = retainHistory?.() ?? null
|
||||
}
|
||||
return true
|
||||
}, [root, retainHistory, sourceKey])
|
||||
const deferTrim = useCallback(() => {
|
||||
|
||||
@@ -256,7 +256,9 @@ export function OnboardingInlineCommandTerminal({
|
||||
return
|
||||
}
|
||||
if (hasPty) {
|
||||
ptyFirstSeenAt ??= Date.now()
|
||||
if (ptyFirstSeenAt == null) {
|
||||
ptyFirstSeenAt = Date.now()
|
||||
}
|
||||
// GPU/canvas renderers may expose no DOM prompt text; settled PTY presence provides a bounded fallback.
|
||||
if (Date.now() - ptyFirstSeenAt >= PTY_TEXT_FALLBACK_MS) {
|
||||
scheduleInsert()
|
||||
|
||||
@@ -15,7 +15,9 @@ export function usePluginPanelThemeRevision(): number {
|
||||
// Compare baked shell values: unrelated root-style writes must not remount iframes and destroy panel state.
|
||||
const snapshotRef = useRef<string | null>(null)
|
||||
useEffect(() => {
|
||||
snapshotRef.current ??= readPanelThemeSnapshot()
|
||||
if (snapshotRef.current == null) {
|
||||
snapshotRef.current = readPanelThemeSnapshot()
|
||||
}
|
||||
const observer = new MutationObserver(() => {
|
||||
const snapshot = readPanelThemeSnapshot()
|
||||
if (snapshot === snapshotRef.current) {
|
||||
|
||||
@@ -148,7 +148,9 @@ export function WorkspacePortScanner({ enabled = true }: { enabled?: boolean }):
|
||||
let sourceChanged =
|
||||
Object.keys(scansByKey).length !== Object.keys(publishedScans).length
|
||||
for (const { key, result } of reconciled) {
|
||||
sourceChanged ||= scansByKey[key] !== result
|
||||
if (!sourceChanged) {
|
||||
sourceChanged = scansByKey[key] !== result
|
||||
}
|
||||
scansByKey[key] = result
|
||||
}
|
||||
const merged = mergeWorkspacePortScans(scansByKey)
|
||||
@@ -290,7 +292,9 @@ export function WorkspacePortScanner({ enabled = true }: { enabled?: boolean }):
|
||||
return
|
||||
}
|
||||
// Keep the leading scan through the quiet window so sequential events share it too.
|
||||
burstRefresh ??= refresh({ force: true, targets: [LOCAL_TARGET] })
|
||||
if (burstRefresh == null) {
|
||||
burstRefresh = refresh({ force: true, targets: [LOCAL_TARGET] })
|
||||
}
|
||||
void burstRefresh.finally(() => {
|
||||
if (disposed || sequence !== eventSequence) {
|
||||
return
|
||||
|
||||
+3
-1
@@ -144,7 +144,9 @@ export function usePluginDeclarativeTree(
|
||||
return {
|
||||
onRender: (payload) => {
|
||||
pendingRef.current = { payload }
|
||||
frameRef.current ??= requestAnimationFrame(flush)
|
||||
if (frameRef.current == null) {
|
||||
frameRef.current = requestAnimationFrame(flush)
|
||||
}
|
||||
},
|
||||
onRefused: (message, retryAfterMs) => {
|
||||
const payload: unknown =
|
||||
|
||||
+3
-1
@@ -101,7 +101,9 @@ export function useGitStatusPushSignalRefresh({
|
||||
fetchStatus
|
||||
}
|
||||
observers.add(observer)
|
||||
disposeSignals ??= subscribeSignals()
|
||||
if (disposeSignals == null) {
|
||||
disposeSignals = subscribeSignals()
|
||||
}
|
||||
return () => {
|
||||
observers.delete(observer)
|
||||
if (observers.size === 0) {
|
||||
|
||||
@@ -152,7 +152,9 @@ export function useStatusBarDensity(): {
|
||||
const bind =
|
||||
(target: ElementRef) =>
|
||||
(node: HTMLElement | null): void => {
|
||||
observerRef.current ??= new ResizeObserver(() => evaluate())
|
||||
if (observerRef.current == null) {
|
||||
observerRef.current = new ResizeObserver(() => evaluate())
|
||||
}
|
||||
if (target.current) {
|
||||
observerRef.current.unobserve(target.current)
|
||||
}
|
||||
|
||||
@@ -41,11 +41,13 @@ export function SpaceWindowStatePublisher(): null {
|
||||
}
|
||||
const offRequest = api.onWindowStateRequested(() => {
|
||||
windowOpen = true
|
||||
offStore ??= useAppStore.subscribe((next, previous) => {
|
||||
if (spaceWindowStateChanged(previous, next)) {
|
||||
queuePublish()
|
||||
}
|
||||
})
|
||||
if (offStore == null) {
|
||||
offStore = useAppStore.subscribe((next, previous) => {
|
||||
if (spaceWindowStateChanged(previous, next)) {
|
||||
queuePublish()
|
||||
}
|
||||
})
|
||||
}
|
||||
publish(true)
|
||||
})
|
||||
const offClose = api.onWindowClosed?.(() => {
|
||||
|
||||
Reference in New Issue
Block a user