Files
discord-decomp/modules/quests/native/BountiesModal/BountiesModalContent.tsx
T
2026-11-01 12:12:55 +02:00

263 lines
13 KiB
TypeScript

// Metro module 14087 (f14088).
import { useMemo, useCallback } from "react";
import { View } from "react-native";
import BountyStore from "../../BountyStore";
import { QuestsExperimentLocations } from "../../QuestConstants";
import { AnalyticEvents } from "../../../../Constants";
import { ThemeTypes } from "../../../../_bundle/Module505";
import useWindowDimensions_native from "../../../screen/useWindowDimensions.native";
import useSafeAreaInsets_native from "../../../safe_area/useSafeAreaInsets.native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import { useStateFromStores } from "../../../../_bundle/Module589";
import { useFetchVirtualCurrencyBalance } from "../../../virtual_currency/hooks/index";
import { useBountiesExperience } from "../../experiments/useBountiesExperience";
import { BountyVideoEndMode, useBountiesModalTiming } from "./useBountiesModalTiming";
import { useBountyVideoProgressPersistence } from "./useBountyVideoProgressPersistence";
import { claimBountyReward } from "../../BountyActionCreators";
import { openBountyRewardClaimErrorToast } from "./bountyError";
import { useBountiesModalVideoAnalytics } from "./useBountiesModalVideoAnalytics";
import { trackAdContentEvent } from "../../lib/analytics/AnalyticsActions";
import { AdCreativeType } from "../../../../_bundle/Module6013";
import { getQuestContentName } from "../../lib/analytics/AnalyticsTypes";
import { QuestContent } from "../../../../_bundle/Module5038";
import { formatVideoProgressRatio } from "../../utils/VideoQuestUtils";
import BountiesModalActionCreators from "./BountiesModalActionCreators";
import { BountyVideo } from "./BountyVideo";
import { QuestContentImpressionTrackerNative, BillableAdPlacementImpressionTrackerNative } from "../QuestContentImpressionTracker.native";
import BountiesModalEndCard from "./BountiesModalEndCard";
import BountiesModalCloseButton from "./BountiesModalCloseButton";
import { SafeAreaPaddingView } from "../../../../components_native/common/SafeAreaView";
import BountiesModalEndedCtaButtons from "./BountiesModalEndedCtaButtons";
import { useQuestHomeBounties } from "../../hooks/QuestHooks";
import { ThemeContextProvider } from "../../../../_bundle/Module3901";
let c9854_13, useStyles;
const BountiesModalContentInner = function BountiesModalContentInner(props) {
let c20892_4, handleProgress, flushProgress, handleVideoProgressAnalytics, isEndCardVisible, maxVideoProgressSeconds, videoDuration;
const { bounty, sourceQuestContent } = props;
c20892_4 = void 0;
handleProgress = void 0;
flushProgress = void 0;
handleVideoProgressAnalytics = void 0;
isEndCardVisible = void 0;
maxVideoProgressSeconds = void 0;
videoDuration = void 0;
const styles = useStyles();
const windowDimensions_native = useWindowDimensions_native();
const { width, height } = windowDimensions_native;
const safeAreaInsets_native = useSafeAreaInsets_native();
let c20893_2 = safeAreaInsets_native;
const memo = useMemo(() => {
const r11 = width - c20893_2.left - c20893_2.right;
const r13 = height - c20893_2.top - c20893_2.bottom;
let r21 = r11 / c9854_13;
let isFullWidth = true;
let r9 = r11;
if (r21 > r13) {
r9 = r13 * c9854_13;
isFullWidth = false;
r21 = r13;
}
return {
top: Math.floor(c20893_2.top + (r13 - r21) / 2),
left: Math.floor(c20893_2.left + (r11 - r9) / 2),
width: Math.floor(r9),
height: Math.floor(r21),
isFullWidth
};
}, [width, height, safeAreaInsets_native.top, safeAreaInsets_native.bottom, safeAreaInsets_native.left, safeAreaInsets_native.right]);
const memo4 = useMemo(() => [styles.videoWrapper, {
top: memo.top,
left: memo.left,
width: memo.width,
height: memo.height
}], [styles.videoWrapper, memo]);
const memo3 = useMemo(() => [styles.closeButton, {
top: memo.top + Module712.space.PX_8,
left: memo.left + memo.width - Module712.space.PX_32 - Module712.space.PX_8
}], [styles.closeButton, memo.top, memo.left, memo.width]);
const memo2 = useMemo(() => {
const isFullWidth = memo.isFullWidth;
const bottomContainer = styles.bottomContainer;
return isFullWidth ? [bottomContainer, styles.bottomContainerFullWidth] : [bottomContainer, styles.bottomContainerNotFullWidth, {
left: memo.left,
width: memo.width
}];
}, [styles.bottomContainer, styles.bottomContainerFullWidth, styles.bottomContainerNotFullWidth, memo.isFullWidth, memo.left, memo.width]);
const stateFromStores = useStateFromStores([BountyStore], () => BountyStore.isBountyCompleted(bounty.id));
const balance = useFetchVirtualCurrencyBalance().balance;
const bountiesExperience = useBountiesExperience(QuestsExperimentLocations.VIDEO_MODAL_MOBILE);
const { loopingEnabled, ownedByVerticalScrollExperiment, stage1Enabled, rewardTimerSeconds } = bountiesExperience;
const endMode = loopingEnabled ? BountyVideoEndMode.LOOP : BountyVideoEndMode.END_CARD;
const rewardDurationMs = !stage1Enabled && !ownedByVerticalScrollExperiment ? 1000 * bounty.rewardTimerSeconds : 1000 * rewardTimerSeconds;
c20892_4 = rewardDurationMs;
const bountyVideoProgressPersistence = useBountyVideoProgressPersistence({
bountyId: bounty.id,
endMode
});
const initialProgress = bountyVideoProgressPersistence.initialProgress;
handleProgress = bountyVideoProgressPersistence.handleProgress;
flushProgress = bountyVideoProgressPersistence.flushProgress;
const callback = useCallback(async () => {
let c27624_2;
let c27624_3 = 0;
let c30697_0;
L10: {
try {
c27624_3 = 1;
await claimBountyReward(bounty.id, sourceQuestContent);
c27624_3 = 0;
} catch ($e) {
const r24 = $e;
let r7 = r24;
c27624_2 = r24;
if (c27624_3 !== 0) {
while (true) {
try {
const r57 = c27624_2;
c27624_3 = 0;
c30697_0 = r57;
openBountyRewardClaimErrorToast(c30697_0);
break L10;
} catch (r53) {
r7 = r53;
c27624_2 = r53;
if (c27624_3 === 0) {
break;
}
}
}
}
throw r7;
}
}
}, [bounty.id, sourceQuestContent]);
const bountiesModalVideoAnalytics = useBountiesModalVideoAnalytics({
bountyId: bounty.id,
sourceQuestContent,
rewardDurationMs,
initialPlaybackTimeSec: initialProgress.timestampSec,
initialMaxVideoProgressSec: initialProgress.maxTimestampSec,
initialVideoDurationSec: initialProgress.duration,
wasPreloaded: false,
startupPath: "carousel",
verticalScrollingPosition: null
});
handleVideoProgressAnalytics = bountiesModalVideoAnalytics.handleVideoProgressAnalytics;
const { handleVideoEndAnalytics, handleVideoLoopedAnalytics, handleVideoPausedAnalytics, handleVideoResumedAnalytics, handleVideoErrorAnalytics, handleLoadStartAnalytics, handleVideoTracksAnalytics, handleReadyForDisplayAnalytics, handleBufferAnalytics } = bountiesModalVideoAnalytics;
const bountiesModalTiming = useBountiesModalTiming({
endMode,
rewardDurationMs,
isCompleted: stateFromStores,
onRewardEarned: callback,
onVideoProgress: useCallback((a0, a1, a2) => {
handleVideoProgressAnalytics(a0, a1, a2);
handleProgress(a0, a1, a2);
}, [handleVideoProgressAnalytics, handleProgress]),
onVideoEnd: handleVideoEndAnalytics,
onVideoLooped: handleVideoLoopedAnalytics,
onVideoPaused: handleVideoPausedAnalytics,
onVideoResumed: handleVideoResumedAnalytics,
initialProgressSec: initialProgress.timestampSec,
initialMaxVideoProgressSec: initialProgress.maxTimestampSec,
initialVideoDurationSec: initialProgress.duration > 0 ? initialProgress.duration : null
});
const isCtaVisible = bountiesModalTiming.isCtaVisible;
isEndCardVisible = bountiesModalTiming.isEndCardVisible;
const { handleVideoEnd, handleVideoProgress, handleVideoPaused, handleVideoResumed, rewardRemainingSeconds, rewardTotalSeconds, normalizedProgress } = bountiesModalTiming;
maxVideoProgressSeconds = bountiesModalTiming.maxVideoProgressSeconds;
videoDuration = bountiesModalTiming.videoDuration;
return <>
<View style={memo4}>
<BountyVideo isActive bounty={bounty} sourceQuestContent={sourceQuestContent} isCompleted={stateFromStores} isCtaVisible={isCtaVisible} isEndCardVisible={isEndCardVisible} isProgressBarVisible={!isEndCardVisible} orbsBalance={balance} handleVideoEnd={handleVideoEnd} handleVideoProgress={handleVideoProgress} handleVideoPaused={handleVideoPaused} handleVideoResumed={handleVideoResumed} handleVideoError={handleVideoErrorAnalytics} onLoadStart={handleLoadStartAnalytics} onBuffer={handleBufferAnalytics} onFirstFrame={handleReadyForDisplayAnalytics} onVideoTracks={handleVideoTracksAnalytics} rewardRemainingSeconds={rewardRemainingSeconds} rewardTotalSeconds={rewardTotalSeconds} normalizedProgress={normalizedProgress} repeat={loopingEnabled} initialProgress={initialProgress} renderEndCard={() => <QuestContentImpressionTrackerNative adContentId={bounty.id} adCreativeType={AdCreativeType.BOUNTY} questContent={QuestContent.VIDEO_MODAL_END_CARD} sourceQuestContent={sourceQuestContent} overrideVisibility={isEndCardVisible}>
{() => <BountiesModalEndCard bounty={bounty} visible={isEndCardVisible} sourceQuestContent={sourceQuestContent} />}
</QuestContentImpressionTrackerNative>} isScrollIndicatorEnabled={false} width={memo.width} height={memo.height} />
</View>
<View style={memo3}>
<BountiesModalCloseButton onPress={useCallback(() => {
const properties = {
content_name: getQuestContentName(QuestContent.VIDEO_MODAL_MOBILE),
content_id: QuestContent.VIDEO_MODAL_MOBILE,
video_progress: null,
threshold_met: null,
reward_timer_seconds: null
};
let r38 = videoDuration;
if (videoDuration == null) {
r38 = 0;
}
properties.video_progress = formatVideoProgressRatio(maxVideoProgressSeconds, r38);
const r1 = 1000 * maxVideoProgressSeconds;
properties.threshold_met = r1 >= c20892_4;
properties.reward_timer_seconds = c20892_4 / 1000;
trackAdContentEvent({
adContentId: bounty.id,
adCreativeType: AdCreativeType.BOUNTY,
event: AnalyticEvents.AD_VIDEO_MODAL_CLOSED,
properties,
sourceQuestContent
});
flushProgress();
BountiesModalActionCreators.hideModal();
}, [bounty.id, maxVideoProgressSeconds, rewardDurationMs, sourceQuestContent, videoDuration, flushProgress])} />
</View>
<SafeAreaPaddingView left={memo.isFullWidth} right={memo.isFullWidth} bottom style={memo2} pointerEvents="box-none">
<BountiesModalEndedCtaButtons bounty={bounty} visible={isEndCardVisible} sourceQuestContent={sourceQuestContent} onClose={useCallback(() => {
const properties = {
content_name: getQuestContentName(QuestContent.VIDEO_MODAL_END_CARD),
content_id: QuestContent.VIDEO_MODAL_END_CARD,
video_progress: null,
threshold_met: true,
reward_timer_seconds: null
};
let r36 = videoDuration;
if (videoDuration == null) {
r36 = 0;
}
properties.video_progress = formatVideoProgressRatio(maxVideoProgressSeconds, r36);
properties.reward_timer_seconds = c20892_4 / 1000;
trackAdContentEvent({
adContentId: bounty.id,
adCreativeType: AdCreativeType.BOUNTY,
event: AnalyticEvents.AD_VIDEO_MODAL_CLOSED,
properties,
sourceQuestContent
});
flushProgress();
BountiesModalActionCreators.hideModal();
}, [bounty.id, maxVideoProgressSeconds, rewardDurationMs, sourceQuestContent, videoDuration, flushProgress])} />
</SafeAreaPaddingView>
</>;
};
c9854_13 = 0.5625;
useStyles = createStyles(() => ({
videoWrapper: {
position: "absolute"
},
closeButton: {
position: "absolute"
},
bottomContainer: {
position: "absolute",
bottom: Module712.space.PX_24,
justifyContent: "flex-end"
},
bottomContainerFullWidth: {
left: Module712.space.PX_16,
right: Module712.space.PX_16
},
bottomContainerNotFullWidth: {
paddingLeft: Module712.space.PX_16,
paddingRight: Module712.space.PX_16
}
}));
export default function BountiesModalContent(props) {
const { bountyId, sourceQuestContent: sourceQuestContent2 } = props;
const bounty2 = useQuestHomeBounties().questHomeBounties.find((questHomeBounty) => questHomeBounty.id === bountyId);
return bounty2 != null ? <ThemeContextProvider theme={ThemeTypes.DARKER}>
<BillableAdPlacementImpressionTrackerNative adContentId={bounty2.id} adCreativeType={AdCreativeType.BOUNTY} questContent={QuestContent.VIDEO_MODAL_MOBILE} sourceQuestContent={sourceQuestContent2} overrideVisibility>
{() => <BountiesModalContentInner bounty={bounty2} sourceQuestContent={sourceQuestContent2} />}
</BillableAdPlacementImpressionTrackerNative>
</ThemeContextProvider> : null;
};