Skip to content

Commit

Permalink
Add ellipsis for permit fiat values
Browse files Browse the repository at this point in the history
  • Loading branch information
OGPoyraz committed Jul 22, 2024
1 parent e3691c0 commit 4dee3b0
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 15 deletions.
16 changes: 11 additions & 5 deletions ui/helpers/utils/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,24 +247,30 @@ export function getRandomFileName() {
* @param {number} options.truncatedCharLimit - The maximum length of the string.
* @param {number} options.truncatedStartChars - The number of characters to preserve at the beginning.
* @param {number} options.truncatedEndChars - The number of characters to preserve at the end.
* @param {boolean} options.skipCharacterInEnd - Skip the character at the end.
* @returns {string} The shortened string.
*/
export function shortenString(
stringToShorten = '',
{ truncatedCharLimit, truncatedStartChars, truncatedEndChars } = {
{
truncatedCharLimit,
truncatedStartChars,
truncatedEndChars,
skipCharacterInEnd,
} = {
truncatedCharLimit: TRUNCATED_NAME_CHAR_LIMIT,
truncatedStartChars: TRUNCATED_ADDRESS_START_CHARS,
truncatedEndChars: TRUNCATED_ADDRESS_END_CHARS,
skipCharacterInEnd: false,
},
) {
if (stringToShorten.length < truncatedCharLimit) {
return stringToShorten;
}

return `${stringToShorten.slice(
0,
truncatedStartChars,
)}...${stringToShorten.slice(-truncatedEndChars)}`;
return `${stringToShorten.slice(0, truncatedStartChars)}...${
skipCharacterInEnd ? '' : stringToShorten.slice(-truncatedEndChars)
}`;
}

/**
Expand Down
11 changes: 11 additions & 0 deletions ui/helpers/utils/util.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1081,5 +1081,16 @@ describe('util', () => {
}),
).toStrictEqual('0x12...7890');
});

it('should shorten the string and remove all characters from the end if skipCharacterInEnd is true', () => {
expect(
util.shortenString('0x1234567890123456789012345678901234567890', {
truncatedCharLimit: 10,
truncatedStartChars: 4,
truncatedEndChars: 4,
skipCharacterInEnd: true,
}),
).toStrictEqual('0x12...');
});
});
});
37 changes: 36 additions & 1 deletion ui/hooks/useFiatFormatter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,40 @@ describe('useFiatFormatter', () => {
expect(formatFiat(0)).toBe('$0.00');
});

describe('shorten the fiat', () => {
it('when currency symbol on the left for given locale', () => {
mockGetIntlLocale.mockReturnValue('en-US');
mockGetCurrentCurrency.mockReturnValue('USD');

const { result } = renderHook(() => useFiatFormatter(true));
const formatFiat = result.current;

expect(formatFiat(100000000000000000)).toBe('$100,000,000,...');
});

it('when currency symbol on the right for given locale', () => {
mockGetIntlLocale.mockReturnValue('es-ES');
mockGetCurrentCurrency.mockReturnValue('EUR');

const { result } = renderHook(() => useFiatFormatter(true));
const formatFiat = result.current;

expect(formatFiat(100000000000000000)).toBe('100.000.000....€');
});

it('handle unknown currencies by returning amount followed by currency code', () => {
mockGetCurrentCurrency.mockReturnValue('storj');
mockGetIntlLocale.mockReturnValue('en-US');

const { result } = renderHook(() => useFiatFormatter(true));
const formatFiat = result.current;

expect(formatFiat(100000)).toBe('100,000 storj');
expect(formatFiat(500.5)).toBe('500.5 storj');
expect(formatFiat(0)).toBe('0 storj');
});
});

it('should use the current locale and currency from the mocked functions', () => {
mockGetIntlLocale.mockReturnValue('fr-FR');
mockGetCurrentCurrency.mockReturnValue('EUR');
Expand All @@ -47,12 +81,13 @@ describe('useFiatFormatter', () => {

it('should gracefully handle unknown currencies by returning amount followed by currency code', () => {
mockGetCurrentCurrency.mockReturnValue('storj');
mockGetIntlLocale.mockReturnValue('en-US');

const { result } = renderHook(() => useFiatFormatter());
const formatFiat = result.current;

// Testing the fallback formatting for an unknown currency
expect(formatFiat(1000)).toBe('1000 storj');
expect(formatFiat(100000)).toBe('100,000 storj');
expect(formatFiat(500.5)).toBe('500.5 storj');
expect(formatFiat(0)).toBe('0 storj');
});
Expand Down
55 changes: 51 additions & 4 deletions ui/hooks/useFiatFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useSelector } from 'react-redux';
import { getIntlLocale } from '../ducks/locale/locale';
import { getCurrentCurrency } from '../selectors';
import { shortenString } from '../helpers/utils/util';

/**
* Returns a function that formats a fiat amount as a localized string.
Expand All @@ -17,19 +18,65 @@ import { getCurrentCurrency } from '../selectors';

type FiatFormatter = (fiatAmount: number) => string;

export const useFiatFormatter = (): FiatFormatter => {
export const useFiatFormatter = (shortenFiatValue?: boolean): FiatFormatter => {
const locale = useSelector(getIntlLocale);
const fiatCurrency = useSelector(getCurrentCurrency);

return (fiatAmount: number) => {
try {
return new Intl.NumberFormat(locale, {
const formatter = new Intl.NumberFormat(locale, {
style: 'currency',
currency: fiatCurrency,
}).format(fiatAmount);
});

if (!shortenFiatValue) {
return formatter.format(fiatAmount);
}

const parts = formatter.formatToParts(fiatAmount);

let currencySymbol = '';
let numberString = '';

parts.forEach((part) => {
if (part.type === 'currency') {
currencySymbol += part.value;
} else {
numberString += part.value;
}
});

// Shorten the number part while preserving commas
const shortenedNumberString = shortenString(numberString, {
truncatedCharLimit: 15,
truncatedStartChars: 12,
truncatedEndChars: 0,
skipCharacterInEnd: true,
});

// Determine the position of the currency symbol
const currencyBeforeNumber =
parts.findIndex((part) => part.type === 'currency') <
parts.findIndex((part) => part.type === 'integer');

// Reassemble the formatted string
return currencyBeforeNumber
? `${currencySymbol}${shortenedNumberString}`
: `${shortenedNumberString}${currencySymbol}`;
} catch (error) {
// Fallback for unknown or unsupported currencies
return `${fiatAmount} ${fiatCurrency}`;
const formattedNumber = new Intl.NumberFormat(locale).format(fiatAmount);
const shortenedNumberString = shortenString(formattedNumber, {
truncatedCharLimit: 15,
truncatedStartChars: 12,
truncatedEndChars: 0,
skipCharacterInEnd: true,
});

if (shortenFiatValue) {
return `${shortenedNumberString} ${fiatCurrency}`;
}
return `${formattedNumber} ${fiatCurrency}`;
}
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ const PermitSimulation: React.FC<{
<Name value={verifyingContract} type={NameType.ETHEREUM_ADDRESS} />
</Box>
<Box>
{fiatValue && <IndividualFiatDisplay fiatAmount={fiatValue} />}
{fiatValue && (
<IndividualFiatDisplay fiatAmount={fiatValue} shortenFiatValue />
)}
</Box>
</Box>
</ConfirmInfoRow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ export function calculateTotalFiat(fiatAmounts: FiatAmount[]): number {
* @param props
* @param props.fiatAmount
*/
export const IndividualFiatDisplay: React.FC<{ fiatAmount: FiatAmount }> = ({
fiatAmount,
}) => {
export const IndividualFiatDisplay: React.FC<{
fiatAmount: FiatAmount;
shortenFiatValue?: boolean;
}> = ({ fiatAmount, shortenFiatValue = false }) => {
const hideFiatForTestnet = useHideFiatForTestnet();
const fiatFormatter = useFiatFormatter();
const fiatFormatter = useFiatFormatter(shortenFiatValue);

if (hideFiatForTestnet) {
return null;
Expand Down

0 comments on commit 4dee3b0

Please sign in to comment.