Skip to content

Commit

Permalink
feat(ui): add QuickPay prompt (#2402)
Browse files Browse the repository at this point in the history
  • Loading branch information
pwltr authored Dec 16, 2024
1 parent 3913667 commit 0bcd35b
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 0 deletions.
118 changes: 118 additions & 0 deletions src/navigation/bottom-sheet/QuickPayPrompt.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React, { memo, ReactElement, useEffect, useMemo } from 'react';
import { useNavigation } from '@react-navigation/native';
import { Trans, useTranslation } from 'react-i18next';

import { __E2E__ } from '../../constants/env';
import { BodyMB, Display } from '../../styles/text';
import BottomSheetWrapper from '../../components/BottomSheetWrapper';
import BottomSheetScreen from '../../components/BottomSheetScreen';
import { objectKeys } from '../../utils/objectKeys';
import { useBalance } from '../../hooks/wallet';
import { useAppDispatch, useAppSelector } from '../../hooks/redux';
import {
useBottomSheetBackPress,
useSnapPoints,
} from '../../hooks/bottomSheet';
import { closeSheet } from '../../store/slices/ui';
import { updateUser } from '../../store/slices/user';
import { showBottomSheet } from '../../store/utils/ui';
import { viewControllersSelector } from '../../store/reselect/ui';
import { quickpayIntroSeenSelector } from '../../store/reselect/user';
import { RootNavigationProp } from '../types';

const imageSrc = require('../../assets/illustrations/fast-forward.png');

const CHECK_DELAY = 3000; // how long user needs to stay on Wallets screen before he will see this prompt

const QuickPayPrompt = ({ enabled }: { enabled: boolean }): ReactElement => {
const { t } = useTranslation('settings');
const navigation = useNavigation<RootNavigationProp>();
const { spendingBalance } = useBalance();
const snapPoints = useSnapPoints('large');
const dispatch = useAppDispatch();
const viewControllers = useAppSelector(viewControllersSelector);
const quickpayIntroSeen = useAppSelector(quickpayIntroSeenSelector);

useBottomSheetBackPress('quickPay');

const anyBottomSheetIsOpen = useMemo(() => {
const viewControllerKeys = objectKeys(viewControllers);
return viewControllerKeys
.filter((view) => view !== 'quickPay')
.some((view) => viewControllers[view].isOpen);
}, [viewControllers]);

// if user hasn't seen this prompt
// and has a spending balance
// and no other bottom-sheets are shown
// and user on "Wallets" screen for CHECK_DELAY
const shouldShowBottomSheet = useMemo(() => {
return (
enabled &&
!__E2E__ &&
!anyBottomSheetIsOpen &&
!quickpayIntroSeen &&
spendingBalance > 0
);
}, [enabled, anyBottomSheetIsOpen, quickpayIntroSeen, spendingBalance]);

useEffect(() => {
if (!shouldShowBottomSheet) {
return;
}

const timer = setTimeout(() => {
showBottomSheet('quickPay');
}, CHECK_DELAY);

return (): void => {
clearTimeout(timer);
};
}, [shouldShowBottomSheet]);

const onMore = (): void => {
navigation.navigate('Settings', { screen: 'QuickpaySettings' });
dispatch(updateUser({ quickpayIntroSeen: true }));
dispatch(closeSheet('quickPay'));
};

const onDismiss = (): void => {
dispatch(updateUser({ quickpayIntroSeen: true }));
dispatch(closeSheet('quickPay'));
};

return (
<BottomSheetWrapper
view="quickPay"
snapPoints={snapPoints}
onClose={(): void => {
dispatch(updateUser({ quickpayIntroSeen: true }));
}}>
<BottomSheetScreen
navTitle={t('quickpay.nav_title')}
title={
<Trans
t={t}
i18nKey="quickpay.intro.title"
components={{ accent: <Display color="green" /> }}
/>
}
description={
<Trans
t={t}
i18nKey="quickpay.intro.description"
components={{ accent: <BodyMB color="white" /> }}
/>
}
image={imageSrc}
continueText={t('learn_more')}
cancelText={t('later')}
testID="QuickPayPrompt"
onContinue={onMore}
onCancel={onDismiss}
/>
</BottomSheetWrapper>
);
};

export default memo(QuickPayPrompt);
2 changes: 2 additions & 0 deletions src/navigation/wallet/WalletNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ActivityFiltered from '../../screens/Activity/ActivityFiltered';
import BackupPrompt from '../../screens/Settings/Backup/BackupPrompt';
import AppUpdatePrompt from '../bottom-sheet/AppUpdatePrompt';
import HighBalanceWarning from '../bottom-sheet/HighBalanceWarning';
import QuickPayPrompt from '../bottom-sheet/QuickPayPrompt';
import TabBar from '../../components/TabBar';
import type { RootStackScreenProps } from '../types';
import { __E2E__ } from '../../constants/env';
Expand Down Expand Up @@ -57,6 +58,7 @@ const WalletsStack = ({
<BackupPrompt enabled={isWalletsScreenFocused} />
<HighBalanceWarning enabled={isWalletsScreenFocused} />
<AppUpdatePrompt enabled={isWalletsScreenFocused} />
<QuickPayPrompt enabled={isWalletsScreenFocused} />
</>
);
};
Expand Down
1 change: 1 addition & 0 deletions src/store/shapes/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const defaultViewControllers: TUiState['viewControllers'] = {
PINNavigation: defaultViewController,
profileAddDataForm: defaultViewController,
pubkyAuth: defaultViewController,
quickPay: defaultViewController,
receiveNavigation: defaultViewController,
sendNavigation: defaultViewController,
timeRangePrompt: defaultViewController,
Expand Down
1 change: 1 addition & 0 deletions src/store/types/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export type ViewControllerParamList = {
PINNavigation: { showLaterButton: boolean };
profileAddDataForm: undefined;
pubkyAuth: { url: string };
quickPay: undefined;
receiveNavigation: { receiveScreen: keyof ReceiveStackParamList } | undefined;
sendNavigation:
| { screen: keyof SendStackParamList }
Expand Down

0 comments on commit 0bcd35b

Please sign in to comment.