chore(cloud): mobile switch exhaustiveness; extract the read-panel hook

This commit is contained in:
Neil
2026-11-10 02:32:17 -08:00
parent 6fb8497a1a
commit 9dcda9941c
4 changed files with 36 additions and 20 deletions
@@ -226,6 +226,8 @@ function prChecksLabel(pr: ReadSnapshotPr, t: Translate): string | null {
case 'pending':
case 'running':
return t('cloud.snapshot.checks.pending', 'Checks running')
// No status, or one this build doesn't name: the VM's own summary line, if any.
case undefined:
default:
return pr.checksSummary
}
+6 -1
View File
@@ -37,7 +37,9 @@ export function attachErrorMessage(
'cloud.error.pairing',
'The workspace is running, but this phone couldn’t connect to it. Your files are safe.'
)
default:
case 'not_found':
return t('cloud.workspace.missing', 'This workspace is gone or you no longer have access.')
case 'failed':
return t(
'cloud.error.failed',
'The workspace couldn’t start. Try again, or open it on your desktop.'
@@ -128,6 +130,9 @@ export function cloudPromptErrorMessage(code: string | undefined, t: Translate):
return t('cloud.prompt.errorNotConnected', 'This phone couldn’t reach the workspace')
case 'cloud_agent_unknown':
return t('cloud.prompt.errorAgent', 'That agent isn’t installed in this workspace')
// An older queue entry may carry no code: it failed to launch all the same.
case undefined:
case 'launch_failed':
default:
return t('cloud.prompt.errorLaunch', 'The agent didn’t start')
}
@@ -1,6 +1,6 @@
// Home: the org's cloud workspaces (registry on the control plane), filterable by who owns them,
// which repo they are in, Mine/Team and archived, grouped by section, with live presence and cost.
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { toast } from 'sonner'
import { useAppStore } from '@/store'
import { useIntlLocale, useTranslate } from '@/i18n/use-translate'
@@ -18,7 +18,7 @@ import { ANY, CloudWorkspacesToolbar, type CloudWorkspacesFilters } from './Clou
import { EmptyState, ErrorState, NewSectionDialog, SkeletonRows } from './CloudWorkspacesStates'
import { CloudWorkspaceConfirmDialog, type PendingConfirm } from './CloudWorkspaceConfirmDialog'
import { CloudReadSnapshotSheet } from './CloudReadSnapshotSheet'
import type { CloudReadWake } from '../orca-cloud/read-snapshot/CloudReadSnapshotView'
import { useCloudReadPanel } from './use-cloud-read-panel'
import { formatSandboxHours, sandboxHours, type MemberDirectory } from './cloud-workspace-format'
import { refreshCloudMessageSenders } from '@/lib/cloud-message-sender'
import { describeError } from './cloud-workspace-errors'
@@ -87,22 +87,7 @@ export function CloudWorkspacesHome({
const [now, setNow] = useState(() => Date.now())
const [sectionFor, setSectionFor] = useState<CloudWorkspace | null>(null)
const [confirm, setConfirm] = useState<PendingConfirm | null>(null)
// The Asleep workspace whose read-only copy is open (never wakes it).
const [readingId, setReadingIdState] = useState<string | null>(null)
// A wake started from the read panel: shown there (elapsed, slow, failed) until it opens.
const [readWake, setReadWake] = useState<CloudReadWake | null>(null)
const readingRef = useRef<string | null>(null)
const setReadingId = useCallback(
(next: string | null | ((id: string | null) => string | null)) => {
const value = typeof next === 'function' ? next(readingRef.current) : next
if (value !== readingRef.current) {
setReadWake(null)
}
readingRef.current = value
setReadingIdState(value)
},
[]
)
const { readingId, readingRef, setReadingId, readWake, setReadWake } = useCloudReadPanel()
const signIn = useAppStore((s) => s.connectCurrentOrcaProfile)
const scope = orgId ? filters.scope : 'mine'
const { state, stale, reading, refresh, replace } = useCloudWorkspaces(
@@ -210,7 +195,7 @@ export function CloudWorkspacesHome({
setOpening((current) => (current === w.id ? null : current))
}
},
[setReadingId]
[readingRef, setReadWake, setReadingId]
)
const patch = useCallback(
@@ -0,0 +1,24 @@
import { useCallback, useRef, useState } from 'react'
import type { CloudReadWake } from '../orca-cloud/read-snapshot/CloudReadSnapshotView'
/**
* The Asleep workspace whose read-only copy is open (opening it never wakes it), plus a wake
* started from that panel, shown there (elapsed, slow, failed) until the workspace opens.
*/
export function useCloudReadPanel() {
const [readingId, setReadingIdState] = useState<string | null>(null)
const [readWake, setReadWake] = useState<CloudReadWake | null>(null)
const readingRef = useRef<string | null>(null)
const setReadingId = useCallback(
(next: string | null | ((id: string | null) => string | null)) => {
const value = typeof next === 'function' ? next(readingRef.current) : next
if (value !== readingRef.current) {
setReadWake(null)
}
readingRef.current = value
setReadingIdState(value)
},
[]
)
return { readingId, readingRef, setReadingId, readWake, setReadWake }
}