Fix dialog focus
This commit is contained in:
@@ -8,11 +8,12 @@
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
||||
import { Box, Text, useInput } from 'ink';
|
||||
import { Box, Text } from 'ink';
|
||||
import { ScrollableList, type ListItemData } from '../components/List.js';
|
||||
import { QRCode } from '../components/QRCode.js';
|
||||
import { useNavigation } from '../hooks/useNavigation.js';
|
||||
import { useAppContext, useStatus, useDialog } from '../hooks/useAppContext.js';
|
||||
import { useAppContext, useStatus } from '../hooks/useAppContext.js';
|
||||
import { useInputLayer, useLayeredInput, useBlockableInput, useIsInputCaptured } from '../hooks/useInputLayer.js';
|
||||
import { colors, formatSatoshis, formatHex, logoSmall } from '../theme.js';
|
||||
import type { HistoryItem } from '../../services/history.js';
|
||||
|
||||
@@ -65,6 +66,39 @@ const menuItems: ListItemData<string>[] = [
|
||||
*/
|
||||
type HistoryListItem = ListItemData<HistoryDisplayRow>;
|
||||
|
||||
/**
|
||||
* QR code dialog overlay — auto-captures input via the layer system.
|
||||
* Rendered only while a QR address is visible; closes on Enter/Esc.
|
||||
*/
|
||||
function QRDialogOverlay({ address, onClose }: { address: string; onClose: () => void }): React.ReactElement {
|
||||
useInputLayer('qr-dialog');
|
||||
|
||||
useLayeredInput('qr-dialog', (_input, key) => {
|
||||
if (key.escape || key.return) {
|
||||
onClose();
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Box
|
||||
position="absolute"
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
width="100%"
|
||||
>
|
||||
<QRCode
|
||||
value={address}
|
||||
dialog
|
||||
dialogTitle="Receive Address"
|
||||
showValue
|
||||
/>
|
||||
<Box justifyContent="center" marginTop={1}>
|
||||
<Text color={colors.textMuted}>Press Enter or Esc to close</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wallet State Screen Component.
|
||||
* Displays wallet balance, history, and action menu.
|
||||
@@ -73,7 +107,6 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
const { navigate } = useNavigation();
|
||||
const { appService, showError, showInfo } = useAppContext();
|
||||
const { setStatus } = useStatus();
|
||||
const { setDialog } = useDialog();
|
||||
|
||||
// State
|
||||
const [balance, setBalance] = useState<{ totalSatoshis: bigint; utxoCount: number } | null>(null);
|
||||
@@ -169,7 +202,6 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
console.log(result);
|
||||
|
||||
setQrAddress(result.address);
|
||||
setDialog({ visible: true, type: 'custom', message: '' });
|
||||
setStatus('Address generated');
|
||||
|
||||
// Refresh to show updated state
|
||||
@@ -227,16 +259,10 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
});
|
||||
}, [history]);
|
||||
|
||||
// Handle keyboard navigation between panels and QR dialog dismissal
|
||||
useInput((input, key) => {
|
||||
if (qrAddress) {
|
||||
if (key.escape || key.return) {
|
||||
setQrAddress(null);
|
||||
setDialog(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Screen input — automatically blocked when any dialog/overlay is capturing.
|
||||
const isCaptured = useIsInputCaptured();
|
||||
|
||||
useBlockableInput((_input, key) => {
|
||||
if (key.tab) {
|
||||
setFocusedPanel(prev => prev === 'menu' ? 'history' : 'menu');
|
||||
}
|
||||
@@ -383,7 +409,7 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
selectedIndex={selectedMenuIndex}
|
||||
onSelect={setSelectedMenuIndex}
|
||||
onActivate={handleMenuItemActivate}
|
||||
focus={focusedPanel === 'menu'}
|
||||
focus={focusedPanel === 'menu' && !isCaptured}
|
||||
emptyMessage="No actions"
|
||||
/>
|
||||
</Box>
|
||||
@@ -411,7 +437,7 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
items={historyListItems}
|
||||
selectedIndex={selectedHistoryIndex}
|
||||
onSelect={setSelectedHistoryIndex}
|
||||
focus={focusedPanel === 'history'}
|
||||
focus={focusedPanel === 'history' && !isCaptured}
|
||||
maxVisible={10}
|
||||
emptyMessage="No history found"
|
||||
renderItem={renderHistoryItem}
|
||||
@@ -429,22 +455,10 @@ export function WalletStateScreen(): React.ReactElement {
|
||||
|
||||
{/* QR Code dialog overlay for generated addresses */}
|
||||
{qrAddress && (
|
||||
<Box
|
||||
position="absolute"
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
width="100%"
|
||||
>
|
||||
<QRCode
|
||||
value={qrAddress}
|
||||
dialog
|
||||
dialogTitle="Receive Address"
|
||||
showValue
|
||||
/>
|
||||
<Box justifyContent="center" marginTop={1}>
|
||||
<Text color={colors.textMuted}>Press Enter or Esc to close</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
<QRDialogOverlay
|
||||
address={qrAddress}
|
||||
onClose={() => setQrAddress(null)}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user