Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance history entry of swap tx #220

Merged
merged 2 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions assets/translations/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@
"clearOverHere": "Sie sind auf dem neusten Stand!",
"totalDmsReceived": "Sie haben {{totalDms}} Cashu token erhalten.",
"swapNow": "Jetzt tauschen",
"swap": "Tausch",
"emptyMint": "Kein Guthaben vorhanden",
"zapSoon": "Zaps werden bald hinzugefügt...",
"enutsPub": "eNuts: ",
Expand Down
1 change: 1 addition & 0 deletions assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@
"clearOverHere": "Everything is clear over here!",
"totalDmsReceived": "You received {{totalDms}} Cashu token.",
"swapNow": "Swap now",
"swap": "Swap",
"emptyMint": "Mint has no funds",
"zapSoon": "Zaps will be added soon...",
"enutsPub": "eNuts public key: ",
Expand Down
1 change: 1 addition & 0 deletions assets/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@
"hideNuts": "Masquer votre solde total",
"checkingDms": "Vérification de vos DM pour l'Ecash...",
"swapNow": "Échanger maintenant",
"swap": "Échange",
"emptyMint": "Mint ne dispose pas de fonds.",
"zapSoon": "Les zaps seront bientôt ajoutés...",
"enutsPub": "eNuts clé public: ",
Expand Down
20 changes: 17 additions & 3 deletions src/components/Balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ export default function Balance({ balance, nav }: IBalanceProps) {
void setPreferences({ ...pref, formatBalance: !formatSats })
}

const getTxTypeStr = (type: number) => {
if (type === 1) { return 'Ecash' }
if (type === 2) { return 'Lightning' }
return t('swap')
}

