mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-03-13 19:16:52 +01:00
Merge pull request #7672 from BlueWallet/cc
REF: CompanionDelegate to hook
This commit is contained in:
commit
d375bd9780
3 changed files with 54 additions and 44 deletions
|
@ -19,25 +19,42 @@ import loc from '../loc';
|
||||||
import { Chain } from '../models/bitcoinUnits';
|
import { Chain } from '../models/bitcoinUnits';
|
||||||
import { navigationRef } from '../NavigationService';
|
import { navigationRef } from '../NavigationService';
|
||||||
import ActionSheet from '../screen/ActionSheet';
|
import ActionSheet from '../screen/ActionSheet';
|
||||||
import { useStorage } from '../hooks/context/useStorage';
|
import { useStorage } from './context/useStorage';
|
||||||
import RNQRGenerator from 'rn-qr-generator';
|
import RNQRGenerator from 'rn-qr-generator';
|
||||||
import presentAlert from './Alert';
|
import presentAlert from '../components/Alert';
|
||||||
import useMenuElements from '../hooks/useMenuElements';
|
import useMenuElements from './useMenuElements';
|
||||||
import useWidgetCommunication from '../hooks/useWidgetCommunication';
|
import useWidgetCommunication from './useWidgetCommunication';
|
||||||
import useWatchConnectivity from '../hooks/useWatchConnectivity';
|
import useWatchConnectivity from './useWatchConnectivity';
|
||||||
import useDeviceQuickActions from '../hooks/useDeviceQuickActions';
|
import useDeviceQuickActions from './useDeviceQuickActions';
|
||||||
import useHandoffListener from '../hooks/useHandoffListener';
|
import useHandoffListener from './useHandoffListener';
|
||||||
|
|
||||||
const ClipboardContentType = Object.freeze({
|
const ClipboardContentType = Object.freeze({
|
||||||
BITCOIN: 'BITCOIN',
|
BITCOIN: 'BITCOIN',
|
||||||
LIGHTNING: 'LIGHTNING',
|
LIGHTNING: 'LIGHTNING',
|
||||||
});
|
});
|
||||||
|
|
||||||
const CompanionDelegates = () => {
|
/**
|
||||||
const { wallets, addWallet, saveToDisk, fetchAndSaveWalletTransactions, refreshAllWalletTransactions, setSharedCosigner } = useStorage();
|
* Hook that initializes all companion listeners and functionality without rendering a component
|
||||||
|
*/
|
||||||
|
const useCompanionListeners = (skipIfNotInitialized = true) => {
|
||||||
|
const {
|
||||||
|
wallets,
|
||||||
|
addWallet,
|
||||||
|
saveToDisk,
|
||||||
|
fetchAndSaveWalletTransactions,
|
||||||
|
refreshAllWalletTransactions,
|
||||||
|
setSharedCosigner,
|
||||||
|
walletsInitialized,
|
||||||
|
} = useStorage();
|
||||||
const appState = useRef<AppStateStatus>(AppState.currentState);
|
const appState = useRef<AppStateStatus>(AppState.currentState);
|
||||||
const clipboardContent = useRef<undefined | string>();
|
const clipboardContent = useRef<undefined | string>();
|
||||||
|
|
||||||
|
// We need to call hooks unconditionally before any conditional logic
|
||||||
|
// We'll use this check inside the effects to conditionally run logic
|
||||||
|
const shouldActivateListeners = !skipIfNotInitialized || walletsInitialized;
|
||||||
|
|
||||||
|
// Initialize other hooks regardless of activation status
|
||||||
|
// They'll handle their own conditional logic internally
|
||||||
useWatchConnectivity();
|
useWatchConnectivity();
|
||||||
useWidgetCommunication();
|
useWidgetCommunication();
|
||||||
useMenuElements();
|
useMenuElements();
|
||||||
|
@ -45,6 +62,8 @@ const CompanionDelegates = () => {
|
||||||
useHandoffListener();
|
useHandoffListener();
|
||||||
|
|
||||||
const processPushNotifications = useCallback(async () => {
|
const processPushNotifications = useCallback(async () => {
|
||||||
|
if (!shouldActivateListeners) return false;
|
||||||
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 200));
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
try {
|
try {
|
||||||
const notifications2process = await getStoredNotifications();
|
const notifications2process = await getStoredNotifications();
|
||||||
|
@ -164,15 +183,19 @@ const CompanionDelegates = () => {
|
||||||
console.error('Failed to process push notifications:', error);
|
console.error('Failed to process push notifications:', error);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}, [fetchAndSaveWalletTransactions, refreshAllWalletTransactions, wallets]);
|
}, [fetchAndSaveWalletTransactions, refreshAllWalletTransactions, wallets, shouldActivateListeners]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!shouldActivateListeners) return;
|
||||||
|
|
||||||
initializeNotifications(processPushNotifications);
|
initializeNotifications(processPushNotifications);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, [shouldActivateListeners]);
|
||||||
|
|
||||||
const handleOpenURL = useCallback(
|
const handleOpenURL = useCallback(
|
||||||
async (event: { url: string }): Promise<void> => {
|
async (event: { url: string }): Promise<void> => {
|
||||||
|
if (!shouldActivateListeners) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!event.url) return;
|
if (!event.url) return;
|
||||||
let decodedUrl: string;
|
let decodedUrl: string;
|
||||||
|
@ -227,11 +250,13 @@ const CompanionDelegates = () => {
|
||||||
presentAlert({ message: err.message || loc.send.qr_error_no_qrcode });
|
presentAlert({ message: err.message || loc.send.qr_error_no_qrcode });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[wallets, addWallet, saveToDisk, setSharedCosigner],
|
[wallets, addWallet, saveToDisk, setSharedCosigner, shouldActivateListeners],
|
||||||
);
|
);
|
||||||
|
|
||||||
const showClipboardAlert = useCallback(
|
const showClipboardAlert = useCallback(
|
||||||
({ contentType }: { contentType: undefined | string }) => {
|
({ contentType }: { contentType: undefined | string }) => {
|
||||||
|
if (!shouldActivateListeners) return;
|
||||||
|
|
||||||
triggerHapticFeedback(HapticFeedbackTypes.ImpactLight);
|
triggerHapticFeedback(HapticFeedbackTypes.ImpactLight);
|
||||||
getClipboardContent().then(clipboard => {
|
getClipboardContent().then(clipboard => {
|
||||||
if (!clipboard) return;
|
if (!clipboard) return;
|
||||||
|
@ -254,12 +279,13 @@ const CompanionDelegates = () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[handleOpenURL],
|
[handleOpenURL, shouldActivateListeners],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleAppStateChange = useCallback(
|
const handleAppStateChange = useCallback(
|
||||||
async (nextAppState: AppStateStatus | undefined) => {
|
async (nextAppState: AppStateStatus | undefined) => {
|
||||||
if (wallets.length === 0) return;
|
if (!shouldActivateListeners || wallets.length === 0) return;
|
||||||
|
|
||||||
if ((appState.current.match(/background/) && nextAppState === 'active') || nextAppState === undefined) {
|
if ((appState.current.match(/background/) && nextAppState === 'active') || nextAppState === undefined) {
|
||||||
setTimeout(() => A(A.ENUM.APP_UNSUSPENDED), 2000);
|
setTimeout(() => A(A.ENUM.APP_UNSUSPENDED), 2000);
|
||||||
updateExchangeRate();
|
updateExchangeRate();
|
||||||
|
@ -299,10 +325,12 @@ const CompanionDelegates = () => {
|
||||||
appState.current = nextAppState;
|
appState.current = nextAppState;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[processPushNotifications, showClipboardAlert, wallets],
|
[processPushNotifications, showClipboardAlert, wallets, shouldActivateListeners],
|
||||||
);
|
);
|
||||||
|
|
||||||
const addListeners = useCallback(() => {
|
const addListeners = useCallback(() => {
|
||||||
|
if (!shouldActivateListeners) return { urlSubscription: null, appStateSubscription: null };
|
||||||
|
|
||||||
const urlSubscription = Linking.addEventListener('url', handleOpenURL);
|
const urlSubscription = Linking.addEventListener('url', handleOpenURL);
|
||||||
const appStateSubscription = AppState.addEventListener('change', handleAppStateChange);
|
const appStateSubscription = AppState.addEventListener('change', handleAppStateChange);
|
||||||
|
|
||||||
|
@ -310,18 +338,16 @@ const CompanionDelegates = () => {
|
||||||
urlSubscription,
|
urlSubscription,
|
||||||
appStateSubscription,
|
appStateSubscription,
|
||||||
};
|
};
|
||||||
}, [handleOpenURL, handleAppStateChange]);
|
}, [handleOpenURL, handleAppStateChange, shouldActivateListeners]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const subscriptions = addListeners();
|
const subscriptions = addListeners();
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
subscriptions.urlSubscription?.remove();
|
subscriptions.urlSubscription?.remove?.();
|
||||||
subscriptions.appStateSubscription?.remove();
|
subscriptions.appStateSubscription?.remove?.();
|
||||||
};
|
};
|
||||||
}, [addListeners]);
|
}, [addListeners]);
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CompanionDelegates;
|
export default useCompanionListeners;
|
|
@ -1,20 +1,16 @@
|
||||||
import React, { lazy, Suspense } from 'react';
|
import React from 'react';
|
||||||
import { useStorage } from '../hooks/context/useStorage';
|
|
||||||
import DevMenu from '../components/DevMenu';
|
import DevMenu from '../components/DevMenu';
|
||||||
import MainRoot from './index';
|
import MainRoot from './index';
|
||||||
const CompanionDelegates = lazy(() => import('../components/CompanionDelegates'));
|
import useCompanionListeners from '../hooks/useCompanionListeners';
|
||||||
|
|
||||||
const MasterView = () => {
|
const MasterView = () => {
|
||||||
const { walletsInitialized } = useStorage();
|
// Initialize companion listeners only when wallets are initialized
|
||||||
|
// The hook checks walletsInitialized internally, so it won't run until ready
|
||||||
|
useCompanionListeners();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MainRoot />
|
<MainRoot />
|
||||||
{walletsInitialized && (
|
|
||||||
<Suspense>
|
|
||||||
<CompanionDelegates />
|
|
||||||
</Suspense>
|
|
||||||
)}
|
|
||||||
{__DEV__ && <DevMenu />}
|
{__DEV__ && <DevMenu />}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { RouteProp, StackActions, useFocusEffect, useIsFocused, useRoute } from '@react-navigation/native';
|
import { RouteProp, StackActions, useIsFocused, useRoute } from '@react-navigation/native';
|
||||||
import * as bitcoin from 'bitcoinjs-lib';
|
import * as bitcoin from 'bitcoinjs-lib';
|
||||||
import createHash from 'create-hash';
|
import createHash from 'create-hash';
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Platform, StyleSheet, TextInput, TouchableOpacity, View } from 'react-native';
|
import { Platform, StyleSheet, TextInput, TouchableOpacity, View } from 'react-native';
|
||||||
import Base43 from '../../blue_modules/base43';
|
import Base43 from '../../blue_modules/base43';
|
||||||
import * as fs from '../../blue_modules/fs';
|
import * as fs from '../../blue_modules/fs';
|
||||||
|
@ -12,7 +12,6 @@ import Button from '../../components/Button';
|
||||||
import { useTheme } from '../../components/themes';
|
import { useTheme } from '../../components/themes';
|
||||||
import { isCameraAuthorizationStatusGranted } from '../../helpers/scan-qr';
|
import { isCameraAuthorizationStatusGranted } from '../../helpers/scan-qr';
|
||||||
import loc from '../../loc';
|
import loc from '../../loc';
|
||||||
import { useSettings } from '../../hooks/context/useSettings';
|
|
||||||
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
|
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
|
||||||
import CameraScreen from '../../components/CameraScreen';
|
import CameraScreen from '../../components/CameraScreen';
|
||||||
import SafeArea from '../../components/SafeArea';
|
import SafeArea from '../../components/SafeArea';
|
||||||
|
@ -57,7 +56,6 @@ const styles = StyleSheet.create({
|
||||||
|
|
||||||
const ScanQRCode = () => {
|
const ScanQRCode = () => {
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const { setIsDrawerShouldHide } = useSettings();
|
|
||||||
const navigation = useExtendedNavigation();
|
const navigation = useExtendedNavigation();
|
||||||
const route = useRoute<RouteProps>();
|
const route = useRoute<RouteProps>();
|
||||||
const navigationState = navigation.getState();
|
const navigationState = navigation.getState();
|
||||||
|
@ -96,16 +94,6 @@ const ScanQRCode = () => {
|
||||||
return createHash('sha256').update(s).digest().toString('hex');
|
return createHash('sha256').update(s).digest().toString('hex');
|
||||||
};
|
};
|
||||||
|
|
||||||
useFocusEffect(
|
|
||||||
useCallback(() => {
|
|
||||||
setIsDrawerShouldHide(true);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
setIsDrawerShouldHide(false);
|
|
||||||
};
|
|
||||||
}, [setIsDrawerShouldHide]),
|
|
||||||
);
|
|
||||||
|
|
||||||
const _onReadUniformResourceV2 = (part: string) => {
|
const _onReadUniformResourceV2 = (part: string) => {
|
||||||
if (!decoder) decoder = new BlueURDecoder();
|
if (!decoder) decoder = new BlueURDecoder();
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Add table
Reference in a new issue