diff --git a/components/ListItem.tsx b/components/ListItem.tsx index f68ed980a..2f88d4541 100644 --- a/components/ListItem.tsx +++ b/components/ListItem.tsx @@ -7,7 +7,7 @@ import { useTheme } from './themes'; // Update the type for the props interface ListItemProps { rightIcon?: any; - leftAvatar?: React.Component; + leftAvatar?: React.JSX.Element; containerStyle?: object; Component?: typeof React.Component | typeof PressableWrapper; bottomDivider?: boolean; @@ -27,6 +27,7 @@ interface ListItemProps { isLoading?: boolean; chevron?: boolean; checkmark?: boolean; + subtitleProps?: object; } export class PressableWrapper extends React.Component { diff --git a/components/TransactionListItem.tsx b/components/TransactionListItem.tsx index 453f55948..01f87162a 100644 --- a/components/TransactionListItem.tsx +++ b/components/TransactionListItem.tsx @@ -1,9 +1,7 @@ +import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import AsyncStorage from '@react-native-async-storage/async-storage'; import Clipboard from '@react-native-clipboard/clipboard'; -import { useNavigation } from '@react-navigation/native'; -import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; import { Linking, StyleSheet, View } from 'react-native'; - import { BlueStorageContext } from '../blue_modules/storage-context'; import Lnurl from '../class/lnurl'; import { LightningTransaction, Transaction } from '../class/wallets/types'; @@ -16,12 +14,14 @@ import TransactionOutgoingIcon from '../components/icons/TransactionOutgoingIcon import TransactionPendingIcon from '../components/icons/TransactionPendingIcon'; import loc, { formatBalanceWithoutSuffix, transactionTimeToReadable } from '../loc'; import { BitcoinUnit } from '../models/bitcoinUnits'; -import * as NavigationService from '../NavigationService'; import { useSettings } from './Context/SettingsContext'; import ListItem from './ListItem'; import { useTheme } from './themes'; import ToolTipMenu from './TooltipMenu'; -import { Action } from './types'; +import { Action, ToolTipMenuProps } from './types'; +import { useExtendedNavigation } from '../hooks/useExtendedNavigation'; +import { NativeStackNavigationProp } from '@react-navigation/native-stack'; +import { DetailViewStackParamList } from '../navigation/DetailViewStackParamList'; interface TransactionListItemProps { itemPriceUnit: BitcoinUnit; @@ -29,11 +29,13 @@ interface TransactionListItemProps { item: Transaction & LightningTransaction; // using type intersection to have less issues with ts } +type NavigationProps = NativeStackNavigationProp; + export const TransactionListItem: React.FC = React.memo(({ item, itemPriceUnit = BitcoinUnit.BTC, walletID }) => { const [subtitleNumberOfLines, setSubtitleNumberOfLines] = useState(1); const { colors } = useTheme(); - const { navigate } = useNavigation(); - const menuRef = useRef(); + const { navigate } = useExtendedNavigation(); + const menuRef = useRef(); const { txMetadata, counterpartyMetadata, wallets } = useContext(BlueStorageContext); const { preferredFiatCurrency, language } = useSettings(); const containerStyle = useMemo( @@ -200,10 +202,8 @@ export const TransactionListItem: React.FC = React.mem }, [subtitle]); const onPress = useCallback(async () => { - // @ts-ignore: idk how to fix menuRef?.current?.dismissMenu?.(); if (item.hash) { - // @ts-ignore: idk how to fix navigate('TransactionStatus', { hash: item.hash, walletID }); } else if (item.type === 'user_invoice' || item.type === 'payment_request' || item.type === 'paid_invoice') { const lightningWallet = wallets.filter(wallet => wallet?.getID() === item.walletID); @@ -217,8 +217,7 @@ export const TransactionListItem: React.FC = React.mem } const loaded = await LN.loadSuccessfulPayment(paymentHash); if (loaded) { - NavigationService.navigate('ScanLndInvoiceRoot', { - // @ts-ignore: idk how to fix + navigate('ScanLndInvoiceRoot', { screen: 'LnurlPaySuccess', params: { paymentHash, @@ -232,7 +231,6 @@ export const TransactionListItem: React.FC = React.mem console.log(e); } - // @ts-ignore: idk how to fix navigate('LNDViewInvoice', { invoice: item, walletID: lightningWallet[0].getID(), @@ -347,7 +345,6 @@ export const TransactionListItem: React.FC = React.mem = ({ - // @ts-ignore: Ugh wallet: initialWallet, - // @ts-ignore: Ugh onWalletUnitChange, - // @ts-ignore: Ugh navigation, - // @ts-ignore: Ugh onManageFundsPressed, - // @ts-ignore: Ugh onWalletBalanceVisibilityChange, }) => { const [wallet, setWallet] = useState(initialWallet); const [allowOnchainAddress, setAllowOnchainAddress] = useState(false); const { preferredFiatCurrency } = useSettings(); - const menuRef = useRef(null); + const menuRef = useRef(null); const verifyIfWalletAllowsOnchainAddress = useCallback(() => { if (wallet.type === LightningCustodianWallet.type) { @@ -85,8 +81,9 @@ const TransactionsNavigationHeader: React.FC }; const changeWalletBalanceUnit = () => { - // @ts-ignore: Ugh - menuRef.current?.dismissMenu(); + if (menuRef.current?.dismissMenu) { + menuRef.current.dismissMenu(); + } let newWalletPreferredUnit = wallet.getPreferredBalanceUnit(); if (newWalletPreferredUnit === BitcoinUnit.BTC) { @@ -140,7 +137,6 @@ const TransactionsNavigationHeader: React.FC ; + const AddressItem = ({ item, balanceUnit, walletID, allowSignVerifyMessage }: AddressItemProps) => { const { wallets } = useStorage(); const { colors } = useTheme(); @@ -52,13 +55,18 @@ const AddressItem = ({ item, balanceUnit, walletID, allowSignVerifyMessage }: Ad }, }); - const { navigate } = useNavigation(); + const { navigate } = useNavigation(); + + const menuRef = useRef(); + + const dismissMenu = () => { + if (menuRef.current?.dismissMenu) { + menuRef.current.dismissMenu(); + } + }; - const menuRef = useRef(); const navigateToReceive = () => { - // @ts-ignore wtf - menuRef.current?.dismissMenu(); - // @ts-ignore wtf + dismissMenu(); navigate('ReceiveDetailsRoot', { screen: 'ReceiveDetails', params: { @@ -69,9 +77,7 @@ const AddressItem = ({ item, balanceUnit, walletID, allowSignVerifyMessage }: Ad }; const navigateToSignVerify = () => { - // @ts-ignore wtf - menuRef.current?.dismissMenu(); - // @ts-ignore wtf + dismissMenu(); navigate('SignVerifyRoot', { screen: 'SignVerify', params: { @@ -114,13 +120,13 @@ const AddressItem = ({ item, balanceUnit, walletID, allowSignVerifyMessage }: Ad }; const onToolTipPress = async (id: string) => { - if (id === AddressItem.actionKeys.CopyToClipboard) { + if (id === actionKeys.CopyToClipboard) { handleCopyPress(); - } else if (id === AddressItem.actionKeys.Share) { + } else if (id === actionKeys.Share) { handleSharePress(); - } else if (id === AddressItem.actionKeys.SignVerify) { + } else if (id === actionKeys.SignVerify) { navigateToSignVerify(); - } else if (id === AddressItem.actionKeys.ExportPrivateKey) { + } else if (id === actionKeys.ExportPrivateKey) { if (await confirm(loc.addresses.sensitive_private_key)) { if (await isBiometricUseCapableAndEnabled()) { if (!(await unlockWithBiometrics())) { @@ -171,14 +177,14 @@ const AddressItem = ({ item, balanceUnit, walletID, allowSignVerifyMessage }: Ad return render(); }; -AddressItem.actionKeys = { +const actionKeys = { Share: 'share', CopyToClipboard: 'copyToClipboard', SignVerify: 'signVerify', ExportPrivateKey: 'exportPrivateKey', }; -AddressItem.actionIcons = { +const actionIcons = { Signature: { iconType: 'SYSTEM', iconValue: 'signature', @@ -220,30 +226,30 @@ const styles = StyleSheet.create({ const getAvailableActions = ({ allowSignVerifyMessage }: { allowSignVerifyMessage: boolean }): Action[] | Action[][] => { const actions = [ { - id: AddressItem.actionKeys.CopyToClipboard, + id: actionKeys.CopyToClipboard, text: loc.transactions.details_copy, - icon: AddressItem.actionIcons.Clipboard, + icon: actionIcons.Clipboard, }, { - id: AddressItem.actionKeys.Share, + id: actionKeys.Share, text: loc.receive.details_share, - icon: AddressItem.actionIcons.Share, + icon: actionIcons.Share, }, ]; if (allowSignVerifyMessage) { actions.push({ - id: AddressItem.actionKeys.SignVerify, + id: actionKeys.SignVerify, text: loc.addresses.sign_title, - icon: AddressItem.actionIcons.Signature, + icon: actionIcons.Signature, }); } if (allowSignVerifyMessage) { actions.push({ - id: AddressItem.actionKeys.ExportPrivateKey, + id: actionKeys.ExportPrivateKey, text: loc.addresses.copy_private_key, - icon: AddressItem.actionIcons.ExportPrivateKey, + icon: actionIcons.ExportPrivateKey, }); } diff --git a/components/types.ts b/components/types.ts index 95daf757a..d9f4b9835 100644 --- a/components/types.ts +++ b/components/types.ts @@ -16,6 +16,7 @@ export interface ToolTipMenuProps { actions: Action[] | Action[][]; children: React.ReactNode; enableAndroidRipple?: boolean; + dismissMenu?: () => void; onPressMenuItem: (id: string) => void; title?: string; isMenuPrimaryAction?: boolean; diff --git a/navigation/DetailViewScreensStack.tsx b/navigation/DetailViewScreensStack.tsx index 34156f1c9..9534ca315 100644 --- a/navigation/DetailViewScreensStack.tsx +++ b/navigation/DetailViewScreensStack.tsx @@ -359,19 +359,6 @@ const DetailViewStackScreensStack = () => { presentation: 'fullScreenModal', statusBarHidden: true, }} - initialParams={{ - isLoading: false, - cameraStatusGranted: undefined, - backdoorPressed: undefined, - launchedBy: undefined, - urTotal: undefined, - urHave: undefined, - backdoorText: '', - onDismiss: undefined, - showFileImportButton: true, - backdoorVisible: false, - animatedQRCodeData: {}, - }} /> diff --git a/navigation/DetailViewStackParamList.ts b/navigation/DetailViewStackParamList.ts index 86688233a..b5734244e 100644 --- a/navigation/DetailViewStackParamList.ts +++ b/navigation/DetailViewStackParamList.ts @@ -1,3 +1,5 @@ +import { LightningTransaction } from '../class/wallets/types'; + export type DetailViewStackParamList = { WalletsList: undefined; WalletTransactions: { walletID: string; walletType: string }; @@ -11,21 +13,32 @@ export type DetailViewStackParamList = { RBFBumpFee: { transactionId: string }; RBFCancel: { transactionId: string }; SelectWallet: undefined; - LNDViewInvoice: { invoiceId: string }; + LNDViewInvoice: { invoice: LightningTransaction; walletID: string }; LNDViewAdditionalInvoiceInformation: { invoiceId: string }; LNDViewAdditionalInvoicePreImage: { invoiceId: string }; Broadcast: undefined; IsItMyAddress: undefined; GenerateWord: undefined; LnurlPay: undefined; - LnurlPaySuccess: undefined; + LnurlPaySuccess: { + paymentHash: string; + justPaid: boolean; + fromWalletID: string; + }; LnurlAuth: undefined; Success: undefined; WalletAddresses: { walletID: string }; AddWalletRoot: undefined; SendDetailsRoot: undefined; LNDCreateInvoiceRoot: undefined; - ScanLndInvoiceRoot: undefined; + ScanLndInvoiceRoot: { + screen: string; + params: { + paymentHash: string; + fromWalletID: string; + justPaid: boolean; + }; + }; AztecoRedeemRoot: undefined; WalletExportRoot: undefined; ExportMultisigCoordinationSetupRoot: undefined; @@ -40,7 +53,9 @@ export type DetailViewStackParamList = { ElectrumSettings: undefined; EncryptStorage: undefined; Language: undefined; - LightningSettings: undefined; + LightningSettings: { + url?: string; + }; NotificationSettings: undefined; SelfTest: undefined; ReleaseNotes: undefined; @@ -48,20 +63,35 @@ export type DetailViewStackParamList = { SettingsPrivacy: undefined; ViewEditMultisigCosignersRoot: { walletID: string; cosigners: string[] }; WalletXpubRoot: undefined; - SignVerifyRoot: undefined; - ReceiveDetailsRoot: undefined; + SignVerifyRoot: { + screen: 'SignVerify'; + params: { + walletID: string; + address: string; + }; + }; + ReceiveDetailsRoot: { + screen: 'ReceiveDetails'; + params: { + walletID: string; + address: string; + }; + }; ScanQRCodeRoot: { - isLoading?: boolean; - cameraStatusGranted?: boolean; - backdoorPressed?: boolean; - launchedBy?: string; - urTotal?: number; - urHave?: number; - backdoorText?: string; - onDismiss?: () => void; - showFileImportButton?: boolean; - backdoorVisible?: boolean; - animatedQRCodeData?: Record; + screen: string; + params: { + isLoading: false; + cameraStatusGranted?: boolean; + backdoorPressed?: boolean; + launchedBy?: string; + urTotal?: number; + urHave?: number; + backdoorText?: string; + onDismiss?: () => void; + showFileImportButton: true; + backdoorVisible?: boolean; + animatedQRCodeData?: Record; + }; }; PaymentCodeRoot: undefined; ReorderWallets: undefined; diff --git a/screen/settings/lightningSettings.tsx b/screen/settings/lightningSettings.tsx index d8e3d0aef..b8275d75e 100644 --- a/screen/settings/lightningSettings.tsx +++ b/screen/settings/lightningSettings.tsx @@ -1,6 +1,6 @@ -import AsyncStorage from '@react-native-async-storage/async-storage'; -import { RouteProp, useNavigation, useRoute } from '@react-navigation/native'; import React, { useCallback, useEffect, useState } from 'react'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import { RouteProp, useRoute } from '@react-navigation/native'; import { Alert, I18nManager, Linking, ScrollView, StyleSheet, TextInput, View } from 'react-native'; import { Button as ButtonRNElements } from 'react-native-elements'; @@ -11,7 +11,7 @@ import { LightningCustodianWallet } from '../../class/wallets/lightning-custodia import presentAlert from '../../components/Alert'; import { Button } from '../../components/Button'; import { useTheme } from '../../components/themes'; -import { requestCameraAuthorization } from '../../helpers/scan-qr'; +import { scanQrHelper } from '../../helpers/scan-qr'; import loc from '../../loc'; const styles = StyleSheet.create({ @@ -52,7 +52,6 @@ const LightningSettings: React.FC = () => { const [URI, setURI] = useState(); const { colors } = useTheme(); const route = useRoute(); - const navigation = useNavigation(); const styleHook = StyleSheet.create({ uri: { borderColor: colors.formBorder, @@ -114,17 +113,11 @@ const LightningSettings: React.FC = () => { }, [URI]); const importScan = () => { - requestCameraAuthorization().then(() => - // @ts-ignore: Address types later - navigation.navigate('ScanQRCodeRoot', { - screen: 'ScanQRCode', - params: { - launchedBy: route.name, - onBarScanned: setLndhubURI, - showFileImportButton: true, - }, - }), - ); + scanQrHelper(route.name).then(data => { + if (data) { + setLndhubURI(data); + } + }); }; return ( diff --git a/screen/transactions/details.tsx b/screen/transactions/details.tsx index 440a62ec4..4a6c675a6 100644 --- a/screen/transactions/details.tsx +++ b/screen/transactions/details.tsx @@ -1,5 +1,5 @@ import Clipboard from '@react-native-clipboard/clipboard'; -import { RouteProp, useFocusEffect, useNavigation, useRoute } from '@react-navigation/native'; +import { RouteProp, useFocusEffect, useRoute } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import assert from 'assert'; import dayjs from 'dayjs'; @@ -18,6 +18,8 @@ import navigationStyle from '../../components/navigationStyle'; import { useTheme } from '../../components/themes'; import ToolTipMenu from '../../components/TooltipMenu'; import loc from '../../loc'; +import { useExtendedNavigation } from '../../hooks/useExtendedNavigation'; +import { DetailViewStackParamList } from '../../navigation/DetailViewStackParamList'; interface TransactionDetailsProps { route: RouteProp<{ params: { hash: string; walletID: string } }, 'params'>; @@ -62,8 +64,10 @@ const toolTipMenuActions = [ }, ]; +type NavigationProps = NativeStackNavigationProp; + const TransactionDetails = () => { - const { setOptions, navigate } = useNavigation(); + const { setOptions, navigate } = useExtendedNavigation(); const { hash, walletID } = useRoute().params; const { saveToDisk, txMetadata, counterpartyMetadata, wallets, getTransactions } = useContext(BlueStorageContext); const [from, setFrom] = useState([]); @@ -204,7 +208,6 @@ const TransactionDetails = () => { }; const navigateToWallet = (wallet: TWallet) => { - // @ts-ignore idk how to fix it navigate('WalletTransactions', { walletID: wallet.getID(), walletType: wallet.type, diff --git a/screen/wallets/ViewEditMultisigCosigners.tsx b/screen/wallets/ViewEditMultisigCosigners.tsx index 3614dc60d..8bedb8b3a 100644 --- a/screen/wallets/ViewEditMultisigCosigners.tsx +++ b/screen/wallets/ViewEditMultisigCosigners.tsx @@ -18,7 +18,7 @@ import { } from 'react-native'; import { Badge, Icon } from 'react-native-elements'; -import { isDesktop } from '../../blue_modules/environment'; +import { isDesktop, isTablet } from '../../blue_modules/environment'; import { useStorage } from '../../blue_modules/storage-context'; import { encodeUR } from '../../blue_modules/ur'; import { @@ -191,7 +191,6 @@ const ViewEditMultisigCosigners: React.FC = () => { await wallet?.fetchBalance(); } newWallets.push(wallet); - // @ts-ignore wtf navigate('WalletsList'); setTimeout(() => { setWalletsWithNewOrder(newWallets); @@ -529,11 +528,9 @@ const ViewEditMultisigCosigners: React.FC = () => { }; const renderProvideMnemonicsModal = () => { - // @ts-ignore weird, property exists on type definition. might be some ts bugs - const isPad: boolean = Platform.isPad; return ( - + {loc.multisig.type_your_mnemonics} @@ -561,12 +558,9 @@ const ViewEditMultisigCosigners: React.FC = () => { }; const renderShareModal = () => { - // @ts-ignore weird, property exists on typedefinition. might be some ts bugs - const isPad: boolean = Platform.isPad; - return ( - + {loc.multisig.this_is_cosigners_xpub} {Platform.OS === 'ios' ? loc.multisig.this_is_cosigners_xpub_airdrop : ''} @@ -627,13 +621,11 @@ const ViewEditMultisigCosigners: React.FC = () => { }; const footer =