Optimize transaction sorting (#86)
* implemented new tx sorting to prevent rerenders * updated component to reduce re-renders * fixing bank transactions page
This commit is contained in:
@@ -63,6 +63,7 @@ import {
|
||||
} from './navigation/screens';
|
||||
import getDeepLinkUser from './app/components/admin/homeComponents/contacts/internalComponents/getDeepLinkUser';
|
||||
import {navigationRef} from './navigation/navigationService';
|
||||
import {GlobalConbinedTxContextProvider} from './context-store/combinedTransactionsContext';
|
||||
|
||||
const Stack = createNativeStackNavigator();
|
||||
|
||||
@@ -70,35 +71,37 @@ function App(): JSX.Element {
|
||||
return (
|
||||
<GestureHandlerRootView>
|
||||
<KeysContextProvider>
|
||||
<AppStatusProvider>
|
||||
<GlobalThemeProvider>
|
||||
<GLobalNodeContextProider>
|
||||
<GlobalContextProvider>
|
||||
<GlobalAppDataProvider>
|
||||
<POSTransactionsProvider>
|
||||
<WebViewProvider>
|
||||
<GlobalContactsList>
|
||||
<GlobaleCashVariables>
|
||||
<PushNotificationManager>
|
||||
<LiquidEventProvider>
|
||||
<LightningEventProvider>
|
||||
{/* <Suspense
|
||||
<GlobalContextProvider>
|
||||
<AppStatusProvider>
|
||||
<GlobalThemeProvider>
|
||||
<GlobaleCashVariables>
|
||||
<GLobalNodeContextProider>
|
||||
<GlobalConbinedTxContextProvider>
|
||||
<GlobalAppDataProvider>
|
||||
<POSTransactionsProvider>
|
||||
<WebViewProvider>
|
||||
<GlobalContactsList>
|
||||
<PushNotificationManager>
|
||||
<LiquidEventProvider>
|
||||
<LightningEventProvider>
|
||||
{/* <Suspense
|
||||
fallback={<FullLoadingScreen text={'Loading Page'} />}> */}
|
||||
<ResetStack />
|
||||
{/* </Suspense> */}
|
||||
</LightningEventProvider>
|
||||
</LiquidEventProvider>
|
||||
</PushNotificationManager>
|
||||
</GlobaleCashVariables>
|
||||
</GlobalContactsList>
|
||||
</WebViewProvider>
|
||||
</POSTransactionsProvider>
|
||||
</GlobalAppDataProvider>
|
||||
{/* <BreezTest /> */}
|
||||
</GlobalContextProvider>
|
||||
</GLobalNodeContextProider>
|
||||
</GlobalThemeProvider>
|
||||
</AppStatusProvider>
|
||||
<ResetStack />
|
||||
{/* </Suspense> */}
|
||||
</LightningEventProvider>
|
||||
</LiquidEventProvider>
|
||||
</PushNotificationManager>
|
||||
</GlobalContactsList>
|
||||
</WebViewProvider>
|
||||
</POSTransactionsProvider>
|
||||
</GlobalAppDataProvider>
|
||||
{/* <BreezTest /> */}
|
||||
</GlobalConbinedTxContextProvider>
|
||||
</GLobalNodeContextProider>
|
||||
</GlobaleCashVariables>
|
||||
</GlobalThemeProvider>
|
||||
</AppStatusProvider>
|
||||
</GlobalContextProvider>
|
||||
</KeysContextProvider>
|
||||
</GestureHandlerRootView>
|
||||
);
|
||||
|
||||
@@ -210,8 +210,8 @@ export default function GiftCardPage() {
|
||||
/>
|
||||
) : (
|
||||
<FlatList
|
||||
initialNumToRender={10}
|
||||
maxToRenderPerBatch={10}
|
||||
initialNumToRender={20}
|
||||
maxToRenderPerBatch={20}
|
||||
windowSize={3}
|
||||
removeClippedSubviews={true}
|
||||
data={filteredGiftCards}
|
||||
|
||||
@@ -2,12 +2,11 @@ import {StyleSheet, View} from 'react-native';
|
||||
import {useNavigation} from '@react-navigation/native';
|
||||
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
|
||||
import {ThemeText} from '../../../../functions/CustomElements';
|
||||
import {useGlobaleCash} from '../../../../../context-store/eCash';
|
||||
import GetThemeColors from '../../../../hooks/themeColors';
|
||||
import FullLoadingScreen from '../../../../functions/CustomElements/loadingScreen';
|
||||
import {useNodeContext} from '../../../../../context-store/nodeContext';
|
||||
import writeAndShareFileToFilesystem from '../../../../functions/writeFileToFilesystem';
|
||||
import SwipeButtonNew from '../../../../functions/CustomElements/sliderButton';
|
||||
import {useGlobalTxContextProvider} from '../../../../../context-store/combinedTransactionsContext';
|
||||
|
||||
export default function ConfirmExportPayments({
|
||||
startExport,
|
||||
@@ -15,14 +14,9 @@ export default function ConfirmExportPayments({
|
||||
darkModeType,
|
||||
}) {
|
||||
const navigate = useNavigation();
|
||||
const {nodeInformation, liquidNodeInformation} = useNodeContext();
|
||||
const {ecashWalletInformation} = useGlobaleCash();
|
||||
const {combinedTransactions} = useGlobalTxContextProvider();
|
||||
const {backgroundOffset, backgroundColor} = GetThemeColors();
|
||||
const ecashTransactions = ecashWalletInformation.transactions;
|
||||
const totalPayments =
|
||||
nodeInformation.transactions.length +
|
||||
liquidNodeInformation.transactions.length +
|
||||
ecashTransactions.length;
|
||||
const totalPayments = combinedTransactions.length;
|
||||
|
||||
const [txNumber, setTxNumber] = useState(0);
|
||||
|
||||
@@ -30,9 +24,6 @@ export default function ConfirmExportPayments({
|
||||
async function generateCSV() {
|
||||
if (!startExport) return;
|
||||
try {
|
||||
const lNdata = nodeInformation.transactions;
|
||||
const liquidData = liquidNodeInformation.transactions;
|
||||
const ecashData = ecashTransactions;
|
||||
const headers = [
|
||||
[
|
||||
'Payment Type',
|
||||
@@ -44,7 +35,7 @@ export default function ConfirmExportPayments({
|
||||
],
|
||||
];
|
||||
|
||||
const conjoinedTxList = [...liquidData, ...lNdata, ...ecashData];
|
||||
const conjoinedTxList = combinedTransactions;
|
||||
let formatedData = [];
|
||||
|
||||
for (let index = 0; index < conjoinedTxList.length; index++) {
|
||||
@@ -71,7 +62,9 @@ export default function ConfirmExportPayments({
|
||||
: !!tx.timestamp
|
||||
? tx.feesSat
|
||||
: tx.feeMsat / 1000,
|
||||
).toLocaleString(),
|
||||
)
|
||||
.toLocaleString()
|
||||
.replace(/,/g, ' '),
|
||||
Math.round(
|
||||
tx.type === 'ecash'
|
||||
? tx.amount * (tx.paymentType === 'sent' ? -1 : 1)
|
||||
|
||||
@@ -5,28 +5,31 @@ import {useGlobalContextProvider} from '../../../../context-store/context';
|
||||
import {GlobalThemeView, ThemeText} from '../../../functions/CustomElements';
|
||||
import CustomFlatList from './homeLightning/cusomFlatlist/CustomFlatList';
|
||||
import getFormattedHomepageTxs from '../../../functions/combinedTransactions';
|
||||
import NavBar from './navBar';
|
||||
import {NavBar} from './navBar';
|
||||
|
||||
import {useNavigation} from '@react-navigation/native';
|
||||
import {useUpdateHomepageTransactions} from '../../../hooks/updateHomepageTransactions';
|
||||
import {useGlobaleCash} from '../../../../context-store/eCash';
|
||||
import {useEffect, useMemo} from 'react';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {useNodeContext} from '../../../../context-store/nodeContext';
|
||||
import {useAppStatus} from '../../../../context-store/appStatus';
|
||||
export default function HomeLightning({tabNavigation}) {
|
||||
import {useGlobalThemeContext} from '../../../../context-store/theme';
|
||||
import {useGlobalTxContextProvider} from '../../../../context-store/combinedTransactionsContext';
|
||||
|
||||
export default function HomeLightning() {
|
||||
console.log('HOME LIGHTNING PAGE');
|
||||
const {theme, darkModeType, toggleTheme} = useGlobalThemeContext();
|
||||
const {masterInfoObject} = useGlobalContextProvider();
|
||||
const {toggleDidGetToHomepage, didGetToHomepage} = useAppStatus();
|
||||
const {nodeInformation, liquidNodeInformation} = useNodeContext();
|
||||
const {ecashWalletInformation} = useGlobaleCash();
|
||||
const {toggleDidGetToHomepage, isConnectedToTheInternet} = useAppStatus();
|
||||
const {combinedTransactions} = useGlobalTxContextProvider();
|
||||
const navigate = useNavigation();
|
||||
const shouldUpdateTransactions = useUpdateHomepageTransactions();
|
||||
const currentTime = useUpdateHomepageTransactions();
|
||||
const {t} = useTranslation();
|
||||
console.log(currentTime);
|
||||
|
||||
const masterFailedTransactions = masterInfoObject.failedTransactions;
|
||||
const enabledEcash = masterInfoObject.enabledEcash;
|
||||
const homepageTxPreferance = masterInfoObject.homepageTxPreferance;
|
||||
const ecashTransactions = ecashWalletInformation.transactions;
|
||||
const userBalanceDenomination = masterInfoObject.userBalanceDenomination;
|
||||
|
||||
useEffect(() => {
|
||||
toggleDidGetToHomepage(true);
|
||||
@@ -34,12 +37,11 @@ export default function HomeLightning({tabNavigation}) {
|
||||
|
||||
const flatListData = useMemo(() => {
|
||||
return getFormattedHomepageTxs({
|
||||
nodeInformation,
|
||||
liquidNodeInformation,
|
||||
combinedTransactions,
|
||||
currentTime,
|
||||
homepageTxPreferance,
|
||||
navigate,
|
||||
frompage: 'home',
|
||||
ecashTransactions,
|
||||
viewAllTxText: t('wallet.see_all_txs'),
|
||||
noTransactionHistoryText: t('wallet.no_transaction_history'),
|
||||
todayText: t('constants.today'),
|
||||
@@ -48,16 +50,20 @@ export default function HomeLightning({tabNavigation}) {
|
||||
monthText: t('constants.month'),
|
||||
yearText: t('constants.year'),
|
||||
agoText: t('transactionLabelText.ago'),
|
||||
theme,
|
||||
darkModeType,
|
||||
userBalanceDenomination,
|
||||
});
|
||||
}, [
|
||||
ecashTransactions,
|
||||
nodeInformation,
|
||||
liquidNodeInformation,
|
||||
masterFailedTransactions,
|
||||
enabledEcash,
|
||||
homepageTxPreferance,
|
||||
shouldUpdateTransactions,
|
||||
navigate,
|
||||
combinedTransactions,
|
||||
currentTime,
|
||||
theme,
|
||||
darkModeType,
|
||||
userBalanceDenomination,
|
||||
]);
|
||||
|
||||
return (
|
||||
@@ -66,22 +72,20 @@ export default function HomeLightning({tabNavigation}) {
|
||||
style={{overflow: 'hidden', flex: 1}}
|
||||
data={flatListData}
|
||||
renderItem={({item}) => item}
|
||||
HeaderComponent={<NavBar />}
|
||||
HeaderComponent={<NavBar theme={theme} toggleTheme={toggleTheme} />}
|
||||
StickyElementComponent={
|
||||
<GlobalThemeView styles={style.balanceContainer}>
|
||||
<ThemeText
|
||||
content={t('constants.total_balance')}
|
||||
styles={{
|
||||
textTransform: 'uppercase',
|
||||
marginTop: nodeInformation.userBalance === 0 ? 20 : 0,
|
||||
}}
|
||||
/>
|
||||
<UserSatAmount
|
||||
nodeInformation={nodeInformation}
|
||||
liquidNodeInformation={liquidNodeInformation}
|
||||
ecashWalletInformation={ecashWalletInformation}
|
||||
isConnectedToTheInternet={isConnectedToTheInternet}
|
||||
theme={theme}
|
||||
darkModeType={darkModeType}
|
||||
/>
|
||||
{/* {nodeInformation.userBalance != 0 && <LiquidityIndicator />} */}
|
||||
</GlobalThemeView>
|
||||
}
|
||||
TopListElementComponent={
|
||||
@@ -89,7 +93,11 @@ export default function HomeLightning({tabNavigation}) {
|
||||
style={{
|
||||
alignItems: 'center',
|
||||
}}>
|
||||
<SendRecieveBTNs tabNavigation={tabNavigation} />
|
||||
<SendRecieveBTNs
|
||||
theme={theme}
|
||||
darkModeType={darkModeType}
|
||||
isConnectedToTheInternet={isConnectedToTheInternet}
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -3,18 +3,27 @@ import {CENTER, COLORS, ICONS} from '../../../../constants';
|
||||
import {useNavigation} from '@react-navigation/native';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import ThemeImage from '../../../../functions/CustomElements/themeImage';
|
||||
import {useMemo} from 'react';
|
||||
import {memo, useCallback, useMemo} from 'react';
|
||||
import CustomSendAndRequsetBTN from '../../../../functions/CustomElements/sendRequsetCircleBTN';
|
||||
import {useGlobalThemeContext} from '../../../../../context-store/theme';
|
||||
import {useAppStatus} from '../../../../../context-store/appStatus';
|
||||
|
||||
export function SendRecieveBTNs() {
|
||||
export const SendRecieveBTNs = memo(function SendRecieveBTNs({
|
||||
theme,
|
||||
darkModeType,
|
||||
isConnectedToTheInternet,
|
||||
}) {
|
||||
console.log('SENd and receiv btns');
|
||||
const navigate = useNavigation();
|
||||
const {isConnectedToTheInternet} = useAppStatus();
|
||||
const {theme, darkModeType} = useGlobalThemeContext();
|
||||
|
||||
const {t} = useTranslation();
|
||||
|
||||
const handleSettingsCheck = useCallback(() => {
|
||||
try {
|
||||
if (!isConnectedToTheInternet) throw new Error('Not Connected To Node');
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}, [isConnectedToTheInternet]);
|
||||
|
||||
const buttonElements = useMemo(
|
||||
() =>
|
||||
['send', 'camera', 'receive'].map(btnType => {
|
||||
@@ -22,8 +31,8 @@ export function SendRecieveBTNs() {
|
||||
if (isArrow) {
|
||||
return CustomSendAndRequsetBTN({
|
||||
btnType,
|
||||
btnFunction: async () => {
|
||||
const areSettingsSet = await handleSettingsCheck();
|
||||
btnFunction: () => {
|
||||
const areSettingsSet = handleSettingsCheck();
|
||||
if (!areSettingsSet) {
|
||||
navigate.navigate('ErrorScreen', {
|
||||
errorMessage: t('constants.internetError'),
|
||||
@@ -53,17 +62,15 @@ export function SendRecieveBTNs() {
|
||||
<TouchableOpacity
|
||||
key={btnType}
|
||||
onPress={() => {
|
||||
(async () => {
|
||||
const areSettingsSet = await handleSettingsCheck();
|
||||
if (!areSettingsSet) {
|
||||
navigate.navigate('ErrorScreen', {
|
||||
errorMessage: t('constants.internetError'),
|
||||
});
|
||||
return;
|
||||
}
|
||||
const areSettingsSet = handleSettingsCheck();
|
||||
if (!areSettingsSet) {
|
||||
navigate.navigate('ErrorScreen', {
|
||||
errorMessage: t('constants.internetError'),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
navigate.navigate('SendBTC');
|
||||
})();
|
||||
navigate.navigate('SendBTC');
|
||||
}}>
|
||||
<View
|
||||
style={{
|
||||
@@ -83,25 +90,17 @@ export function SendRecieveBTNs() {
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}),
|
||||
[isConnectedToTheInternet, theme, darkModeType],
|
||||
[
|
||||
isConnectedToTheInternet,
|
||||
theme,
|
||||
darkModeType,
|
||||
handleSettingsCheck,
|
||||
navigate,
|
||||
],
|
||||
);
|
||||
|
||||
return <View style={styles.container}>{buttonElements}</View>;
|
||||
|
||||
async function handleSettingsCheck() {
|
||||
try {
|
||||
if (!isConnectedToTheInternet) throw new Error('Not Connected To Node');
|
||||
|
||||
return new Promise(resolve => {
|
||||
resolve(true);
|
||||
});
|
||||
} catch (err) {
|
||||
return new Promise(resolve => {
|
||||
resolve(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
||||
@@ -2,22 +2,24 @@ import {StyleSheet, TouchableOpacity, View} from 'react-native';
|
||||
import {COLORS, SIZES} from '../../../../constants';
|
||||
import {useGlobalContextProvider} from '../../../../../context-store/context';
|
||||
import FormattedSatText from '../../../../functions/CustomElements/satTextDisplay';
|
||||
import {useRef, useState} from 'react';
|
||||
import {memo, useRef, useState} from 'react';
|
||||
import handleDBStateChange from '../../../../functions/handleDBStateChange';
|
||||
import Icon from '../../../../functions/CustomElements/Icon';
|
||||
import {useNavigation} from '@react-navigation/native';
|
||||
import {useAppStatus} from '../../../../../context-store/appStatus';
|
||||
import {useGlobalThemeContext} from '../../../../../context-store/theme';
|
||||
import {useNodeContext} from '../../../../../context-store/nodeContext';
|
||||
import {useGlobaleCash} from '../../../../../context-store/eCash';
|
||||
|
||||
export function UserSatAmount({
|
||||
nodeInformation,
|
||||
liquidNodeInformation,
|
||||
ecashWalletInformation,
|
||||
export const UserSatAmount = memo(function UserSatAmount({
|
||||
isConnectedToTheInternet,
|
||||
theme,
|
||||
darkModeType,
|
||||
}) {
|
||||
console.log('User sat amount container');
|
||||
const {nodeInformation, liquidNodeInformation} = useNodeContext();
|
||||
const {ecashWalletInformation} = useGlobaleCash();
|
||||
const {masterInfoObject, toggleMasterInfoObject, setMasterInfoObject} =
|
||||
useGlobalContextProvider();
|
||||
const {isConnectedToTheInternet} = useAppStatus();
|
||||
const {darkModeType, theme} = useGlobalThemeContext();
|
||||
|
||||
const eCashBalance = ecashWalletInformation.balance;
|
||||
const saveTimeoutRef = useRef(null);
|
||||
const navigate = useNavigation();
|
||||
@@ -102,7 +104,7 @@ export function UserSatAmount({
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
balanceContainer: {
|
||||
|
||||
@@ -3,13 +3,11 @@ import {CENTER, ICONS} from '../../../constants';
|
||||
import {useNavigation} from '@react-navigation/native';
|
||||
import {WINDOWWIDTH} from '../../../constants/theme';
|
||||
import ThemeImage from '../../../functions/CustomElements/themeImage';
|
||||
import {useGlobalThemeContext} from '../../../../context-store/theme';
|
||||
import {memo} from 'react';
|
||||
|
||||
export default function NavBar() {
|
||||
export const NavBar = memo(function NavBar({theme, toggleTheme}) {
|
||||
console.log('NAV BAR PAGE');
|
||||
|
||||
const navigate = useNavigation();
|
||||
const {theme, toggleTheme} = useGlobalThemeContext();
|
||||
|
||||
return (
|
||||
<View style={[styles.topBar]}>
|
||||
@@ -39,7 +37,7 @@ export default function NavBar() {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
const styles = StyleSheet.create({
|
||||
topBar: {
|
||||
width: WINDOWWIDTH,
|
||||
|
||||
@@ -4,34 +4,65 @@ import {useNavigation} from '@react-navigation/native';
|
||||
import {GlobalThemeView, ThemeText} from '../../../../functions/CustomElements';
|
||||
import getFormattedHomepageTxs from '../../../../functions/combinedTransactions';
|
||||
import FormattedSatText from '../../../../functions/CustomElements/satTextDisplay';
|
||||
import {useGlobaleCash} from '../../../../../context-store/eCash';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import CustomButton from '../../../../functions/CustomElements/button';
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
||||
import {ANDROIDSAFEAREA, CENTER} from '../../../../constants/styles';
|
||||
import {useWebView} from '../../../../../context-store/webViewContext';
|
||||
import CustomSettingsTopBar from '../../../../functions/CustomElements/settingsTopBar';
|
||||
import {useNodeContext} from '../../../../../context-store/nodeContext';
|
||||
import {useAppStatus} from '../../../../../context-store/appStatus';
|
||||
import {INSET_WINDOW_WIDTH} from '../../../../constants/theme';
|
||||
import GetThemeColors from '../../../../hooks/themeColors';
|
||||
import {useUpdateHomepageTransactions} from '../../../../hooks/updateHomepageTransactions';
|
||||
import {useGlobalContextProvider} from '../../../../../context-store/context';
|
||||
import {useGlobalThemeContext} from '../../../../../context-store/theme';
|
||||
import {useEffect, useState} from 'react';
|
||||
import FullLoadingScreen from '../../../../functions/CustomElements/loadingScreen';
|
||||
|
||||
export default function LiquidWallet() {
|
||||
const {isConnectedToTheInternet} = useAppStatus();
|
||||
const {nodeInformation, liquidNodeInformation} = useNodeContext();
|
||||
const {ecashWalletInformation} = useGlobaleCash();
|
||||
const {liquidNodeInformation} = useNodeContext();
|
||||
const {theme, darkModeType} = useGlobalThemeContext();
|
||||
const {masterInfoObject} = useGlobalContextProvider();
|
||||
const navigate = useNavigation();
|
||||
const {t} = useTranslation();
|
||||
const insets = useSafeAreaInsets();
|
||||
const {autoChannelRebalanceIDs} = useWebView();
|
||||
const {backgroundColor} = GetThemeColors();
|
||||
const ecashTransactions = ecashWalletInformation.transactions;
|
||||
const [txs, setTxs] = useState([]);
|
||||
|
||||
const currentTime = useUpdateHomepageTransactions();
|
||||
const userBalanceDenomination = masterInfoObject.userBalanceDenomination;
|
||||
const bottomPadding = Platform.select({
|
||||
ios: insets.bottom,
|
||||
android: ANDROIDSAFEAREA,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const formattedTxs = getFormattedHomepageTxs({
|
||||
currentTime,
|
||||
liquidNodeInformation,
|
||||
navigate,
|
||||
isBankPage: true,
|
||||
noTransactionHistoryText: t('wallet.no_transaction_history'),
|
||||
todayText: t('constants.today'),
|
||||
yesterdayText: t('constants.yesterday'),
|
||||
dayText: t('constants.day'),
|
||||
monthText: t('constants.month'),
|
||||
yearText: t('constants.year'),
|
||||
agoText: t('transactionLabelText.ago'),
|
||||
theme,
|
||||
darkModeType,
|
||||
userBalanceDenomination,
|
||||
});
|
||||
setTxs(formattedTxs);
|
||||
}, [
|
||||
currentTime,
|
||||
liquidNodeInformation,
|
||||
navigate,
|
||||
theme,
|
||||
darkModeType,
|
||||
userBalanceDenomination,
|
||||
]);
|
||||
|
||||
return (
|
||||
<GlobalThemeView useStandardWidth={true} styles={styles.container}>
|
||||
<CustomSettingsTopBar
|
||||
@@ -52,44 +83,32 @@ export default function LiquidWallet() {
|
||||
navigate.navigate('LiquidSettingsPage');
|
||||
}}
|
||||
/>
|
||||
|
||||
<FlatList
|
||||
style={{flex: 1, width: '100%'}}
|
||||
showsVerticalScrollIndicator={false}
|
||||
stickyHeaderIndices={[1]} // Selects only the second item
|
||||
ListHeaderComponent={<View style={{marginTop: 25}} />}
|
||||
data={[
|
||||
<View
|
||||
style={{...styles.stickyHeader, backgroundColor: backgroundColor}}>
|
||||
<ThemeText content={'Balance'} styles={styles.amountText} />
|
||||
<FormattedSatText
|
||||
styles={{...styles.valueText}}
|
||||
balance={liquidNodeInformation.userBalance}
|
||||
/>
|
||||
</View>, // Dummy item to shift indices
|
||||
...getFormattedHomepageTxs({
|
||||
nodeInformation,
|
||||
liquidNodeInformation,
|
||||
navigate,
|
||||
isBankPage: true,
|
||||
ecashTransactions,
|
||||
noTransactionHistoryText: t('wallet.no_transaction_history'),
|
||||
todayText: t('constants.today'),
|
||||
yesterdayText: t('constants.yesterday'),
|
||||
dayText: t('constants.day'),
|
||||
monthText: t('constants.month'),
|
||||
yearText: t('constants.year'),
|
||||
agoText: t('transactionLabelText.ago'),
|
||||
autoChannelRebalanceIDs,
|
||||
}),
|
||||
]}
|
||||
renderItem={
|
||||
({item, index}) => item // Skip dummy item
|
||||
}
|
||||
ListFooterComponent={
|
||||
<View style={{width: '100%', height: bottomPadding + 60}} />
|
||||
}
|
||||
/>
|
||||
<View
|
||||
key={'balance'}
|
||||
style={{
|
||||
...styles.stickyHeader,
|
||||
backgroundColor: backgroundColor,
|
||||
}}>
|
||||
<ThemeText content={'Balance'} styles={styles.amountText} />
|
||||
<FormattedSatText
|
||||
styles={{...styles.valueText}}
|
||||
balance={liquidNodeInformation.userBalance}
|
||||
/>
|
||||
</View>
|
||||
{!txs.length ? (
|
||||
<FullLoadingScreen />
|
||||
) : (
|
||||
<FlatList
|
||||
style={{flex: 1, width: '100%'}}
|
||||
contentContainerStyle={{paddingBottom: bottomPadding + 60}}
|
||||
initialNumToRender={20}
|
||||
maxToRenderPerBatch={20}
|
||||
windowSize={3}
|
||||
showsVerticalScrollIndicator={false}
|
||||
data={txs}
|
||||
renderItem={({item, index}) => item}
|
||||
/>
|
||||
)}
|
||||
|
||||
<CustomButton
|
||||
buttonStyles={{
|
||||
|
||||
@@ -26,7 +26,7 @@ const VALID_URL_REGEX =
|
||||
const EMAIL_REGEX = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||
|
||||
const VALID_USERNAME_REGEX = /^(?=.*\p{L})[\p{L}\p{N}_]+$/u;
|
||||
const BITCOIN_SATS_ICON = '₿';
|
||||
const BITCOIN_SATS_ICON = '\u20BF';
|
||||
const HIDDEN_BALANCE_TEXT = `* * * * *`;
|
||||
|
||||
const ECASH_TX_STORAGE_KEY = 'CASHU_TRANSACTIONS';
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
BLITZ_DEFAULT_PAYMENT_DESCRIPTION,
|
||||
CENTER,
|
||||
COLORS,
|
||||
FONT,
|
||||
HIDDEN_BALANCE_TEXT,
|
||||
ICONS,
|
||||
SIZES,
|
||||
@@ -12,19 +11,17 @@ import {ThemeText} from './CustomElements';
|
||||
import FormattedSatText from './CustomElements/satTextDisplay';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import Icon from './CustomElements/Icon';
|
||||
import {useGlobalThemeContext} from '../../context-store/theme';
|
||||
import {useGlobalContextProvider} from '../../context-store/context';
|
||||
import {useMemo} from 'react';
|
||||
import MinHeap from './minHeap';
|
||||
import {memo, useMemo} from 'react';
|
||||
import {mergeArrays} from './mergeArrays';
|
||||
|
||||
export default function getFormattedHomepageTxs({
|
||||
nodeInformation,
|
||||
combinedTransactions,
|
||||
currentTime,
|
||||
liquidNodeInformation,
|
||||
homepageTxPreferance = 25,
|
||||
navigate,
|
||||
isBankPage,
|
||||
frompage,
|
||||
ecashTransactions,
|
||||
viewAllTxText,
|
||||
noTransactionHistoryText,
|
||||
todayText,
|
||||
@@ -33,23 +30,18 @@ export default function getFormattedHomepageTxs({
|
||||
monthText,
|
||||
yearText,
|
||||
agoText,
|
||||
theme,
|
||||
darkModeType,
|
||||
userBalanceDenomination,
|
||||
}) {
|
||||
console.log('re-rendering transactions');
|
||||
const arr1 = [...nodeInformation.transactions];
|
||||
|
||||
const n1 = nodeInformation.transactions.length;
|
||||
|
||||
const arr2 = [...liquidNodeInformation.transactions];
|
||||
|
||||
const n2 = liquidNodeInformation.transactions.length;
|
||||
|
||||
const arr3 = [...ecashTransactions];
|
||||
|
||||
const n3 = ecashTransactions.length;
|
||||
const arr2 = liquidNodeInformation?.transactions;
|
||||
const n2 = liquidNodeInformation?.transactions?.length;
|
||||
|
||||
const conjoinedTxList = isBankPage
|
||||
? mergeArrays({arr2, n2})
|
||||
: mergeArrays({arr1, arr2, n1, n2, arr3, n3});
|
||||
: combinedTransactions;
|
||||
|
||||
console.log('re-rendering transactions');
|
||||
|
||||
if (conjoinedTxList.length === 0) {
|
||||
return [
|
||||
@@ -64,12 +56,11 @@ export default function getFormattedHomepageTxs({
|
||||
let formattedTxs = [];
|
||||
let currentGroupedDate = '';
|
||||
let transactionIndex = 0;
|
||||
const currentTime = new Date();
|
||||
|
||||
while (
|
||||
formattedTxs.length <
|
||||
(isBankPage
|
||||
? arr2.length
|
||||
? n2
|
||||
: frompage === 'viewAllTx'
|
||||
? conjoinedTxList.length
|
||||
: homepageTxPreferance) &&
|
||||
@@ -104,7 +95,6 @@ export default function getFormattedHomepageTxs({
|
||||
tx={currentTransaction}
|
||||
currentTime={currentTime}
|
||||
navigate={navigate}
|
||||
nodeInformation={nodeInformation}
|
||||
isLiquidPayment={isLiquidPayment}
|
||||
isLightningPayment={isLightningPayment}
|
||||
isEcashPayment={isEcashPayment}
|
||||
@@ -113,6 +103,9 @@ export default function getFormattedHomepageTxs({
|
||||
id={uniuqeIDFromTx}
|
||||
isBankPage={isBankPage}
|
||||
frompage={frompage}
|
||||
theme={theme}
|
||||
darkModeType={darkModeType}
|
||||
userBalanceDenomination={userBalanceDenomination}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -175,6 +168,7 @@ export default function getFormattedHomepageTxs({
|
||||
if (!isBankPage && frompage != 'viewAllTx')
|
||||
formattedTxs.push(
|
||||
<TouchableOpacity
|
||||
key={'view_all_tx_btn'}
|
||||
style={{marginBottom: 10, ...CENTER}}
|
||||
onPress={() => {
|
||||
navigate.navigate('ViewAllTxPage');
|
||||
@@ -186,67 +180,8 @@ export default function getFormattedHomepageTxs({
|
||||
return formattedTxs;
|
||||
}
|
||||
}
|
||||
function mergeArrays({
|
||||
arr1 = [],
|
||||
arr2 = [],
|
||||
n1 = 0,
|
||||
n2 = 0,
|
||||
arr3 = [],
|
||||
n3 = 0,
|
||||
}) {
|
||||
console.log('re-ordering transaactins');
|
||||
let mergedArray = [];
|
||||
const minHeap = new MinHeap();
|
||||
|
||||
// Function to push elements into the heap
|
||||
const pushToHeap = (arr, index, identifier) => {
|
||||
if (arr[index]) {
|
||||
const time =
|
||||
arr[index].paymentTime * 1000 ||
|
||||
arr[index].timestamp * 1000 ||
|
||||
arr[index].time ||
|
||||
Infinity;
|
||||
|
||||
const element = {
|
||||
...arr[index],
|
||||
[identifier === 'arr1'
|
||||
? 'usesLightningNode'
|
||||
: identifier === 'arr2'
|
||||
? 'usesLiquidNode'
|
||||
: 'usesEcash']: true,
|
||||
source: identifier,
|
||||
index,
|
||||
time,
|
||||
};
|
||||
|
||||
minHeap.add(element);
|
||||
}
|
||||
};
|
||||
|
||||
// Add first elements of each array to the heap
|
||||
if (n1 > 0) pushToHeap(arr1, 0, 'arr1');
|
||||
if (n2 > 0) pushToHeap(arr2, 0, 'arr2');
|
||||
if (n3 > 0) pushToHeap(arr3, 0, 'arr3');
|
||||
|
||||
// Process heap
|
||||
while (!minHeap.isEmpty()) {
|
||||
const minElement = minHeap.poll();
|
||||
mergedArray.push(minElement);
|
||||
|
||||
// Push next element from the same source array
|
||||
let {source, index} = minElement;
|
||||
if (source === 'arr1' && index + 1 < n1)
|
||||
pushToHeap(arr1, index + 1, 'arr1');
|
||||
if (source === 'arr2' && index + 1 < n2)
|
||||
pushToHeap(arr2, index + 1, 'arr2');
|
||||
if (source === 'arr3' && index + 1 < n3)
|
||||
pushToHeap(arr3, index + 1, 'arr3');
|
||||
}
|
||||
|
||||
return mergedArray;
|
||||
}
|
||||
|
||||
export function UserTransaction({
|
||||
export const UserTransaction = memo(function UserTransaction({
|
||||
tx: transaction,
|
||||
currentTime,
|
||||
paymentDate,
|
||||
@@ -258,9 +193,10 @@ export function UserTransaction({
|
||||
navigate,
|
||||
isBankPage,
|
||||
frompage,
|
||||
theme,
|
||||
darkModeType,
|
||||
userBalanceDenomination,
|
||||
}) {
|
||||
const {theme, darkModeType} = useGlobalThemeContext();
|
||||
const {masterInfoObject} = useGlobalContextProvider();
|
||||
const {t} = useTranslation();
|
||||
const endDate = currentTime;
|
||||
|
||||
@@ -391,7 +327,7 @@ export function UserTransaction({
|
||||
content={
|
||||
isFailedPayment
|
||||
? t('transactionLabelText.failed')
|
||||
: masterInfoObject.userBalanceDenomination === 'hidden'
|
||||
: userBalanceDenomination === 'hidden'
|
||||
? `${HIDDEN_BALANCE_TEXT}`
|
||||
: isDefaultDescription || !paymentDescription
|
||||
? transaction?.paymentType !== 'receive' &&
|
||||
@@ -456,7 +392,7 @@ export function UserTransaction({
|
||||
}
|
||||
containerStyles={{marginLeft: 'auto', marginBottom: 'auto'}}
|
||||
frontText={
|
||||
masterInfoObject.userBalanceDenomination !== 'hidden'
|
||||
userBalanceDenomination !== 'hidden'
|
||||
? transaction.paymentType === 'closed_channel'
|
||||
? ''
|
||||
: isLiquidPayment
|
||||
@@ -489,7 +425,7 @@ export function UserTransaction({
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
export function dateBanner(bannerText) {
|
||||
return (
|
||||
|
||||
@@ -44,7 +44,7 @@ const startLiquidUpdateInterval = (toggleLiquidNodeInformation, runCount) => {
|
||||
};
|
||||
|
||||
// Run 2 times with 30 second interval
|
||||
return runIntervalTimes(updateNodeInfo, 1000 * 30, runCount || 2);
|
||||
return runIntervalTimes(updateNodeInfo, 1000 * 30, runCount);
|
||||
};
|
||||
|
||||
export default startLiquidUpdateInterval;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import MaxHeap from './minHeap';
|
||||
|
||||
export function mergeArrays({
|
||||
arr1 = [],
|
||||
arr2 = [],
|
||||
n1 = 0,
|
||||
n2 = 0,
|
||||
arr3 = [],
|
||||
n3 = 0,
|
||||
}) {
|
||||
// console.log('re-ordering transaactins');
|
||||
let mergedArray = [];
|
||||
const minHeap = new MaxHeap();
|
||||
|
||||
// Function to push elements into the heap
|
||||
const pushToHeap = (arr, index, identifier) => {
|
||||
if (arr[index]) {
|
||||
const time =
|
||||
arr[index].paymentTime * 1000 ||
|
||||
arr[index].timestamp * 1000 ||
|
||||
arr[index].time ||
|
||||
Infinity;
|
||||
|
||||
const element = {
|
||||
...arr[index],
|
||||
[identifier === 'arr1'
|
||||
? 'usesLightningNode'
|
||||
: identifier === 'arr2'
|
||||
? 'usesLiquidNode'
|
||||
: 'usesEcash']: true,
|
||||
source: identifier,
|
||||
index,
|
||||
time,
|
||||
};
|
||||
|
||||
minHeap.add(element);
|
||||
}
|
||||
};
|
||||
|
||||
// Add first elements of each array to the heap
|
||||
if (n1 > 0) pushToHeap(arr1, 0, 'arr1');
|
||||
if (n2 > 0) pushToHeap(arr2, 0, 'arr2');
|
||||
if (n3 > 0) pushToHeap(arr3, 0, 'arr3');
|
||||
|
||||
// Process heap
|
||||
while (!minHeap.isEmpty()) {
|
||||
const minElement = minHeap.poll();
|
||||
mergedArray.push(minElement);
|
||||
|
||||
// Push next element from the same source array
|
||||
let {source, index} = minElement;
|
||||
if (source === 'arr1' && index + 1 < n1)
|
||||
pushToHeap(arr1, index + 1, 'arr1');
|
||||
if (source === 'arr2' && index + 1 < n2)
|
||||
pushToHeap(arr2, index + 1, 'arr2');
|
||||
if (source === 'arr3' && index + 1 < n3)
|
||||
pushToHeap(arr3, index + 1, 'arr3');
|
||||
}
|
||||
|
||||
return mergedArray;
|
||||
}
|
||||
@@ -1,23 +1,38 @@
|
||||
import {useFocusEffect} from '@react-navigation/native';
|
||||
import {useState, useEffect, useRef, useCallback} from 'react';
|
||||
import {useState, useRef, useCallback, useMemo} from 'react';
|
||||
|
||||
export function useUpdateHomepageTransactions() {
|
||||
const [updateTransaction, setUpdateTransaction] = useState(0);
|
||||
const [minuteTick, setMinuteTick] = useState(Math.floor(Date.now() / 60000));
|
||||
const intervalRef = useRef(null);
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
console.log('Starting homepage interval');
|
||||
const homepageUpdateInterval = setInterval(() => {
|
||||
setUpdateTransaction(prev => (prev = prev + 1));
|
||||
console.log('Starting stable time interval');
|
||||
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
}
|
||||
|
||||
setMinuteTick(Math.floor(Date.now() / 60000));
|
||||
|
||||
intervalRef.current = setInterval(() => {
|
||||
setMinuteTick(Math.floor(Date.now() / 60000));
|
||||
}, 60000);
|
||||
setUpdateTransaction(prev => (prev = prev + 1));
|
||||
|
||||
return () => {
|
||||
console.log('clearing homepage interval');
|
||||
clearInterval(homepageUpdateInterval);
|
||||
console.log('Clearing stable time interval');
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
intervalRef.current = null;
|
||||
}
|
||||
};
|
||||
}, []),
|
||||
);
|
||||
|
||||
return updateTransaction;
|
||||
const stableTime = useMemo(
|
||||
() => new Date(minuteTick * 60000).getTime(),
|
||||
[minuteTick],
|
||||
);
|
||||
|
||||
return stableTime;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
import {Back_BTN} from '../../../components/login';
|
||||
import {retrieveData, storeData} from '../../../functions';
|
||||
import {CENTER, COLORS, FONT, SIZES} from '../../../constants';
|
||||
import {useEffect, useRef, useState} from 'react';
|
||||
import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
|
||||
import isValidMnemonic from '../../../functions/isValidMnemonic';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {GlobalThemeView, ThemeText} from '../../../functions/CustomElements';
|
||||
@@ -56,24 +56,27 @@ export default function RestoreWallet({
|
||||
key11: '',
|
||||
key12: '',
|
||||
});
|
||||
|
||||
function handleInputElement(text, keyNumber) {
|
||||
const handleInputElement = useCallback((text, keyNumber) => {
|
||||
setInputedKey(prev => ({...prev, [`key${keyNumber}`]: text}));
|
||||
}
|
||||
}, []);
|
||||
|
||||
function handleFocus(keyNumber) {
|
||||
const handleFocus = useCallback(keyNumber => {
|
||||
setCurrentFocused(keyNumber); // Update the current focused key
|
||||
}
|
||||
function handleSubmit(keyNumber) {
|
||||
if (keyNumber < 12) {
|
||||
const nextKey = keyNumber + 1;
|
||||
keyRefs.current[nextKey]?.focus(); // Focus the next input
|
||||
} else {
|
||||
keyRefs.current[12]?.blur(); // Blur the last input
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
function createInputKeys() {
|
||||
const handleSubmit = useCallback(
|
||||
keyNumber => {
|
||||
if (keyNumber < 12) {
|
||||
const nextKey = keyNumber + 1;
|
||||
keyRefs.current[nextKey]?.focus(); // Focus the next input
|
||||
} else {
|
||||
keyRefs.current[12]?.blur(); // Blur the last input
|
||||
}
|
||||
},
|
||||
[keyRefs],
|
||||
);
|
||||
|
||||
const inputKeys = useMemo(() => {
|
||||
let keyRows = [];
|
||||
let keyItem = [];
|
||||
NUMARRAY.forEach(item => {
|
||||
@@ -82,7 +85,6 @@ export default function RestoreWallet({
|
||||
key={item}
|
||||
style={{
|
||||
...styles.seedItem,
|
||||
|
||||
backgroundColor: theme
|
||||
? COLORS.darkModeBackgroundOffset
|
||||
: COLORS.darkModeText,
|
||||
@@ -112,9 +114,7 @@ export default function RestoreWallet({
|
||||
}
|
||||
});
|
||||
return keyRows;
|
||||
}
|
||||
|
||||
const keyElements = createInputKeys();
|
||||
}, [handleSubmit, theme, inputedKey, keyRefs]);
|
||||
|
||||
useEffect(() => {
|
||||
const keyboardDidHideListener = Keyboard.addListener(
|
||||
@@ -168,7 +168,7 @@ export default function RestoreWallet({
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={styles.contentContainer}
|
||||
contentContainerStyle={{paddingBottom: 10}}>
|
||||
{keyElements}
|
||||
{inputKeys}
|
||||
</ScrollView>
|
||||
{params && !currentFocused && (
|
||||
<CustomButton
|
||||
|
||||
@@ -432,7 +432,7 @@ export default function ConnectingToNodeLoadingScreen({
|
||||
'CHEKCING RETRY LOGIC',
|
||||
);
|
||||
|
||||
if (didRestoreWallet && !payments.length) {
|
||||
if (didRestoreWallet) {
|
||||
console.log('RETRYING LIQUID INFORMATION, LOADING....');
|
||||
await new Promise(resolve => setTimeout(resolve, 10000));
|
||||
console.log('FINISHED WAITING');
|
||||
@@ -458,12 +458,14 @@ export default function ConnectingToNodeLoadingScreen({
|
||||
};
|
||||
}
|
||||
|
||||
toggleLiquidNodeInformation(liquidNodeObject);
|
||||
toggleLiquidNodeInformation({
|
||||
...liquidNodeObject,
|
||||
didConnectToNode: true,
|
||||
});
|
||||
|
||||
return liquidNodeObject;
|
||||
} catch (err) {
|
||||
console.log(err, 'LIQUID INFORMATION ERROR');
|
||||
|
||||
return new Promise(resolve => {
|
||||
resolve(false);
|
||||
});
|
||||
@@ -489,6 +491,7 @@ export default function ConnectingToNodeLoadingScreen({
|
||||
balance: balance || 0,
|
||||
transactions: transactions,
|
||||
proofs: storedProofs,
|
||||
didConnectToNode: true,
|
||||
};
|
||||
toggleEcashWalletInformation(ecashWalletData);
|
||||
toggleMintList(mintList);
|
||||
|
||||
@@ -1,101 +1,90 @@
|
||||
import {useNavigation} from '@react-navigation/native';
|
||||
import {
|
||||
FlatList,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import {CENTER, COLORS, ICONS, SIZES} from '../../constants';
|
||||
import {FlatList, Platform, View} from 'react-native';
|
||||
import {ICONS} from '../../constants';
|
||||
import {ANDROIDSAFEAREA} from '../../constants/styles';
|
||||
import {GlobalThemeView} from '../../functions/CustomElements';
|
||||
import {WINDOWWIDTH} from '../../constants/theme';
|
||||
import getFormattedHomepageTxs from '../../functions/combinedTransactions';
|
||||
import {useGlobaleCash} from '../../../context-store/eCash';
|
||||
import ThemeImage from '../../functions/CustomElements/themeImage';
|
||||
import {useTranslation} from 'react-i18next';
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context';
|
||||
import {useGlobalThemeContext} from '../../../context-store/theme';
|
||||
import {useNodeContext} from '../../../context-store/nodeContext';
|
||||
import useHandleBackPressNew from '../../hooks/useHandleBackPressNew';
|
||||
import CustomSettingsTopBar from '../../functions/CustomElements/settingsTopBar';
|
||||
import {useUpdateHomepageTransactions} from '../../hooks/updateHomepageTransactions';
|
||||
import {useGlobalContextProvider} from '../../../context-store/context';
|
||||
import {useGlobalTxContextProvider} from '../../../context-store/combinedTransactionsContext';
|
||||
import {useEffect, useState} from 'react';
|
||||
import FullLoadingScreen from '../../functions/CustomElements/loadingScreen';
|
||||
|
||||
export default function ViewAllTxPage() {
|
||||
const navigate = useNavigation();
|
||||
const {nodeInformation, liquidNodeInformation} = useNodeContext();
|
||||
const {combinedTransactions} = useGlobalTxContextProvider();
|
||||
const {masterInfoObject} = useGlobalContextProvider();
|
||||
const {theme, darkModeType} = useGlobalThemeContext();
|
||||
const {ecashWalletInformation} = useGlobaleCash();
|
||||
const ecashTransactions = ecashWalletInformation.transactions;
|
||||
const [txs, setTxs] = useState([]);
|
||||
const currentTime = useUpdateHomepageTransactions();
|
||||
const insets = useSafeAreaInsets();
|
||||
const {t} = useTranslation();
|
||||
useHandleBackPressNew();
|
||||
const userBalanceDenomination = masterInfoObject.userBalanceDenomination;
|
||||
|
||||
const bottomPadding = Platform.select({
|
||||
ios: insets.bottom,
|
||||
android: ANDROIDSAFEAREA,
|
||||
});
|
||||
|
||||
return (
|
||||
<GlobalThemeView styles={{paddingBottom: 0}}>
|
||||
<View style={styles.globalContainer}>
|
||||
<View style={styles.topBar}>
|
||||
<TouchableOpacity
|
||||
style={{position: 'absolute', top: 0, left: 0}}
|
||||
onPress={() => {
|
||||
navigate.goBack();
|
||||
}}>
|
||||
<ThemeImage
|
||||
darkModeIcon={ICONS.smallArrowLeft}
|
||||
lightModeIcon={ICONS.smallArrowLeft}
|
||||
lightsOutIcon={ICONS.arrow_small_left_white}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
<Text
|
||||
style={[
|
||||
styles.mainHeader,
|
||||
{
|
||||
color: theme ? COLORS.darkModeText : COLORS.lightModeText,
|
||||
},
|
||||
]}>
|
||||
Transactions
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={{position: 'absolute', top: 0, right: 0}}
|
||||
onPress={() => {
|
||||
navigate.navigate('CustomHalfModal', {
|
||||
wantedContent: 'exportTransactions',
|
||||
sliderHight: 0.5,
|
||||
});
|
||||
}}>
|
||||
<ThemeImage
|
||||
darkModeIcon={ICONS.share}
|
||||
lightModeIcon={ICONS.share}
|
||||
lightsOutIcon={ICONS.shareWhite}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
useEffect(() => {
|
||||
const formattedTxs = getFormattedHomepageTxs({
|
||||
currentTime,
|
||||
combinedTransactions,
|
||||
navigate,
|
||||
isBankPage: false,
|
||||
frompage: 'viewAllTx',
|
||||
noTransactionHistoryText: t('wallet.no_transaction_history'),
|
||||
todayText: t('constants.today'),
|
||||
yesterdayText: t('constants.yesterday'),
|
||||
dayText: t('constants.day'),
|
||||
monthText: t('constants.month'),
|
||||
yearText: t('constants.year'),
|
||||
agoText: t('transactionLabelText.ago'),
|
||||
theme,
|
||||
darkModeType,
|
||||
userBalanceDenomination,
|
||||
});
|
||||
setTxs(formattedTxs);
|
||||
}, [
|
||||
currentTime,
|
||||
combinedTransactions,
|
||||
navigate,
|
||||
theme,
|
||||
darkModeType,
|
||||
userBalanceDenomination,
|
||||
]);
|
||||
|
||||
return (
|
||||
<GlobalThemeView useStandardWidth={true} styles={{paddingBottom: 0}}>
|
||||
<CustomSettingsTopBar
|
||||
showLeftImage={true}
|
||||
leftImageBlue={ICONS.share}
|
||||
LeftImageDarkMode={ICONS.shareWhite}
|
||||
label={'Transactions'}
|
||||
leftImageFunction={() => {
|
||||
navigate.navigate('CustomHalfModal', {
|
||||
wantedContent: 'exportTransactions',
|
||||
sliderHight: 0.5,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
{!txs.length ? (
|
||||
<FullLoadingScreen />
|
||||
) : (
|
||||
<FlatList
|
||||
initialNumToRender={20}
|
||||
maxToRenderPerBatch={20}
|
||||
windowSize={3}
|
||||
style={{flex: 1, width: '100%'}}
|
||||
showsVerticalScrollIndicator={false}
|
||||
data={getFormattedHomepageTxs({
|
||||
nodeInformation,
|
||||
liquidNodeInformation,
|
||||
navigate,
|
||||
isBankPage: false,
|
||||
frompage: 'viewAllTx',
|
||||
ecashTransactions,
|
||||
noTransactionHistoryText: t('wallet.no_transaction_history'),
|
||||
todayText: t('constants.today'),
|
||||
yesterdayText: t('constants.yesterday'),
|
||||
dayText: t('constants.day'),
|
||||
monthText: t('constants.month'),
|
||||
yearText: t('constants.year'),
|
||||
agoText: t('transactionLabelText.ago'),
|
||||
})}
|
||||
data={txs}
|
||||
renderItem={({item}) => item}
|
||||
ListFooterComponent={
|
||||
<View
|
||||
@@ -106,26 +95,7 @@ export default function ViewAllTxPage() {
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</GlobalThemeView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
globalContainer: {
|
||||
flex: 1,
|
||||
width: WINDOWWIDTH,
|
||||
...CENTER,
|
||||
},
|
||||
topBar: {
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 10,
|
||||
},
|
||||
mainHeader: {
|
||||
fontSize: SIZES.xLarge,
|
||||
...CENTER,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import {
|
||||
createContext,
|
||||
useState,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useCallback,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import {useGlobaleCash} from './eCash';
|
||||
import {useGlobalContextProvider} from './context';
|
||||
import {mergeArrays} from '../app/functions/mergeArrays';
|
||||
import {useNodeContext} from './nodeContext';
|
||||
|
||||
// Initiate context
|
||||
const combinedTxContextManager = createContext(null);
|
||||
|
||||
const GlobalConbinedTxContextProvider = ({children}) => {
|
||||
const {masterInfoObject} = useGlobalContextProvider();
|
||||
const {nodeInformation, liquidNodeInformation} = useNodeContext();
|
||||
const {ecashWalletInformation} = useGlobaleCash();
|
||||
const [combinedTransactions, setCombinedTransactions] = useState([]);
|
||||
const prevDependencies = useRef({arr1, arr2, arr3, n1, n2, n3});
|
||||
|
||||
const didConnectToLiquidNode = liquidNodeInformation.didConnectToNode;
|
||||
const didConnectToLightningNode = nodeInformation.didConnectToNode;
|
||||
const didConnectToEcashNode = ecashWalletInformation.didConnectToNode;
|
||||
const enabledEcash = masterInfoObject.enabledEcash;
|
||||
const enabledLightning =
|
||||
masterInfoObject.liquidWalletSettings?.isLightningEnabled;
|
||||
|
||||
const shouldStartToMergeArrays = useMemo(() => {
|
||||
return (
|
||||
(didConnectToLightningNode || !enabledLightning) &&
|
||||
didConnectToLiquidNode &&
|
||||
(didConnectToEcashNode || !enabledEcash)
|
||||
);
|
||||
}, [
|
||||
didConnectToEcashNode,
|
||||
didConnectToLightningNode,
|
||||
didConnectToLiquidNode,
|
||||
enabledEcash,
|
||||
enabledLightning,
|
||||
]);
|
||||
|
||||
const arr1 = nodeInformation.transactions;
|
||||
const arr2 = liquidNodeInformation.transactions;
|
||||
const arr3 = ecashWalletInformation.transactions;
|
||||
const n1 = nodeInformation.transactions.length;
|
||||
const n2 = liquidNodeInformation.transactions.length;
|
||||
const n3 = ecashWalletInformation.transactions.length;
|
||||
|
||||
useEffect(() => {
|
||||
const hasChanged =
|
||||
JSON.stringify(prevDependencies.current.arr1) !== JSON.stringify(arr1) ||
|
||||
JSON.stringify(prevDependencies.current.arr2) !== JSON.stringify(arr2) ||
|
||||
JSON.stringify(prevDependencies.current.arr3) !== JSON.stringify(arr3) ||
|
||||
prevDependencies.current.n1 !== n1 ||
|
||||
prevDependencies.current.n2 !== n2 ||
|
||||
prevDependencies.current.n3 !== n3;
|
||||
|
||||
if (!hasChanged || !shouldStartToMergeArrays) return;
|
||||
console.log('re-filtering transaactins');
|
||||
|
||||
const txs = mergeArrays({arr1, arr2, arr3, n1, n2, n3});
|
||||
setCombinedTransactions(txs);
|
||||
}, [arr1, arr2, arr3, n1, n2, n3, shouldStartToMergeArrays]);
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
combinedTransactions,
|
||||
}),
|
||||
[combinedTransactions],
|
||||
);
|
||||
|
||||
return (
|
||||
<combinedTxContextManager.Provider value={contextValue}>
|
||||
{children}
|
||||
</combinedTxContextManager.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
function useGlobalTxContextProvider() {
|
||||
const context = useContext(combinedTxContextManager);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'useGlobalTxContextProvider must be used within a GlobalConbinedTxContextProvider',
|
||||
);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
export {
|
||||
combinedTxContextManager,
|
||||
GlobalConbinedTxContextProvider,
|
||||
useGlobalTxContextProvider,
|
||||
};
|
||||
+26
-56
@@ -12,19 +12,13 @@ import {
|
||||
} from '../app/functions/messaging/encodingAndDecodingMessages';
|
||||
import {useKeysContext} from './keys';
|
||||
import {sumProofsValue} from '../app/functions/eCash/proofs';
|
||||
import {receivePayment} from '@breeztech/react-native-breez-sdk';
|
||||
import {MintQuoteState} from '@cashu/cashu-ts';
|
||||
import {LIGHTNINGAMOUNTBUFFER} from '../app/constants/math';
|
||||
import {useNodeContext} from './nodeContext';
|
||||
import {useAppStatus} from './appStatus';
|
||||
import {
|
||||
checkMintQuote,
|
||||
claimUnclaimedEcashQuotes,
|
||||
formatEcashTx,
|
||||
getMeltQuote,
|
||||
hanleEcashQuoteStorage,
|
||||
mintEcash,
|
||||
payLnInvoiceFromEcash,
|
||||
} from '../app/functions/eCash/wallet';
|
||||
import {
|
||||
getAllMints,
|
||||
@@ -48,11 +42,10 @@ const GlobaleCash = createContext(null);
|
||||
|
||||
export const GlobaleCashVariables = ({children}) => {
|
||||
const {contactsPrivateKey, publicKey} = useKeysContext();
|
||||
const {didGetToHomepage} = useAppStatus();
|
||||
const {nodeInformation} = useNodeContext();
|
||||
const countersRef = useRef({});
|
||||
const [globalEcashInformation, setGlobalEcashInformation] = useState([]);
|
||||
const [ecashWalletInformation, setEcashWalletInformation] = useState({
|
||||
didConnectToNode: null,
|
||||
balance: 0,
|
||||
transactions: [],
|
||||
mintURL: '',
|
||||
@@ -136,40 +129,6 @@ export const GlobaleCashVariables = ({children}) => {
|
||||
: [];
|
||||
}, [globalEcashInformation, publicKey]);
|
||||
|
||||
const drainEcashBalance = async () => {
|
||||
try {
|
||||
if (ecashWalletInformation.balance - 5 < 1) return;
|
||||
const lightningInvoice = await receivePayment({
|
||||
amountMsat: (ecashWalletInformation.balance - 5) * 1000,
|
||||
description: 'Auto Channel Rebalance',
|
||||
});
|
||||
const meltQuote = await getMeltQuote(lightningInvoice.lnInvoice.bolt11);
|
||||
if (!meltQuote) throw new Error('unable to create melt quote');
|
||||
const didPay = await payLnInvoiceFromEcash({
|
||||
quote: meltQuote.quote,
|
||||
invoice: lightningInvoice.lnInvoice.bolt11,
|
||||
proofsToUse: meltQuote.proofsToUse,
|
||||
description: 'Auto Channel Rebalance',
|
||||
});
|
||||
|
||||
console.log(didPay, 'pay response in drain ecash balance');
|
||||
} catch (err) {
|
||||
console.log(err, 'draining ecash balance error');
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!didGetToHomepage) return;
|
||||
if (nodeInformation.userBalance === 0) return;
|
||||
if (
|
||||
nodeInformation.inboundLiquidityMsat / 1000 + LIGHTNINGAMOUNTBUFFER <
|
||||
ecashWalletInformation?.balance
|
||||
)
|
||||
return;
|
||||
|
||||
drainEcashBalance();
|
||||
}, [didGetToHomepage]);
|
||||
|
||||
useEffect(() => {
|
||||
function listenForPayment(event) {
|
||||
const receiveEcashQuote = event?.quote;
|
||||
@@ -263,21 +222,32 @@ export const GlobaleCashVariables = ({children}) => {
|
||||
claimUnclaimedEcashQuotes(); //if a receive ecash timeout clears before payment is receve this will try and claim the ecash quote on the next wallet load
|
||||
}, [ecashWalletInformation.mintURL]);
|
||||
|
||||
const memoedValues = useMemo(() => {
|
||||
return {
|
||||
parsedEcashInformation,
|
||||
globalEcashInformation,
|
||||
toggleGLobalEcashInformation,
|
||||
ecashWalletInformation,
|
||||
toggleEcashWalletInformation,
|
||||
usersMintList,
|
||||
toggleMintList,
|
||||
pendingNavigation,
|
||||
setPendingNavigation,
|
||||
};
|
||||
}, [
|
||||
parsedEcashInformation,
|
||||
globalEcashInformation,
|
||||
toggleGLobalEcashInformation,
|
||||
ecashWalletInformation,
|
||||
toggleEcashWalletInformation,
|
||||
usersMintList,
|
||||
toggleMintList,
|
||||
pendingNavigation,
|
||||
setPendingNavigation,
|
||||
]);
|
||||
|
||||
return (
|
||||
<GlobaleCash.Provider
|
||||
value={{
|
||||
parsedEcashInformation,
|
||||
globalEcashInformation,
|
||||
toggleGLobalEcashInformation,
|
||||
ecashWalletInformation,
|
||||
toggleEcashWalletInformation,
|
||||
usersMintList,
|
||||
toggleMintList,
|
||||
pendingNavigation,
|
||||
setPendingNavigation,
|
||||
}}>
|
||||
{children}
|
||||
</GlobaleCash.Provider>
|
||||
<GlobaleCash.Provider value={memoedValues}>{children}</GlobaleCash.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ const BLOCKED_PAYMENT_CODES = [
|
||||
];
|
||||
// Create a context for the WebView ref
|
||||
export function LiquidEventProvider({children}) {
|
||||
const {toggleLiquidNodeInformation} = useNodeContext();
|
||||
const {toggleLiquidNodeInformation, liquidNodeInformation} = useNodeContext();
|
||||
const {didGetToHomepage} = useAppStatus();
|
||||
const intervalId = useRef(null);
|
||||
const debounceTimer = useRef(null);
|
||||
@@ -197,7 +197,9 @@ export function LiquidEventProvider({children}) {
|
||||
|
||||
useEffect(() => {
|
||||
if (!didGetToHomepage) return;
|
||||
if (liquidNodeInformation.userBalance) return;
|
||||
console.log('Makeing sure user balance is loaded');
|
||||
|
||||
debouncedStartInterval(0);
|
||||
}, [didGetToHomepage]);
|
||||
|
||||
|
||||
@@ -6,11 +6,21 @@ import {
|
||||
useMemo,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import {LIGHTNINGAMOUNTBUFFER} from '../app/constants/math';
|
||||
import {useGlobaleCash} from './eCash';
|
||||
import {
|
||||
getMeltQuote,
|
||||
payLnInvoiceFromEcash,
|
||||
} from '../app/functions/eCash/wallet';
|
||||
import {receivePayment} from '@breeztech/react-native-breez-sdk';
|
||||
import {useAppStatus} from './appStatus';
|
||||
|
||||
// Initiate context
|
||||
const NodeContextManager = createContext(null);
|
||||
|
||||
const GLobalNodeContextProider = ({children}) => {
|
||||
const {didGetToHomepage} = useAppStatus();
|
||||
const {ecashWalletInformation} = useGlobaleCash();
|
||||
const [nodeInformation, setNodeInformation] = useState({
|
||||
didConnectToNode: null,
|
||||
transactions: [],
|
||||
@@ -22,6 +32,7 @@ const GLobalNodeContextProider = ({children}) => {
|
||||
lsp: [],
|
||||
});
|
||||
const [liquidNodeInformation, setLiquidNodeInformation] = useState({
|
||||
didConnectToNode: null,
|
||||
transactions: [],
|
||||
userBalance: 0,
|
||||
});
|
||||
@@ -33,6 +44,40 @@ const GLobalNodeContextProider = ({children}) => {
|
||||
setLiquidNodeInformation(prev => ({...prev, ...newInfo}));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!didGetToHomepage) return;
|
||||
if (nodeInformation.userBalance === 0) return;
|
||||
if (
|
||||
nodeInformation.inboundLiquidityMsat / 1000 + LIGHTNINGAMOUNTBUFFER <
|
||||
ecashWalletInformation?.balance
|
||||
)
|
||||
return;
|
||||
|
||||
drainEcashBalance();
|
||||
}, [didGetToHomepage]);
|
||||
|
||||
const drainEcashBalance = useCallback(async () => {
|
||||
try {
|
||||
if (ecashWalletInformation.balance - 5 < 1) return;
|
||||
const lightningInvoice = await receivePayment({
|
||||
amountMsat: (ecashWalletInformation.balance - 5) * 1000,
|
||||
description: 'Auto Channel Rebalance',
|
||||
});
|
||||
const meltQuote = await getMeltQuote(lightningInvoice.lnInvoice.bolt11);
|
||||
if (!meltQuote) throw new Error('unable to create melt quote');
|
||||
const didPay = await payLnInvoiceFromEcash({
|
||||
quote: meltQuote.quote,
|
||||
invoice: lightningInvoice.lnInvoice.bolt11,
|
||||
proofsToUse: meltQuote.proofsToUse,
|
||||
description: 'Auto Channel Rebalance',
|
||||
});
|
||||
|
||||
console.log(didPay, 'pay response in drain ecash balance');
|
||||
} catch (err) {
|
||||
console.log(err, 'draining ecash balance error');
|
||||
}
|
||||
}, [ecashWalletInformation]);
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
nodeInformation,
|
||||
|
||||
Reference in New Issue
Block a user