diff --git a/src/components/PaymentConfirmModal.tsx b/src/components/PaymentConfirmModal.tsx index 68c466726..73ce0fd50 100644 --- a/src/components/PaymentConfirmModal.tsx +++ b/src/components/PaymentConfirmModal.tsx @@ -1,4 +1,4 @@ -import { PropsWithChildren, useMemo } from 'react' +import { PropsWithChildren, useMemo, useState } from 'react' import { Trans, useTranslation } from 'react-i18next' import * as rb from 'react-bootstrap' import Sprite from './Sprite' @@ -10,6 +10,9 @@ import { AmountSats, BitcoinAddress } from '../libs/JmWalletApi' import { jarInitial } from './jars/Jar' import { isValidNumber } from '../utils' import styles from './PaymentConfirmModal.module.css' +import { Utxos } from '../context/WalletContext' +import { SelectableUtxo, UtxoListDisplay } from './Send/ShowUtxos' +import Divider from './Divider' const feeRange: (txFee: TxFee, txFeeFactor: number) => [number, number] = (txFee, txFeeFactor) => { if (txFee.unit !== 'sats/kilo-vbyte') { @@ -55,6 +58,37 @@ const useMiningFeeText = ({ tx_fees, tx_fees_factor }: Pick { + const { t } = useTranslation() + const settings = useSettings() + const [isOpen, setIsOpen] = useState(false) + + return ( + + + {t('show_utxos.considered_utxos')} + + + setIsOpen((current) => !current)} /> + + + + { + // No-op since these UTXOs are only for review and are not selectable + }} + /> + + + + ) +} + interface PaymentDisplayInfo { sourceJarIndex?: JarIndex destination: BitcoinAddress | string @@ -64,6 +98,7 @@ interface PaymentDisplayInfo { numCollaborators?: number feeConfigValues?: FeeValues showPrivacyInfo?: boolean + consideredUtxos?: Utxos } interface PaymentConfirmModalProps extends ConfirmModalProps { @@ -80,6 +115,7 @@ export function PaymentConfirmModal({ numCollaborators, feeConfigValues, showPrivacyInfo = true, + consideredUtxos = [], }, children, ...confirmModalProps @@ -97,7 +133,7 @@ export function PaymentConfirmModal({ return ( - + {showPrivacyInfo && ( @@ -207,6 +243,9 @@ export function PaymentConfirmModal({ )} + {consideredUtxos.length !== 0 && ( + ({ ...it, checked: false, selectable: false }))} /> + )} {children && ( {children} diff --git a/src/components/Send/ShowUtxos.module.css b/src/components/Send/ShowUtxos.module.css index 50bea0e8c..520ab714c 100644 --- a/src/components/Send/ShowUtxos.module.css +++ b/src/components/Send/ShowUtxos.module.css @@ -1,5 +1,5 @@ .utxoListDisplayHeight { - max-height: 17.6rem; + max-height: 15.7rem; } .row.row-normal { @@ -31,6 +31,7 @@ height: 24px; } -.checkbox:checked { +.checkbox:checked, +.checkbox:indeterminate { accent-color: var(--bs-black); } diff --git a/src/components/Send/ShowUtxos.tsx b/src/components/Send/ShowUtxos.tsx index b7100ab49..51898b344 100755 --- a/src/components/Send/ShowUtxos.tsx +++ b/src/components/Send/ShowUtxos.tsx @@ -33,28 +33,29 @@ interface UtxoRowProps { utxo: SelectableUtxoTableRowData onToggle: (utxo: SelectableUtxoTableRowData) => void settings: Settings - showBackgroundColor: boolean walletInfo: WalletInfo t: TFunction + // TODO: remove + showBackgroundColor?: boolean } interface UtxoListDisplayProps { utxos: SelectableUtxo[] onToggle: (utxo: SelectableUtxo) => void settings: Settings - showBackgroundColor: boolean + // TODO: remove + showBackgroundColor?: boolean } -const UtxoRow = ({ utxo, onToggle, showBackgroundColor, settings, walletInfo, t }: UtxoRowProps) => { +const UtxoRow = ({ utxo, onToggle, settings, walletInfo, t }: UtxoRowProps) => { const displayAddress = useMemo(() => shortenStringMiddle(utxo.address, 24), [utxo.address]) const tags = useMemo(() => utxoTags(utxo, walletInfo, t), [utxo, walletInfo, t]) return ( -const UtxoListDisplay = ({ utxos, onToggle, settings, showBackgroundColor = true }: UtxoListDisplayProps) => { +const DEFAULT_UTXO_LIST_THEME = { + Table: ` + --data-table-library_grid-template-columns: 2.5rem 2.5rem 17rem 3rem 12rem 1fr}; +`, + BaseCell: ` + padding: 0.35rem 0.25rem !important; + margin: 0.15rem 0px !important; +`, + Cell: ` + &:nth-of-type(3) { + text-align: left; + } + &:nth-of-type(5) { + text-align: right; + } +`, +} + +const UtxoListDisplay = ({ utxos, onToggle, settings }: UtxoListDisplayProps) => { const { t } = useTranslation() const walletInfo = useCurrentWalletInfo() - const TABLE_THEME = { - Table: ` - --data-table-library_grid-template-columns: 2.5rem 2.5rem 17rem 3rem 12rem 1fr}; - `, - BaseCell: ` - padding: 0.35rem 0.25rem !important; - margin: 0.15rem 0px !important; - `, - Cell: ` - &:nth-of-type(5) { - text-align: right; - } - `, - } - const tableTheme = useTheme(TABLE_THEME) + const tableTheme = useTheme(DEFAULT_UTXO_LIST_THEME) const tableData: TableTypes.Data = useMemo( () => ({ @@ -155,7 +160,6 @@ const UtxoListDisplay = ({ utxos, onToggle, settings, showBackgroundColor = true key={index} utxo={utxo} onToggle={onToggle} - showBackgroundColor={showBackgroundColor} settings={settings} walletInfo={walletInfo} t={t} @@ -169,7 +173,7 @@ const UtxoListDisplay = ({ utxos, onToggle, settings, showBackgroundColor = true ) } -type SelectableUtxo = Utxo & { checked: boolean; selectable: boolean } +export type SelectableUtxo = Utxo & { checked: boolean; selectable: boolean } // TODO: rename to QuickFreezeUtxosModal? const ShowUtxos = ({ isOpen, onCancel, onConfirm, isLoading, utxos, alert }: ShowUtxosProps) => { @@ -241,7 +245,6 @@ const ShowUtxos = ({ isOpen, onCancel, onConfirm, isLoading, utxos, alert }: Sho ) }} settings={settings} - showBackgroundColor={true} /> {upperUtxos.length > 0 && lowerUtxos.length > 0 && ( @@ -261,7 +264,6 @@ const ShowUtxos = ({ isOpen, onCancel, onConfirm, isLoading, utxos, alert }: Sho ) }} settings={settings} - showBackgroundColor={true} /> @@ -290,4 +292,4 @@ const ShowUtxos = ({ isOpen, onCancel, onConfirm, isLoading, utxos, alert }: Sho ) } -export { ShowUtxos } +export { ShowUtxos, UtxoListDisplay } diff --git a/src/components/Send/SourceJarSelector.tsx b/src/components/Send/SourceJarSelector.tsx index a6e8e516b..34a061618 100644 --- a/src/components/Send/SourceJarSelector.tsx +++ b/src/components/Send/SourceJarSelector.tsx @@ -41,8 +41,6 @@ export const SourceJarSelector = ({ const reloadCurrentWalletInfo = useReloadCurrentWalletInfo() const [showUtxos, setShowUtxos] = useState() - //const [unFrozenUtxos, setUnFrozenUtxos] = useState([]) - //const [frozenUtxos, setFrozenUtxos] = useState([]) const jarBalances = useMemo(() => { if (!walletInfo) return [] @@ -51,27 +49,6 @@ export const SourceJarSelector = ({ ) }, [walletInfo]) - /*useEffect(() => { - if (frozenUtxos.length === 0 && unFrozenUtxos.length === 0) { - return - } - const frozenUtxosToUpdate = frozenUtxos.filter((utxo: Utxo) => utxo.checked && !utxo.locktime) - const timeLockedUtxo = frozenUtxos.find((utxo: Utxo) => utxo.checked && utxo.locktime) - const allUnFrozenUnchecked = unFrozenUtxos.every((utxo: Utxo) => !utxo.checked) - - if (frozenUtxos.length > 0 && timeLockedUtxo) { - setAlert({ variant: 'danger', message: `${t('show_utxos.alert_for_time_locked')} ${timeLockedUtxo.locktime}` }) - } else if ( - (frozenUtxos.length > 0 || unFrozenUtxos.length > 0) && - allUnFrozenUnchecked && - frozenUtxosToUpdate.length === 0 - ) { - setAlert({ variant: 'warning', message: t('show_utxos.alert_for_unfreeze_utxos'), dismissible: true }) - } else { - setAlert(undefined) - } - }, [frozenUtxos, unFrozenUtxos, t, setAlert])*/ - const handleUtxosFrozenState = useCallback( async (selectedUtxos: Utxos) => { if (!showUtxos) return diff --git a/src/components/Send/index.tsx b/src/components/Send/index.tsx index 7f6dd561d..2d4b3f4ed 100644 --- a/src/components/Send/index.tsx +++ b/src/components/Send/index.tsx @@ -18,7 +18,6 @@ import { useLoadConfigValue } from '../../context/ServiceConfigContext' import { useWaitForUtxosToBeSpent } from '../../hooks/WaitForUtxosToBeSpent' import { routes } from '../../constants/routes' import { JM_MINIMUM_MAKERS_DEFAULT } from '../../constants/config' - import { initialNumCollaborators } from './helpers' const INITIAL_DESTINATION = null @@ -515,6 +514,9 @@ export default function Send({ wallet }: SendProps) { isCoinjoin: showConfirmSendModal.isCoinJoin, numCollaborators: showConfirmSendModal.numCollaborators!, feeConfigValues: { ...feeConfigValues, tx_fees: showConfirmSendModal.txFee }, + consideredUtxos: (walletInfo?.utxosByJar[showConfirmSendModal.sourceJarIndex!] || []) + .filter((utxo) => !utxo.frozen) + .sort((a, b) => a.confirmations - b.confirmations), }} /> )} diff --git a/src/components/jar_details/UtxoList.tsx b/src/components/jar_details/UtxoList.tsx index 891ab4330..9a46d97a5 100644 --- a/src/components/jar_details/UtxoList.tsx +++ b/src/components/jar_details/UtxoList.tsx @@ -45,6 +45,14 @@ const TABLE_THEME = { `, BaseCell: ` padding: 0.25rem 0.25rem !important; + + input[type="checkbox"] { + width: 16px; + height: 16px; + } + input:checked, input:indeterminate { + accent-color: var(--bs-black); + } &:nth-of-type(1) { text-align: center; } diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index 1df8f5cc5..c425b388e 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -707,7 +707,7 @@ }, "show_utxos": { "select_utxos": "Select UTXOs", - "selected_utxos": "Selected UTXOs", + "considered_utxos": "Considered UTXOs", "show_utxo_title": "Select UTXOs to be considered", "show_utxo_subtitle": "The following UTXOs are considered in the transaction. Every unselected UTXO will be frozen and can be unfrozen later on.", "show_utxo_subtitle_when_allutxos_are_frozen": "The following UTXOs are frozen. Please select them to be considered in the transaction."