FIX: TX details screen would hang when loading large data

This commit is contained in:
Marcos Rodriguez Velez 2024-05-04 19:38:39 -04:00
parent 538a1327b6
commit b395e1b782
No known key found for this signature in database
GPG key ID: 6030B2F48CCE86D7
2 changed files with 80 additions and 74 deletions

View file

@ -8,6 +8,7 @@ import loc from '../loc';
import * as BlueElectrum from './BlueElectrum'; import * as BlueElectrum from './BlueElectrum';
import triggerHapticFeedback, { HapticFeedbackTypes } from './hapticFeedback'; import triggerHapticFeedback, { HapticFeedbackTypes } from './hapticFeedback';
import A from '../blue_modules/analytics'; import A from '../blue_modules/analytics';
import { InteractionManager } from 'react-native';
const BlueApp = BlueAppClass.getInstance(); const BlueApp = BlueAppClass.getInstance();
@ -71,30 +72,27 @@ export const BlueStorageProvider = ({ children }: { children: React.ReactNode })
const [reloadTransactionsMenuActionFunction, setReloadTransactionsMenuActionFunction] = useState<() => void>(() => {}); const [reloadTransactionsMenuActionFunction, setReloadTransactionsMenuActionFunction] = useState<() => void>(() => {});
useEffect(() => { useEffect(() => {
BlueElectrum.isDisabled().then(setIsElectrumDisabled); setWallets(BlueApp.getWallets());
}, []);
useEffect(() => { BlueElectrum.isDisabled().then(setIsElectrumDisabled);
if (walletsInitialized) { if (walletsInitialized) {
BlueElectrum.connectMain(); BlueElectrum.connectMain();
} }
}, [walletsInitialized]); }, [walletsInitialized]);
const saveToDisk = async (force: boolean = false) => { const saveToDisk = async (force: boolean = false) => {
if (BlueApp.getWallets().length === 0 && !force) { InteractionManager.runAfterInteractions(async () => {
console.log('not saving empty wallets array'); if (BlueApp.getWallets().length === 0 && !force) {
return; console.log('not saving empty wallets array');
} return;
BlueApp.tx_metadata = txMetadata; }
await BlueApp.saveToDisk(); BlueApp.tx_metadata = txMetadata;
setWallets([...BlueApp.getWallets()]); await BlueApp.saveToDisk();
txMetadata = BlueApp.tx_metadata; setWallets([...BlueApp.getWallets()]);
txMetadata = BlueApp.tx_metadata;
});
}; };
useEffect(() => {
setWallets(BlueApp.getWallets());
}, []);
const resetWallets = () => { const resetWallets = () => {
setWallets(BlueApp.getWallets()); setWallets(BlueApp.getWallets());
}; };

View file

