From 1f0b6f79cfb56b21e33d7db009dfcdaa510b45e1 Mon Sep 17 00:00:00 2001 From: Jon Tzeng Date: Fri, 1 Nov 2024 15:16:15 -0700 Subject: [PATCH] Update `NotificationView` to use `deviceNotifState` and allow close on all notifications --- src/actions/LocalSettingsActions.ts | 2 +- .../notification/NotificationView.tsx | 109 ++++++++++-------- 2 files changed, 61 insertions(+), 50 deletions(-) diff --git a/src/actions/LocalSettingsActions.ts b/src/actions/LocalSettingsActions.ts index 0e2b32f165c..c34b42150e1 100644 --- a/src/actions/LocalSettingsActions.ts +++ b/src/actions/LocalSettingsActions.ts @@ -113,7 +113,7 @@ export const writeSpendingLimits = async (account: EdgeAccount, spendingLimits: * Track the state of whether particular one-time notifications associated with * the account were interacted with or dismissed. **/ -export const writeNotifDismissInfo = async (account: EdgeAccount, accountNotifDismissInfo: AccountNotifDismissInfo) => { +export const writeAccountNotifDismissInfo = async (account: EdgeAccount, accountNotifDismissInfo: AccountNotifDismissInfo) => { const updatedSettings = { ...localAccountSettings, accountNotifDismissInfo } return await writeLocalAccountSettings(account, updatedSettings) } diff --git a/src/components/notification/NotificationView.tsx b/src/components/notification/NotificationView.tsx index 81b3cf8beb5..2673bbeb82a 100644 --- a/src/components/notification/NotificationView.tsx +++ b/src/components/notification/NotificationView.tsx @@ -5,8 +5,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context' import { sprintf } from 'sprintf-js' import { showBackupModal } from '../../actions/BackupModalActions' -import { getLocalAccountSettings, writeNotifDismissInfo } from '../../actions/LocalSettingsActions' -import { useAsyncEffect } from '../../hooks/useAsyncEffect' +import { getDeviceSettings, modifyDeviceNotifInfo } from '../../actions/DeviceSettingsActions' import { useAsyncNavigation } from '../../hooks/useAsyncNavigation' import { useHandler } from '../../hooks/useHandler' import { useWatch } from '../../hooks/useWatch' @@ -33,42 +32,60 @@ interface Props { footerHeight: number } +const hideBanner = async (deviceNotifStateKey: string) => { + await modifyDeviceNotifInfo(deviceNotifStateKey, { isBannerHidden: true }) +} + const NotificationViewComponent = (props: Props) => { const { navigation, hasTabs, footerHeight } = props + const { deviceNotifState } = getDeviceSettings() + const navigationDebounced = useAsyncNavigation(navigation) const theme = useTheme() const dispatch = useDispatch() const account = useSelector(state => state.core.account) const detectedTokensRedux = useSelector(state => state.core.enabledDetectedTokens) - const needsPasswordCheck = useSelector(state => state.ui.passwordReminder.needsPasswordCheck) - const wallets = useWatch(account, 'currencyWallets') - const otpKey = useWatch(account, 'otpKey') const { bottom: insetBottom } = useSafeAreaInsets() const footerOpenRatio = useSceneFooterState(state => state.footerOpenRatio) const [autoDetectTokenCards, setAutoDetectTokenCards] = React.useState([]) - const [otpReminderCard, setOtpReminderCard] = React.useState() - const accountNotifDismissInfo = getLocalAccountSettings().accountNotifDismissInfo - - const isLightAccount = account.id != null && account.username == null + const handleBackupClose = useHandler(async () => { + await hideBanner('lightAccountReminder') + }) const handleBackupPress = useHandler(async () => { + await handleBackupClose() await showBackupModal({ navigation: navigationDebounced }) }) + const handlePasswordReminderClose = useHandler(async () => { + await hideBanner('pwReminder') + }) const handlePasswordReminderPress = useHandler(async () => { + await handlePasswordReminderClose() await Airship.show(bridge => ) }) - const handle2FaEnabledDismiss = useHandler(async () => { - await writeNotifDismissInfo(account, { ...accountNotifDismissInfo, ip2FaNotifShown: true }) + const handle2FaEnabledClose = useHandler(async () => { + await hideBanner('ip2FaReminder') + // TODO: Move this to NotificationCenterScene + // await writeAccountNotifDismissInfo(account, { ...accountNotifDismissInfo, ip2FaNotifShown: true }) }) const handle2FaEnabledPress = useHandler(async () => { + await handle2FaEnabledClose() await openBrowserUri(config.ip2faSite) - await handle2FaEnabledDismiss() + }) + + const handleOtpReminderClose = useHandler(async () => { + await hideBanner('otpReminder') + }) + const handleOtpReminderPress = useHandler(async () => { + await handleOtpReminderClose() + const otpReminderModal = await getOtpReminderModal(account) + if (otpReminderModal != null) await otpReminderModal() }) const handleLayout = useHandler((event: LayoutChangeEvent) => { @@ -80,16 +97,28 @@ const NotificationViewComponent = (props: Props) => { React.useEffect(() => { const newNotifs: React.JSX.Element[] = [] Object.keys(wallets).forEach(walletId => { + const newTokenKey = `newToken-${walletId}` const newTokenIds = detectedTokensRedux[walletId] - const dismissNewTokens = (walletId: string) => { + const handleCloseNewToken = async () => { + // Since this isn't a priority notification, we can just fully complete + // it here + await modifyDeviceNotifInfo(newTokenKey, { isBannerHidden: true, isCompleted: true, isShown: false }) dispatch({ type: 'CORE/DISMISS_NEW_TOKENS', data: { walletId } }) } + const handlePressNewToken = async () => { + await handleCloseNewToken() + navigationDebounced.navigate('manageTokens', { + walletId, + newTokenIds + }) + } - if (newTokenIds != null && newTokenIds.length > 0) { + const isShowNewTokenNotif = deviceNotifState[newTokenKey] != null && !deviceNotifState[newTokenKey].isBannerHidden + if (isShowNewTokenNotif && newTokenIds != null && newTokenIds.length > 0) { const { name, currencyInfo } = wallets[walletId] newNotifs.push( @@ -102,14 +131,8 @@ const NotificationViewComponent = (props: Props) => { ? sprintf(lstrings.notif_tokens_detected_on_address_1s, currencyInfo.currencyCode) : sprintf(lstrings.notif_tokens_detected_on_wallet_name_1s, name) } - onPress={() => { - dismissNewTokens(walletId) - navigationDebounced.navigate('manageTokens', { - walletId, - newTokenIds - }) - }} - onClose={() => dismissNewTokens(walletId)} + onPress={handlePressNewToken} + onClose={handleCloseNewToken} /> ) } @@ -117,23 +140,7 @@ const NotificationViewComponent = (props: Props) => { setAutoDetectTokenCards(newNotifs) }) // eslint-disable-next-line react-hooks/exhaustive-deps - }, [detectedTokensRedux, handleBackupPress, theme]) - - // Check for 2FA/OTP reminder disabled notifications - // Periodically remind the user to enable 2FA/OTP - useAsyncEffect( - async () => { - const otpReminderModal = await getOtpReminderModal(account) - - if (otpReminderModal != null) { - setOtpReminderCard( - - ) - } - }, - [account], - 'otpNotificationCard' - ) + }, [detectedTokensRedux, deviceNotifState, handleBackupPress, theme]) return ( { footerOpenRatio={footerOpenRatio} onLayout={handleLayout} > - + 0} enter={fadeIn} exit={fadeOut}> {autoDetectTokenCards} - - {otpReminderCard} + + - + - +