From 93052477d6e5293d1200a9a1efdb825a2cdf59dd Mon Sep 17 00:00:00 2001 From: Atatakai Date: Fri, 24 May 2024 18:56:54 +0400 Subject: [PATCH 1/7] Add keep agent running alert --- electron/store.js | 4 +++ frontend/components/Main/KeepAgentRunning.tsx | 36 +++++++++++++++++++ frontend/components/Main/Main.tsx | 2 ++ frontend/components/Main/MainNeedsFunds.tsx | 2 +- frontend/context/RewardProvider.tsx | 11 ++++++ frontend/types/ElectronApi.ts | 6 ++-- 6 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 frontend/components/Main/KeepAgentRunning.tsx diff --git a/electron/store.js b/electron/store.js index b69bbbd6b..7abfa6e81 100644 --- a/electron/store.js +++ b/electron/store.js @@ -4,6 +4,10 @@ const schema = { type: 'boolean', default: false, }, + rewardsEarnedOnce: { + type: 'boolean', + default: false, + }, }; const setupStoreIpc = async (ipcChannel, mainWindow) => { diff --git a/frontend/components/Main/KeepAgentRunning.tsx b/frontend/components/Main/KeepAgentRunning.tsx new file mode 100644 index 000000000..674843127 --- /dev/null +++ b/frontend/components/Main/KeepAgentRunning.tsx @@ -0,0 +1,36 @@ +import { Flex, Typography } from 'antd'; + +import { DeploymentStatus } from '@/client'; +import { useServices } from '@/hooks'; +import { useStore } from '@/hooks/useStore'; + +import { Alert } from '../common/Alert'; +import { CardSection } from '../styled/CardSection'; + +const { Text } = Typography; + +export const KeepAgentRunning = () => { + const { storeState } = useStore(); + const { serviceStatus } = useServices(); + + const rewardsEarnedOnce = storeState?.rewardsEarnedOnce; + + if (rewardsEarnedOnce) return false; + if (serviceStatus !== DeploymentStatus.DEPLOYED) return; + + return ( + + + Your agent has not hit its target yet. + Keep the agent running to earn today’s rewards. + + } + /> + + ); +}; diff --git a/frontend/components/Main/Main.tsx b/frontend/components/Main/Main.tsx index cfffd7026..cfede1da7 100644 --- a/frontend/components/Main/Main.tsx +++ b/frontend/components/Main/Main.tsx @@ -5,6 +5,7 @@ import { useEffect } from 'react'; import { PageState } from '@/enums'; import { useBalance, usePageState, useServices } from '@/hooks'; +import { KeepAgentRunning } from './KeepAgentRunning'; import { MainAddFunds } from './MainAddFunds'; import { MainGasBalance } from './MainGasBalance'; import { MainHeader } from './MainHeader'; @@ -41,6 +42,7 @@ export const Main = () => { + diff --git a/frontend/components/Main/MainNeedsFunds.tsx b/frontend/components/Main/MainNeedsFunds.tsx index fd6e67bb1..738eda621 100644 --- a/frontend/components/Main/MainNeedsFunds.tsx +++ b/frontend/components/Main/MainNeedsFunds.tsx @@ -19,7 +19,7 @@ const useNeedsFunds = () => { const { storeState } = useStore(); const { safeBalance } = useBalance(); - const isInitialFunded = storeState?.isInitialFunded as boolean | undefined; + const isInitialFunded = storeState?.isInitialFunded; const serviceFundRequirements = useMemo(() => { const monthlyGasEstimate = Number( diff --git a/frontend/context/RewardProvider.tsx b/frontend/context/RewardProvider.tsx index 59a5a0031..3fc95e107 100644 --- a/frontend/context/RewardProvider.tsx +++ b/frontend/context/RewardProvider.tsx @@ -4,11 +4,14 @@ import { PropsWithChildren, useCallback, useContext, + useEffect, useMemo, useState, } from 'react'; import { useInterval } from 'usehooks-ts'; +import { useElectronApi } from '@/hooks/useElectronApi'; +import { useStore } from '@/hooks/useStore'; import { AutonolasService } from '@/service/Autonolas'; import { ServicesContext } from './ServicesProvider'; @@ -32,6 +35,8 @@ export const RewardContext = createContext<{ export const RewardProvider = ({ children }: PropsWithChildren) => { const { services } = useContext(ServicesContext); const service = useMemo(() => services?.[0], [services]); + const { storeState } = useStore(); + const electronApi = useElectronApi(); const [accruedServiceStakingRewards, setAccruedServiceStakingRewards] = useState(); @@ -78,6 +83,12 @@ export const RewardProvider = ({ children }: PropsWithChildren) => { setAvailableRewardsForEpoch(rewards); }, [service]); + useEffect(() => { + if (isEligibleForRewards && !storeState?.rewardsEarnedOnce) { + electronApi.store?.set?.('rewardsEarnedOnce', true); + } + }, [electronApi.store, isEligibleForRewards, storeState?.rewardsEarnedOnce]); + useInterval(async () => updateRewards(), 5000); return ( diff --git a/frontend/types/ElectronApi.ts b/frontend/types/ElectronApi.ts index 59a362a49..73d1955ee 100644 --- a/frontend/types/ElectronApi.ts +++ b/frontend/types/ElectronApi.ts @@ -1,4 +1,6 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -export type ElectronStore = Record; +export type ElectronStore = { + isInitialFunded?: boolean; + rewardsEarnedOnce?: boolean; +}; export type ElectronTrayIconStatus = 'low-gas' | 'running' | 'paused'; From 7dc9edc0d0304a2db88d0dad58e4b11c2b812462 Mon Sep 17 00:00:00 2001 From: Atatakai Date: Fri, 24 May 2024 19:20:12 +0400 Subject: [PATCH 2/7] Rename store property --- electron/store.js | 2 +- frontend/components/Main/KeepAgentRunning.tsx | 4 ++-- frontend/context/RewardProvider.tsx | 10 +++++++--- frontend/types/ElectronApi.ts | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/electron/store.js b/electron/store.js index 7abfa6e81..3efecf037 100644 --- a/electron/store.js +++ b/electron/store.js @@ -4,7 +4,7 @@ const schema = { type: 'boolean', default: false, }, - rewardsEarnedOnce: { + firstStakingRewardAchieved: { type: 'boolean', default: false, }, diff --git a/frontend/components/Main/KeepAgentRunning.tsx b/frontend/components/Main/KeepAgentRunning.tsx index 674843127..d822f52b4 100644 --- a/frontend/components/Main/KeepAgentRunning.tsx +++ b/frontend/components/Main/KeepAgentRunning.tsx @@ -13,9 +13,9 @@ export const KeepAgentRunning = () => { const { storeState } = useStore(); const { serviceStatus } = useServices(); - const rewardsEarnedOnce = storeState?.rewardsEarnedOnce; + const firstStakingRewardAchieved = storeState?.firstStakingRewardAchieved; - if (rewardsEarnedOnce) return false; + if (firstStakingRewardAchieved) return false; if (serviceStatus !== DeploymentStatus.DEPLOYED) return; return ( diff --git a/frontend/context/RewardProvider.tsx b/frontend/context/RewardProvider.tsx index 3fc95e107..6bf4ebdb3 100644 --- a/frontend/context/RewardProvider.tsx +++ b/frontend/context/RewardProvider.tsx @@ -84,10 +84,14 @@ export const RewardProvider = ({ children }: PropsWithChildren) => { }, [service]); useEffect(() => { - if (isEligibleForRewards && !storeState?.rewardsEarnedOnce) { - electronApi.store?.set?.('rewardsEarnedOnce', true); + if (isEligibleForRewards && !storeState?.firstStakingRewardAchieved) { + electronApi.store?.set?.('firstStakingRewardAchieved', true); } - }, [electronApi.store, isEligibleForRewards, storeState?.rewardsEarnedOnce]); + }, [ + electronApi.store, + isEligibleForRewards, + storeState?.firstStakingRewardAchieved, + ]); useInterval(async () => updateRewards(), 5000); diff --git a/frontend/types/ElectronApi.ts b/frontend/types/ElectronApi.ts index 73d1955ee..5df5177e8 100644 --- a/frontend/types/ElectronApi.ts +++ b/frontend/types/ElectronApi.ts @@ -1,6 +1,6 @@ export type ElectronStore = { isInitialFunded?: boolean; - rewardsEarnedOnce?: boolean; + firstStakingRewardAchieved?: boolean; }; export type ElectronTrayIconStatus = 'low-gas' | 'running' | 'paused'; From 970da3c4708d5c43b183b5a343b4de7b380559cd Mon Sep 17 00:00:00 2001 From: Atatakai Date: Fri, 24 May 2024 19:28:19 +0400 Subject: [PATCH 3/7] Review fixes --- frontend/components/Main/KeepAgentRunning.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/frontend/components/Main/KeepAgentRunning.tsx b/frontend/components/Main/KeepAgentRunning.tsx index d822f52b4..e0ad0f5ee 100644 --- a/frontend/components/Main/KeepAgentRunning.tsx +++ b/frontend/components/Main/KeepAgentRunning.tsx @@ -13,10 +13,8 @@ export const KeepAgentRunning = () => { const { storeState } = useStore(); const { serviceStatus } = useServices(); - const firstStakingRewardAchieved = storeState?.firstStakingRewardAchieved; - - if (firstStakingRewardAchieved) return false; - if (serviceStatus !== DeploymentStatus.DEPLOYED) return; + if (storeState?.firstStakingRewardAchieved) return null; + if (serviceStatus !== DeploymentStatus.DEPLOYED) return null; return ( From 340fa92c07d9b3e1b82e07088c4a2695629c8957 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 24 May 2024 21:18:30 +0530 Subject: [PATCH 4/7] chore: add firstRewardNotificationShown property to store --- electron/store.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/electron/store.js b/electron/store.js index 3efecf037..a9a5867c6 100644 --- a/electron/store.js +++ b/electron/store.js @@ -8,6 +8,10 @@ const schema = { type: 'boolean', default: false, }, + firstRewardNotificationShown: { + type: 'boolean', + default: false, + }, }; const setupStoreIpc = async (ipcChannel, mainWindow) => { From 3e1f08504a07e4a290659fb457ce382a50219886 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 24 May 2024 21:28:06 +0530 Subject: [PATCH 5/7] add logs --- frontend/components/Main/MainRewards.tsx | 29 +++++++++++++++++------- frontend/types/ElectronApi.ts | 1 + 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/frontend/components/Main/MainRewards.tsx b/frontend/components/Main/MainRewards.tsx index 411b71331..350757b1b 100644 --- a/frontend/components/Main/MainRewards.tsx +++ b/frontend/components/Main/MainRewards.tsx @@ -2,12 +2,14 @@ import { Button, Col, Flex, Modal, Row, Skeleton, Tag, Typography } from 'antd'; import Image from 'next/image'; import { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; +import { useTimeout } from 'usehooks-ts'; import { balanceFormat } from '@/common-util'; import { COLOR } from '@/constants'; import { useBalance } from '@/hooks'; import { useElectronApi } from '@/hooks/useElectronApi'; import { useReward } from '@/hooks/useReward'; +import { useStore } from '@/hooks/useStore'; import { ConfettiAnimation } from '../common/ConfettiAnimation'; @@ -81,20 +83,29 @@ const DisplayRewards = () => { const NotifyRewards = () => { const { isEligibleForRewards, availableRewardsForEpochEth } = useReward(); const { totalOlasBalance } = useBalance(); - const { showNotification } = useElectronApi(); + const { showNotification, store } = useElectronApi(); + const { storeState } = useStore(); const [canShowNotification, setCanShowNotification] = useState(false); - useEffect(() => { - // TODO: Implement this once state persistence is available - const hasAlreadyNotified = true; + useTimeout(() => { + // notification shown + setCanShowNotification(true); + }, 3000); + useEffect(() => { if (!isEligibleForRewards) return; - if (hasAlreadyNotified) return; + if (!storeState) return; + if (storeState?.firstRewardNotificationShown) return; if (!availableRewardsForEpochEth) return; setCanShowNotification(true); - }, [isEligibleForRewards, availableRewardsForEpochEth, showNotification]); + }, [ + isEligibleForRewards, + availableRewardsForEpochEth, + showNotification, + storeState, + ]); // hook to show app notification useEffect(() => { @@ -108,8 +119,10 @@ const NotifyRewards = () => { const closeNotificationModal = useCallback(() => { setCanShowNotification(false); - // TODO: add setter for hasAlreadyNotified - }, []); + store?.set?.('firstRewardNotificationShown', true); + }, [store]); + + console.log(storeState); if (!canShowNotification) return null; diff --git a/frontend/types/ElectronApi.ts b/frontend/types/ElectronApi.ts index 5df5177e8..221b00000 100644 --- a/frontend/types/ElectronApi.ts +++ b/frontend/types/ElectronApi.ts @@ -1,6 +1,7 @@ export type ElectronStore = { isInitialFunded?: boolean; firstStakingRewardAchieved?: boolean; + firstRewardNotificationShown?: boolean; }; export type ElectronTrayIconStatus = 'low-gas' | 'running' | 'paused'; From 5345e79d0197ee19aa45e90834fd251654b68170 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 24 May 2024 21:29:45 +0530 Subject: [PATCH 6/7] chore: Refactor MainRewards component and add desktop app notification --- frontend/components/Main/MainRewards.tsx | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/frontend/components/Main/MainRewards.tsx b/frontend/components/Main/MainRewards.tsx index 350757b1b..f014b45f8 100644 --- a/frontend/components/Main/MainRewards.tsx +++ b/frontend/components/Main/MainRewards.tsx @@ -2,7 +2,6 @@ import { Button, Col, Flex, Modal, Row, Skeleton, Tag, Typography } from 'antd'; import Image from 'next/image'; import { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; -import { useTimeout } from 'usehooks-ts'; import { balanceFormat } from '@/common-util'; import { COLOR } from '@/constants'; @@ -88,11 +87,7 @@ const NotifyRewards = () => { const [canShowNotification, setCanShowNotification] = useState(false); - useTimeout(() => { - // notification shown - setCanShowNotification(true); - }, 3000); - + // hook to set the flag to show the notification useEffect(() => { if (!isEligibleForRewards) return; if (!storeState) return; @@ -107,7 +102,7 @@ const NotifyRewards = () => { storeState, ]); - // hook to show app notification + // hook to show desktop app notification useEffect(() => { if (!canShowNotification) return; @@ -119,11 +114,11 @@ const NotifyRewards = () => { const closeNotificationModal = useCallback(() => { setCanShowNotification(false); + + // once the notification is closed, set the flag to true store?.set?.('firstRewardNotificationShown', true); }, [store]); - console.log(storeState); - if (!canShowNotification) return null; return ( From 2a3bbc57ee7a6ab4494ad7894c1827aaf0cc9e52 Mon Sep 17 00:00:00 2001 From: mohandast52 Date: Fri, 24 May 2024 21:31:25 +0530 Subject: [PATCH 7/7] hide share to twitter button --- frontend/components/Main/MainRewards.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/Main/MainRewards.tsx b/frontend/components/Main/MainRewards.tsx index f014b45f8..b4b5bf2c8 100644 --- a/frontend/components/Main/MainRewards.tsx +++ b/frontend/components/Main/MainRewards.tsx @@ -134,7 +134,7 @@ const NotifyRewards = () => { size="large" className="mt-8" disabled - // TODO: add twitter share functionality + style={{ display: 'none' }} // TODO: add twitter share functionality > Share on