Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions projects/keepkey-vault/src/mainview/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,15 @@ function App() {
onEnableEmulator={async () => {
const settings = await rpcRequest<AppSettings>('setEmulatorEnabled', { enabled: true }, 10000)
setEmulatorEnabled(settings.emulatorEnabled)
// Enabling the flag alone is a dead end on first run: with no flash
// images DeviceGrid has nothing to show and the Start card vanishes.
// Bootstrap and boot a default emulator wallet so "Start emulator"
// actually starts one (mirrors the DeviceSettingsDrawer install path).
const wallets = await rpcRequest<Array<{ name: string }>>('emulatorListWallets').catch(() => [])
if (wallets.length === 0) {
try { await rpcRequest('emulatorPair', undefined, 10000) } catch { /* may already be paired */ }
await rpcRequest('emulatorInit', { flashName: 'default' }, 30000)
}
}}
emulatorEnabled={emulatorEnabled}
/>
Expand Down
68 changes: 41 additions & 27 deletions projects/keepkey-vault/src/mainview/components/DeviceGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,38 @@ export function DeviceGrid({ onViewPortfolio, onReady, onEnableEmulator, emulato
const emuRunning = emuStatus?.state === "running"
const hasContent = devices.length > 0 || emuWallets.length > 0

// Emulator entry point. Rendered identically in the empty-state hero AND the
// populated workspace so a Start-emulator affordance is ALWAYS reachable —
// registered devices (hasContent) must not hide it. Parity with macOS, where
// the emulator flow is always offered regardless of what's already in the DB.
const emulatorStartCard = (!emulatorEnabled && onEnableEmulator) ? (
<Box
w="100%"
maxW="440px"
borderRadius="18px"
border="1px solid rgba(168,85,247,0.28)"
bg="rgba(168,85,247,0.06)"
p="5"
>
<Flex align="center" gap="3">
<EmulatorIcon active={false} />
<Box flex="1" minW="0">
<Text fontSize="13px" fontWeight="600" color="var(--text-0)" mb="1">
Testing with an emulator?
</Text>
<Text fontSize="12px" color="var(--text-2)" lineHeight="1.5">
Open the local emulator wallet picker without connecting a USB device.
</Text>
</Box>
</Flex>
<Box mt="3">
<CardCta tone="teal" onClick={handleEnableEmu} loading={loading === "emu:__enable"}>
Start emulator
</CardCta>
</Box>
</Box>
) : null

useEffect(() => {
// Always notify parent once revealed — even when empty — so SplashScreen
// can slide the logo to the top and reveal the connect-prompt hero.
Expand Down Expand Up @@ -206,6 +238,14 @@ export function DeviceGrid({ onViewPortfolio, onReady, onEnableEmulator, emulato
</Text>
</Flex>

{/* Emulator entry point in the populated workspace — always offered,
never hidden by registered devices (parity with the empty state). */}
{hasContent && emulatorStartCard && (
<Flex justify="center" mb="4">
{emulatorStartCard}
</Flex>
)}

{/* Error banner */}
{error && (
<Box mb="3" px="3" py="2" bg="rgba(224,140,123,0.12)" border="1px solid" borderColor="rgba(224,140,123,0.32)" borderRadius="lg">
Expand Down Expand Up @@ -249,33 +289,7 @@ export function DeviceGrid({ onViewPortfolio, onReady, onEnableEmulator, emulato
</Box>
</Flex>
</Box>
{!emulatorEnabled && onEnableEmulator && (
<Box
w="100%"
maxW="440px"
borderRadius="18px"
border="1px solid rgba(168,85,247,0.28)"
bg="rgba(168,85,247,0.06)"
p="5"
>
<Flex align="center" gap="3">
<EmulatorIcon active={false} />
<Box flex="1" minW="0">
<Text fontSize="13px" fontWeight="600" color="var(--text-0)" mb="1">
Testing with an emulator?
</Text>
<Text fontSize="12px" color="var(--text-2)" lineHeight="1.5">
Open the local emulator wallet picker without connecting a USB device.
</Text>
</Box>
</Flex>
<Box mt="3">
<CardCta tone="teal" onClick={handleEnableEmu} loading={loading === "emu:__enable"}>
Start emulator
</CardCta>
</Box>
</Box>
)}
{emulatorStartCard}
</Flex>
)}

Expand Down
Loading