useEffect(() => {
void (async () => {
const stored = (await getLatestHistory()).reverse()
Expand Down Expand Up @@ -98,7 +104,8 @@ export default function Balance({ balance, nav }: IBalanceProps) {
:
<EcashIcon color={mainColors.WHITE} />
}
txType={h.type === 2 || h.type === 3 ? 'Lightning' : 'Ecash'}
isSwap={h.type === 3}
txType={getTxTypeStr(h.type)}
timestamp={h.timestamp}
amount={h.amount}
onPress={() => nav?.navigate('history entry details', { entry: h })}
Expand Down Expand Up @@ -138,13 +145,20 @@ export default function Balance({ balance, nav }: IBalanceProps) {
interface IHistoryEntryProps {
icon: React.ReactNode
txType: string
isSwap?: boolean
timestamp: number
amount: number
onPress: () => void
}

function HistoryEntry({ icon, txType, timestamp, amount, onPress }: IHistoryEntryProps) {
function HistoryEntry({ icon, txType, isSwap, timestamp, amount, onPress }: IHistoryEntryProps) {
const { t } = useTranslation([NS.history])

const getAmount = () => {
if (isSwap) { return `${formatInt(Math.abs(amount))} Satoshi` }
return `${amount > 0 ? '+' : ''}${formatInt(amount)} Satoshi`
}

return (
<>
<TouchableOpacity
Expand All @@ -162,7 +176,7 @@ function HistoryEntry({ icon, txType, timestamp, amount, onPress }: IHistoryEntr
</Text>
</View>
</View>
<Txt txt={`${amount > 0 ? '+' : ''}${formatInt(amount)} Satoshi`} styles={[{ color: mainColors.WHITE }]} />
<Txt txt={getAmount()} styles={[{ color: mainColors.WHITE }]} />
</TouchableOpacity>
</>
)
Expand Down
27 changes: 20 additions & 7 deletions src/screens/History/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ import { truncateNostrProfileInfo } from '@nostr/util'
import { usePromptContext } from '@src/context/Prompt'
import { useThemeContext } from '@src/context/Theme'
import { NS } from '@src/i18n'
import { l } from '@src/logger'
import { addToHistory } from '@src/storage/store/latestHistoryEntries'
import { historyStore } from '@store'
import { globals, mainColors } from '@styles'
import { copyStrToClipboard, formatInt, formatMintUrl, getLnInvoiceInfo, isUndef } from '@util'
import { copyStrToClipboard, formatInt, formatMintUrl, getLnInvoiceInfo, isNum, isUndef } from '@util'
import { claimToken, isTokenSpendable } from '@wallet'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
Expand Down Expand Up @@ -57,7 +56,21 @@ export default function DetailsPage({ navigation, route }: THistoryEntryPageProp
const { hash, memo } = isLn ? getLnInvoiceInfo(value) : { hash: '', memo: '' }
const tokenMemo = !isLn ? getDecodedToken(value).memo : t('noMemo', { ns: NS.history })
const { openPromptAutoClose } = usePromptContext()
l({ fee })

const getTxColor = () => {
if (type === 3) { return color.TEXT }
return amount < 0 ? mainColors.ERROR : mainColors.VALID
}

const getScreenName = () => {
if (type === 3) { return t('multimintSwap') }
return isLn ? LNstr : Ecash
}

const getAmount = () => {
if (type === 3) { return `${formatInt(Math.abs(amount))}` }
return `${amount > 0 ? '+' : ''}${formatInt(amount)}`
}

const copyValue = async () => {
await copyStrToClipboard(value)
Expand Down Expand Up @@ -144,14 +157,14 @@ export default function DetailsPage({ navigation, route }: THistoryEntryPageProp
return (
<View style={[globals(color).container, styles.container]}>
<TopNav
screenName={isLn ? LNstr : Ecash}
screenName={getScreenName()}
withBackBtn
handlePress={() => navigation.goBack()}
/>
<ScrollView style={{ marginTop: 110, marginBottom: insets.bottom }} showsVerticalScrollIndicator={false} >
<View style={styles.topSection}>
<Text style={[styles.amount, { color: amount < 0 ? mainColors.ERROR : mainColors.VALID }]}>
{formatInt(amount < 0 ? Math.abs(amount) : amount)}
<Text style={[styles.amount, { color: getTxColor() }]}>
{getAmount()}
</Text>
<Txt
txt='Satoshi'
Expand Down Expand Up @@ -311,7 +324,7 @@ export default function DetailsPage({ navigation, route }: THistoryEntryPageProp
{/* LN payment fees */}
<View style={styles.entryInfo}>
<Txt txt={t('fee')} />
<Txt txt={fee ? `${fee} Satoshi` : t('n/a')} />
<Txt txt={isNum(fee) ? `${fee} Satoshi` : t('n/a')} />
</View>
<Separator />
</>
Expand Down
41 changes: 31 additions & 10 deletions src/screens/History/Entry.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IncomingArrowIcon, OutgoingArrowIcon } from '@comps/Icons'
import { IncomingArrowIcon, OutgoingArrowIcon, SwapCurrencyIcon } from '@comps/Icons'
import Txt from '@comps/Txt'
import type { IHistoryEntry } from '@model'
import type { THistoryPageProps } from '@model/nav'
Expand All @@ -19,31 +19,52 @@ interface IHistoryEntryProps {
export default function HistoryEntry({ nav, item }: IHistoryEntryProps) {
const { t } = useTranslation([NS.history])
const { color, highlight } = useThemeContext()

const getTxTypeStr = () => {
if (item.type === 1) { return 'Ecash' }
if (item.type === 2) { return 'Lightning' }
return t('swap', { ns: NS.common})
}

const getTxColor = () => {
if (item.type === 3) { return color.TEXT }
return item.amount < 0 ? mainColors.ERROR : mainColors.VALID
}

const getAmount = () => {
if (item.type === 3) { return `${formatInt(Math.abs(item.amount), 'compact', 'en')}` }
return `${item.amount > 0 ? '+' : ''}${formatInt(item.amount, 'compact', 'en')}`
}

const getIcon = () => {
if (item.type === 3) { return <SwapCurrencyIcon width={16} height={16} color={color.TEXT} /> }
return item.amount < 0 ?
<OutgoingArrowIcon color={color.TEXT} />
:
<IncomingArrowIcon color={color.TEXT} />
}

return (
<TouchableOpacity
style={styles.listItem}
onPress={() => nav.navigation.navigate('history entry details', { entry: item })}
>
{item.amount < 0 ?
<OutgoingArrowIcon color={color.TEXT} />
:
<IncomingArrowIcon color={color.TEXT} />
}
{getIcon()}
<View style={styles.infoWrap}>
<Txt txt={item.type === 1 ? 'Ecash' : 'Lightning'} />
<Txt txt={getTxTypeStr()} />
<Text style={[globals(color, highlight).txt, { color: color.TEXT_SECONDARY, fontSize: 14 }]}>
<EntryTime from={item.timestamp * 1000} fallback={t('justNow')} />
</Text>
</View>
<View style={styles.placeholder} />
<View style={styles.amount}>
<Txt
txt={`${item.amount > 0 ? '+' : '-'}${formatInt(item.amount < 0 ? Math.abs(item.amount) : item.amount, 'compact', 'en')}`}
styles={[{ color: item.amount < 0 ? mainColors.ERROR : mainColors.VALID }]}
txt={getAmount()}
styles={[{ color: getTxColor() }]}
/>
<Txt
txt=' Sat.'
styles={[{ color: item.amount < 0 ? mainColors.ERROR : mainColors.VALID }]}
styles={[{ color: getTxColor() }]}
/>
</View>
</TouchableOpacity>
Expand Down
3 changes: 3 additions & 0 deletions src/screens/History/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ export default function HistoryPage({ navigation, route }: THistoryPageProps) {
const { color } = useThemeContext()
const { claimed } = useFocusClaimContext()
const [data, setData] = useState<Record<string, IHistoryEntry[]>>({})

// update history after claiming from clipboard when the app comes to the foreground
useEffect(() => {
void (async () => {
setData(await getHistory())
})()
}, [claimed])

// update history after navigating to this page
useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
Expand All @@ -37,6 +39,7 @@ export default function HistoryPage({ navigation, route }: THistoryPageProps) {
})
return focusHandler
}, [navigation])

return (
<View style={[globals(color).container, styles.container, { paddingBottom: isIOS ? insets.bottom : 0 }]}>
<TopNav
Expand Down
Loading