diff --git a/public/sprite.svg b/public/sprite.svg index 2cab6f11e..8cb0527e4 100644 --- a/public/sprite.svg +++ b/public/sprite.svg @@ -240,6 +240,9 @@ + + + diff --git a/src/components/Send/index.tsx b/src/components/Send/index.tsx index 838ed39aa..beedf3d89 100644 --- a/src/components/Send/index.tsx +++ b/src/components/Send/index.tsx @@ -57,11 +57,6 @@ function SweepAccordionToggle({ eventKey }: SweepAccordionToggleProps) { ) } -type Alert = { - variant: 'success' | 'danger' - message: string -} - type SendProps = { wallet: CurrentWallet } @@ -78,7 +73,7 @@ export default function Send({ wallet }: SendProps) { const isCoinjoinInProgress = useMemo(() => serviceInfo && serviceInfo.coinjoinInProgress, [serviceInfo]) const isMakerRunning = useMemo(() => serviceInfo && serviceInfo.makerRunning, [serviceInfo]) - const [alert, setAlert] = useState() + const [alert, setAlert] = useState() const [isSending, setIsSending] = useState(false) const [isCoinjoin, setIsCoinjoin] = useState(IS_COINJOIN_DEFAULT_VAL) const [minNumCollaborators, setMinNumCollaborators] = useState(MINIMUM_MAKERS_DEFAULT_VAL) @@ -90,7 +85,7 @@ export default function Send({ wallet }: SendProps) { const [feeConfigValues, setFeeConfigValues] = useState() const [waitForUtxosToBeSpent, setWaitForUtxosToBeSpent] = useState([]) - const [paymentSuccessfulInfoAlert, setPaymentSuccessfulInfoAlert] = useState() + const [paymentSuccessfulInfoAlert, setPaymentSuccessfulInfoAlert] = useState() const isOperationDisabled = useMemo( () => isCoinjoinInProgress || isMakerRunning || waitForUtxosToBeSpent.length > 0, @@ -141,7 +136,7 @@ export default function Send({ wallet }: SendProps) { return walletInfo.data.utxos.utxos.filter((it) => it.mixdepth === sourceJarIndex) }, [walletInfo, sourceJarIndex]) - const coinjoinPreconditionSummary = useMemo(() => { + const sourceJarCoinjoinPreconditionSummary = useMemo(() => { if (sourceJarUtxos === null) return null return buildCoinjoinRequirementSummary(sourceJarUtxos) }, [sourceJarUtxos]) @@ -151,23 +146,24 @@ export default function Send({ wallet }: SendProps) { const submitButtonRef = useRef(null) const submitButtonOptions = useMemo(() => { if (!isLoading) { - if (!isCoinjoin) + if (!isCoinjoin) { return { variant: 'danger', text: t('send.button_send_without_improved_privacy'), } - if (coinjoinPreconditionSummary && !coinjoinPreconditionSummary.isFulfilled) + } else if (sourceJarCoinjoinPreconditionSummary?.isFulfilled === false) { return { variant: 'warning', text: t('send.button_send_despite_warning'), } + } } return { variant: 'dark', text: t('send.button_send'), } - }, [isLoading, isCoinjoin, coinjoinPreconditionSummary, t]) + }, [isLoading, isCoinjoin, sourceJarCoinjoinPreconditionSummary, t]) const formIsValid = useMemo(() => { return ( @@ -597,25 +593,35 @@ export default function Send({ wallet }: SendProps) { {t('send.text_maker_running')} - + )} {isCoinjoinInProgress && ( - - {t('send.text_coinjoin_already_running')} - +
+
+
+ +
+
+ + {t('send.text_coinjoin_already_running')} + + abortCoinjoin()} > - {t('global.abort')} +
+ + {t('global.abort')} +
- +
)} @@ -625,22 +631,17 @@ export default function Send({ wallet }: SendProps) {
)} {paymentSuccessfulInfoAlert && ( - - {paymentSuccessfulInfoAlert.message} - - )} - {!isLoading && - !isOperationDisabled && - isCoinjoin && - coinjoinPreconditionSummary && - !coinjoinPreconditionSummary.isFulfilled && ( -
- + <> +
+
+ +
- )} + + {paymentSuccessfulInfoAlert.message} + + + )} {!isLoading && walletInfo && ( setSourceJarIndex(jarIndex)} /> ))}
)} + + {!isLoading && + !isOperationDisabled && + isCoinjoin && + sourceJarCoinjoinPreconditionSummary?.isFulfilled === false && ( +
+ +
+ )} + {t('send.label_recipient')}
diff --git a/src/components/jars/Jar.module.css b/src/components/jars/Jar.module.css index 3273edb55..9aaa9bb72 100644 --- a/src/components/jars/Jar.module.css +++ b/src/components/jars/Jar.module.css @@ -62,6 +62,7 @@ --bs-code-color: var(--bs-blue); color: var(--bs-blue); font-size: 0.75rem; + min-height: 1rem; } .selectableJarContainer { @@ -77,21 +78,20 @@ cursor: none; } -.selectableJarContainer > .selectionCircle { - height: 1.25rem; - width: 1.25rem; - margin-top: 0.8rem; +.selectableJarContainer .selectionCircle { + height: 1.5rem; + width: 1.5rem; border-radius: 50%; display: inline-block; border: 1px solid var(--bs-body-color); } -.selectableJarContainer:not(.selectable) > .selectionCircle { +.selectableJarContainer:not(.selectable) .selectionCircle { visibility: hidden; } -.selectableJarContainer.selected > .selectionCircle { +.selectableJarContainer.selected .selectionCircle { visibility: visible !important; background-color: var(--bs-body-color); } diff --git a/src/components/jars/Jar.tsx b/src/components/jars/Jar.tsx index ae6b9463d..be92d80fe 100644 --- a/src/components/jars/Jar.tsx +++ b/src/components/jars/Jar.tsx @@ -22,6 +22,7 @@ interface JarProps { interface SelectableJarProps { isSelectable: boolean isSelected: boolean + variant?: 'default' | 'warning' onClick: (index: JarIndex) => void } @@ -127,16 +128,18 @@ const Jar = ({ index, balance, frozenBalance, fillLevel, isOpen = false }: JarPr
- {frozenBalance && frozenBalance > 0 ? ( -
- - -
- ) : null} +
+ {frozenBalance && frozenBalance > 0 ? ( + <> + + + + ) : null} +
) @@ -153,6 +156,7 @@ const SelectableJar = ({ isSelectable, isSelected, onClick, + variant = 'default', }: JarProps & SelectableJarProps) => { return (
isSelectable && onClick(index)} > -
+
+
+ {variant === 'warning' && ( +
+ +
+ )} +
) }