Files
orca/mobile/src/components/NewWorktreeModalController.tsx
T
Brennan BensonandMerge Sim 9a56797486 fix(mobile): surface host create warnings and terminal-create errors (#20125)
* fix(mobile): surface host create warnings and terminal-create errors

A workspace created from the phone could land on "No tabs in this session"
with a bare red "Failed to create terminal" and no way to tell why. Two
independent drops hid the host's own explanation:

- createWorktreeWithNameRetry returned only {worktreeId, name}, discarding
  worktree.create's `warning`, and hostNewWorktreeSessionRoute built the
  session route with only `name` + `created=1`. The session screen has always
  had the banner (MobileSessionContentRow + createWarningState) -- only the
  tasks create path ever fed it, so the New Workspace path could never report
  a startup terminal that failed to spawn.
- handleCreateTerminal collapsed every failure to the literal
  'Failed to create terminal', throwing away response.error.message.

Both now propagate, so the daemon's pty-allocation hint ("Your system cannot
allocate any more pty devices.") reaches the phone instead of dying in the
main process. Behaviour is otherwise unchanged: a blank warning is still
omitted from the route, and a host that gives no reason still reads
'Failed to create terminal'.

* test(mobile): refresh route parity baselines

---------

Co-authored-by: Merge Sim <sim@local>
2026-09-11 11:21:31 -07:00

73 lines
1.8 KiB
TypeScript

import { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react'
import type { RpcClient } from '../transport/rpc-client'
import { NewWorktreeModal } from './NewWorktreeModal'
export type NewWorktreeModalControllerHandle = {
open: () => void
}
type Props = {
routeVisible: boolean
client: RpcClient | null
hostId?: string
existingWorktreePaths?: readonly string[]
existingWorktrees?: readonly { repoId: string; branch: string }[]
openExternalUrl: (url: string) => Promise<unknown>
onVisibleChange?: (visible: boolean) => void
onRouteVisibleChange: (visible: boolean) => void
onCreated: (worktreeId: string, name: string, warning?: string) => void
}
export const NewWorktreeModalController = forwardRef<NewWorktreeModalControllerHandle, Props>(
function NewWorktreeModalController(
{
routeVisible,
client,
hostId,
existingWorktreePaths,
existingWorktrees,
openExternalUrl,
onVisibleChange,
onRouteVisibleChange,
onCreated
},
ref
) {
const [manualVisible, setManualVisible] = useState(false)
const visible = routeVisible || manualVisible
useImperativeHandle(
ref,
() => ({
open: () => setManualVisible(true)
}),
[]
)
const close = useCallback(() => {
setManualVisible(false)
if (routeVisible) {
onRouteVisibleChange(false)
}
}, [onRouteVisibleChange, routeVisible])
useEffect(() => {
onVisibleChange?.(visible)
}, [onVisibleChange, visible])
return (
<NewWorktreeModal
visible={visible}
client={client}
hostId={hostId}
existingWorktreePaths={existingWorktreePaths}
existingWorktrees={existingWorktrees}
openExternalUrl={openExternalUrl}
onCreated={onCreated}
onClose={close}
/>
)
}
)