Skip to content

Commit

Permalink
TW-1307 Use SWR instead of Redux to fetch Optimal ads
Browse files Browse the repository at this point in the history
  • Loading branch information
keshan3262 committed Feb 27, 2024
1 parent e58d955 commit 76ba8d9
Show file tree
Hide file tree
Showing 21 changed files with 99 additions and 205 deletions.
3 changes: 0 additions & 3 deletions src/components/activity-groups-list/activity-groups-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { emptyFn } from 'src/config/general';
import { useAdTemporaryHiding } from 'src/hooks/use-ad-temporary-hiding.hook';
import { useFakeRefreshControlProps } from 'src/hooks/use-fake-refresh-control-props.hook';
import { useInternalAdsAnalytics } from 'src/hooks/use-internal-ads-analytics.hook';
import { usePartnersPromoLoad } from 'src/hooks/use-partners-promo';
import { ActivityGroup, emptyActivity } from 'src/interfaces/activity.interface';
import { useIsPartnersPromoEnabledSelector } from 'src/store/partners-promotion/partners-promotion-selectors';
import { isTheSameDay, isToday, isYesterday } from 'src/utils/date.utils';
Expand Down Expand Up @@ -43,8 +42,6 @@ export const ActivityGroupsList: FC<Props> = ({
handleUpdate = emptyFn,
pageName
}) => {
usePartnersPromoLoad(PROMOTION_ID);

const styles = useActivityGroupsListStyles();

const partnersPromotionEnabled = useIsPartnersPromoEnabledSelector();
Expand Down
8 changes: 2 additions & 6 deletions src/components/hypelab-promotion/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ export const HypelabPromotion: FC<SingleProviderPromotionProps> = ({
[adHref, onError]
);

const handleAdFrameError = useCallback(() => {
onError();
}, [onError]);

const handleAdFrameMessage = useCallback(
(e: WebViewMessageEvent) => {
try {
Expand Down Expand Up @@ -111,7 +107,7 @@ export const HypelabPromotion: FC<SingleProviderPromotionProps> = ({
<WebView
source={adFrameSource}
containerStyle={styles.imageAdFrame}
onError={handleAdFrameError}
onError={onError}
onMessage={handleAdFrameMessage}
webviewDebuggingEnabled={__DEV__}
scrollEnabled={false}
Expand All @@ -128,7 +124,7 @@ export const HypelabPromotion: FC<SingleProviderPromotionProps> = ({
source={adFrameSource}
containerStyle={styles.textAdFrame}
style={[styles.textAdFrame, { aspectRatio: adFrameAspectRatio }]}
onError={handleAdFrameError}
onError={onError}
onMessage={handleAdFrameMessage}
webviewDebuggingEnabled={__DEV__}
scrollEnabled={false}
Expand Down
76 changes: 35 additions & 41 deletions src/components/optimal-promotion/index.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,69 @@
import React, { FC, useCallback, useEffect, useRef, useState } from 'react';
import FastImage from 'react-native-fast-image';
import useSWR from 'swr';

import { ImagePromotionView } from 'src/components/image-promotion-view';
import { TextPromotionView } from 'src/components/text-promotion-view';
// import { PROMO_SYNC_INTERVAL } from 'src/config/fixed-times';
import { PromotionVariantEnum } from 'src/enums/promotion-variant.enum';
import {
usePartnersPromoErrorSelector,
usePartnersPromoLoadingSelector,
usePartnersPromoSelector
} from 'src/store/partners-promotion/partners-promotion-selectors';
import { useCurrentAccountPkhSelector } from 'src/store/wallet/wallet-selectors';
import { SingleProviderPromotionProps } from 'src/types/promotion';
import { useTimeout } from 'src/utils/hooks';
import { isDefined } from 'src/utils/is-defined';
import { useIsEmptyPromotion } from 'src/utils/optimal.utils';
import { getOptimalPromotion, OptimalPromotionAdType, useIsEmptyPromotion } from 'src/utils/optimal.utils';

import { useOptimalPromotionStyles } from './styles';

export const OptimalPromotion: FC<SingleProviderPromotionProps> = ({
interface SelfRefreshingPromotionProps {
shouldRefreshAd: boolean;
}

export const OptimalPromotion: FC<SingleProviderPromotionProps & SelfRefreshingPromotionProps> = ({
variant,
isVisible,
shouldShowCloseButton,
// shouldRefreshAd,
onClose,
onReady,
onError,
...testIDProps
}) => {
const isImageAd = variant === PromotionVariantEnum.Image;
const styles = useOptimalPromotionStyles();
const promo = usePartnersPromoSelector();
const isLoading = usePartnersPromoLoadingSelector();
const errorFromStore = usePartnersPromoErrorSelector();
const [isImageBroken, setIsImageBroken] = useState(false);
const [wasLoading, setWasLoading] = useState(false);
const [shouldPreventShowingPrevAd, setShouldPreventShowingPrevAd] = useState(true);
const [adViewIsReady, setAdViewIsReady] = useState(isImageAd);
const prevIsLoadingRef = useRef(isLoading);
const promotionIsEmpty = useIsEmptyPromotion(promo);
const apiQueryFailed = (isDefined(errorFromStore) || promotionIsEmpty) && wasLoading;
const adIsNotLikelyToLoad = (isDefined(errorFromStore) || promotionIsEmpty) && !isLoading;
const accountPkh = useCurrentAccountPkhSelector();

useTimeout(
() => {
if (adIsNotLikelyToLoad) {
onError();
}
},
2000,
[adIsNotLikelyToLoad, onError]
const localGetOptimalPromotion = useCallback(
() => getOptimalPromotion(isImageAd ? OptimalPromotionAdType.TwMobile : OptimalPromotionAdType.TwToken, accountPkh),
[accountPkh, isImageAd]
);
const {
data: promo,
error,
isValidating,
mutate
} = useSWR(['optimal-promotion', accountPkh, isImageAd], localGetOptimalPromotion, {
// refreshInterval: shouldRefreshAd ? PROMO_SYNC_INTERVAL : undefined
});
const prevIsValidatingRef = useRef(isValidating);

useEffect(() => {
if (wasLoading) {
setShouldPreventShowingPrevAd(false);
}
}, [wasLoading]);
useTimeout(() => setShouldPreventShowingPrevAd(false), 2000, []);
const [isImageBroken, setIsImageBroken] = useState(false);
const [adViewIsReady, setAdViewIsReady] = useState(isImageAd);
const promotionIsEmpty = useIsEmptyPromotion(promo);

useEffect(() => {
if (!isLoading && prevIsLoadingRef.current) {
setWasLoading(true);
if (!isValidating) {
mutate();
}
prevIsLoadingRef.current = isLoading;
}, [isLoading]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
if (apiQueryFailed) {
if (isDefined(error) || promotionIsEmpty) {
onError();
} else if (!promotionIsEmpty && !shouldPreventShowingPrevAd && adViewIsReady) {
} else if (!promotionIsEmpty && promo && adViewIsReady) {
onReady();
}
}, [apiQueryFailed, onError, onReady, promotionIsEmpty, shouldPreventShowingPrevAd, adViewIsReady]);
prevIsValidatingRef.current = isValidating;
}, [onError, onReady, promotionIsEmpty, adViewIsReady, error, promo, isValidating]);

const onImageError = useCallback(() => {
setIsImageBroken(true);
Expand All @@ -78,7 +72,7 @@ export const OptimalPromotion: FC<SingleProviderPromotionProps> = ({

const handleTextPromotionReady = useCallback(() => setAdViewIsReady(true), []);

if (isDefined(errorFromStore) || promotionIsEmpty || isImageBroken || shouldPreventShowingPrevAd) {
if (isDefined(error) || promotionIsEmpty || isImageBroken || !promo) {
return null;
}

Expand Down
21 changes: 21 additions & 0 deletions src/components/promotion-item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import { StyleProp, View, ViewProps, ViewStyle } from 'react-native';
import { ActivityIndicator } from 'src/components/activity-indicator';
import { HypelabPromotion } from 'src/components/hypelab-promotion';
import { OptimalPromotion } from 'src/components/optimal-promotion';
import { PROMO_SYNC_INTERVAL } from 'src/config/fixed-times';
import { isAndroid } from 'src/config/system';
import { PromotionProviderEnum } from 'src/enums/promotion-provider.enum';
import { PromotionVariantEnum } from 'src/enums/promotion-variant.enum';
import { useAdTemporaryHiding } from 'src/hooks/use-ad-temporary-hiding.hook';
import { useAuthorisedInterval } from 'src/hooks/use-authed-interval';
import { TestIdProps } from 'src/interfaces/test-id.props';
import { useIsPartnersPromoEnabledSelector } from 'src/store/partners-promotion/partners-promotion-selectors';

Expand All @@ -17,6 +19,7 @@ import { usePromotionItemStyles } from './styles';
interface Props extends TestIdProps {
id: string;
style?: StyleProp<ViewStyle>;
shouldRefreshAd?: boolean;
shouldShowCloseButton?: boolean;
shouldTryHypelabAd?: boolean;
variant?: PromotionVariantEnum;
Expand All @@ -30,6 +33,7 @@ export const PromotionItem = forwardRef<View, Props>(
{
id,
style,
shouldRefreshAd = false,
shouldShowCloseButton = true,
variant = PromotionVariantEnum.Image,
shouldTryHypelabAd = true,
Expand Down Expand Up @@ -63,6 +67,22 @@ export const PromotionItem = forwardRef<View, Props>(
}
}, [isFocused]);

useAuthorisedInterval(
() => {
if (!shouldRefreshAd || !partnersPromotionEnabled || isHiddenTemporarily) {
return;
}

setAdsState({
currentProvider: PromotionProviderEnum.Optimal,
adError: false,
adIsReady: false
});
},
PROMO_SYNC_INTERVAL,
[partnersPromotionEnabled, isHiddenTemporarily, shouldRefreshAd]
);

const handleAdError = useCallback(() => {
setAdsState(prevState => ({ ...prevState, adError: true }));
onError && onError();
Expand Down Expand Up @@ -113,6 +133,7 @@ export const PromotionItem = forwardRef<View, Props>(
variant={variant}
isVisible={adIsReady}
shouldShowCloseButton={shouldShowCloseButton}
shouldRefreshAd={shouldRefreshAd}
onClose={hidePromotion}
onReady={handleOptimalAdReady}
onError={handleOptimalError}
Expand Down
20 changes: 17 additions & 3 deletions src/hooks/use-element-is-seen.hook.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useIsFocused } from '@react-navigation/native';
import { useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';

/**
* @param isVisible Indicates whether the element is visible right now, assuming that the screen is focused.
Expand All @@ -9,6 +9,7 @@ import { useEffect, useRef, useState } from 'react';
export const useElementIsSeen = (isVisible: boolean, seenTimeout: number, shouldResetOnScreenBlur = true) => {
const isFocused = useIsFocused();
const [isSeen, setIsSeen] = useState(false);
const resetWasCalledRef = useRef(false);
const isVisibleRef = useRef(isVisible);

useEffect(() => {
Expand All @@ -17,7 +18,7 @@ export const useElementIsSeen = (isVisible: boolean, seenTimeout: number, should
}
}, [isFocused, shouldResetOnScreenBlur]);

useEffect(() => {
const updateIsSeen = useCallback(() => {
isVisibleRef.current = isVisible && isFocused;

if (isVisible && isFocused) {
Expand All @@ -31,5 +32,18 @@ export const useElementIsSeen = (isVisible: boolean, seenTimeout: number, should
}
}, [isFocused, isVisible, seenTimeout]);

return isSeen;
const resetIsSeen = useCallback(() => {
setIsSeen(false);
resetWasCalledRef.current = true;
}, []);

useEffect(updateIsSeen, [updateIsSeen]);
useEffect(() => {
if (resetWasCalledRef.current) {
resetWasCalledRef.current = false;
updateIsSeen();
}
}, [updateIsSeen, isSeen]);

return { isSeen, resetIsSeen };
};
15 changes: 13 additions & 2 deletions src/hooks/use-internal-ads-analytics.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ export const useInternalAdsAnalytics = (
const { trackEvent } = useAnalytics();
const [adAreaIsVisible, setAdAreaIsVisible] = useState(false);
const [loadedPromotionProvider, setLoadedPromotionProvider] = useState<PromotionProviderEnum | undefined>();
const adIsSeen = useElementIsSeen(adAreaIsVisible && isDefined(loadedPromotionProvider), seenTimeout);
const { isSeen: adIsSeen, resetIsSeen: resetAdIsSeen } = useElementIsSeen(
adAreaIsVisible && isDefined(loadedPromotionProvider),
seenTimeout
);
const prevAdIsSeenRef = useRef(adIsSeen);

useEffect(() => {
Expand Down Expand Up @@ -96,6 +99,14 @@ export const useInternalAdsAnalytics = (
setLoadedPromotionProvider(undefined);
}, []);

const onAdLoad = useCallback(
(provider: PromotionProviderEnum) => {
resetAdIsSeen();
setLoadedPromotionProvider(provider);
},
[setLoadedPromotionProvider, resetAdIsSeen]
);

const {
onListScroll,
onElementLayoutChange: onInsideScrollAdLayout,
Expand All @@ -107,7 +118,7 @@ export const useInternalAdsAnalytics = (
onInsideScrollAdLayout,
onListLayoutChange,
onOutsideOfScrollAdLayout,
onAdLoad: setLoadedPromotionProvider,
onAdLoad,
resetAdState
};
};
35 changes: 0 additions & 35 deletions src/hooks/use-partners-promo.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';

import { PROMO_SYNC_INTERVAL } from 'src/config/fixed-times';
import { loadPartnersPromoActions } from 'src/store/partners-promotion/partners-promotion-actions';
import { useIsPartnersPromoEnabledSelector } from 'src/store/partners-promotion/partners-promotion-selectors';
import { useIsEnabledAdsBannerSelector } from 'src/store/settings/settings-selectors';
import { OptimalPromotionAdType } from 'src/utils/optimal.utils';

import { useAdTemporaryHiding } from './use-ad-temporary-hiding.hook';
import { useAuthorisedInterval } from './use-authed-interval';

export const useIsPartnersPromoShown = (id: string) => {
const areAdsNotEnabled = useIsEnabledAdsBannerSelector();
Expand All @@ -17,31 +10,3 @@ export const useIsPartnersPromoShown = (id: string) => {

return isEnabled && !areAdsNotEnabled && !isHiddenTemporarily;
};

export const usePartnersPromoLoad = (id: string) => {
const promoIsShown = useIsPartnersPromoShown(id);

const dispatch = useDispatch();

useEffect(() => {
if (promoIsShown) {
dispatch(loadPartnersPromoActions.submit(OptimalPromotionAdType.TwMobile));
}
}, [dispatch, promoIsShown]);
};

export const usePartnersPromoSync = (id: string) => {
const promoIsShown = useIsPartnersPromoShown(id);

const dispatch = useDispatch();

useAuthorisedInterval(
() => {
if (promoIsShown) {
dispatch(loadPartnersPromoActions.submit(OptimalPromotionAdType.TwMobile));
}
},
PROMO_SYNC_INTERVAL,
[promoIsShown]
);
};
4 changes: 1 addition & 3 deletions src/screens/d-apps/promotion-carousel/promotion-carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { CarouselRenderItemInfo } from 'react-native-reanimated-carousel/li
import { PromotionItem } from 'src/components/promotion-item';
import { useInternalAdsAnalytics } from 'src/hooks/use-internal-ads-analytics.hook';
import { useLayoutSizes } from 'src/hooks/use-layout-sizes.hook';
import { useIsPartnersPromoShown, usePartnersPromoLoad } from 'src/hooks/use-partners-promo';
import { useIsPartnersPromoShown } from 'src/hooks/use-partners-promo';
import { useActivePromotionSelector } from 'src/store/advertising/advertising-selectors';
import { formatSize } from 'src/styles/format-size';
import { isDefined } from 'src/utils/is-defined';
Expand All @@ -31,8 +31,6 @@ export const PromotionCarousel = () => {
const refs = useMemo(() => ({ parent: layoutRef, element: adRef }), [layoutRef, adRef]);
const { onOutsideOfScrollAdLayout, onAdLoad } = useInternalAdsAnalytics('DApps', refs, promotionOffset, 500);

usePartnersPromoLoad(PROMOTION_ID);

const data = useMemo<Array<JSX.Element>>(() => {
const result = [...COMMON_PROMOTION_CAROUSEL_DATA];

Expand Down
5 changes: 1 addition & 4 deletions src/screens/market/market.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@ import { useDispatch } from 'react-redux';
import { HeaderCard } from 'src/components/header-card/header-card';
import { MARKET_SYNC_INTERVAL } from 'src/config/fixed-times';
import { useAuthorisedInterval } from 'src/hooks/use-authed-interval';
import { usePartnersPromoSync } from 'src/hooks/use-partners-promo';
import { ScreensEnum } from 'src/navigator/enums/screens.enum';
import { loadMarketTokensSlugsActions } from 'src/store/market/market-actions';
import { usePageAnalytic } from 'src/utils/analytics/use-analytics.hook';

import { TezosInfo } from './tezos-info/tezos-info';
import { PROMOTION_ID, TopTokensTable } from './top-coins-table/top-tokens-table';
import { TopTokensTable } from './top-coins-table/top-tokens-table';

export const Market = () => {
const dispatch = useDispatch();

useAuthorisedInterval(() => dispatch(loadMarketTokensSlugsActions.submit()), MARKET_SYNC_INTERVAL);

usePartnersPromoSync(PROMOTION_ID);

usePageAnalytic(ScreensEnum.Market);

return (
Expand Down
Loading

0 comments on commit 76ba8d9

Please sign in to comment.