From 038ec4245bccbb3a0d93ffa346c1ce2a07111a90 Mon Sep 17 00:00:00 2001 From: Marcos Rodriguez Velez Date: Sat, 9 Mar 2024 15:21:06 -0400 Subject: [PATCH] ADD: Discard changes prompt --- .../xcschemes/BlueWallet-NoLDK.xcscheme | 2 +- loc/en.json | 2 + screen/wallets/viewEditMultisigCosigners.tsx | 59 ++++++++++++++++++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/ios/BlueWallet.xcodeproj/xcshareddata/xcschemes/BlueWallet-NoLDK.xcscheme b/ios/BlueWallet.xcodeproj/xcshareddata/xcschemes/BlueWallet-NoLDK.xcscheme index e3d93fbf9..a79d28974 100644 --- a/ios/BlueWallet.xcodeproj/xcshareddata/xcschemes/BlueWallet-NoLDK.xcscheme +++ b/ios/BlueWallet.xcodeproj/xcshareddata/xcschemes/BlueWallet-NoLDK.xcscheme @@ -48,7 +48,7 @@ shouldAutocreateTestPlan = "YES"> { const hasLoaded = useRef(false); const { colors } = useTheme(); const { wallets, setWalletsWithNewOrder, isElectrumDisabled, isAdvancedModeEnabled } = useContext(BlueStorageContext); - const { navigate, goBack } = useNavigation(); + const { navigate, goBack, dispatch, addListener } = useNavigation(); const openScannerButtonRef = useRef(); const { walletId } = route.params; const w = useRef(wallets.find((wallet: AbstractWallet) => wallet.getID() === walletId)); @@ -77,6 +80,11 @@ const ViewEditMultisigCosigners = ({ route }: Props) => { const [askPassphrase, setAskPassphrase] = useState(false); const [isAdvancedModeEnabledRender, setIsAdvancedModeEnabledRender] = useState(false); const data = useRef(); + /* discardChangesRef is only so the action sheet can be shown on mac catalyst when a + user tries to leave the screen with unsaved changes. + Why the container view ? It was the easiest to get the ref for. No other reason. + */ + const discardChangesRef = useRef(null); const { enableBlur, disableBlur } = usePrivacy(); const stylesHook = StyleSheet.create({ @@ -109,6 +117,53 @@ const ViewEditMultisigCosigners = ({ route }: Props) => { color: colors.buttonTextColor, }, }); + useFocusEffect( + useCallback(() => { + const unsubscribe = addListener('beforeRemove', e => { + // Check if there are unsaved changes + if (isSaveButtonDisabled) { + // If there are no unsaved changes, let the user leave the screen + return; + } + + // Prevent the default action (going back) + e.preventDefault(); + + // Show an alert asking the user to discard changes or cancel + if (isDesktop) { + if (!discardChangesRef.current) return dispatch(e.data.action); + const anchor = findNodeHandle(discardChangesRef.current); + if (!anchor) return dispatch(e.data.action); + ActionSheet.showActionSheetWithOptions( + { + options: [loc._.cancel, loc._.ok], + cancelButtonIndex: 0, + title: loc._.discard_changes, + message: loc._.discard_changes_explain, + anchor, + }, + buttonIndex => { + if (buttonIndex === 1) { + dispatch(e.data.action); + } + }, + ); + } else { + Alert.alert(loc._.discard_changes, loc._.discard_changes_explain, [ + { text: loc._.cancel, style: 'cancel', onPress: () => {} }, + { + text: loc._.ok, + style: 'default', + // If the user confirms, then we dispatch the action we blocked earlier + onPress: () => dispatch(e.data.action), + }, + ]); + } + }); + + return unsubscribe; + }, [isSaveButtonDisabled, addListener, dispatch]), + ); useEffect(() => { isAdvancedModeEnabled().then(setIsAdvancedModeEnabledRender); @@ -576,7 +631,7 @@ const ViewEditMultisigCosigners = ({ route }: Props) => { const isPad: boolean = Platform.isPad; return ( - +