From a1d905f3421dbbd0f7c9c16dde46e82015ff0d03 Mon Sep 17 00:00:00 2001 From: Michal Date: Tue, 29 Oct 2024 10:03:27 +0000 Subject: [PATCH] WIP --- .../.storybook/storybook.requires.js | 9 -- .../Notifications/useCases/common/hooks.ts | 2 + .../common/rewards-updated-notification.ts | 87 +++++++++++++++++++ 3 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 apps/wallet-mobile/src/features/Notifications/useCases/common/rewards-updated-notification.ts diff --git a/apps/wallet-mobile/.storybook/storybook.requires.js b/apps/wallet-mobile/.storybook/storybook.requires.js index efdffe4715..25d1517202 100644 --- a/apps/wallet-mobile/.storybook/storybook.requires.js +++ b/apps/wallet-mobile/.storybook/storybook.requires.js @@ -171,8 +171,6 @@ const getStories = () => { "./src/features/Scan/useCases/ShowCameraPermissionDeniedScreen/OpenDeviceAppSettingsButton.stories.tsx": require("../src/features/Scan/useCases/ShowCameraPermissionDeniedScreen/OpenDeviceAppSettingsButton.stories.tsx"), "./src/features/Scan/useCases/ShowCameraPermissionDeniedScreen/ShowCameraPermissionDeniedScreen.stories.tsx": require("../src/features/Scan/useCases/ShowCameraPermissionDeniedScreen/ShowCameraPermissionDeniedScreen.stories.tsx"), "./src/features/Send/common/ButtonGroup/ButtonGroup.stories.tsx": require("../src/features/Send/common/ButtonGroup/ButtonGroup.stories.tsx"), - "./src/features/Send/useCases/ConfirmTx/FailedTx/FailedTxScreen.stories.tsx": require("../src/features/Send/useCases/ConfirmTx/FailedTx/FailedTxScreen.stories.tsx"), - "./src/features/Send/useCases/ConfirmTx/SubmittedTx/SubmittedTxScreen.stories.tsx": require("../src/features/Send/useCases/ConfirmTx/SubmittedTx/SubmittedTxScreen.stories.tsx"), "./src/features/Send/useCases/ListAmountsToSend/AddToken/AddToken.stories.tsx": require("../src/features/Send/useCases/ListAmountsToSend/AddToken/AddToken.stories.tsx"), "./src/features/Send/useCases/ListAmountsToSend/AddToken/SelectTokenFromListScreen.stories.tsx": require("../src/features/Send/useCases/ListAmountsToSend/AddToken/SelectTokenFromListScreen.stories.tsx"), "./src/features/Send/useCases/ListAmountsToSend/AddToken/Show/MaxAmountsPerTx.stories.tsx": require("../src/features/Send/useCases/ListAmountsToSend/AddToken/Show/MaxAmountsPerTx.stories.tsx"), @@ -195,8 +193,6 @@ const getStories = () => { "./src/features/Settings/useCases/changeAppSettings/TermsOfService/TermsOfServiceScreen.stories.tsx": require("../src/features/Settings/useCases/changeAppSettings/TermsOfService/TermsOfServiceScreen.stories.tsx"), "./src/features/Settings/useCases/changeWalletSettings/ChangePassword/ChangePasswordScreen.stories.tsx": require("../src/features/Settings/useCases/changeWalletSettings/ChangePassword/ChangePasswordScreen.stories.tsx"), "./src/features/Settings/useCases/changeWalletSettings/EasyConfirmation/EasyConfirmationScreen.stories.tsx": require("../src/features/Settings/useCases/changeWalletSettings/EasyConfirmation/EasyConfirmationScreen.stories.tsx"), - "./src/features/Settings/useCases/changeWalletSettings/ManageCollateral/ConfirmTx/FailedTx/FailedTxScreen.stories.tsx": require("../src/features/Settings/useCases/changeWalletSettings/ManageCollateral/ConfirmTx/FailedTx/FailedTxScreen.stories.tsx"), - "./src/features/Settings/useCases/changeWalletSettings/ManageCollateral/ConfirmTx/SubmittedTx/SubmittedTxScreen.stories.tsx": require("../src/features/Settings/useCases/changeWalletSettings/ManageCollateral/ConfirmTx/SubmittedTx/SubmittedTxScreen.stories.tsx"), "./src/features/Settings/useCases/changeWalletSettings/ManageCollateral/ManageCollateralScreen.stories.tsx": require("../src/features/Settings/useCases/changeWalletSettings/ManageCollateral/ManageCollateralScreen.stories.tsx"), "./src/features/Settings/useCases/changeWalletSettings/RemoveWallet/RemoveWalletScreen.stories.tsx": require("../src/features/Settings/useCases/changeWalletSettings/RemoveWallet/RemoveWalletScreen.stories.tsx"), "./src/features/Settings/useCases/changeWalletSettings/RenameWalletScreen/RenameWalletScreen.stories.tsx": require("../src/features/Settings/useCases/changeWalletSettings/RenameWalletScreen/RenameWalletScreen.stories.tsx"), @@ -226,11 +222,9 @@ const getStories = () => { "./src/features/Staking/Governance/common/LearnMoreLink/LearnMoreLink.stories.tsx": require("../src/features/Staking/Governance/common/LearnMoreLink/LearnMoreLink.stories.tsx"), "./src/features/Staking/Governance/useCases/ChangeVote/ChangeVoteScreen.stories.tsx": require("../src/features/Staking/Governance/useCases/ChangeVote/ChangeVoteScreen.stories.tsx"), "./src/features/Staking/Governance/useCases/EnterDrepIdModal/EnterDrepIdModal.stories.tsx": require("../src/features/Staking/Governance/useCases/EnterDrepIdModal/EnterDrepIdModal.stories.tsx"), - "./src/features/Staking/Governance/useCases/FailedTx/FailedTxScreen.stories.tsx": require("../src/features/Staking/Governance/useCases/FailedTx/FailedTxScreen.stories.tsx"), "./src/features/Staking/Governance/useCases/Home/HomeScreen.stories.tsx": require("../src/features/Staking/Governance/useCases/Home/HomeScreen.stories.tsx"), "./src/features/Staking/Governance/useCases/NoFunds/NoFundsScreen.stories.tsx": require("../src/features/Staking/Governance/useCases/NoFunds/NoFundsScreen.stories.tsx"), "./src/features/Staking/Governance/useCases/NotSupportedCardanoAppVersion/NotSupportedCardanoAppVersion.stories.tsx": require("../src/features/Staking/Governance/useCases/NotSupportedCardanoAppVersion/NotSupportedCardanoAppVersion.stories.tsx"), - "./src/features/Staking/Governance/useCases/SuccessTx/SuccessTxScreen.stories.tsx": require("../src/features/Staking/Governance/useCases/SuccessTx/SuccessTxScreen.stories.tsx"), "./src/features/Swap/common/AmountCard/AmountCard.stories.tsx": require("../src/features/Swap/common/AmountCard/AmountCard.stories.tsx"), "./src/features/Swap/common/ButtonGroup/ButtonGroup.stories.tsx": require("../src/features/Swap/common/ButtonGroup/ButtonGroup.stories.tsx"), "./src/features/Swap/common/ConfirmRawTx/ConfirmRawTx.stories.tsx": require("../src/features/Swap/common/ConfirmRawTx/ConfirmRawTx.stories.tsx"), @@ -238,8 +232,6 @@ const getStories = () => { "./src/features/Swap/common/LiquidityPool/LiquidityPool.stories.tsx": require("../src/features/Swap/common/LiquidityPool/LiquidityPool.stories.tsx"), "./src/features/Swap/common/SelectPool/SelectPoolFromList/SelectPoolFromList.stories.tsx": require("../src/features/Swap/common/SelectPool/SelectPoolFromList/SelectPoolFromList.stories.tsx"), "./src/features/Swap/common/ServiceUnavailable/ServiceUnavailable.stories.tsx": require("../src/features/Swap/common/ServiceUnavailable/ServiceUnavailable.stories.tsx"), - "./src/features/Swap/useCases/ConfirmTxScreen/ShowFailedTxScreen/ShowFailedTxScreen.stories.tsx": require("../src/features/Swap/useCases/ConfirmTxScreen/ShowFailedTxScreen/ShowFailedTxScreen.stories.tsx"), - "./src/features/Swap/useCases/ConfirmTxScreen/ShowSubmittedTxScreen/ShowSubmittedTxScreen.stories.tsx": require("../src/features/Swap/useCases/ConfirmTxScreen/ShowSubmittedTxScreen/ShowSubmittedTxScreen.stories.tsx"), "./src/features/Swap/useCases/ReviewSwap/TransactionSummary.stories.tsx": require("../src/features/Swap/useCases/ReviewSwap/TransactionSummary.stories.tsx"), "./src/features/Swap/useCases/ShowPreprodNoticeScreen/ShowPreprodNoticeScreen.stories.tsx": require("../src/features/Swap/useCases/ShowPreprodNoticeScreen/ShowPreprodNoticeScreen.stories.tsx"), "./src/features/Swap/useCases/StartOrderSwapScreen/CreateOrder/Actions/AmountActions/AmountActions.stories.tsx": require("../src/features/Swap/useCases/StartOrderSwapScreen/CreateOrder/Actions/AmountActions/AmountActions.stories.tsx"), @@ -283,7 +275,6 @@ const getStories = () => { "./src/legacy/HW/LedgerConnect/DeviceItem/DeviceItem.stories.tsx": require("../src/legacy/HW/LedgerConnect/DeviceItem/DeviceItem.stories.tsx"), "./src/legacy/HW/LedgerConnect/LedgerConnect.stories.tsx": require("../src/legacy/HW/LedgerConnect/LedgerConnect.stories.tsx"), "./src/legacy/HW/LedgerTransportSwitchModal/LedgerTransportSwitchModal.stories.tsx": require("../src/legacy/HW/LedgerTransportSwitchModal/LedgerTransportSwitchModal.stories.tsx"), - "./src/legacy/Staking/FailedTx/FailedTxScreen.stories.tsx": require("../src/legacy/Staking/FailedTx/FailedTxScreen.stories.tsx"), "./src/legacy/Staking/PoolDetails/PoolDetailScreen.stories.tsx": require("../src/legacy/Staking/PoolDetails/PoolDetailScreen.stories.tsx"), "./src/legacy/Staking/PoolTransition/PoolTransitionModal.stories.tsx": require("../src/legacy/Staking/PoolTransition/PoolTransitionModal.stories.tsx"), "./src/legacy/Staking/StakingCenter/StakingCenter.stories.tsx": require("../src/legacy/Staking/StakingCenter/StakingCenter.stories.tsx"), diff --git a/apps/wallet-mobile/src/features/Notifications/useCases/common/hooks.ts b/apps/wallet-mobile/src/features/Notifications/useCases/common/hooks.ts index 21e427fe42..f2d11e98df 100644 --- a/apps/wallet-mobile/src/features/Notifications/useCases/common/hooks.ts +++ b/apps/wallet-mobile/src/features/Notifications/useCases/common/hooks.ts @@ -7,6 +7,7 @@ import {notificationManager} from './notification-manager' import {parseNotificationId} from './notifications' import {usePrimaryTokenPriceChangedNotification} from './primary-token-price-changed-notification' import {useTransactionReceivedNotifications} from './transaction-received-notification' +import {useRewardsUpdatedNotifications} from './rewards-updated-notification' let initialized = false @@ -41,4 +42,5 @@ export const useInitNotifications = ({enabled}: {enabled: boolean}) => { React.useEffect(() => (enabled ? init() : undefined), [enabled]) useTransactionReceivedNotifications({enabled}) usePrimaryTokenPriceChangedNotification({enabled}) + useRewardsUpdatedNotifications({enabled}) } diff --git a/apps/wallet-mobile/src/features/Notifications/useCases/common/rewards-updated-notification.ts b/apps/wallet-mobile/src/features/Notifications/useCases/common/rewards-updated-notification.ts new file mode 100644 index 0000000000..c3292da11c --- /dev/null +++ b/apps/wallet-mobile/src/features/Notifications/useCases/common/rewards-updated-notification.ts @@ -0,0 +1,87 @@ +import * as BackgroundFetch from 'expo-background-fetch' +import * as TaskManager from 'expo-task-manager' +import * as React from 'react' +import {mountAsyncStorage, useAsyncStorage} from '@yoroi/common' +import {walletManager} from '../../../WalletManager/wallet-manager' +import {notificationManager} from './notification-manager' +import {Notifications as NotificationTypes} from '@yoroi/types' +import {generateNotificationId} from './notifications' +import {Subject} from 'rxjs' +import {useWalletManager} from '../../../WalletManager/context/WalletManagerProvider' + +const backgroundTaskId = 'yoroi-rewards-updated-notifications-background-fetch' +const backgroundSyncInMinutes = 60 * 10 + +// Check is needed for hot reloading, as task can not be defined twice +if (!TaskManager.isTaskDefined(backgroundTaskId)) { + const appStorage = mountAsyncStorage({path: '/'}) + TaskManager.defineTask(backgroundTaskId, async () => { + await syncAllWallets() + const notifications = await buildNotifications(appStorage) + notifications.forEach((notification) => notificationManager.events.push(notification)) + const hasNewData = notifications.length > 0 + return hasNewData ? BackgroundFetch.BackgroundFetchResult.NewData : BackgroundFetch.BackgroundFetchResult.NoData + }) +} + +export const rewardsUpdatedSubject = new Subject() + +const registerBackgroundFetchAsync = () => { + return BackgroundFetch.registerTaskAsync(backgroundTaskId, { + minimumInterval: backgroundSyncInMinutes, + stopOnTerminate: false, + startOnBoot: true, + }) +} + +const unregisterBackgroundFetchAsync = () => { + return BackgroundFetch.unregisterTaskAsync(backgroundTaskId) +} + +const syncAllWallets = async () => { + const ids = [...walletManager.walletMetas.keys()] + for (const id of ids) { + const wallet = walletManager.getWalletById(id) + if (!wallet) continue + await wallet.sync({}) + } +} + +const createRewardsUpdatedNotification = () => { + return { + id: generateNotificationId(), + date: new Date().toISOString(), + isRead: false, + trigger: NotificationTypes.Trigger.RewardsUpdated, + } as const +} + +export const useRewardsUpdatedNotifications = ({enabled}: {enabled: boolean}) => { + const {walletManager} = useWalletManager() + const asyncStorage = useAsyncStorage() + + React.useEffect(() => { + if (!enabled) return + registerBackgroundFetchAsync() + return () => { + unregisterBackgroundFetchAsync() + } + }, [enabled]) + + React.useEffect(() => { + if (!enabled) return + const subscription = walletManager.syncWalletInfos$.subscribe(async (status) => { + const walletInfos = Array.from(status.values()) + const walletsDoneSyncing = walletInfos.filter((info) => info.status === 'done') + const areAllDone = walletsDoneSyncing.length === walletInfos.length + if (!areAllDone) return + + const notifications = await buildNotifications(asyncStorage) + notifications.forEach((notification) => rewardsUpdatedSubject.next(notification)) + }) + + return () => { + subscription.unsubscribe() + } + }, [walletManager, asyncStorage, enabled]) +}