Compare commits
3 Commits
12b7bde74f
...
use-flatma
| Author | SHA1 | Date | |
|---|---|---|---|
|
941414b3ee
|
|||
|
e9bc6186b9
|
|||
|
b2ccff5b19
|
@@ -510,7 +510,7 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
const templates = await this.engine.listImportedTemplates();
|
const templates = await this.engine.listImportedTemplates();
|
||||||
|
|
||||||
// For each template, we need to create a 2d array of all the outputs
|
// For each template, we need to create a 2d array of all the outputs
|
||||||
const outputs = templates.map(template => {
|
const outputs = templates.flatMap(template => {
|
||||||
return Object.keys(template.outputs).map(output => {
|
return Object.keys(template.outputs).map(output => {
|
||||||
const templateIdentifier = generateTemplateIdentifier(template);
|
const templateIdentifier = generateTemplateIdentifier(template);
|
||||||
|
|
||||||
@@ -522,7 +522,7 @@ export class Invitation extends EventEmitter<InvitationEventMap> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// then, for each output, we need to get the spendable resources
|
// then, for each output, we need to get the spendable resources
|
||||||
const spendableResources = await Promise.all(outputs.flat().map(output => {
|
const spendableResources = await Promise.all(outputs.map(output => {
|
||||||
return this.engine.getSpendableResources(this.data, {
|
return this.engine.getSpendableResources(this.data, {
|
||||||
templateIdentifier: output.templateIdentifier,
|
templateIdentifier: output.templateIdentifier,
|
||||||
outputIdentifier: output.outputIdentifier,
|
outputIdentifier: output.outputIdentifier,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import path from 'path';
|
|||||||
import { createMnemonicFile } from '../../cli/mnemonic.js';
|
import { createMnemonicFile } from '../../cli/mnemonic.js';
|
||||||
import { getMnemonicsDir } from '../../utils/paths.js';
|
import { getMnemonicsDir } from '../../utils/paths.js';
|
||||||
import { BCHMnemonicURL } from '../../utils/bch-mnemonic-url.js';
|
import { BCHMnemonicURL } from '../../utils/bch-mnemonic-url.js';
|
||||||
import { encodeBip39Mnemonic } from '@bitauth/libauth';
|
import { encodeBip39Mnemonic, generateBip39Mnemonic } from '@bitauth/libauth';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status message type.
|
* Status message type.
|
||||||
@@ -41,7 +41,7 @@ interface MnemonicFileEntry {
|
|||||||
* Focus sections the user can tab between.
|
* Focus sections the user can tab between.
|
||||||
* When saved wallets exist the file list is shown first.
|
* When saved wallets exist the file list is shown first.
|
||||||
*/
|
*/
|
||||||
type FocusSection = 'files' | 'input' | 'saveCheckbox' | 'button';
|
type FocusSection = 'files' | 'input' | 'saveCheckbox' | 'generateRandomSeed' | 'button';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads mnemonic-* files from ~/.config/xo-cli/mnemonics/ (same as xo-cli),
|
* Reads mnemonic-* files from ~/.config/xo-cli/mnemonics/ (same as xo-cli),
|
||||||
@@ -117,8 +117,8 @@ export function SeedInputScreen(): React.ReactElement {
|
|||||||
* The ordered list of focusable sections (files section only when entries exist).
|
* The ordered list of focusable sections (files section only when entries exist).
|
||||||
*/
|
*/
|
||||||
const focusSections: FocusSection[] = mnemonicFiles.length > 0
|
const focusSections: FocusSection[] = mnemonicFiles.length > 0
|
||||||
? ['files', 'input', 'saveCheckbox', 'button']
|
? ['files', 'input', 'generateRandomSeed', 'saveCheckbox', 'button']
|
||||||
: ['input', 'saveCheckbox', 'button'];
|
: ['input', 'generateRandomSeed', 'saveCheckbox', 'button'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows a status message with the given type.
|
* Shows a status message with the given type.
|
||||||
@@ -202,7 +202,7 @@ export function SeedInputScreen(): React.ReactElement {
|
|||||||
}, [mnemonicFiles, doInitialize]);
|
}, [mnemonicFiles, doInitialize]);
|
||||||
|
|
||||||
// Keyboard navigation
|
// Keyboard navigation
|
||||||
useBlockableInput((_input, key) => {
|
useBlockableInput((input, key) => {
|
||||||
if (isSubmitting) return;
|
if (isSubmitting) return;
|
||||||
|
|
||||||
// Tab / Shift-Tab to cycle focus sections
|
// Tab / Shift-Tab to cycle focus sections
|
||||||
@@ -219,7 +219,7 @@ export function SeedInputScreen(): React.ReactElement {
|
|||||||
|
|
||||||
// Space or Enter toggles "save mnemonic" when that row is focused
|
// Space or Enter toggles "save mnemonic" when that row is focused
|
||||||
if (focusedSection === 'saveCheckbox') {
|
if (focusedSection === 'saveCheckbox') {
|
||||||
if (_input === ' ' || key.return) {
|
if (input === ' ' || key.return) {
|
||||||
setSaveMnemonicChecked((v) => !v);
|
setSaveMnemonicChecked((v) => !v);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -241,6 +241,18 @@ export function SeedInputScreen(): React.ReactElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ctrl-R generates a random seed phrase and fills it in the input
|
||||||
|
if (key.ctrl && input === 'r') {
|
||||||
|
setSeedPhrase(generateBip39Mnemonic());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If pressing enter while the generate random seed section is focused, generate a random seed and fill it in the input
|
||||||
|
if (key.return && focusedSection === 'generateRandomSeed') {
|
||||||
|
setSeedPhrase(generateBip39Mnemonic());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Enter on button submits manual seed
|
// Enter on button submits manual seed
|
||||||
if (key.return && focusedSection === 'button') {
|
if (key.return && focusedSection === 'button') {
|
||||||
handleSubmit();
|
handleSubmit();
|
||||||
@@ -358,6 +370,19 @@ export function SeedInputScreen(): React.ReactElement {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{/* Generate random seed phrase and fill in the input */}
|
||||||
|
<Box marginTop={1}>
|
||||||
|
<Box
|
||||||
|
paddingX={1}
|
||||||
|
paddingY={0}
|
||||||
|
backgroundColor={focusedSection === 'generateRandomSeed' ? colors.focus : colors.bgSelected}
|
||||||
|
>
|
||||||
|
<Text color={focusedSection === 'generateRandomSeed' ? colors.bg : colors.text} bold>Generate Random Seed</Text>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Text color={colors.textMuted}> (Ctrl-R)</Text>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{/* Save mnemonic checkbox (manual entry only; applies on Continue) */}
|
{/* Save mnemonic checkbox (manual entry only; applies on Continue) */}
|
||||||
<Box
|
<Box
|
||||||
marginTop={1}
|
marginTop={1}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Invitation } from "../services/invitation.js";
|
import type { Invitation } from "../services/invitation.js";
|
||||||
import type { XOTemplate } from "@xo-cash/types";
|
import type { XOInvitationCommit, XOTemplate } from "@xo-cash/types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Color names for invitation states.
|
* Color names for invitation states.
|
||||||
@@ -249,9 +249,9 @@ export function formatInvitationId(id: string, maxLength: number = 16): string {
|
|||||||
* @param invitation - The invitation to check
|
* @param invitation - The invitation to check
|
||||||
* @returns Array of unique entity identifiers
|
* @returns Array of unique entity identifiers
|
||||||
*/
|
*/
|
||||||
export function getInvitationParticipants(invitation: Invitation): string[] {
|
export function getInvitationParticipants(commits: Array<XOInvitationCommit>): string[] {
|
||||||
const participants = new Set<string>();
|
const participants = new Set<string>();
|
||||||
for (const commit of invitation.data.commits || []) {
|
for (const commit of commits) {
|
||||||
if (commit.entityIdentifier) {
|
if (commit.entityIdentifier) {
|
||||||
participants.add(commit.entityIdentifier);
|
participants.add(commit.entityIdentifier);
|
||||||
}
|
}
|
||||||
@@ -267,9 +267,14 @@ export function getInvitationParticipants(invitation: Invitation): string[] {
|
|||||||
* @returns True if the user has made at least one commit
|
* @returns True if the user has made at least one commit
|
||||||
*/
|
*/
|
||||||
export function isUserParticipant(
|
export function isUserParticipant(
|
||||||
invitation: Invitation,
|
invitation: Invitation | Array<XOInvitationCommit>,
|
||||||
userEntityId: string | null,
|
userEntityId: string | null,
|
||||||
): boolean {
|
): boolean {
|
||||||
if (!userEntityId) return false;
|
if (!userEntityId) return false;
|
||||||
return getInvitationParticipants(invitation).includes(userEntityId);
|
|
||||||
|
if (Array.isArray(invitation)) {
|
||||||
|
return invitation.some(commit => commit.entityIdentifier === userEntityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return getInvitationParticipants(invitation.data.commits).includes(userEntityId);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user