Merge pull request #3834 from kaloudis/fix-intent-retrigger

fix: prevent deep link re-triggering on app resume from background
This commit is contained in:
Evan Kaloudis
2026-03-16 10:09:48 -04:00
committed by GitHub
4 changed files with 49 additions and 62 deletions
+6 -3
View File
@@ -7,6 +7,7 @@ import { SafeAreaView } from 'react-native-safe-area-context';
import {
BackHandler,
NativeEventSubscription,
Platform,
StatusBar,
AppState
} from 'react-native';
@@ -351,9 +352,11 @@ export default class App extends React.PureComponent {
if (nextAppState === 'active' && this.navigation) {
LinkingUtils.resetShareIntentFlag();
setTimeout(() => {
LinkingUtils.handleInitialUrl(this.navigation);
}, 100);
if (Platform.OS === 'android') {
setTimeout(() => {
LinkingUtils.handleAndroidIntents(this.navigation);
}, 100);
}
}
// Apply stealth mode when app goes to background
+42 -36
View File
@@ -22,44 +22,50 @@ class LinkingUtils {
return;
}
if (Platform.OS === 'android') {
const nfcData =
await NativeModules.MobileTools.getIntentNfcData();
if (nfcData) {
this.handleDeepLink(nfcData, navigation);
return;
}
if (!this.shareIntentProcessed) {
const shareIntentResult = await processSharedQRImageFast();
if (shareIntentResult && shareIntentResult.success) {
this.shareIntentProcessed = true;
const requiresAuth = settingsStore.loginRequired();
const requiresWalletSelection =
settingsStore.settings?.selectNodeOnStartup;
// Clear the Android share intent immediately to prevent reprocessing
try {
await NativeModules.MobileTools.clearSharedIntent();
} catch (clearError) {
console.warn(
'[LinkingUtils] Failed to clear share intent:',
clearError
);
}
// Always show processing screen immediately for share intents
// Background sync and authentication will be handled by the processing screen
navigation.navigate('ShareIntentProcessing', {
...shareIntentResult.params,
requiresAuth,
requiresWalletSelection
});
}
}
await this.handleAndroidIntents(navigation);
}
});
handleAndroidIntents = async (
navigation: StackNavigationProp<any, any>
) => {
const nfcData = await NativeModules.MobileTools.getIntentNfcData();
if (nfcData) {
this.handleDeepLink(nfcData, navigation);
return;
}
if (!this.shareIntentProcessed) {
const shareIntentResult = await processSharedQRImageFast();
if (shareIntentResult && shareIntentResult.success) {
this.shareIntentProcessed = true;
const requiresAuth = settingsStore.loginRequired();
const requiresWalletSelection =
settingsStore.settings?.selectNodeOnStartup;
// Clear the Android share intent immediately to prevent reprocessing
try {
await NativeModules.MobileTools.clearSharedIntent();
} catch (clearError) {
console.warn(
'[LinkingUtils] Failed to clear share intent:',
clearError
);
}
// Always show processing screen immediately for share intents
// Background sync and authentication will be handled by the processing screen
navigation.navigate('ShareIntentProcessing', {
...shareIntentResult.params,
requiresAuth,
requiresWalletSelection
});
}
}
};
handleDeepLink = (
url: string,
navigation: NativeStackNavigationProp<any, any>
-23
View File
@@ -312,13 +312,6 @@ export default class Lockscreen extends React.Component<
navigation.replace('Wallets', { fromStartup: true });
}
return;
} else if (
!(
SettingsStore.settings.selectNodeOnStartup &&
SettingsStore.initialStart
)
) {
LinkingUtils.handleInitialUrl(navigation);
}
if (!SettingsStore.settings.selectNodeOnStartup) {
if (
@@ -339,14 +332,6 @@ export default class Lockscreen extends React.Component<
(duressPin && pinAttempt === duressPin)
) {
SettingsStore.setLoginStatus(true);
if (
!(
SettingsStore.settings.selectNodeOnStartup &&
SettingsStore.initialStart
)
) {
LinkingUtils.handleInitialUrl(navigation);
}
this.deleteNodes();
} else {
// need to fetch updated settings to get incremented value of
@@ -362,14 +347,6 @@ export default class Lockscreen extends React.Component<
});
if (authenticationAttempts >= maxAuthenticationAttempts) {
SettingsStore.setLoginStatus(true);
if (
!(
SettingsStore.settings.selectNodeOnStartup &&
SettingsStore.initialStart
)
) {
LinkingUtils.handleInitialUrl(navigation);
}
// wipe node configs, passwords, and pins
this.authenticationFailure();
} else {
+1
View File
@@ -375,6 +375,7 @@ export default class Wallet extends React.Component<WalletProps, WalletState> {
// If select wallet on startup is enabled and this is initial start,
// navigate to wallet selection screen without activating any wallet
if (settings.selectNodeOnStartup && initialStart) {
SettingsStore.setInitialStart(false);
// Update UI state but don't connect to any wallet yet
if (!this.state.unlocked) {
this.setState({ unlocked: true });