diff --git a/.env b/.env index 3ec994bc..d076383f 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ -APP_VERSION=2.5.7 +APP_VERSION=2.5.8 -APP_BUILD_NUMBER=434 \ No newline at end of file +APP_BUILD_NUMBER=435 \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/435.txt b/fastlane/metadata/android/en-US/changelogs/435.txt new file mode 100644 index 00000000..b59e9538 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/435.txt @@ -0,0 +1 @@ +- Improved sats notation on invoices \ No newline at end of file diff --git a/fastlane/metadata/android/fr-FR/changelogs/435.txt b/fastlane/metadata/android/fr-FR/changelogs/435.txt new file mode 100644 index 00000000..1facead1 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/435.txt @@ -0,0 +1 @@ +- Amélioré la notation en sats sur les factures \ No newline at end of file diff --git a/src/screens/Invoice/Invoice.tsx b/src/screens/Invoice/Invoice.tsx index 9cf98b1e..8518bf3a 100644 --- a/src/screens/Invoice/Invoice.tsx +++ b/src/screens/Invoice/Invoice.tsx @@ -1,10 +1,4 @@ -import React, { - useCallback, - useEffect, - useMemo, - useState, - useRef -} from "react"; +import { useCallback, useEffect, useMemo, useState, useRef } from "react"; import { bech32 } from "bech32"; import axios from "axios"; import { useTranslation } from "react-i18next"; @@ -137,9 +131,10 @@ export type InvoiceType = { merchantName: string; tag: string; title: string; - time: number; + createdAt: number; description: string; expiry: number; + delay: number; amount: number; grossAmount?: number; status: Status; @@ -160,6 +155,21 @@ const truncate = (str: string, length: number, separator = "...") => { return [start, separator, end].join(""); }; +const formatDecimalComponents = (input: number) => { + const divisor = 100000000; + const whole = Math.floor(input / divisor); + const decimal = (input % divisor).toString().padStart(8, "0"); + + const formattedDecimal = + decimal.slice(0, 2) + " " + decimal.slice(2, 5) + " " + decimal.slice(5); + + const result = [...whole.toString(), ".", ...formattedDecimal].map((char) => + char === " " ? " " : isNaN(char) ? char : Number(char) + ); + + return result; +}; + const TEXT_ICON_SIZE = 16; const STATUS_ICON_SIZE = 120; const MAX_QR_SIZE = 320; @@ -225,8 +235,8 @@ export const Invoice = () => { const updateProgressAndUpdateRateTime = useCallback(() => { const now = Math.round(Date.now() / 1000); - const timeElapsed = now - createdAt; - const newProgress = timeElapsed / delay; + const timeElapsed = now - (createdAt || 0); + const newProgress = timeElapsed / (delay || 1); setProgress(1 - newProgress); const remainder = timeElapsed % rateUpdateDelay; @@ -300,66 +310,97 @@ export const Invoice = () => { ); }, [invoiceCurrency]); - const fiatSatAmountComponent = useMemo( - () => ( + const fiatSatAmountComponent = useMemo(() => { + const elements = formatDecimalComponents((amount || 0) / 1000).reduce( + (result, v) => { + const currentIsEnabled = + result[result.length - 1]?.isEnabled || + (typeof v === "number" && v !== 0); + return [ + ...result, + { + value: v, + isEnabled: currentIsEnabled + } + ]; + }, + [] as { value: string | number; isEnabled: boolean }[] + ); + + const isSatBtcInvoice = + invoiceCurrency && ["sat", "BTC"].includes(invoiceCurrency); + + return ( <> - {getFormattedUnit( - invoiceFiatAmount, - invoiceCurrency || "", - unitDecimals - )} - - {invoiceCurrency !== "sat" && ( - <> - {amount > 0 && ( - - {amount ? numberWithSpaces(amount / 1000) : ""} sats - + {!isSatBtcInvoice && + getFormattedUnit( + invoiceFiatAmount, + invoiceCurrency || "", + unitDecimals )} - {isExternalInvoice && - createdAt && - delay && - isAlive && - delay > rateUpdateDelay && ( - + {isAlive && ( + + + <> + {elements.map((element) => ( + - - {t("rateUpdatedIn")} {formatSecondsToMMSS(updateRateTime)} - - - - )} - + {element.value} + + ))} + + sats + )} + {isExternalInvoice && + createdAt && + delay && + isAlive && + delay > rateUpdateDelay && ( + + + {t("rateUpdatedIn")} {formatSecondsToMMSS(updateRateTime)} + + + + )} - ), - [ - invoiceFiatAmount, - invoiceCurrency, - unitDecimals, - amount, - isExternalInvoice, - createdAt, - delay, - isAlive, - colors.grey, - colors.primaryLight, - t, - updateRateTime - ] - ); + ); + }, [ + invoiceFiatAmount, + invoiceCurrency, + unitDecimals, + amount, + isExternalInvoice, + createdAt, + delay, + isAlive, + colors.grey, + colors.primaryLight, + t, + updateRateTime + ]); const successLottieRef = useRef(null); @@ -584,8 +625,8 @@ export const Invoice = () => { } setTitle(getInvoiceData.title); - setCreatedAt(getInvoiceData.time); - setDelay(getInvoiceData.expiry - getInvoiceData.time); + setCreatedAt(getInvoiceData.createdAt); + setDelay(getInvoiceData.delay); setPr(_pr); setReadingNfcData(_pr); setOnChainAddr(unpaidOnchain?.address); diff --git a/src/screens/Invoice/styled.tsx b/src/screens/Invoice/styled.tsx index 601e211a..0f4e23e5 100644 --- a/src/screens/Invoice/styled.tsx +++ b/src/screens/Invoice/styled.tsx @@ -245,6 +245,13 @@ export const AmountText = styled(Text).attrs( }) )``; +export const BtcSatsContainer = styled(ComponentStack)` + display: flex; + flex-direction: row; +`; + +export const BtcSatsText = styled(Text)``; + export const BitcoinSlotText = styled(AmountText)` display: flex; margin-top: 16px;