diff --git a/packages/extension/src/libs/rate-state/index.ts b/packages/extension/src/libs/rate-state/index.ts index 626dc3940..62b498389 100644 --- a/packages/extension/src/libs/rate-state/index.ts +++ b/packages/extension/src/libs/rate-state/index.ts @@ -11,17 +11,45 @@ export default class RateState { this.storage = new BrowserStorage(InternalStorageNamespace.rateState); } - async showPopup(): Promise { + /** + * + * @param immediate + * @returns boolean + * + * allow popup to show immediately + * + */ + async showPopup(immediate: boolean = false): Promise { const state: IState | undefined = await this.storage.get( StorageKeys.rateInfo, ); + const now = Date.now(); + const popupTime = Date.now() + POPUP_TIME; + + /** + * Case 1: if the user has already been asked after activity + * - set askedAfterActivity to true + * - set popupTime to now + 30 days + * Case 2: if the user has not rated (this means that the user got asked after activity) + * - askedAfterActivity is already true + * - set popupTime to now + 30 days + * Case 3: if the user has already rated + * - always return false + * Case 4: if no state exists + * - create a new state with askedAfterActivity = false + * - set popupTime to now + 30 days + * - return immediate + */ if (state) { - if (!state.alreadyRated) { - const now = Date.now(); + if (!state.askedAfterActivity) { + state.askedAfterActivity = true; + await this.storage.set(StorageKeys.rateInfo, state); + return true; + } + if (!state.alreadyRated) { if (state.popupTime < now) { - const popupTime = Date.now() + POPUP_TIME; state.popupTime = popupTime; await this.storage.set(StorageKeys.rateInfo, state); @@ -30,18 +58,18 @@ export default class RateState { } else { return false; } + + if (immediate) return false } - // set value when state is not set - const popupTime = Date.now() + POPUP_TIME; const newState: IState = { popupTime, alreadyRated: false, + askedAfterActivity: immediate, }; this.storage.set(StorageKeys.rateInfo, newState); - - return false; + return immediate; } async resetPopupTimer(): Promise { @@ -59,6 +87,7 @@ export default class RateState { const newState: IState = { alreadyRated: false, popupTime, + askedAfterActivity: false, }; await this.storage.set(StorageKeys.rateInfo, newState); diff --git a/packages/extension/src/libs/rate-state/types.ts b/packages/extension/src/libs/rate-state/types.ts index bc0f8e46b..9369aba0c 100644 --- a/packages/extension/src/libs/rate-state/types.ts +++ b/packages/extension/src/libs/rate-state/types.ts @@ -5,6 +5,7 @@ export enum StorageKeys { export interface Rate { alreadyRated: boolean; popupTime: number; + askedAfterActivity: boolean; } export type IState = Rate; diff --git a/packages/extension/src/providers/bitcoin/ui/send-transaction/verify-transaction/index.vue b/packages/extension/src/providers/bitcoin/ui/send-transaction/verify-transaction/index.vue index 6585285f2..5836c43d2 100644 --- a/packages/extension/src/providers/bitcoin/ui/send-transaction/verify-transaction/index.vue +++ b/packages/extension/src/providers/bitcoin/ui/send-transaction/verify-transaction/index.vue @@ -98,10 +98,19 @@ import { BitcoinNetwork } from '@/providers/bitcoin/types/bitcoin-network'; import BitcoinAPI from '@/providers/bitcoin/libs/api'; import { trackSendEvents } from '@/libs/metrics'; import { SendEventType } from '@/libs/metrics/types'; +import RateState from '@/libs/rate-state'; +import { useRateStore } from '@action/store/rate-store'; + +/** ------------------- + * Rate + -------------------*/ +const rateStore = useRateStore(); +const { toggleRatePopup } = rateStore; const KeyRing = new PublicKeyRing(); const route = useRoute(); const router = useRouter(); +const rateState = new RateState(); const selectedNetwork: string = route.query.id as string; const txData: VerifyTransactionParams = JSON.parse( Buffer.from(route.query.txData as string, 'base64').toString('utf8'), @@ -185,11 +194,13 @@ const sendAction = async () => { if (getCurrentContext() === 'popup') { setTimeout(() => { isProcessing.value = false; + callToggleRate(); router.go(-2); }, 4500); } else { setTimeout(() => { isProcessing.value = false; + callToggleRate(); window.close(); }, 1500); } @@ -213,6 +224,16 @@ const sendAction = async () => { errorMsg.value = JSON.stringify(error); }); }; + +const callToggleRate = () => { + /** + * will only show the user if they haven't rated it + * and never been shown before + */ + rateState.showPopup(true).then(show => { + if (show) toggleRatePopup(true); + }); +}; const isHasScroll = () => { if (verifyScrollRef.value) { return verifyScrollRef.value.$el.classList.contains('ps--active-y'); diff --git a/packages/extension/src/providers/ethereum/ui/send-transaction/verify-transaction/index.vue b/packages/extension/src/providers/ethereum/ui/send-transaction/verify-transaction/index.vue index 413d64e83..4201a009b 100644 --- a/packages/extension/src/providers/ethereum/ui/send-transaction/verify-transaction/index.vue +++ b/packages/extension/src/providers/ethereum/ui/send-transaction/verify-transaction/index.vue @@ -109,10 +109,19 @@ import { toBN } from 'web3-utils'; import { bufferToHex, toBase } from '@enkryptcom/utils'; import { trackSendEvents } from '@/libs/metrics'; import { SendEventType } from '@/libs/metrics/types'; +import RateState from '@/libs/rate-state'; +import { useRateStore } from '@action/store/rate-store'; + +/** ------------------- + * Rate + -------------------*/ +const rateStore = useRateStore(); +const { toggleRatePopup } = rateStore; const KeyRing = new PublicKeyRing(); const route = useRoute(); const router = useRouter(); +const rateState = new RateState(); const selectedNetwork: string = route.query.id as string; const txData: VerifyTransactionParams = JSON.parse( Buffer.from(route.query.txData as string, 'base64').toString('utf8'), @@ -141,6 +150,16 @@ const close = () => { } }; +const callToggleRate = () => { + /** + * will only show the user if they haven't rated it + * and never been shown before + */ + rateState.showPopup(true).then(show => { + if (show) toggleRatePopup(true); + }); +}; + const sendAction = async () => { isProcessing.value = true; trackSendEvents(SendEventType.SendApprove, { @@ -198,11 +217,13 @@ const sendAction = async () => { if (getCurrentContext() === 'popup') { setTimeout(() => { isProcessing.value = false; + callToggleRate(); router.go(-2); }, 4500); } else { setTimeout(() => { isProcessing.value = false; + callToggleRate(); window.close(); }, 1500); } diff --git a/packages/extension/src/providers/kadena/ui/send-transaction/verify-transaction/index.vue b/packages/extension/src/providers/kadena/ui/send-transaction/verify-transaction/index.vue index e717deb72..46473d3ea 100644 --- a/packages/extension/src/providers/kadena/ui/send-transaction/verify-transaction/index.vue +++ b/packages/extension/src/providers/kadena/ui/send-transaction/verify-transaction/index.vue @@ -104,12 +104,21 @@ import KadenaAPI from '@/providers/kadena/libs/api'; import { KadenaNetwork } from '@/providers/kadena/types/kadena-network'; import { trackSendEvents } from '@/libs/metrics'; import { SendEventType } from '@/libs/metrics/types'; +import RateState from '@/libs/rate-state'; +import { useRateStore } from '@action/store/rate-store'; + +/** ------------------- + * Rate + -------------------*/ +const rateStore = useRateStore(); +const { toggleRatePopup } = rateStore; const isSendDone = ref(false); const account = ref(); const chainId = ref(); const kdaToken = ref(); const KeyRing = new PublicKeyRing(); +const rateState = new RateState(); const route = useRoute(); const router = useRouter(); const selectedNetwork: string = route.query.id as string; @@ -197,11 +206,13 @@ const sendAction = async () => { if (getCurrentContext() === 'popup') { setTimeout(() => { isProcessing.value = false; + callToggleRatePopup(); router.push({ name: 'activity', params: { id: network.value.name } }); }, 2500); } else { setTimeout(() => { isProcessing.value = false; + callToggleRatePopup(); window.close(); }, 1500); } @@ -218,6 +229,16 @@ const sendAction = async () => { } }; +const callToggleRatePopup = () => { + /** + * will only show the user if they haven't rated it + * and never been shown before + */ + rateState.showPopup(true).then(show => { + if (show) toggleRatePopup(true); + }); +}; + const isHasScroll = () => { if (verifyScrollRef.value) { return verifyScrollRef.value.$el.classList.contains('ps--active-y'); diff --git a/packages/extension/src/providers/polkadot/ui/send-transaction/verify-transaction/index.vue b/packages/extension/src/providers/polkadot/ui/send-transaction/verify-transaction/index.vue index 299730846..238393f00 100644 --- a/packages/extension/src/providers/polkadot/ui/send-transaction/verify-transaction/index.vue +++ b/packages/extension/src/providers/polkadot/ui/send-transaction/verify-transaction/index.vue @@ -107,10 +107,19 @@ import CustomScrollbar from '@action/components/custom-scrollbar/index.vue'; import { BaseNetwork } from '@/types/base-network'; import { trackSendEvents } from '@/libs/metrics'; import { SendEventType } from '@/libs/metrics/types'; +import RateState from '@/libs/rate-state'; +import { useRateStore } from '@action/store/rate-store'; + +/** ------------------- + * Rate + -------------------*/ +const rateStore = useRateStore(); +const { toggleRatePopup } = rateStore; const isSendDone = ref(false); const account = ref(); const KeyRing = new PublicKeyRing(); +const rateState = new RateState(); const route = useRoute(); const router = useRouter(); const selectedNetwork: string = route.query.id as string; @@ -207,11 +216,13 @@ const sendAction = async () => { if (getCurrentContext() === 'popup') { setTimeout(() => { isProcessing.value = false; + callToggleRatePopup(); router.go(-2); }, 2500); } else { setTimeout(() => { isProcessing.value = false; + callToggleRatePopup(); window.close(); }, 1500); } @@ -240,6 +251,16 @@ const sendAction = async () => { } }; +const callToggleRatePopup = () => { + /** + * will only show the user if they haven't rated it + * and never been shown before + */ + rateState.showPopup(true).then(show => { + if (show) toggleRatePopup(true); + }); +}; + const isHasScroll = () => { if (verifyScrollRef.value) { return verifyScrollRef.value.$el.classList.contains('ps--active-y'); diff --git a/packages/extension/src/providers/solana/ui/send-transaction/verify-transaction/index.vue b/packages/extension/src/providers/solana/ui/send-transaction/verify-transaction/index.vue index 7daceaa0b..5fd314ba8 100644 --- a/packages/extension/src/providers/solana/ui/send-transaction/verify-transaction/index.vue +++ b/packages/extension/src/providers/solana/ui/send-transaction/verify-transaction/index.vue @@ -115,8 +115,17 @@ import { getSimulationComputeUnits } from '@solana-developers/helpers'; import SolanaAPI from '@/providers/solana/libs/api'; import bs58 from 'bs58'; import { TransactionSigner } from '../../libs/signer'; +import RateState from '@/libs/rate-state'; +import { useRateStore } from '@action/store/rate-store'; + +/** ------------------- + * Rate + -------------------*/ +const rateStore = useRateStore(); +const { toggleRatePopup } = rateStore; const KeyRing = new PublicKeyRing(); +const rateState = new RateState(); const route = useRoute(); const router = useRouter(); const selectedNetwork: string = route.query.id as string; @@ -227,14 +236,23 @@ const sendAction = async () => { }, ); isSendDone.value = true; + /** + * will only show the user if they haven't rated it + * and never been shown before + */ + rateState.showPopup(true).then(show => { + if (show) toggleRatePopup(true); + }); if (getCurrentContext() === 'popup') { setTimeout(() => { isProcessing.value = false; + callToggleRatePopup(); router.go(-2); }, 4500); } else { setTimeout(() => { isProcessing.value = false; + callToggleRatePopup(); window.close(); }, 1500); } @@ -275,6 +293,17 @@ const sendAction = async () => { console.error('ERROR', errror); }); }; + +const callToggleRatePopup = () => { + /** + * will only show the user if they haven't rated it + * and never been shown before + */ + rateState.showPopup(true).then(show => { + if (show) toggleRatePopup(true); + }); +}; + const isHasScroll = () => { if (verifyScrollRef.value) { return verifyScrollRef.value.$el.classList.contains('ps--active-y'); diff --git a/packages/extension/src/ui/action/App.vue b/packages/extension/src/ui/action/App.vue index 366854fe6..2c0132f09 100644 --- a/packages/extension/src/ui/action/App.vue +++ b/packages/extension/src/ui/action/App.vue @@ -65,7 +65,7 @@ @close:popup="settingsShow = !settingsShow" @action:lock="lockAction" /> - + (''); const kr = new PublicKeyRing(); const addNetworkShow = ref(false); const settingsShow = ref(false); -const rateShow = ref(false); const updateShow = ref(false); const isLoading = ref(true); const currentVersion = __PACKAGE_VERSION__; const latestVersion = ref(''); + +/** ------------------- + * Rate + -------------------*/ +const rateStore = useRateStore(); +const { isRatePopupOpen } = storeToRefs(rateStore); +const { toggleRatePopup } = rateStore; /** ------------------- * Exapnded Menu -------------------*/ @@ -270,7 +277,8 @@ onMounted(async () => { setTimeout(() => { rateState.showPopup().then(show => { if (show) { - rateShow.value = true; + console.log('show rate popup', show); + toggleRatePopup(true); } else { getLatestEnkryptVersion().then(version => { if ( diff --git a/packages/extension/src/ui/action/store/rate-store.ts b/packages/extension/src/ui/action/store/rate-store.ts new file mode 100644 index 000000000..85a965e74 --- /dev/null +++ b/packages/extension/src/ui/action/store/rate-store.ts @@ -0,0 +1,17 @@ +import { defineStore } from 'pinia' +import { ref, } from 'vue'; + +export const useRateStore = defineStore('useRateStore', () => { + + const isRatePopupOpen = ref(false); + + const toggleRatePopup = async (value: boolean) => { + isRatePopupOpen.value = !!value; + } + + return { + isRatePopupOpen, + toggleRatePopup + } +}) + diff --git a/packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue b/packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue index 3f4890fbe..edb8ff6d8 100644 --- a/packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue +++ b/packages/extension/src/ui/action/views/swap/views/swap-best-offer/index.vue @@ -157,10 +157,19 @@ import { trackSwapEvents } from '@/libs/metrics'; import { SwapEventType } from '@/libs/metrics/types'; import { getSolanaTransactionFees } from '../../libs/solana-gasvals'; import { SolanaNetwork } from '@/providers/solana/types/sol-network'; +import RateState from '@/libs/rate-state'; +import { useRateStore } from '@action/store/rate-store'; + +/** ------------------- + * Rate + -------------------*/ +const rateStore = useRateStore(); +const { toggleRatePopup } = rateStore; const router = useRouter(); const route = useRoute(); +const rateState = new RateState(); const isInitiated = ref(false); const bestOfferScrollRef = ref>(); const scrollProgress = ref(0); @@ -354,8 +363,10 @@ const close = () => { swapProvider: pickedTrade.value.provider, }); if (!isWindowPopup.value) { + callToggleRatePopup(); router.go(-2); } else { + callToggleRatePopup(); window.close(); } }; @@ -462,6 +473,16 @@ const sendAction = async () => { } }; +const callToggleRatePopup = () => { + /** + * will only show the user if they haven't rated it + * and never been shown before + */ + rateState.showPopup(true).then(show => { + if (show) toggleRatePopup(true); + }); +}; + const handleScroll = (e: any) => { const progress = Number(e.target.lastChild.style.top.replace('px', '')); scrollProgress.value = progress;