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

255 lines
12 KiB
TypeScript

// Metro module 14622 (f14623).
import { useMemo, useCallback } from "react";
import { Image as Image2, View } from "react-native";
import CollectiblesCategoryStore from "../CollectiblesCategoryStore";
import { CollectiblesMobileShopScreen } from "../CollectiblesShopConstants";
import { AnalyticEvents, UserSettingsSections, VerticalGradient } from "../../../Constants";
import CollectiblesShopCardV2, { COLLECTIBLES_SHOP_CARD_WIDTH } from "./CollectiblesShopCardV2";
import { createStyles } from "../../../design/components/Styles/native/createStyles";
import Module712 from "../../../_bundle/Module712";
import SkeletonCard from "./SkeletonCard";
import { useCollectiblesCoachmarkScrollDismissContext } from "./CollectiblesCoachmarkScrollDismissContext";
import { useNavigation } from "../../../design/components/Navigator/native/useNavigation.native";
import { useCollectiblesAnalyticsContext, CollectiblesAnalyticsProvider } from "../CollectiblesAnalyticsContext";
import { useStateFromStores } from "../../../_bundle/Module589";
import useTheme from "../../../hooks/useTheme";
import { useTrackProductCardImpression } from "../hooks/useTrackProductCardImpression";
import { useToken } from "../../../design/tokens/native/useToken";
import { hexToRgbaString, hexWithOpacity } from "../../../utils/ColorUtils";
import useGetProductsFromSkus from "../hooks/useGetProductsFromSkus";
import { useFilteredAndSortedProducts } from "./hooks/useFilteredAndSortedProducts";
import useAnalyticsLocations, { AnalyticsLocationProvider } from "../../app_analytics/useAnalyticsLocations";
import AnalyticsLocation from "../../app_analytics/AnalyticsLocation";
import FeaturedFirstCardCoachmarkAnchor from "./FeaturedFirstCardCoachmarkAnchor";
import AnalyticsUtils from "../../../utils/AnalyticsUtils";
import { isThemeDark } from "../../../design/shared";
import Module14617 from "../../../_bundle/Module14617";
import Module14618 from "../../../_bundle/Module14618";
import VisibilitySensor from "./VisibilitySensor";
import Module4611 from "../../../_bundle/Module4611";
import { Text } from "../../../design/components/Text/native/Text";
import { Button } from "../../../design/components/Button/native/Button.native";
import { intl, t } from "../../../intl/index.native";
import { openQuestHome } from "../../quests/native/QuestUtils.native";
import { QuestContent } from "../../../_bundle/Module5038";
import { PressableOpacity } from "../../../design/void/Pressables/native/Pressables";
import { ChevronSmallRightIcon } from "../../../design/components/Icon/native/redesign/generated/ChevronSmallRightIcon";
import { LayerScope } from "../../../design/components/Layers/native/LayerScope.native";
import FeedProductList from "./FeedProductList";
import { FlashList } from "../../../_bundle/noop_6676";
let useStyles;
const SkeletonLoading = function SkeletonLoading(props) {
const accessibilityLabel = props.accessibilityLabel;
return <View style={useStyles().skeletonContainer} accessibilityRole="list" accessibilityLabel={accessibilityLabel} accessibilityState={{
busy: true
}} accessible>
{Array.from({
length: 10
}).map((item, index) => <SkeletonCard key={index} width={COLLECTIBLES_SHOP_CARD_WIDTH} />)}
</View>;
};
useStyles = createStyles({
heroContainer: {
width: "100%"
},
heroBannerContainer: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
maxHeight: 240 + 0.75 * COLLECTIBLES_SHOP_CARD_WIDTH,
aspectRatio: 1.4883720930232558
},
heroBannerImage: {
width: "100%",
height: "100%",
resizeMode: "cover"
},
orbsBackgroundGradient: {
position: "absolute",
top: 0,
left: 0,
bottom: 0,
right: 0
},
fadeOutGradient: {
position: "absolute",
bottom: 0,
height: "50%",
width: "100%",
zIndex: 1
},
heroInfoContainer: {
display: "flex",
justifyContent: "center",
flex: 1,
minWidth: "100%",
maxHeight: 240,
aspectRatio: 2.2
},
innerContainer: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingHorizontal: Module712.space.PX_16,
width: "100%",
height: "100%"
},
heroLogoContainer: {
flex: 1,
maxWidth: "80%",
maxHeight: "80%"
},
heroLogo: {
resizeMode: "contain",
maxHeight: "100%",
maxWidth: "100%",
aspectRatio: 1
},
heroViewAllIcon: {
backgroundColor: Module712.colors.CONTROL_OVERLAY_SECONDARY_BACKGROUND_DEFAULT,
padding: Module712.space.PX_8,
borderRadius: Module712.radii.round
},
orbsInnerContainer: {
paddingHorizontal: Module712.space.PX_16,
alignItems: "flex-start",
gap: Module712.space.PX_16
},
orbsTitle: {
fontSize: 24,
lineHeight: 30
},
productCardsContainer: {
zIndex: 1
},
skeletonContainer: {
flexDirection: "row",
gap: Module712.space.PX_12,
paddingHorizontal: Module712.space.PX_16
}
});
export default ({ heroBlock, preferVCPrice, screen }) => {
let c21261_5, c21261_6;
c21261_5 = void 0;
c21261_6 = void 0;
const handleDismissCoachmarkOnScroll = useCollectiblesCoachmarkScrollDismissContext().handleDismissCoachmarkOnScroll;
const navigation = useNavigation();
const collectiblesAnalyticsContext = useCollectiblesAnalyticsContext();
let mobileHeroUrl = heroBlock.mobileHeroUrl;
if (mobileHeroUrl == null) {
mobileHeroUrl = heroBlock.heroBannerUrl;
}
const heroLogoUrl = heroBlock.heroLogoUrl;
const stateFromStores = useStateFromStores([CollectiblesCategoryStore], () => CollectiblesCategoryStore.getCategory(heroBlock.categorySkuId));
const bypassAndroidUnsyncedFilter = stateFromStores != null && stateFromStores.isOrbsExclusive;
const theme = useTheme();
const handleCardVisibilityChange = useTrackProductCardImpression(heroBlock.categoryStoreListingId, "mobile_home", "hero_block").handleCardVisibilityChange;
const styles = useStyles();
const r37 = hexToRgbaString(hexWithOpacity(useToken(Module712.colors.BACKGROUND_BASE_LOW), 0));
const token = useToken(Module712.colors.BACKGROUND_BASE_LOWEST);
const getProductsFromSkus = useGetProductsFromSkus();
c21261_5 = getProductsFromSkus;
const filteredAndSortedProducts = useFilteredAndSortedProducts({
products: useMemo(() => c21261_5(heroBlock.rankedSkuIds), [heroBlock.rankedSkuIds, getProductsFromSkus]),
bypassAndroidUnsyncedFilter
});
const r4 = screen === CollectiblesMobileShopScreen.FEATURED_PAGE;
c21261_6 = r4;
const analyticsLocations = useAnalyticsLocations(AnalyticsLocation.COLLECTIBLES_SHOP_HERO).analyticsLocations;
const callback = useCallback(({ item, index }) => {
const r18 = <CollectiblesShopCardV2 solidBackground product={item} unpublishedAt={stateFromStores?.unpublishedAt} preferVCPrice={preferVCPrice} />;
return <CollectiblesAnalyticsProvider newValue={{
tilePosition: index
}}>
{index === 0 ? c21261_6 ? <FeaturedFirstCardCoachmarkAnchor>{r18}</FeaturedFirstCardCoachmarkAnchor> : r18 : r18}
</CollectiblesAnalyticsProvider>;
}, [stateFromStores?.unpublishedAt, preferVCPrice, r4]);
if (stateFromStores === void 0) {
return null;
}
const r31 = heroBlock.mobileTitle != null ? heroBlock.mobileTitle : heroBlock.title;
const r32 = heroBlock.mobileSummary != null ? heroBlock.mobileSummary : heroBlock.summary;
if (bypassAndroidUnsyncedFilter) {
mobileHeroUrl = isThemeDark(theme) ? Module14617 : Module14618;
}
return <AnalyticsLocationProvider value={analyticsLocations}>
<VisibilitySensor onChange={handleCardVisibilityChange} resetKey={heroBlock.categoryStoreListingId}>
<View style={styles.heroContainer}>
<View style={styles.heroBannerContainer}>
{mobileHeroUrl != null && <>
{bypassAndroidUnsyncedFilter && <Module4611 colors={["rgba(39, 30, 173, 0.3)", "transparent"]} start={VerticalGradient.START} end={VerticalGradient.END} style={styles.orbsBackgroundGradient} />}
<Image2 style={[styles.heroBannerImage]} source={{
uri: mobileHeroUrl
}} />
<Module4611 colors={[r37, token]} start={VerticalGradient.START} end={VerticalGradient.END} style={styles.fadeOutGradient} />
</>}
</View>
<View style={styles.heroInfoContainer}>
{bypassAndroidUnsyncedFilter ? <View style={styles.orbsInnerContainer}>
<View>
{r31 != null && <Text variant="display-md" color="mobile-text-heading-primary" style={styles.orbsTitle}>{r31}</Text>}
{r32 != null && r32 !== "" && <Text variant="text-md/medium">{r32}</Text>}
</View>
<Button variant="tertiary" shrink grow={false} size="sm" text={intl.string(t.ynollq)} onPress={function onPress() {
openQuestHome({
mergeExistingRoutes: true,
fromContent: QuestContent.ORBS_SHOP_HERO_CTA
});
}} />
</View> : <PressableOpacity key={stateFromStores.storeListingId} accessibilityRole="button" accessibilityLabel={intl.formatToPlainString(t.FNtLb3, {
category: stateFromStores.name
})} accessibilityHint={intl.string(t.F8ma9x)} activeOpacity={0.6} androidRippleConfig={{
radius: Module712.radii.lg
}} hitSlop={8} onPress={() => {
AnalyticsUtils.track(AnalyticEvents.COLLECTIBLES_SHOP_ELEMENT_CLICKED, {
collectibles_shop_session_id: collectiblesAnalyticsContext?.sessionId,
sku_id: heroBlock.categoryStoreListingId,
page_type: "mobile_home",
page_section: collectiblesAnalyticsContext?.pageSection,
page_category: collectiblesAnalyticsContext?.pageCategory,
tile_type: "HERO_BLOCK",
tile_position: String(collectiblesAnalyticsContext?.tilePosition),
cta_name: null
});
navigation.navigate(UserSettingsSections.COLLECTIBLES_SHOP_VIEW_ALL_CATEGORY_ITEMS, {
category: stateFromStores,
analyticsContext: collectiblesAnalyticsContext
});
}}>
<View style={styles.innerContainer}>
{heroLogoUrl != null && <View style={styles.heroLogoContainer}>
<Image2 style={styles.heroLogo} source={{
uri: heroLogoUrl
}} />
</View>}
<View style={styles.heroViewAllIcon}>
<ChevronSmallRightIcon size="sm" color="white" />
</View>
</View>
</PressableOpacity>}
</View>
<View style={styles.productCardsContainer}>
<LayerScope>
{bypassAndroidUnsyncedFilter ? <FeedProductList products={filteredAndSortedProducts} loadingCardsNum={filteredAndSortedProducts.length !== 0 ? filteredAndSortedProducts.length : 4} preferVCPrice={preferVCPrice} accessibilityLabel={intl.formatToPlainString(t.FNtLb3, {
category: stateFromStores.name
})} /> : <>
{filteredAndSortedProducts.length === 0 ? <SkeletonLoading accessibilityLabel={intl.formatToPlainString(t.FNtLb3, {
category: stateFromStores.name
})} /> : <FlashList horizontal accessibilityLabel={intl.formatToPlainString(t.FNtLb3, {
category: stateFromStores.name
})} accessibilityRole="list" data={filteredAndSortedProducts} onScroll={handleDismissCoachmarkOnScroll} renderItem={callback} decelerationRate="fast" snapToInterval={COLLECTIBLES_SHOP_CARD_WIDTH + Module712.space.PX_12} showsHorizontalScrollIndicator={false} ListHeaderComponent={() => <View style={{
width: Module712.space.PX_16
}} />} ListFooterComponent={() => <View style={{
width: Module712.space.PX_16
}} />} ItemSeparatorComponent={() => <View style={{
width: Module712.space.PX_12
}} />} />}
</>}
</LayerScope>
</View>
</View>
</VisibilitySensor>
</AnalyticsLocationProvider>;
};