@ -1,6 +1,6 @@
import React, { useContext, useEffect, useLayoutEffect, useState } from 'react'; import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { View, ScrollView, TouchableOpacity, Text, TextInput, Linking, StyleSheet, Keyboard } from 'react-native'; import { View, ScrollView, TouchableOpacity, Text, TextInput, Linking, StyleSheet, Keyboard, InteractionManager } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useFocusEffect, useNavigation, useRoute } from '@react-navigation/native';
import Clipboard from '@react-native-clipboard/clipboard'; import Clipboard from '@react-native-clipboard/clipboard';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { BlueCard, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents'; import { BlueCard, BlueLoading, BlueSpacing20, BlueText } from '../../BlueComponents';
@ -59,68 +59,76 @@ const TransactionsDetails = () => {
}, },
}); });
useLayoutEffect(() => { const handleOnSaveButtonTapped = useCallback(() => {
setOptions({
// eslint-disable-next-line react/no-unstable-nested-components
headerRight: () => (
<TouchableOpacity
accessibilityRole="button"
disabled={isLoading}
style={[styles.save, stylesHooks.save]}
onPress={handleOnSaveButtonTapped}
>
<Text style={[styles.saveText, stylesHooks.saveText]}>{loc.wallets.details_save}</Text>
</TouchableOpacity>
),
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [colors, isLoading, memo]);
useEffect(() => {
let foundTx = {};
let newFrom = [];
let newTo = [];
for (const transaction of getTransactions(null, Infinity, true)) {
if (transaction.hash === hash) {
foundTx = transaction;
for (const input of foundTx.inputs) {
newFrom = newFrom.concat(input.addresses);
}
for (const output of foundTx.outputs) {
if (output.addresses) newTo = newTo.concat(output.addresses);
if (output.scriptPubKey && output.scriptPubKey.addresses) newTo = newTo.concat(output.scriptPubKey.addresses);
}
}
}
for (const w of wallets) {
for (const t of w.getTransactions()) {
if (t.hash === hash) {
console.log('tx', hash, 'belongs to', w.getLabel());
}
}
}
if (txMetadata[foundTx.hash]) {
if (txMetadata[foundTx.hash].memo) {
setMemo(txMetadata[foundTx.hash].memo);
}
}
setTX(foundTx);
setFrom(newFrom);
setTo(newTo);
setIsLoading(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hash, wallets]);
const handleOnSaveButtonTapped = () => {
Keyboard.dismiss(); Keyboard.dismiss();
txMetadata[tx.hash] = { memo }; txMetadata[tx.hash] = { memo };
saveToDisk().then(_success => { saveToDisk().then(_success => {
triggerHapticFeedback(HapticFeedbackTypes.Success); triggerHapticFeedback(HapticFeedbackTypes.Success);
presentAlert({ message: loc.transactions.transaction_note_saved }); presentAlert({ message: loc.transactions.transaction_note_saved });
}); });
}; }, [tx, memo, saveToDisk, txMetadata]);
const HeaderRightButton = useMemo(() => {
return (
<TouchableOpacity
accessibilityRole="button"
disabled={isLoading}
style={[styles.save, stylesHooks.save]}
onPress={handleOnSaveButtonTapped}
>
<Text style={[styles.saveText, stylesHooks.saveText]}>{loc.wallets.details_save}</Text>
</TouchableOpacity>
);
}, [isLoading, stylesHooks.save, stylesHooks.saveText, handleOnSaveButtonTapped]);
useEffect(() => {
// This effect only handles changes in `colors`
setOptions({ headerRight: () => HeaderRightButton });
}, [colors, HeaderRightButton, setOptions]);
useFocusEffect(
useCallback(() => {
const task = InteractionManager.runAfterInteractions(() => {
let foundTx = {};
let newFrom = [];
let newTo = [];
for (const transaction of getTransactions(null, Infinity, true)) {
if (transaction.hash === hash) {
foundTx = transaction;
for (const input of foundTx.inputs) {
newFrom = newFrom.concat(input.addresses);
}
for (const output of foundTx.outputs) {
if (output.addresses) newTo = newTo.concat(output.addresses);
if (output.scriptPubKey && output.scriptPubKey.addresses) newTo = newTo.concat(output.scriptPubKey.addresses);
}
}
}
for (const w of wallets) {
for (const t of w.getTransactions()) {
if (t.hash === hash) {
console.log('tx', hash, 'belongs to', w.getLabel());
}
}
}
if (txMetadata[foundTx.hash]) {
if (txMetadata[foundTx.hash].memo) {
setMemo(txMetadata[foundTx.hash].memo);
}
}
setTX(foundTx);
setFrom(newFrom);
setTo(newTo);
setIsLoading(false);
});
return () => {
task.cancel();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hash, wallets]),
);
const handleOnOpenTransactionOnBlockExplorerTapped = () => { const handleOnOpenTransactionOnBlockExplorerTapped = () => {
const url = `https://mempool.space/tx/${tx.hash}`; const url = `https://mempool.space/tx/${tx.hash}`;