fix: turn duplicate emulator action into go-to

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinwoo-H
2026-06-07 21:18:42 -07:00
co-authored by Orca
parent aecb2ca000
commit ec5bfccc2e
3 changed files with 25 additions and 18 deletions
@@ -423,7 +423,7 @@ describe('TabBar context menu wiring', () => {
expect(menuLabels[3]).toContain('New Browser Tab')
})
it('disables New Mobile Emulator when the workspace already has one', async () => {
it('turns New Mobile Emulator into a go-to action when the workspace already has one', async () => {
const onNewSimulatorTab = vi.fn()
appStoreSnapshot.unifiedTabsByWorktree = {
'wt-1': [
@@ -449,13 +449,19 @@ describe('TabBar context menu wiring', () => {
})
const emulatorItem = findChildrenByType(element, 'DropdownMenuItem').find((item) =>
extractText(item.props.children).includes('New Mobile Emulator')
extractText(item.props.children).includes('Go to Mobile Emulator')
)
expect(emulatorItem?.props.disabled).toBe(true)
expect(emulatorItem?.props.onSelect).toBeUndefined()
expect(emulatorItem).toBeTruthy()
if (!emulatorItem) {
throw new Error('Go to Mobile Emulator menu item not rendered')
}
expect(emulatorItem.props.disabled).toBeUndefined()
expect(emulatorItem.props.onSelect).toBeTypeOf('function')
;(emulatorItem.props.onSelect as () => void)()
expect(onNewSimulatorTab).toHaveBeenCalledTimes(1)
const tooltip = findChildrenByType(element, 'TooltipContent').find((item) =>
extractText(item.props.children).includes('An emulator already exists in this workspace.')
extractText(item.props.children).includes('Open the existing emulator tab.')
)
expect(tooltip).toBeTruthy()
})
+9 -12
View File
@@ -63,7 +63,6 @@ type GitStatusEntries = ReturnType<typeof useAppStore.getState>['gitStatusByWork
const EMPTY_GIT_STATUS_ENTRIES: GitStatusEntries = []
const EMPTY_AGENT_CMD_OVERRIDES: Partial<Record<TuiAgent, string>> = {}
const EMPTY_UNIFIED_TABS: readonly Tab[] = []
const EMULATOR_EXISTS_TOOLTIP = 'An emulator already exists in this workspace.'
type TabBarProps = {
tabs: (TerminalTab & { unifiedTabId?: string })[]
@@ -498,19 +497,17 @@ function TabBarInner({
workspaceHasSimulatorTab ? (
<Tooltip>
<TooltipTrigger asChild>
<span className="block">
<DropdownMenuItem
disabled
className="gap-2 rounded-[7px] px-2 py-1.5 text-[12px] leading-5 font-medium"
>
<Smartphone className="size-4 text-muted-foreground" />
New Mobile Emulator
<DropdownMenuShortcut>{newSimulatorShortcut}</DropdownMenuShortcut>
</DropdownMenuItem>
</span>
<DropdownMenuItem
onSelect={onNewSimulatorTab}
className="gap-2 rounded-[7px] px-2 py-1.5 text-[12px] leading-5 font-medium"
>
<Smartphone className="size-4 text-muted-foreground" />
Go to Mobile Emulator
<DropdownMenuShortcut>{newSimulatorShortcut}</DropdownMenuShortcut>
</DropdownMenuItem>
</TooltipTrigger>
<TooltipContent side="right" sideOffset={8} className="z-[80]">
{EMULATOR_EXISTS_TOOLTIP}
Open the existing emulator tab.
</TooltipContent>
</Tooltip>
) : (
@@ -26,6 +26,7 @@ import {
import { closeTerminalTab } from '../terminal/terminal-tab-actions'
import { openTabBarEntry, type TabCreateEntryArgs } from '../tab-bar/tab-create-entry-action'
import { openMobileEmulatorTab } from '@/lib/open-mobile-emulator-tab'
import { ensureSimulatorTab, getSimulatorTabForWorktree } from '@/lib/ensure-simulator-tab'
export function recordTerminalTabGroupSplit(createdTerminal: TerminalTab | null | undefined): void {
if (!createdTerminal) {
@@ -577,8 +578,11 @@ export function useTabGroupWorkspaceModel({
},
newSimulatorTab: worktreeState.mobileEmulatorEnabled
? () => {
if (getSimulatorTabForWorktree(worktreeId)) {
void ensureSimulatorTab(worktreeId, { surfacePane: true })
return
}
// Why: mobile simulators are most useful beside the current tab group.
// Re-open is guarded as a no-op once a worktree emulator tab exists.
void openMobileEmulatorTab(worktreeId, {
placement: 'rightSplit',
targetGroupId: groupId