diff --git a/assets/translations/de.json b/assets/translations/de.json index 178cc7d1..af0b004e 100644 --- a/assets/translations/de.json +++ b/assets/translations/de.json @@ -176,6 +176,8 @@ "version": "Version", "willDoLater": "Mache ich später", "yes": "Ja", + "invalidPubKey": "Invalider öffentlicher Schlüssel!", + "whatsNostr": "Was ist NOSTR?", "walletLocked": "Wallet gesperrt", "explainer1": "eNuts ist eine treuhänderische Lightning-Wallet, die private und sofortige Transaktionen mit dem Cashu-Protokoll ermöglicht. Ihre Gelder werden von Mints verwaltet, mit denen Sie interagieren, und Ecash wird lokal auf Ihrem Gerät gespeichert.", "explainer2": "Cashu ist ein neues Ecash-Protokoll für treuhänderische Bitcoin-Apps, bei denen Mints nur Lightning-Knoten sind, die Bitcoin-Transaktionen durchführen und Ihnen Ecash zur Verfügung stellen. Seien Sie versichert, die Mints bleiben unwissend über Ihre Ecash-Zahlungen.", diff --git a/assets/translations/en.json b/assets/translations/en.json index ac4cd2ef..20b60e63 100644 --- a/assets/translations/en.json +++ b/assets/translations/en.json @@ -176,6 +176,8 @@ "version": "Version", "willDoLater": "Will do later", "yes": "Yes", + "invalidPubKey": "Invalid public key!", + "whatsNostr": "What is NOSTR?", "walletLocked": "Wallet locked", "explainer1": "eNuts is a custodial Lightning wallet, allowing private and instant transactions using the Cashu protocol. Your funds are held by mints you interact with, and Ecash is stored locally on your device.", "explainer2": "Cashu is a new Ecash protocol for custodial Bitcoin apps, where mints are Lightning nodes performing Bitcoin transactions and offer you Ecash. Rest assured, the mint remains unaware of your Ecash payments.", diff --git a/assets/translations/fr.json b/assets/translations/fr.json index 54137b2c..7494eecd 100644 --- a/assets/translations/fr.json +++ b/assets/translations/fr.json @@ -176,6 +176,8 @@ "version": "Version", "willDoLater": "Je ferai plus tard", "yes": "Oui", + "invalidPubKey": "Clé publique invalide!", + "whatsNostr": "C'est quoi NOSTR?", "walletLocked": "Wallet verrouillé", "explainer1": "eNuts est une wallet Lightning sous garde, permettant des transactions privées et instantanées en utilisant le protocole Cashu. Vos fonds sont détenus par des mints avec lesquels vous interagissez, et l'Ecash est stocké localement sur votre appareil.", "explainer2": "Cashu est un nouveau protocole Ecash pour les applications Bitcoin sous garde, où les mints sont des nœuds Lightning facilitant les transactions Bitcoin pour vous offrir de l'Ecash. Soyez rassuré, les mints reste ignorant de vos paiements Ecash.", diff --git a/src/components/Empty.tsx b/src/components/Empty.tsx index 27549a45..1a1777af 100644 --- a/src/components/Empty.tsx +++ b/src/components/Empty.tsx @@ -2,7 +2,7 @@ import type { RootStackParamList } from '@model/nav' import type { NativeStackNavigationProp } from '@react-navigation/native-stack' import { useThemeContext } from '@src/context/Theme' import { useTranslation } from 'react-i18next' -import { Image, StyleSheet } from 'react-native' +import { Image, StyleSheet, TouchableOpacity } from 'react-native' import { TxtButton } from './Button' import Txt from './Txt' @@ -10,10 +10,12 @@ import Txt from './Txt' interface IEmptyProps { txt: string hasOk?: boolean + pressable?: boolean + onPress?: () => void nav?: NativeStackNavigationProp } -export default function Empty({ txt, hasOk, nav }: IEmptyProps) { +export default function Empty({ txt, hasOk, pressable, onPress, nav }: IEmptyProps) { const { t } = useTranslation() const { color } = useThemeContext() return ( @@ -23,10 +25,19 @@ export default function Empty({ txt, hasOk, nav }: IEmptyProps) { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment source={require('@assets/mixed_forest.png')} /> - + {pressable && onPress ? + + + + : + + } {hasOk && ([]) const [newNpubModal, setNewNpubModal] = useState(false) @@ -184,13 +188,20 @@ export default function AddressbookPage({ navigation, route }: TAddressBookPageP } // paste from clipboard const clipboard = await getStrFromClipboard() - if (!clipboard || clipboard === 'null') { return } + if (!clipboard) { + return + } // check if is npub if (clipboard.startsWith('npub')) { setPubKey({ encoded: clipboard, hex: nip19.decode(clipboard).data as string || '' }) return } - setPubKey({ encoded: nip19.npubEncode(clipboard), hex: clipboard }) + try { + const encoded = nip19.npubEncode(clipboard) + setPubKey({ encoded, hex: clipboard }) + } catch (e) { + openPromptAutoClose({ msg: t('invalidPubKey') }) + } } // save npub pasted by user @@ -286,6 +297,7 @@ export default function AddressbookPage({ navigation, route }: TAddressBookPageP // check if user has nostr data saved previously useEffect(() => { void (async () => { + startLoading() const data = await Promise.all([ store.get(STORE_KEYS.npub), store.get(STORE_KEYS.npubHex), @@ -294,6 +306,8 @@ export default function AddressbookPage({ navigation, route }: TAddressBookPageP setPubKey({ encoded: data[0] || '', hex: data[1] || '' }) setUserRelays(data[2] || []) initUserData({ hex: data[1] || '', userRelays: data[2] || [] }) + if (!data[0]) { setNewNpubModal(true) } + stopLoading() })() // eslint-disable-next-line react-hooks/exhaustive-deps }, []) @@ -309,52 +323,66 @@ export default function AddressbookPage({ navigation, route }: TAddressBookPageP - {/* user own profile */} - - {/* user contacts */} - {contacts.length > 0 && - - item[0]} - renderItem={({ item, index }) => ( - handleContactPress({ contact: item[1], npub: nip19.npubEncode(item[0]) })} - handleSend={() => { - void handleSend({ - npub: item[0], - name: getNostrUsername(item[1]) - }) + {loading ? + + + + : + <> + {/* user own profile */} + {nutPub && } + {/* user contacts */} + {contacts.length > 0 ? + + item[0]} + renderItem={({ item, index }) => ( + handleContactPress({ contact: item[1], npub: nip19.npubEncode(item[0]) })} + handleSend={() => { + void handleSend({ + npub: item[0], + name: getNostrUsername(item[1]) + }) + }} + isFirst={index === 0} + isLast={index === contacts.length - 1} + isPayment={route.params?.isMelt || route.params?.isSendEcash} + /> + )} + ItemSeparatorComponent={() => } /> - )} - ItemSeparatorComponent={() => } - /> - + + : + setNewNpubModal(true)} + /> + } + } {/* Add user npub modal */} setNewNpubModal(false)} > - {t('yourProfile', { ns: NS.addrBook })} + {t('addOwnLnurl', { ns: NS.addrBook })}