diff --git a/.changeset/seven-ravens-rest.md b/.changeset/seven-ravens-rest.md
new file mode 100644
index 000000000000..8a4f89f57f08
--- /dev/null
+++ b/.changeset/seven-ravens-rest.md
@@ -0,0 +1,5 @@
+---
+"ledger-live-desktop": minor
+---
+
+LLD: LIVE-15143 use a debounce on the memotag field
diff --git a/apps/ledger-live-desktop/src/newArch/features/MemoTag/__tests__/MemoTagField.test.tsx b/apps/ledger-live-desktop/src/newArch/features/MemoTag/__tests__/MemoTagField.test.tsx
index 8e75955c2f66..6dc92249e143 100644
--- a/apps/ledger-live-desktop/src/newArch/features/MemoTag/__tests__/MemoTagField.test.tsx
+++ b/apps/ledger-live-desktop/src/newArch/features/MemoTag/__tests__/MemoTagField.test.tsx
@@ -7,6 +7,14 @@ import { render, screen, fireEvent } from "tests/testUtils";
import MemoTagField from "../components/MemoTagField";
describe("MemoTagField", () => {
+ beforeAll(() => {
+ jest.useFakeTimers();
+ });
+
+ afterAll(() => {
+ jest.useRealTimers();
+ });
+
it("renders MemoTagField with label and text field", () => {
render();
expect(screen.getByText(/Tag \/ Memo/gi)).toBeInTheDocument();
@@ -19,12 +27,14 @@ describe("MemoTagField", () => {
expect(screen.queryByText(/Tag \/ Memo/gi)).not.toBeInTheDocument();
});
- it("should call onChange when input value changes", () => {
+ it("should call onChange when input value changes with a debounce", () => {
const handleChange = jest.fn();
render();
fireEvent.change(screen.getByPlaceholderText(/Enter Tag \/ Memo/gi), {
target: { value: "new memo" },
});
+ expect(handleChange).not.toHaveBeenCalled();
+ jest.runAllTimers();
expect(handleChange).toHaveBeenCalledTimes(1);
});
diff --git a/apps/ledger-live-desktop/src/newArch/features/MemoTag/components/MemoTagField.tsx b/apps/ledger-live-desktop/src/newArch/features/MemoTag/components/MemoTagField.tsx
index a6be608741a6..c54b41585285 100644
--- a/apps/ledger-live-desktop/src/newArch/features/MemoTag/components/MemoTagField.tsx
+++ b/apps/ledger-live-desktop/src/newArch/features/MemoTag/components/MemoTagField.tsx
@@ -1,12 +1,12 @@
-import React from "react";
+import React, { useState, useEffect } from "react";
import Input, { Props as InputBaseProps } from "~/renderer/components/Input";
+import { useDebounce } from "@ledgerhq/live-common//hooks/useDebounce";
import Label from "~/renderer/components/Label";
import Box from "~/renderer/components/Box";
import { useTranslation } from "react-i18next";
import { Flex, Text, Tooltip } from "@ledgerhq/react-ui";
import styled from "styled-components";
import InfoCircle from "~/renderer/icons/InfoCircle";
-
const TooltipContainer = styled(Box)`
background-color: ${({ theme }) => theme.colors.palette.neutral.c100};
padding: 10px;
@@ -30,6 +30,7 @@ type MemoTagFieldProps = InputBaseProps & {
placeholder?: string;
label?: string;
tooltipText?: string;
+ validationHandler?: (newValue: string) => string;
};
const MemoTagField = ({
@@ -44,8 +45,20 @@ const MemoTagField = ({
placeholder,
label,
tooltipText,
+ validationHandler,
}: MemoTagFieldProps) => {
const { t } = useTranslation();
+ const [memoValue, setMemoValue] = useState(value);
+ const debouncedMemoValue = useDebounce(memoValue, 300);
+
+ useEffect(() => {
+ if (debouncedMemoValue !== value) onChange?.(debouncedMemoValue || "");
+ }, [debouncedMemoValue, onChange, value]);
+
+ const handleChange = (newValue: string) => {
+ setMemoValue(validationHandler ? validationHandler(newValue) : newValue);
+ };
+
return (
{showLabel && (
@@ -68,10 +81,10 @@ const MemoTagField = ({
{CaracterCountComponent && }
{
- value = value.replace(/\D/g, "");
if (value !== "") onChange(bridge.updateTransaction(transaction, { transferId: value }));
else onChange(bridge.updateTransaction(transaction, { transferId: undefined }));
},
@@ -32,6 +31,7 @@ const MemoField = ({ onChange, account, transaction, status, autoFocus }: MemoTa
onChange={onTransferIdFieldChange}
spellCheck="false"
autoFocus={autoFocus}
+ validationHandler={newValue => newValue.replace(/\D/g, "")}
/>
);
};
diff --git a/apps/ledger-live-desktop/src/renderer/families/xrp/SendRecipientFields.tsx b/apps/ledger-live-desktop/src/renderer/families/xrp/SendRecipientFields.tsx
index 14b073addb19..8c9a3e56239d 100644
--- a/apps/ledger-live-desktop/src/renderer/families/xrp/SendRecipientFields.tsx
+++ b/apps/ledger-live-desktop/src/renderer/families/xrp/SendRecipientFields.tsx
@@ -15,7 +15,7 @@ const TagField = ({ onChange, account, transaction, autoFocus }: Props) => {
const onChangeTag = useCallback(
(str: string) => {
const bridge = getAccountBridge(account);
- const tag = BigNumber(str.replace(/[^0-9]/g, ""));
+ const tag = BigNumber(str);
const patch = {
tag:
!tag.isNaN() &&
@@ -37,6 +37,7 @@ const TagField = ({ onChange, account, transaction, autoFocus }: Props) => {
value={String(transaction.tag || "")}
onChange={onChangeTag}
autoFocus={autoFocus}
+ validationHandler={str => str.replace(/[^0-9]/g, "")}
/>
);
};