mirror of
https://github.com/stablyai/orca.git
synced 2026-11-15 18:37:24 +00:00
feat(cloud): asleep Files tab shows the files changed at sleep, read-only, with Wake; neutral note when nothing was saved (RA-10)
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import React from 'react'
|
||||
import { Play } from 'lucide-react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { useNow } from '@/hooks/use-now'
|
||||
import { useTranslate } from '@/i18n/use-translate'
|
||||
import { formatElapsedTime } from '@/components/worktree-creation/worktree-creation-clock'
|
||||
import { CloudGitChanges } from '../CloudGitChanges'
|
||||
import { wakeCloudWorkspace } from '../cloud-workspace-actions'
|
||||
import { useCloudOfflineData } from './use-cloud-offline-data'
|
||||
import type { CloudOfflineSnapshot } from '../../../../../shared/hosted-sandbox/cloud-workspace-offline-api'
|
||||
|
||||
/**
|
||||
* The Files tab of an Orca Cloud workspace that is asleep (RA-10). There is no file tree without
|
||||
* the VM, so instead of a read error and Retry: the files that had changed when it went to sleep
|
||||
* (from its read snapshot or this computer's cache), read-only and labeled as such, then Wake for
|
||||
* the full view. With no snapshot, a neutral note and Wake.
|
||||
*/
|
||||
export function CloudAsleepFilesPanel({ workspaceId }: { workspaceId: string }): React.JSX.Element {
|
||||
const t = useTranslate()
|
||||
const { snapshot } = useCloudOfflineData(workspaceId, true)
|
||||
const now = useNow(30_000)
|
||||
const git = snapshot?.git ?? null
|
||||
const wake = (
|
||||
<Button size="xs" variant="outline" onClick={() => void wakeCloudWorkspace(workspaceId)}>
|
||||
<Play />
|
||||
{t('orcaCloudWorkspace.wake', 'Wake')}
|
||||
</Button>
|
||||
)
|
||||
return (
|
||||
<div
|
||||
className="flex h-full min-h-0 flex-col gap-3 overflow-y-auto px-3 py-3 text-xs scrollbar-sleek"
|
||||
data-cloud-asleep-files={git ? 'snapshot' : 'none'}
|
||||
>
|
||||
{git ? (
|
||||
<>
|
||||
<SavedChanges git={git} at={snapshot?.capturedAt ?? null} now={now} />
|
||||
<div className="flex flex-col items-start gap-2 border-t border-border/60 pt-3 text-muted-foreground">
|
||||
<p>
|
||||
{t(
|
||||
'orcaCloudWorkspace.files.wakeForAll',
|
||||
'Wake the workspace to browse all its files.'
|
||||
)}
|
||||
</p>
|
||||
{wake}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex flex-col items-start gap-2 text-muted-foreground">
|
||||
<p>
|
||||
{t(
|
||||
'orcaCloudWorkspace.files.asleep',
|
||||
'Files aren’t available while the workspace is asleep.'
|
||||
)}
|
||||
</p>
|
||||
{wake}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function SavedChanges({
|
||||
git,
|
||||
at,
|
||||
now
|
||||
}: {
|
||||
git: NonNullable<CloudOfflineSnapshot['git']>
|
||||
at: number | null
|
||||
now: number
|
||||
}): React.JSX.Element {
|
||||
const t = useTranslate()
|
||||
return (
|
||||
<section className="flex flex-col gap-1.5">
|
||||
<h3 className="font-medium text-foreground">
|
||||
{at
|
||||
? t(
|
||||
'orcaCloudWorkspace.files.changedAtSleep',
|
||||
'Changed files when this workspace went to sleep · {{time}}',
|
||||
{
|
||||
time: t('orcaCloudWorkspace.ago', '{{ago}} ago', {
|
||||
ago: formatElapsedTime(Math.max(0, now - at))
|
||||
})
|
||||
}
|
||||
)
|
||||
: t(
|
||||
'orcaCloudWorkspace.files.changedAtSleepNoTime',
|
||||
'Changed files when this workspace went to sleep'
|
||||
)}
|
||||
</h3>
|
||||
<CloudGitChanges
|
||||
now={now}
|
||||
data={{
|
||||
branch: git.branch,
|
||||
changes: git.changes,
|
||||
changeCount: git.changeCount,
|
||||
lineTotals:
|
||||
typeof git.added === 'number' && typeof git.removed === 'number'
|
||||
? { added: git.added, removed: git.removed }
|
||||
: null,
|
||||
commits: git.commits.map((commit) => ({
|
||||
sha: commit.id,
|
||||
subject: commit.subject,
|
||||
at: commit.at
|
||||
}))
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { useAppStore } from '@/store'
|
||||
import { useCloudWorkspaceView } from '../use-cloud-workspace-view'
|
||||
|
||||
/** The active workspace's id when it is an Orca Cloud workspace that is asleep (or failed to wake). */
|
||||
export function useAsleepCloudWorkspaceId(): string | null {
|
||||
const activeWorktreeId = useAppStore((state) => state.activeWorktreeId)
|
||||
const view = useCloudWorkspaceView(activeWorktreeId ?? '')
|
||||
if (!activeWorktreeId || !view.isCloud) {
|
||||
return null
|
||||
}
|
||||
return view.state === 'sleeping' || view.state === 'wakeFailed' ? activeWorktreeId : null
|
||||
}
|
||||
+7
@@ -9,6 +9,8 @@ import type { RuntimeFileListState } from '@/components/quick-open-file-list'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type { RightSidebarExplorerView } from '../../../../../../shared/ui-chrome-types'
|
||||
import { FileExplorerTreeStatus } from './FileExplorerTreeStatus'
|
||||
import { CloudAsleepFilesPanel } from '@/components/orca-cloud/offline/CloudAsleepFilesPanel'
|
||||
import { useAsleepCloudWorkspaceId } from '@/components/orca-cloud/offline/use-asleep-cloud-workspace-id'
|
||||
import { FileExplorerVirtualRows } from '../panel/FileExplorerVirtualRows'
|
||||
import { canShowAddAsProjectAction } from '../navigation/file-explorer-add-project-action'
|
||||
import type { FileExplorerNameFilterProjectionSource } from './file-explorer-name-filter-projection'
|
||||
@@ -132,6 +134,11 @@ export function FileExplorerFilesTreePane({
|
||||
hasNameFilter && !nameFilterFiles.loadError
|
||||
? t('auto.components.right.sidebar.FileExplorer.2f4483d6c4', 'No files match this filter')
|
||||
: undefined
|
||||
// An asleep Orca Cloud workspace has no tree to read: its saved changes and Wake, not an error.
|
||||
const asleepCloudId = useAsleepCloudWorkspaceId()
|
||||
if (asleepCloudId) {
|
||||
return <CloudAsleepFilesPanel workspaceId={asleepCloudId} />
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollArea
|
||||
|
||||
@@ -27011,7 +27011,13 @@
|
||||
"deleteFailedNamed": "Couldn’t delete {{name}}",
|
||||
"productName": "Orca Cloud",
|
||||
"cloudMarkLabel": "Cloud workspace · {{state}}",
|
||||
"statusUnavailableTitle": "Couldn’t get the sandbox status."
|
||||
"statusUnavailableTitle": "Couldn’t get the sandbox status.",
|
||||
"files": {
|
||||
"wakeForAll": "Wake the workspace to browse all its files.",
|
||||
"asleep": "Files aren’t available while the workspace is asleep.",
|
||||
"changedAtSleep": "Changed files when this workspace went to sleep · {{time}}",
|
||||
"changedAtSleepNoTime": "Changed files when this workspace went to sleep"
|
||||
}
|
||||
},
|
||||
"cloudAgentSetup": {
|
||||
"loading": "Checking what agents can use…",
|
||||
|
||||
Reference in New Issue
Block a user