Massive changes. I dont know what happens. Rewrote the action wizard again. Fixed several bugs related to the utxo selection. QR codes were added for address. Add support for data results. Experiment with other methods of role extraction
This commit is contained in:
149
src/tui/screens/action-wizard/hooks/useWizardKeyboard.ts
Normal file
149
src/tui/screens/action-wizard/hooks/useWizardKeyboard.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import { useInput } from 'ink';
|
||||
import type { ActionWizardState } from './useActionWizard.js';
|
||||
|
||||
/**
|
||||
* Keyboard input handler for the action wizard.
|
||||
*
|
||||
* Dispatches key presses to step-specific handlers based on the
|
||||
* current step type and focus area. Extracted from the screen
|
||||
* component to keep it purely presentational.
|
||||
*/
|
||||
export function useWizardKeyboard(wizard: ActionWizardState): void {
|
||||
useInput(
|
||||
(input, key) => {
|
||||
// ── Tab: cycle through content and button bar ─────────
|
||||
if (key.tab) {
|
||||
handleTab(wizard);
|
||||
return;
|
||||
}
|
||||
|
||||
// ── Content-area: step-specific input handling ────────
|
||||
if (wizard.focusArea === 'content') {
|
||||
if (wizard.currentStepData?.type === 'role-select') {
|
||||
handleRoleSelectInput(wizard, input, key);
|
||||
return;
|
||||
}
|
||||
if (wizard.currentStepData?.type === 'inputs') {
|
||||
handleInputsStepInput(wizard, input, key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Button bar navigation + activation ────────────────
|
||||
if (wizard.focusArea === 'buttons') {
|
||||
handleButtonBarInput(wizard, key);
|
||||
}
|
||||
|
||||
// ── Global shortcuts ──────────────────────────────────
|
||||
if (input === 'c' && wizard.currentStepData?.type === 'publish' && wizard.invitationId) {
|
||||
wizard.copyId();
|
||||
}
|
||||
if (input === 'a' && wizard.currentStepData?.type === 'inputs') {
|
||||
wizard.selectAll();
|
||||
}
|
||||
if (input === 'n' && wizard.currentStepData?.type === 'inputs') {
|
||||
wizard.deselectAll();
|
||||
}
|
||||
},
|
||||
{ isActive: !wizard.textInputHasFocus },
|
||||
);
|
||||
}
|
||||
|
||||
// ── Tab cycling ─────────────────────────────────────────────────
|
||||
|
||||
function handleTab(wizard: ActionWizardState): void {
|
||||
if (wizard.focusArea === 'content') {
|
||||
// Within role-select, tab through roles before moving to buttons
|
||||
if (
|
||||
wizard.currentStepData?.type === 'role-select' &&
|
||||
wizard.availableRoles.length > 0 &&
|
||||
wizard.selectedRoleIndex < wizard.availableRoles.length - 1
|
||||
) {
|
||||
wizard.setSelectedRoleIndex((prev) => prev + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Within inputs, tab through UTXOs before moving to buttons
|
||||
if (
|
||||
wizard.currentStepData?.type === 'inputs' &&
|
||||
wizard.availableUtxos.length > 0 &&
|
||||
wizard.selectedUtxoIndex < wizard.availableUtxos.length - 1
|
||||
) {
|
||||
wizard.setSelectedUtxoIndex((prev) => prev + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Move to button bar
|
||||
wizard.setFocusArea('buttons');
|
||||
wizard.setFocusedButton('next');
|
||||
} else {
|
||||
// Cycle through buttons, then wrap back to content
|
||||
if (wizard.focusedButton === 'back') {
|
||||
wizard.setFocusedButton('cancel');
|
||||
} else if (wizard.focusedButton === 'cancel') {
|
||||
wizard.setFocusedButton('next');
|
||||
} else {
|
||||
wizard.setFocusArea('content');
|
||||
wizard.setFocusedInput(0);
|
||||
wizard.setSelectedUtxoIndex(0);
|
||||
wizard.setSelectedRoleIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Role-select step ────────────────────────────────────────────
|
||||
|
||||
function handleRoleSelectInput(
|
||||
wizard: ActionWizardState,
|
||||
_input: string,
|
||||
key: { upArrow: boolean; downArrow: boolean },
|
||||
): void {
|
||||
if (key.upArrow) {
|
||||
wizard.setSelectedRoleIndex((p) => Math.max(0, p - 1));
|
||||
} else if (key.downArrow) {
|
||||
wizard.setSelectedRoleIndex((p) =>
|
||||
Math.min(wizard.availableRoles.length - 1, p + 1),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Inputs step (UTXO selection) ────────────────────────────────
|
||||
|
||||
function handleInputsStepInput(
|
||||
wizard: ActionWizardState,
|
||||
input: string,
|
||||
key: { upArrow: boolean; downArrow: boolean; return: boolean },
|
||||
): void {
|
||||
if (key.upArrow) {
|
||||
wizard.setSelectedUtxoIndex((p) => Math.max(0, p - 1));
|
||||
} else if (key.downArrow) {
|
||||
wizard.setSelectedUtxoIndex((p) =>
|
||||
Math.min(wizard.availableUtxos.length - 1, p + 1),
|
||||
);
|
||||
} else if (key.return || input === ' ') {
|
||||
wizard.toggleUtxoSelection(wizard.selectedUtxoIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Button bar ──────────────────────────────────────────────────
|
||||
|
||||
function handleButtonBarInput(
|
||||
wizard: ActionWizardState,
|
||||
key: { leftArrow: boolean; rightArrow: boolean; return: boolean },
|
||||
): void {
|
||||
if (key.leftArrow) {
|
||||
wizard.setFocusedButton((p) =>
|
||||
p === 'next' ? 'cancel' : p === 'cancel' ? 'back' : 'back',
|
||||
);
|
||||
} else if (key.rightArrow) {
|
||||
wizard.setFocusedButton((p) =>
|
||||
p === 'back' ? 'cancel' : p === 'cancel' ? 'next' : 'next',
|
||||
);
|
||||
}
|
||||
|
||||
if (key.return) {
|
||||
if (wizard.focusedButton === 'back') wizard.previousStep();
|
||||
else if (wizard.focusedButton === 'cancel') wizard.cancel();
|
||||
else if (wizard.focusedButton === 'next') wizard.nextStep();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user