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

443 lines
19 KiB
TypeScript

// Metro module 14032 (f14033).
import * as Module19 from "react";
import { useCallback, useMemo, useEffect, useRef, useState } from "react";
import { ActivityIndicator, View, StyleSheet } from "react-native";
import AccessibilityStore from "../../a11y/AccessibilityStore";
import QuestHomeNavigationStore from "../QuestHomeNavigationStore";
import QuestStore from "../QuestStore";
import QuestUtmStore from "../QuestUtmStore";
import { QuestsExperimentLocations } from "../QuestConstants";
import { AnalyticEvents, UserSettingsSections } from "../../../Constants";
import { createStyles } from "../../../design/components/Styles/native/createStyles";
import Module712 from "../../../_bundle/Module712";
import { useStateFromStoresArray, useStateFromStores } from "../../../_bundle/Module589";
import { useNavigation } from "../../../design/components/Navigator/native/useNavigation.native";
import BountiesModalActionCreators, { BOUNTIES_MODAL_KEY } from "./BountiesModal/BountiesModalActionCreators";
import Dispatcher from "../../../Dispatcher";
import { fireSurveyAction } from "../../qualtrics/QualtricsActionCreators";
import { SurveyActionTypes } from "../../../_bundle/Module9280";
import QuestHomeEmptyState from "./QuestHomeEmptyState";
import { Button } from "../../../design/components/Button/native/Button.native";
import { intl, t } from "../../../intl/index.native";
import ModalActionCreators from "../../../actions/ModalActionCreators";
import { openUserSettings } from "../../user_settings/core/native/openUserSettings";
import { useShouldShowPreviewToolTab, useFilteredQuests, QuestTabs, useQuestHomeSortingFilteringAnalytics, useFetchQuestHomeBounties } from "../hooks/QuestHooks";
import { useBountiesExperience } from "../experiments/useBountiesExperience";
import { Text } from "../../../design/components/Text/native/Text";
import { PressableOpacity } from "../../../design/void/Pressables/native/Pressables";
import openBountiesNuxPromoSheet from "./openBountiesNuxPromoSheet";
import { CircleInformationIcon } from "../../../design/components/Icon/native/redesign/generated/CircleInformationIcon";
import QuestHomeBounties from "./QuestHomeBounties";
import { getIsEligibleForQuests } from "../lib/QuestsEligibility";
import useSafeAreaInsets_native from "../../safe_area/useSafeAreaInsets.native";
import { isQuestExpired, findQuestOrReplacement } from "../utils/QuestDataUtils";
import { markAdContentSeen } from "../QuestActionCreators";
import { AdCreativeType } from "../../../_bundle/Module6013";
import ToastActionCreators from "../../toast/native/ToastActionCreators";
import Module9172 from "../../../_bundle/Module9172";
import AnalyticsUtils from "../../../utils/AnalyticsUtils";
import useTrackImpression from "../../app_analytics/useTrackImpression";
import { ImpressionNames, ImpressionTypes } from "../../../_bundle/Module503";
import { QuestHomeOpenTriggerPoint } from "../../experiments/trigger_points/QuestHomeOpenTriggerPoint";
import { useVirtualCurrencyMobileEnabled } from "../../virtual_currency/hooks/native/useVirtualCurrencyMobileEnabled";
import { OrbsHoldoutExperiment } from "../experiments/OrbsHoldoutExperiment";
import { useRoute } from "../../../_bundle/Module1481";
import { QuestContent } from "../QuestTypes";
import * as _QuestUtils from "../utils/QuestUtils";
import { BountiesShopCarouselExperiment } from "../experiments/BountiesShopCarouselExperiment";
import { useQuestHomeOrbShopCarouselData } from "./QuestHomeOrbShopCarousel";
import { QuestContentImpressionTrackerNative } from "./QuestContentImpressionTracker.native";
import { QuestCard } from "./QuestCard";
import QuestHomeRoundtripTracker from "../QuestHomeRoundtripTracker";
import { FlashList } from "../../../_bundle/noop_6676";
let useStyles, EmptyStateFiltered, HeaderPreviewButton, HeaderWithBounties, Component;
const EmptyStateNoQuestsAvailable = function EmptyStateNoQuestsAvailable() {
const navigation = useNavigation();
const callback5 = useCallback(() => navigation.goBack(), [navigation]);
return <QuestHomeEmptyState action={<Button variant="secondary" text={intl.string(t["/g10LC"])} onPress={callback5} />} />;
};
EmptyStateFiltered = function EmptyStateFiltered(props) {
const onClearFilters = props.onClearFilters;
return <QuestHomeEmptyState action={<Button variant="secondary" text={intl.string(t.urZl31)} onPress={onClearFilters} />} title={intl.string(t.PBfFnx)} subtitle={intl.string(t.nwdKFC)} />;
};
HeaderPreviewButton = function HeaderPreviewButton() {
const styles = useStyles();
const callback5 = useCallback(() => {
ModalActionCreators.popAll();
openUserSettings({
screen: UserSettingsSections.QUEST_PREVIEW_TOOL_2
});
}, []);
return useShouldShowPreviewToolTab() ? <View style={styles.previewButton}>
<Button grow onPress={callback5} variant="primary" text={intl.string(t.tx5Ax5)} />
</View> : null;
};
HeaderWithBounties = function HeaderWithBounties(props) {
const { orbShopProducts, obtainableOrbRewards: obtainableOrbRewards2, showOrbShopPlaceholderCarousel } = props;
const styles = useStyles();
const verticalScrollEnabled2 = useBountiesExperience(QuestsExperimentLocations.QUEST_HOME_MOBILE).verticalScrollEnabled;
return <>
<HeaderPreviewButton />
{verticalScrollEnabled2 ? !verticalScrollEnabled2 : <View style={[styles.sectionHeader, styles.sectionHeaderRow]}>
<Text variant="text-lg/semibold" color="text-strong">
{intl.string(t.qetVDw)}
</Text>
<PressableOpacity onPress={openBountiesNuxPromoSheet} hitSlop={14} aria-label={intl.string(t.hvVgAZ)} accessibilityRole="button">
<CircleInformationIcon size="xs" color={Module712.colors.ICON_SUBTLE} />
</PressableOpacity>
</View>}
<QuestHomeBounties verticalScrollEnabled={verticalScrollEnabled2} orbShopProducts={orbShopProducts} obtainableOrbRewards={obtainableOrbRewards2} showOrbShopPlaceholderCarousel={showOrbShopPlaceholderCarousel} />
<View style={[styles.sectionHeader, styles.sectionHeaderWithTag]}>
<Text variant="text-lg/semibold" color="text-strong">
{intl.string(t.JALI2K)}
</Text>
</View>
</>;
};
useStyles = createStyles({
container: {
flex: 1
},
loadingContainer: {
...StyleSheet.absoluteFillObject,
justifyContent: "center",
alignItems: "center"
},
sectionHeader: {
marginBottom: Module712.space.PX_16,
paddingHorizontal: Module712.space.PX_16
},
sectionHeaderRow: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_4
},
previewButton: {
marginBottom: Module712.space.PX_16,
paddingHorizontal: Module712.space.PX_16,
backgroundColor: "transparent"
},
sectionHeaderWithTag: {
gap: Module712.space.PX_4
}
});
Component = Module19.memo(function({ shouldShowBounties, onLayout: onLayout2, orbShopProducts, obtainableOrbRewards: obtainableOrbRewards2, showOrbShopPlaceholderCarousel }) {
return <View onLayout={onLayout2}>
{shouldShowBounties ? <HeaderWithBounties orbShopProducts={orbShopProducts} obtainableOrbRewards={obtainableOrbRewards2} showOrbShopPlaceholderCarousel={showOrbShopPlaceholderCarousel} /> : <HeaderPreviewButton />}
</View>;
});
const r91 = Module19.memo(function QuestHome(props) {
let quests, excludedQuests, isFetchingCurrentQuests, hasFetched, stateFromStoresArray, ref, ref2, callback, callback2, ref3, verticalScrollEnabled, previewAdCreativeIds, isLoading, questHomeBounties, shouldShowBountiesGivenFilters, products, obtainableOrbRewards, showPlaceholderCarousel, c20857_22, ref4;
let memo, stateFromStores, ref5, ref6, callback3, state, setState, callback4;
const { containerStyle, isNavigationComplete, scrollToQuestId, filters, sortMethod, onClearFilters } = props;
quests = void 0;
excludedQuests = void 0;
isFetchingCurrentQuests = void 0;
hasFetched = void 0;
stateFromStoresArray = void 0;
ref = void 0;
ref2 = void 0;
callback = void 0;
callback2 = void 0;
ref3 = void 0;
verticalScrollEnabled = void 0;
previewAdCreativeIds = void 0;
isLoading = void 0;
questHomeBounties = void 0;
shouldShowBountiesGivenFilters = void 0;
products = void 0;
obtainableOrbRewards = void 0;
showPlaceholderCarousel = void 0;
c20857_22 = void 0;
ref4 = void 0;
const isEligibleForQuests = getIsEligibleForQuests();
const styles = useStyles();
const bottom = useSafeAreaInsets_native().bottom;
const filteredQuests = useFilteredQuests(QuestTabs.ALL, useMemo(() => ({
filters,
sortMethod
}), [filters, sortMethod]));
quests = filteredQuests.quests;
excludedQuests = filteredQuests.excludedQuests;
let isFetchingCurrentQuests2 = filteredQuests.isFetchingCurrentQuests;
isFetchingCurrentQuests = isFetchingCurrentQuests2;
hasFetched = filteredQuests.hasFetched;
stateFromStoresArray = useStateFromStoresArray([QuestStore], () => Array.from(QuestStore.quests.values()).filter((item) => !isQuestExpired(item)).map((item) => item.id).sort(), []);
useEffect(() => {
if (stateFromStoresArray.length > 0) {
markAdContentSeen(AdCreativeType.QUEST, stateFromStoresArray);
}
}, [stateFromStoresArray]);
ref = useRef(null);
const memo2 = useMemo(() => {
if (scrollToQuestId == null) {
return null;
}
const r13 = findQuestOrReplacement(scrollToQuestId, quests, excludedQuests);
let c27612_0 = r13;
return r13 == null ? null : quests.findIndex((quest) => quest.id === c27612_0.id);
}, [scrollToQuestId, quests, excludedQuests]);
useEffect(() => {
if (scrollToQuestId != null && scrollToQuestId !== "" && hasFetched && !isFetchingCurrentQuests && findQuestOrReplacement(scrollToQuestId, quests, excludedQuests) == null && ref.current !== scrollToQuestId) {
ToastActionCreators.open({
key: "QUEST_HOME_MOBILE_DEEP_LINK_QUEST_NOT_FOUND",
content: intl.string(t.sIyHuY),
icon: Module9172,
toastDurationMs: 5000
});
AnalyticsUtils.track(AnalyticEvents.QUEST_HOME_MOBILE_DEEP_LINK_MISSING_QUEST, {
quest_id: scrollToQuestId
});
ref.current = scrollToQuestId;
}
}, [scrollToQuestId, quests, excludedQuests, hasFetched, isFetchingCurrentQuests]);
memo = memo2;
stateFromStores = void 0;
ref5 = void 0;
ref6 = void 0;
callback3 = void 0;
state = void 0;
setState = void 0;
callback4 = void 0;
stateFromStores = useStateFromStores([AccessibilityStore], () => AccessibilityStore.useReducedMotion);
ref5 = useRef(null);
ref6 = useRef({
parent: {
scrollY: 0
},
children: {}
});
callback3 = useCallback((a0) => {
for (const item2 of Object.keys(ref6.current.children)) {
if (!(a0 != null && item2 !== a0)) {
const r36 = ref6.current.children[item2];
if (r36 != null) {
const calculateVisibility = r36.calculateVisibility;
if (calculateVisibility != null) {
calculateVisibility.call(r36);
}
}
}
}
}, []);
const callback5 = useCallback((a0) => {
ref6.current.parent.scrollY = a0.nativeEvent.contentOffset.y;
callback3();
}, [callback3]);
const callback6 = useCallback((a0) => {
ref6.current.parent.layout = a0.nativeEvent.layout;
callback3();
}, [callback3]);
[state, setState] = useState(false);
const callback7 = useCallback(() => {
setState(true);
}, []);
const callback8 = useCallback((a0, a1) => {
ref6.current.children[a1] = {
...ref6.current.children[a1],
layout: a0.nativeEvent.layout
};
callback3(a1);
}, [callback3]);
callback4 = useCallback((a0) => {
if (ref5.current != null) {
ref5.current.scrollToIndex({
index: a0,
animated: !stateFromStores,
viewOffset: Module712.space.PX_8
});
}
}, [stateFromStores]);
const callback9 = useCallback((a0) => {
ref6.current.parent.firstItemOffset = a0.nativeEvent.layout.height;
callback3();
}, [callback3]);
useEffect(() => {
if (memo != null && memo !== -1 && state) {
callback4(memo);
QuestHomeNavigationStore.setState({
scrollToQuestId: null
});
}
}, [state, stateFromStores, memo, callback4]);
ref2 = ref5;
callback = callback8;
callback2 = callback9;
ref3 = ref6;
const r123 = QuestUtmStore((a0) => a0.getUtmCurrentContext());
useTrackImpression({
name: ImpressionNames.QUEST_HOME,
type: ImpressionTypes.VIEW,
properties: {
utm_source_current: r123.utmSourceCurrent,
utm_medium_current: r123.utmMediumCurrent,
utm_campaign_current: r123.utmCampaignCurrent,
utm_content_current: r123.utmContentCurrent,
tab: QuestTabs.ALL
}
});
useEffect(() => {
if (isEligibleForQuests) {
QuestHomeOpenTriggerPoint.trigger();
}
}, [isEligibleForQuests]);
useEffect(() => {
if (ref2.current != null && hasFetched) {
ref2.current.scrollToOffset({
offset: 0,
animated: false
});
}
}, [filters, sortMethod, hasFetched, ref5]);
useQuestHomeSortingFilteringAnalytics({
selectedSortMethod: sortMethod,
selectedFilters: filters,
numQuestsVisible: quests.length
});
let enabled = useVirtualCurrencyMobileEnabled().enabled;
const bountiesExperience = useBountiesExperience(QuestsExperimentLocations.QUEST_HOME_MOBILE);
const showBounties = bountiesExperience.showBounties;
verticalScrollEnabled = bountiesExperience.verticalScrollEnabled;
const enabled2 = OrbsHoldoutExperiment.useConfig({
location: QuestsExperimentLocations.QUEST_HOME_MOBILE
}).enabled;
previewAdCreativeIds = useRoute().params?.previewAdCreativeIds;
const fetchQuestHomeBounties = useFetchQuestHomeBounties({
previewAdCreativeIds
});
isLoading = fetchQuestHomeBounties.isLoading;
questHomeBounties = fetchQuestHomeBounties.questHomeBounties;
useEffect(() => {
if (previewAdCreativeIds != null && previewAdCreativeIds.length !== 0 && verticalScrollEnabled && !isLoading) {
const r7 = questHomeBounties.find((questHomeBounty) => previewAdCreativeIds.includes(questHomeBounty.id));
if (r7 != null) {
BountiesModalActionCreators.showModal({
bountyId: r7.id,
sourceQuestContent: QuestContent.VIDEO_MODAL_MOBILE
});
}
}
}, [previewAdCreativeIds, verticalScrollEnabled, isLoading, questHomeBounties]);
if (enabled) {
enabled = showBounties;
}
if (enabled) {
enabled = !enabled2;
}
if (enabled) {
enabled = _QuestUtils.shouldShowBountiesGivenFilters(filters);
}
shouldShowBountiesGivenFilters = enabled;
const config = BountiesShopCarouselExperiment.useConfig({
location: QuestsExperimentLocations.QUEST_HOME_MOBILE
});
let enabled3 = config.enabled;
const variation = config.variation;
if (enabled3) {
enabled3 = shouldShowBountiesGivenFilters;
}
const questHomeOrbShopCarouselData = useQuestHomeOrbShopCarouselData({
enabled: enabled3,
variation
});
products = questHomeOrbShopCarouselData.products;
obtainableOrbRewards = questHomeOrbShopCarouselData.obtainableOrbRewards;
showPlaceholderCarousel = questHomeOrbShopCarouselData.showPlaceholderCarousel;
const r216 = (shouldShowBountiesGivenFilters ? !isLoading : shouldShowBountiesGivenFilters) && questHomeBounties.length > 0;
let c20859_0 = r216;
const navigation2 = useNavigation();
const ref7 = useRef(false);
const ref8 = useRef(false);
const ref9 = useRef(false);
useEffect(() => {
if (c20859_0) {
ref7.current = true;
}
}, [r216]);
useEffect(() => {
const handleBountiesModalPush2 = function handleBountiesModalPush(a0) {
if (a0.key === BOUNTIES_MODAL_KEY) {
ref8.current = true;
}
};
Dispatcher.subscribe("MODAL_PUSH", handleBountiesModalPush2);
return () => {
Dispatcher.unsubscribe("MODAL_PUSH", handleBountiesModalPush2);
};
}, []);
useEffect(() => {
const handleClaimSuccess2 = function handleClaimSuccess() {
ref9.current = true;
};
Dispatcher.subscribe("BOUNTIES_CLAIM_REWARD_SUCCESS", handleClaimSuccess2);
return () => {
Dispatcher.unsubscribe("BOUNTIES_CLAIM_REWARD_SUCCESS", handleClaimSuccess2);
};
}, []);
useEffect(() => navigation2.addListener("beforeRemove", () => {
if (ref7.current) {
if (ref9.current) {
fireSurveyAction(SurveyActionTypes.BOUNTY_SESSION_COMPLETED);
} else if (ref8.current) {
fireSurveyAction(SurveyActionTypes.BOUNTY_ABANDONED);
} else {
fireSurveyAction(SurveyActionTypes.BOUNTY_IMMEDIATE_DISMISSAL);
}
}
}), [navigation2]);
const callback10 = useCallback(() => <Component shouldShowBounties={shouldShowBountiesGivenFilters} onLayout={callback2} orbShopProducts={products} obtainableOrbRewards={obtainableOrbRewards} showOrbShopPlaceholderCarousel={showPlaceholderCarousel} />, [shouldShowBountiesGivenFilters, callback2, products, obtainableOrbRewards, showPlaceholderCarousel]);
const callback11 = useCallback(({ item, index }) => <QuestContentImpressionTrackerNative questOrQuests={item} questContent={QuestContent.QUEST_HOME_MOBILE} questContentPosition={index} trackGuildAndChannelMetadata={false} visibilityRef={ref3} skipRemountKey sourceQuestContent={QuestContent.QUEST_HOME_MOBILE}>
{() => <QuestCard quest={item} questContentPosition={index} containerPadding={0} sourceQuestContent={QuestContent.QUEST_HOME_MOBILE} />}
</QuestContentImpressionTrackerNative>, [ref6]);
const callback12 = useCallback((a0) => {
return <View {...a0} onLayout={(event) => {
const r7 = quests[a0.index];
if (r7 != null) {
callback(event, r7.id);
}
a0.onLayout(event);
}} />;
}, [quests, callback]);
let r257 = isNavigationComplete ? shouldShowBountiesGivenFilters ? isLoading : shouldShowBountiesGivenFilters : !isNavigationComplete;
if (!r257) {
if (isFetchingCurrentQuests) {
isFetchingCurrentQuests2 = quests.length === 0;
}
r257 = isFetchingCurrentQuests2;
}
c20857_22 = r257;
ref4 = useRef(shouldShowBountiesGivenFilters);
useEffect(() => {
ref4.current = shouldShowBountiesGivenFilters;
}, [shouldShowBountiesGivenFilters]);
useEffect(() => {
if (isEligibleForQuests) {
QuestHomeRoundtripTracker.startTracking({
includesBounties: ref4.current
});
return () => {
QuestHomeRoundtripTracker.clearTracking();
};
}
}, [isEligibleForQuests]);
useEffect(() => {
let r1 = isEligibleForQuests;
if (isEligibleForQuests) {
r1 = !c20857_22;
}
if (r1) {
QuestHomeRoundtripTracker.stopTracking({
includesBounties: ref4.current
});
}
}, [isEligibleForQuests, r257]);
const shouldShowPreviewToolTab = useShouldShowPreviewToolTab();
return isEligibleForQuests ? r257 ? <View style={[styles.loadingContainer, containerStyle]}>
<ActivityIndicator animating />
</View> : quests.length === 0 ? filters.length === 0 ? <EmptyStateNoQuestsAvailable /> : <EmptyStateFiltered onClearFilters={onClearFilters} /> : <FlashList ref={ref5} contentContainerStyle={{
paddingTop: verticalScrollEnabled ? shouldShowPreviewToolTab ? Module712.space.PX_16 : 0 : Module712.space.PX_16,
paddingBottom: bottom
}} style={[styles.container, containerStyle]} accessibilityLabel={intl.string(t.JALI2K)} data={quests} renderItem={callback11} showsHorizontalScrollIndicator={false} ListHeaderComponent={callback10} CellRendererComponent={callback12} onLayout={callback6} onScroll={callback5} onLoad={callback7} scrollEventThrottle={16} /> : null;
});
export default r91;