This commit is contained in:
janisslsm committed 2026-11-01 12:12:55 +02:00
1 parent 1781d25a15
commit 732c0ad767
33051 files changed
+2591613 -3019689

No files matched your search

@@ -0,0 +1,168 @@
// Metro module 11943 (f11944).
import { useState, useMemo, useEffect, useCallback, useLayoutEffect } from "react";
import { ScrollView, View } from "react-native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import { useNavigation } from "../../../../design/components/Navigator/native/useNavigation.native";
import { generateViewId, trackGameProfileFeedback } from "../../GameProfileAnalyticUtils";
import { fetchDetectableGames } from "../GameDetectionReportActionCreators";
import ModalActionCreators from "../../../../actions/ModalActionCreators";
import { intl, t } from "../../../../intl/index.native";
import { HeaderActionButton } from "../../../../design/components/Navigator/native/HeaderActionButton.native";
import { XSmallIcon } from "../../../../design/components/Icon/native/redesign/generated/XSmallIcon";
import { getHeaderBackButton } from "../../../../design/components/Navigator/native/NavigatorHeader.native";
import { Text } from "../../../../design/components/Text/native/Text";
import { TableRadioGroup } from "../../../../design/components/TableRow/native/TableRadioGroup.native";
import { TableRadioRow } from "../../../../design/components/TableRow/native/TableRadioRow.native";
import { TextInput } from "../../../../design/components/TextInput/native/TextInput.native";
import { Button } from "../../../../design/components/Button/native/Button.native";
import { TextArea } from "../../../../design/components/TextInput/native/TextArea.native";
import { Navigator } from "../../../../design/components/Navigator/native/Navigator.native";
let c8190_10, useStyles, name;
const ReportContent = function ReportContent(props) {
let callback, memo2;
const applicationId = props.applicationId;
callback = void 0;
memo2 = void 0;
const styles = useStyles();
const navigation = useNavigation();
const [state, setState] = useState("issue_selection");
const [state2, setState2] = useState([]);
const [state3, setState3] = useState("");
const [state4, setState4] = useState(null);
const [state5, onChange2] = useState("");
const memo = useMemo(() => generateViewId(), []);
useEffect(() => {
fetchDetectableGames().then(setState2).catch(() => {});
}, []);
callback = useCallback(() => {
ModalActionCreators.popWithKey(c8190_10);
}, []);
useLayoutEffect(() => {
if (state === "issue_selection") {
navigation.setOptions({
title: intl.string(t["6tnjbD"]),
headerLeft: () => null,
headerRight: () => <HeaderActionButton IconComponent={XSmallIcon} accessibilityLabel={intl.string(t.cpT0Cq)} onPress={callback} />
});
} else if (state === "game_search") {
navigation.setOptions({
title: intl.string(t.TZgkxY),
headerLeft: getHeaderBackButton(() => setState("issue_selection")),
headerRight: () => null
});
} else {
navigation.setOptions({
title: intl.string(t.tdDpJj),
headerLeft: getHeaderBackButton(() => setState("issue_selection")),
headerRight: () => null
});
}
}, [state, navigation, callback]);
const callback2 = useCallback(() => {
const suggestedGameName = state3.trim() !== "" ? state3.trim() : void 0;
let suggestedGameApplicationId = state4?.id;
if (suggestedGameApplicationId == null) {
suggestedGameApplicationId = null;
}
trackGameProfileFeedback({
viewId: memo,
applicationId,
suggestedGameName,
suggestedGameApplicationId,
feedback: state5.trim() !== "" ? state5.trim() : void 0,
submitted: true
});
callback();
}, [memo, applicationId, state3, state4, state5, callback]);
memo2 = useMemo(() => {
if (state3.trim() === "") {
return [];
}
let c27212_0 = state3.toLowerCase();
return state2.filter((item) => item.name.toLowerCase().includes(c27212_0)).slice(0, 10);
}, [state2, state3]);
return <ScrollView style={styles.container} keyboardShouldPersistTaps="handled">
{state === "issue_selection" ? <View style={styles.content}>
<Text variant="text-sm/normal" color="text-muted">
{intl.string(t.IQHicr)}
</Text>
<TableRadioGroup value={void 0} onChange={(c30475_0) => {
setTimeout(() => {
setState(c30475_0 === "wrong_game_shown" ? "game_search" : "other_feedback");
}, 100);
}} hasIcons={false}>
<TableRadioRow value="wrong_game_shown" label={intl.string(t.TZgkxY)} />
<TableRadioRow value="other_feedback" label={intl.string(t.tdDpJj)} />
</TableRadioGroup>
</View> : state === "game_search" ? <>
<View style={styles.content}>
<Text variant="text-sm/normal" color="text-muted">
{intl.string(t["79o/iq"])}
</Text>
<TextInput value={state3} onChange={(event) => {
setState3(event);
if (state4 != null && event !== state4.name) {
setState4(null);
}
}} placeholder={intl.string(t["/SGi7v"])} />
{memo2.length > 0 && <TableRadioGroup value={state4?.id} onChange={(c30476_0) => {
let r8 = memo2.find((item) => item.id === c30476_0);
if (r8 == null) {
r8 = null;
}
setState4(r8);
if (r8 != null) {
setState3(r8.name);
}
}} hasIcons={false}>
{memo2.map((item, index) => <TableRadioRow key={`${item.id}-${index}`} value={item.id} label={item.name} />)}
</TableRadioGroup>}
</View>
<View style={styles.submitContainer}>
<Button variant="primary" size="md" text={intl.string(t.geKm7t)} disabled={state3.trim() === ""} onPress={callback2} />
</View>
</> : state === "other_feedback" ? <>
<View style={styles.content}>
<Text variant="text-sm/normal" color="text-muted">
{intl.string(t.IblYEw)}
</Text>
<TextArea value={state5} onChange={onChange2} placeholder={intl.string(t.aiPKV4)} maxLength={300} />
</View>
<View style={styles.submitContainer}>
<Button variant="primary" size="md" text={intl.string(t.geKm7t)} disabled={state5.trim() === ""} onPress={callback2} />
</View>
</> : void 0}
</ScrollView>;
};
c8190_10 = "game-detection-report";
useStyles = createStyles({
container: {
flex: 1,
backgroundColor: Module712.colors.BACKGROUND_BASE_LOW
},
content: {
padding: Module712.space.PX_16,
gap: Module712.space.PX_24
},
submitContainer: {
padding: Module712.space.PX_16
}
});
name = "REPORT";
export default function GameDetectionReportModal(props) {
const applicationId2 = props.applicationId;
return <Navigator screens={useMemo(() => {
const r0 = {};
r0[name] = {
render: (a0) => <ReportContent {...a0} />
};
return r0;
}, [])} initialRouteStack={[{
name,
params: {
applicationId: applicationId2
}
}]} />;
};
export const MODAL_KEY = "game-detection-report";
@@ -0,0 +1,376 @@
// Metro module 8650 (f8651).
import { memo, useCallback } from "react";
import { ActivityIndicator, Image as Image2, Pressable, ScrollView, View } from "react-native";
import { getParser } from "../../../markup/CustomMarkup.native";
import { intl, t } from "../../../../intl/index.native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import { getPosterUrl, getPollExpiryLabel } from "../../AnnouncementMessageUtils";
import { Text } from "../../../../design/components/Text/native/Text";
import { ImageWithPlaceholder } from "../../../../components_native/common/ImageWithPlaceholder";
import { dateFormat } from "../../../../utils/DateUtils";
import { ReactionIcon } from "../../../../design/components/Icon/native/redesign/generated/ReactionIcon";
import useAnalyticsLocations from "../../../app_analytics/useAnalyticsLocations";
import useGameAnnouncements from "../../hooks/useGameAnnouncements";
import { GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
import GameProfileActionCreators_native from "../../GameProfileActionCreators.native";
import navigateToGameAnnouncement from "../../navigateToGameAnnouncement";
import { Button } from "../../../../design/components/Button/native/Button.native";
import { ChevronSmallRightIcon } from "../../../../design/components/Icon/native/redesign/generated/ChevronSmallRightIcon";
let c5627_12, parser, c5627_14, useStyles, MessageAnnouncementCard, PollAnnouncementCard, Component;
const EmbedAnnouncementCard = function EmbedAnnouncementCard(props) {
const { message, onPress: onPress2, guildId: guildId2, channelId: channelId2 } = props;
const styles2 = useStyles();
if (parser == null) {
parser = getParser();
}
const r23 = parser;
let r43 = message.media?.proxyUrl;
if (r43 == null) {
r43 = message.media?.url;
}
let uri = r43 != null ? getPosterUrl(r43, 160, c5627_12) : null;
if (uri == null) {
uri = r43;
}
const embedSource = message.embedSource;
if (embedSource == null) {
return null;
}
const r14 = embedSource.color != null ? {
borderLeftColor: embedSource.color
} : void 0;
const props2 = {
style: styles2.card,
onPress: () => onPress2(message.id),
accessibilityRole: "button",
accessibilityLabel: message.title,
children: null
};
const r70 = [embedSource.url != null && <Text variant="text-xs/medium" color="text-link" lineClamp={1}>{embedSource.url}</Text>, ,];
const r90 = [embedSource.authorName != null && <View style={styles2.embedAuthorRow}>
{embedSource.authorIconUrl != null && <Image2 source={{
uri: embedSource.authorIconUrl
}} style={styles2.embedAuthorIcon} />}
<Text variant="text-xs/semibold" color="text-strong" lineClamp={1}>{embedSource.authorName}</Text>
</View>, message.media != null && uri != null && <View style={styles2.embedMedia}>
<ImageWithPlaceholder uri={uri} placeholder={message.media.placeholder} placeholderVersion={message.media.placeholderVersion} style={styles2.mediaImage} />
</View>, message.title != null && <Text variant="text-md/semibold" color="mobile-text-heading-primary" lineClamp={2}>
{r23(message.title, true, {
guildId: guildId2,
channelId: channelId2
})}
</Text>, message.body.length > 0 && <Text variant="text-sm/medium" color="text-default" lineClamp={3}>
{r23(message.body, true, {
guildId: guildId2,
channelId: channelId2
})}
</Text>, ,];
const r142 = [embedSource.providerIconUrl != null && <Image2 source={{
uri: embedSource.providerIconUrl
}} style={styles2.embedProviderIcon} />, <Text variant="text-xs/medium" color="text-muted">
{embedSource.providerName != null ? `${embedSource.providerName} · ` : ""}
{dateFormat(new Date(message.timestamp), "LL")}
</Text>, ,];
let r169 = message.reactionCount > 0;
if (r169) {
const r182 = [<ReactionIcon size="xs" color={Module712.colors.TEXT_MUTED} />, ,];
const reactionCount = message.reactionCount;
if (!(c5627_14 != null && c5627_14.locale === intl.currentLocale)) {
c5627_14 = {
locale: intl.currentLocale,
format: new Intl.NumberFormat(intl.currentLocale)
};
}
r182[1] = <Text variant="text-xs/medium" color="text-muted">
{c5627_14.format.format(reactionCount)}
</Text>;
r169 = <View style={styles2.reactionInfo}>{r182}</View>;
}
r142[2] = r169;
r90[4] = <View style={styles2.metadataRow}>{r142}</View>;
r70[1] = <View style={[styles2.embedContentArea, r14]}>{r90}</View>;
props2.children = <View style={styles2.cardBody}>{r70}</View>;
return <Pressable {...props2} />;
};
MessageAnnouncementCard = function MessageAnnouncementCard(props) {
const { message: message2, onPress: onPress3, guildId: guildId2, channelId: channelId2 } = props;
const styles2 = useStyles();
if (parser == null) {
parser = getParser();
}
const r20 = parser;
let r39 = message2.media?.proxyUrl;
if (r39 == null) {
r39 = message2.media?.url;
}
let uri = r39 != null ? getPosterUrl(r39, 160, c5627_12) : null;
if (uri == null) {
uri = r39;
}
const props2 = {
style: styles2.card,
onPress: () => onPress3(message2.id),
accessibilityRole: "button",
accessibilityLabel: message2.title,
children: null
};
const children = [message2.media != null && uri != null && <View style={styles2.smallCardMedia}>
<ImageWithPlaceholder uri={uri} placeholder={message2.media.placeholder} placeholderVersion={message2.media.placeholderVersion} style={styles2.mediaImage} />
</View>, ,];
const r83 = [message2.title != null && <Text variant="text-md/semibold" color="mobile-text-heading-primary" lineClamp={2}>
{r20(message2.title, true, {
guildId: guildId2,
channelId: channelId2
})}
</Text>, message2.body.length > 0 && <Text variant="text-sm/medium" color="text-default" lineClamp={3}>
{r20(message2.body, true, {
guildId: guildId2,
channelId: channelId2
})}
</Text>, ,];
const r115 = [<Text variant="text-xs/medium" color="text-muted">
{dateFormat(new Date(message2.timestamp), "LL")}
</Text>, ,];
let r117 = message2.reactionCount > 0;
if (r117) {
const r130 = [<ReactionIcon size="xs" color={Module712.colors.TEXT_MUTED} />, ,];
const reactionCount = message2.reactionCount;
if (!(c5627_14 != null && c5627_14.locale === intl.currentLocale)) {
c5627_14 = {
locale: intl.currentLocale,
format: new Intl.NumberFormat(intl.currentLocale)
};
}
r130[1] = <Text variant="text-xs/medium" color="text-muted">
{c5627_14.format.format(reactionCount)}
</Text>;
r117 = <View style={styles2.reactionInfo}>{r130}</View>;
}
r115[1] = r117;
r83[2] = <View style={styles2.metadataRow}>{r115}</View>;
children[1] = <View style={styles2.cardBody}>{r83}</View>;
props2.children = children;
return <Pressable {...props2} />;
};
PollAnnouncementCard = function PollAnnouncementCard(props) {
const { message: message3, onPress: onPress4 } = props;
const styles = useStyles();
const poll = message3.poll;
if (poll == null) {
return null;
}
const r15 = poll.answers.slice(0, 3);
const count = poll.answers.length - r15.length;
return <Pressable style={styles.card} onPress={() => onPress4(message3.id)} accessibilityRole="button" accessibilityLabel={poll.question.text}>
<View style={styles.cardBody}>
<Text variant="text-md/semibold" color="mobile-text-heading-primary">{poll.question.text}</Text>
<View style={styles.pollAnswers}>
{r15.map((item) => {
let text = item.poll_media.text;
if (text == null) {
text = "";
}
return <View key={item.answer_id} style={styles.pollAnswerOption}>
<Text variant="text-sm/medium" color="text-default" lineClamp={1}>{text}</Text>
</View>;
})}
{count > 0 && <Text variant="text-xs/medium" color="text-muted" style={styles.pollMoreOptions}>
{intl.format(t["mv/nIa"], {
count
})}
</Text>}
</View>
<View style={styles.metadataRow}>
<Text variant="text-xs/medium" color="text-muted">
{intl.format(t.t0FTsH, {
createdAt: new Date(message3.timestamp),
expiryLabel: getPollExpiryLabel(poll)
})}
</Text>
</View>
</View>
</Pressable>;
};
c5627_12 = 120;
parser = null;
c5627_14 = null;
useStyles = createStyles({
container: {
gap: Module712.space.PX_8
},
smallCardsScroller: {
marginHorizontal: -Module712.space.PX_16,
overflow: "visible"
},
smallCardsContainer: {
flexDirection: "row",
gap: Module712.space.PX_12,
paddingHorizontal: Module712.space.PX_16
},
sectionHeader: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: Module712.space.PX_8
},
loadingContainer: {
height: 120,
alignItems: "center",
justifyContent: "center"
},
card: {
flexDirection: "column",
borderRadius: Module712.radii.lg,
overflow: "hidden",
backgroundColor: Module712.colors.BACKGROUND_BASE_LOW,
borderWidth: 1,
borderColor: Module712.colors.BORDER_SUBTLE,
width: 160
},
cardBody: {
flex: 1,
flexDirection: "column",
gap: Module712.space.PX_4,
overflow: "hidden",
padding: Module712.space.PX_12
},
smallCardMedia: {
height: 120,
overflow: "hidden",
flexShrink: 0
},
mediaImage: {
width: "100%",
height: "100%",
resizeMode: "cover"
},
metadataRow: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_8,
marginTop: "auto"
},
reactionInfo: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_4
},
embedContentArea: {
flex: 1,
gap: Module712.space.PX_4,
borderLeftWidth: 4,
borderLeftColor: Module712.colors.BORDER_SUBTLE,
borderTopLeftRadius: Module712.radii.xs,
borderBottomLeftRadius: Module712.radii.xs,
paddingLeft: Module712.space.PX_8
},
embedAuthorRow: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_4
},
embedAuthorIcon: {
width: 20,
height: 20,
borderRadius: Module712.radii.round
},
embedProviderIcon: {
width: 16,
height: 16
},
embedMedia: {
overflow: "hidden",
borderRadius: Module712.radii.sm,
aspectRatio: 1.7777777777777777
},
pollAnswers: {
flexDirection: "column",
gap: Module712.space.PX_4,
flex: 1
},
pollAnswerOption: {
paddingVertical: Module712.space.PX_8,
paddingHorizontal: Module712.space.PX_12,
borderRadius: Module712.radii.sm,
backgroundColor: Module712.colors.BACKGROUND_BASE_LOWEST
},
pollMoreOptions: {
paddingHorizontal: Module712.space.PX_12
}
});
Component = memo(function(a0) {
return a0.message.poll != null ? <PollAnnouncementCard {...a0} /> : a0.message.embedSource != null ? <EmbedAnnouncementCard {...a0} /> : <MessageAnnouncementCard {...a0} />;
});
export default function GameProfileAnnouncements(props) {
let callback;
const { gameId, invite, closeModal, trackAction, scrollOffsetRef } = props;
callback = void 0;
const styles2 = useStyles();
const analyticsLocations = useAnalyticsLocations().analyticsLocations;
const gameAnnouncements = useGameAnnouncements(gameId, 10);
const { messages, channelId, guildId, loading } = gameAnnouncements;
const callback2 = useCallback(() => {
let guildId2 = invite == null ? void 0 : invite.guild?.id;
if (guildId2 == null) {
guildId2 = guildId;
}
if (guildId2 != null && channelId != null) {
trackAction(GameProfileTrackActionActions.Announcements);
GameProfileActionCreators_native.setGameProfilePendingReturn({
gameId,
channelId,
initialScrollOffset: scrollOffsetRef.current
});
closeModal();
navigateToGameAnnouncement({
invite,
guildId: guildId2,
channelId,
analyticsLocationStack: analyticsLocations
});
}
}, [trackAction, closeModal, invite, guildId, channelId, analyticsLocations, gameId, scrollOffsetRef]);
callback = useCallback((a0) => {
let guildId2 = invite == null ? void 0 : invite.guild?.id;
if (guildId2 == null) {
guildId2 = guildId;
}
if (guildId2 != null && channelId != null) {
trackAction(GameProfileTrackActionActions.AnnouncementsItem);
GameProfileActionCreators_native.setGameProfilePendingReturn({
gameId,
channelId,
initialScrollOffset: scrollOffsetRef.current
});
closeModal();
navigateToGameAnnouncement({
invite,
guildId: guildId2,
channelId,
messageId: a0,
analyticsLocationStack: analyticsLocations
});
}
}, [trackAction, closeModal, invite, guildId, channelId, analyticsLocations, gameId, scrollOffsetRef]);
return loading ? <View style={styles2.container}>
<View style={styles2.sectionHeader}>
<Text variant="heading-sm/semibold" color="mobile-text-heading-primary">
{intl.string(t.B0BV3Y)}
</Text>
</View>
<View style={styles2.loadingContainer}>
<ActivityIndicator />
</View>
</View> : channelId == null ? null : messages.length !== 0 ? <View style={styles2.container}>
<View style={styles2.sectionHeader}>
<Text variant="heading-sm/semibold" color="mobile-text-heading-primary">
{intl.string(t.B0BV3Y)}
</Text>
<Button text={intl.string(t.budhsM)} variant="tertiary" size="sm" icon={<ChevronSmallRightIcon size="sm" />} iconPosition="end" onPress={callback2} />
</View>
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles2.smallCardsScroller} contentContainerStyle={styles2.smallCardsContainer} decelerationRate="fast" snapToInterval={172} snapToStart={false} snapToEnd={false}>
{messages.map((a0) => <Component key={a0.id} message={a0} onPress={callback} guildId={guildId} channelId={channelId} />)}
</ScrollView>
</View> : null;
};
@@ -0,0 +1,250 @@
// Metro module 8647 (f8648).
import { useState, useRef, useEffect, useMemo, useCallback } from "react";
import { View } from "react-native";
import GuildMembershipStore from "../../../../stores/GuildMembershipStore";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import { ThirdPartyGameApplicationWebsiteCategory } from "../../../../_bundle/Module8490";
import { findCodedLink } from "../../../coded_links/findCodedLinks";
import { CodedLinkType } from "../../../coded_links/CodedLink";
import resolveInvite from "../../../instant_invite/resolveInvite";
import { useStateFromStores } from "../../../../_bundle/Module589";
import { GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
import { transitionToGuild } from "../../../routing/transitionToGuild.native";
import { showInvite } from "../../../../actions/native/DisplayedInviteActionCreators";
import { fromInviteGuild } from "../../../../utils/GuildRecordUtils";
import { Text } from "../../../../design/components/Text/native/Text";
import { intl, t } from "../../../../intl/index.native";
import FastImage from "../../../../components_native/common/FastImage";
import AvatarUtils from "../../../../utils/AvatarUtils";
import GuildIcon, { GuildIconSizes } from "../../../guild/native/GuildIcon";
import GuildBadgeV2 from "../../../guild/native/GuildBadgeV2";
import { Icon } from "../../../../design/void/native";
import { Button } from "../../../../design/components/Button/native/Button.native";
const useStyles = createStyles({
container: {
gap: Module712.space.PX_8
},
headerText: {
paddingHorizontal: Module712.space.PX_8
},
card: {
borderRadius: Module712.radii.lg,
borderWidth: 1,
borderColor: Module712.colors.BORDER_SUBTLE,
overflow: "hidden",
backgroundColor: Module712.colors.BACKGROUND_BASE_LOW
},
guildBanner: {
height: 112,
width: "100%",
resizeMode: "cover"
},
guildContent: {
flexDirection: "column",
padding: Module712.space.PX_16,
gap: Module712.space.PX_16
},
guildIcon: {
width: 56,
height: 56,
borderRadius: Module712.radii.md,
overflow: "hidden",
borderWidth: Module712.space.PX_4,
borderColor: Module712.colors.BACKGROUND_BASE_LOW,
marginLeft: -Module712.space.PX_4
},
guildIconWithBanner: {
marginTop: -Module712.space.PX_48
},
guildIconImage: {
width: "100%",
height: "100%",
borderRadius: Module712.radii.none
},
guildInfo: {
flex: 1,
gap: Module712.space.PX_16
},
guildNameDescriptionContainer: {
gap: Module712.space.PX_4
},
guildNameRow: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_4
},
memberCountsContainer: {
flexDirection: "row",
gap: Module712.space.PX_16
},
memberCountContainer: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_4
},
onlineEllipse: {
width: 8,
height: 8,
borderRadius: Module712.radii.round,
backgroundColor: Module712.colors.STATUS_POSITIVE
},
membersEllipse: {
width: 8,
height: 8,
borderRadius: Module712.radii.round,
backgroundColor: Module712.colors.TEXT_DEFAULT
}
});
export default function GameProfileCommunityServer(props) {
let memo, stateFromStores;
const { game, trackAction, onInviteResolved, closeModal } = props;
memo = void 0;
stateFromStores = void 0;
const styles = useStyles();
const [state, setState] = useState(null);
const ref = useRef(onInviteResolved);
useEffect(() => {
ref.current = onInviteResolved;
}, [onInviteResolved]);
memo = useMemo(() => {
const r2 = game == null;
let r7 = void 0;
if (!r2) {
const websites = game.websites;
r7 = websites == null ? void 0 : websites.find((website) => website.category === ThirdPartyGameApplicationWebsiteCategory.DISCORD);
}
return r7;
}, [game?.websites]);
useEffect(() => {
let _resolve2 = function _resolve() {
const r9 = async () => {
let c31471_2 = 0;
let c31978_0, c31978_1, c31978_2;
L20: {
L19: {
try {
c31978_0 = void 0;
c31978_1 = void 0;
c31978_2 = void 0;
if (memo == null) {
break L20;
}
const r35 = findCodedLink(memo.url);
if (r35 == null) {
break L20;
}
if (r35.type === CodedLinkType.INVITE) {
c31471_2 = 1;
c31978_0 = await resolveInvite(r35.code, "game_profile");
c31978_1 = c31978_0.invite;
c31978_2 = c31978_0.banned;
if (c31978_1 != null && c31978_2 !== true) {
(0, setState)(c31978_1);
const current = ref.current;
if (current != null) {
current.call(ref, c31978_1);
}
}
c31471_2 = 0;
break L19;
}
break L20;
} catch ($e) {
let r28 = $e;
if (c31471_2 !== 0) {
while (true) {
try {
c31471_2 = 0;
break L19;
} catch ($e) {
r28 = $e;
if (c31471_2 === 0) {
break;
}
}
}
}
throw r28;
}
}
return void 0;
}
};
_resolve2 = r9;
return r9.apply(this, arguments);
};
if (memo != null) {
(function resolve() {
return _resolve2.apply(this, arguments);
})();
}
}, [memo]);
stateFromStores = useStateFromStores([GuildMembershipStore], () => (state == null ? void 0 : state.guild?.id) != null && GuildMembershipStore.isMember(state.guild.id));
const callback = useCallback(() => {
L7: {
if (state != null) {
trackAction(GameProfileTrackActionActions.JoinServer);
closeModal();
if (stateFromStores) {
if (state.guild?.id != null) {
transitionToGuild(state.guild.id);
break L7;
}
}
showInvite(state.code);
}
}
}, [state, stateFromStores, trackAction, closeModal]);
if (state != null && state.guild != null) {
const guild = fromInviteGuild(state.guild);
let approximate_member_count = state.approximate_member_count;
if (approximate_member_count == null) {
approximate_member_count = state.guild.approximate_member_count;
}
let approximate_presence_count = state.approximate_presence_count;
if (approximate_presence_count == null) {
approximate_presence_count = state.guild.approximate_presence_count;
}
const r88 = [<Text variant="heading-sm/semibold" color="mobile-text-heading-primary" style={styles.headerText}>
{intl.string(t["U2N+ci"])}
</Text>, ,];
const r100 = [guild.banner != null && <FastImage source={AvatarUtils.getGuildBannerSource(guild)} style={styles.guildBanner} />, ,];
r100[1] = <View style={styles.guildContent}>
<View style={[styles.guildIcon, guild.banner != null ? styles.guildIconWithBanner : null]}>
<GuildIcon guild={guild} size={GuildIconSizes.LARGE} style={styles.guildIconImage} />
</View>
<View style={styles.guildInfo}>
<View style={styles.guildNameDescriptionContainer}>
<View style={styles.guildNameRow}>
<Text variant="text-md/semibold" color="mobile-text-heading-primary" lineClamp={1}>{guild.name}</Text>
<GuildBadgeV2 guild={guild} size={Icon.Sizes.REFRESH_SMALL_16} />
</View>
<Text variant="text-sm/medium" color="text-default" lineClamp={3}>{guild.description}</Text>
</View>
<View style={styles.memberCountsContainer}>
{approximate_presence_count != null ? <View style={styles.memberCountContainer}>
<View style={styles.onlineEllipse} />
<Text variant="text-xs/normal" color="text-default">
{intl.formatToPlainString(t["LC+S+m"], {
membersOnline: approximate_presence_count
})}
</Text>
</View> : null}
{approximate_member_count != null ? <View style={styles.memberCountContainer}>
<View style={styles.membersEllipse} />
<Text variant="text-xs/normal" color="text-default">
{intl.formatToPlainString(t.zRl6XR, {
count: approximate_member_count
})}
</Text>
</View> : null}
</View>
</View>
<Button variant="secondary" size="md" text={stateFromStores ? intl.string(t.cEnaWx) : intl.string(t.XpeFYr)} onPress={callback} />
</View>;
r88[1] = <View style={styles.card}>{r100}</View>;
return <View style={styles.container}>{r88}</View>;
}
return null;
};
@@ -0,0 +1,149 @@
// Metro module 11924 (f11925).
import { useCallback, useMemo } from "react";
import { Pressable, View } from "react-native";
import { IGDB_ATTRIBUTION_LINK } from "../../../content_inventory/ContentInventoryConstants";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import Linking from "../../../../lib/native/Linking";
import { getGenreText } from "../../../../utils/SKUUtils";
import { intl, t } from "../../../../intl/index.native";
import { GameCompanyRole } from "../../../../flow/Server";
import { dateFormat } from "../../../../utils/DateUtils";
import { GameUpdatePlatformIcon } from "../../../game_update/native/GameUpdatePlatformIcon";
import getGameProfileWebsiteData from "../utils/getGameProfileWebsiteData";
import { Text } from "../../../../design/components/Text/native/Text";
let useStyles;
const GameProfileWebsiteButton = function GameProfileWebsiteButton(props) {
const { icon, action, title, trackAction, url } = props;
return <Pressable accessibilityRole="button" accessibilityLabel={title} onPress={useCallback(() => {
Linking.openURL(url);
trackAction(action);
}, [trackAction, action, url])} hitSlop={Module712.space.PX_4}>{icon}</Pressable>;
};
useStyles = createStyles({
container: {
gap: Module712.space.PX_8
},
headerText: {
paddingHorizontal: Module712.space.PX_8
},
detailsContainer: {
borderRadius: Module712.radii.lg,
borderWidth: 1,
borderColor: Module712.colors.BORDER_SUBTLE,
overflow: "hidden",
backgroundColor: Module712.colors.BACKGROUND_BASE_LOW
},
detailsRow: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
padding: Module712.space.PX_12
},
detailsRowValue: {
flexDirection: "column",
flexShrink: 1,
paddingLeft: Module712.space.PX_32
},
detailsRowBottomBorder: {
borderBottomWidth: 1,
borderBottomColor: Module712.colors.BORDER_SUBTLE
},
platformsContainer: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_12
},
linksContainer: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_12
}
});
export default function GameProfileDetails(props) {
const { game, trackAction: trackAction2 } = props;
const styles = useStyles();
const memo = useMemo(() => {
if (game == null) {
return [];
}
const value = game == null ? void 0 : game.genres.map(getGenreText).join(", ");
const r26 = value != null && value !== "";
const r28 = [];
if (r26) {
r28.push({
label: game.genres.length !== 1 ? intl.string(t.pDgwYB) : intl.string(t.mjFKqn),
value
});
}
const r59 = game == null ? void 0 : game.getCompanyByRole(GameCompanyRole.PUBLISHER);
const value2 = r59.map((item) => item.name).join(", ");
if (value2 != null && value2 !== "") {
r28.push({
label: r59.length !== 1 ? intl.string(t.Hc7Enk) : intl.string(t["4Byy/G"]),
value: value2
});
}
const r108 = game == null ? void 0 : game.getCompanyByRole(GameCompanyRole.DEVELOPER);
const value3 = r108.map((item) => item.name).join(", ");
if (value3 != null && value3 !== "") {
r28.push({
label: r108.length !== 1 ? intl.string(t.KATEJB) : intl.string(t.na3PT0),
value: value3
});
}
const firstReleaseDate = game?.firstReleaseDate;
if (firstReleaseDate != null && firstReleaseDate !== "") {
r28.push({
label: intl.string(t.H3mPDT),
value: dateFormat(new Date(firstReleaseDate), "LL")
});
}
const platforms = game?.platforms;
if (platforms != null && platforms.length > 0) {
r28.push({
label: game.platforms.length !== 1 ? intl.string(t.PNqxNe) : intl.string(t["UxAag+"]),
value: <View style={styles.platformsContainer}>
{platforms.map((a0) => <GameUpdatePlatformIcon key={a0} platform={a0} size="md" color={Module712.colors.ICON_SUBTLE} />)}
</View>
});
}
const r237 = game == null;
let r238 = void 0;
if (!r237) {
const websites = game.websites;
r238 = websites == null ? void 0 : websites.map((website) => getGameProfileWebsiteData(website, Module712.colors.ICON_SUBTLE)).filter((item) => item != null);
}
if (r238 == null) {
r238 = [];
}
if (r238 != null && r238.length > 0) {
r28.push({
label: intl.string(t["Oj3o1/"]),
value: <View style={styles.linksContainer}>
{r238.map(({ title, icon, action: action2, url: url2 }) => <GameProfileWebsiteButton key={url2} icon={icon} action={action2} title={title} url={url2} trackAction={trackAction2} />)}
</View>
});
}
if (r28.length > 0) {
r28.push({
label: intl.string(t["BwQ+9e"]),
value: intl.format(t.XPFZVl, {
igdbLink: IGDB_ATTRIBUTION_LINK
})
});
}
return r28;
}, [styles.linksContainer, styles.platformsContainer, game, trackAction2]);
return memo.length !== 0 ? <View style={styles.container}>
<Text variant="heading-sm/semibold" color="mobile-text-heading-primary" style={styles.headerText}>
{intl.string(t["7OjmmH"])}
</Text>
<View style={styles.detailsContainer}>
{memo.map((item, index) => <View key={item.label} style={[styles.detailsRow, memo.length > 1 ? index < memo.length - 1 ? styles.detailsRowBottomBorder : null : null]}>
<Text variant="text-sm/medium" color="text-subtle" lineClamp={1}>{item.label}</Text>
{typeof item.value === "string" ? <Text variant="text-sm/normal" color="text-subtle" lineClamp={1} style={styles.detailsRowValue}>{item.value}</Text> : item.value}
</View>)}
</View>
</View> : null;
};
@@ -0,0 +1,18 @@
// Metro module 11941 (f11942).
import { useCallback } from "react";
import { RelativeMarketingURLs } from "../../../../Constants";
import { GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
import MobileWebHandoffLinking from "../../../mobile_web_handoff/native/MobileWebHandoffLinking";
import { GameLinkTypes } from "../../../../flow/Server";
import { Button } from "../../../../design/components/Button/native/Button.native";
import { intl, t } from "../../../../intl/index.native";
export default function GameProfileGameClaimCta(props) {
const { game, trackAction } = props;
const callback = useCallback(async () => {
trackAction(GameProfileTrackActionActions.ClaimGame);
await MobileWebHandoffLinking.redirectDeveloperPortalWithHandoffToken(RelativeMarketingURLs.DEVELOPER_PORTAL_APPLICATIONS_GAME_IDENTITY);
}, [trackAction]);
const linkedApplications = game.linkedApplications;
const r18 = linkedApplications == null ? void 0 : linkedApplications.some((linkedApplication) => linkedApplication.type === GameLinkTypes.OFFICIAL);
return r18 != null ? r18 ? null : <Button variant="secondary" size="md" text={intl.string(t["mqg+to"])} onPress={callback} /> : <Button variant="secondary" size="md" text={intl.string(t["mqg+to"])} onPress={callback} />;
};
@@ -0,0 +1,155 @@
// Metro module 8516 (f8517).
import { useState, useMemo, useCallback } from "react";
import { Image as Image2, View } from "react-native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import ReanimatedRexport, { useSharedValue, useAnimatedStyle } from "../../../reanimated/ReanimatedRexport";
import { getGenreText } from "../../../../utils/SKUUtils";
import Module4611 from "../../../../_bundle/Module4611";
import GameProfileRankPill from "./GameProfileRankPill";
import { Text } from "../../../../design/components/Text/native/Text";
const useStyles = createStyles({
container: {
backgroundColor: Module712.colors.BACKGROUND_BASE_LOWEST
},
artHero: {
width: "100%",
position: "absolute",
top: 0,
bottom: -Module712.space.PX_80,
left: 0,
right: 0
},
artHeroImage: {
height: "100%",
width: "100%",
resizeMode: "cover"
},
artHeroGradient: {
position: "absolute",
top: 0,
bottom: 0,
left: 0,
right: 0
},
headerContent: {
paddingTop: Module712.space.PX_32,
paddingHorizontal: Module712.space.PX_16,
gap: Module712.space.PX_12,
flexDirection: "row",
alignItems: "flex-end",
maxWidth: 520,
alignSelf: "center",
width: "100%"
},
shadowContainer: {
borderRadius: Module712.radii.sm,
...Module712.shadows.SHADOW_LOW
},
coverContainer: {
width: 85,
height: 114,
borderRadius: Module712.radii.sm,
backgroundColor: Module712.colors.BACKGROUND_BASE_LOW,
overflow: "hidden"
},
iconContainer: {
width: 85,
height: 85,
borderRadius: Module712.radii.sm,
backgroundColor: Module712.colors.BACKGROUND_BASE_LOW,
overflow: "hidden"
},
image: {
width: "100%",
height: "100%"
},
titleContainer: {
flex: 1,
flexDirection: "column",
alignItems: "flex-start"
},
textShadow: {
textShadowColor: Module712.colors.BLACK,
textShadowOffset: {
width: 0,
height: 0
},
textShadowRadius: 1
}
});
const __initData = {
code: "function GameProfileHeaderTsx1(){const{effectiveScrollY}=this.__closure;return{top:-Math.max(0,-effectiveScrollY.get())};}"
};
export default function GameProfileHeader(props) {
let sharedValue;
const game = props.game;
let scrollY = props.scrollY;
const onHeightMeasured = props.onHeightMeasured;
sharedValue = void 0;
const styles = useStyles();
const [state] = useState(() => Math.random());
const sharedValue2 = useSharedValue(0);
if (scrollY == null) {
scrollY = sharedValue2;
}
sharedValue = scrollY;
const _ = function _() {
return {
top: -Math.max(0, -sharedValue.get())
};
};
_.__closure = {
effectiveScrollY: sharedValue
};
_.__workletHash = 1177397229282;
_.__initData = __initData;
const animatedStyle = useAnimatedStyle(_);
const name = game?.name;
const r43 = game == null ? void 0 : game.genres.map(getGenreText).join(", ");
const l30Rank = game?.l30Rank;
const memo = useMemo(() => {
let r3 = game == null ? void 0 : game.getBannerURL(1024);
if (r3 == null) {
r3 = game?.screenshotUrls != null ? game.screenshotUrls.length > 0 ? game.screenshotUrls[Math.floor(state * game.screenshotUrls.length)] : null : null;
}
return r3;
}, [game, state]);
const memo2 = useMemo(() => game == null ? void 0 : game.getCoverURL(114), [game]);
const memo3 = useMemo(() => game == null ? void 0 : game.getIconURL(114), [game]);
const props2 = {
style: styles.container,
onLayout: useCallback((a0) => {
if (onHeightMeasured != null) {
onHeightMeasured(a0.nativeEvent.layout.height);
}
}, [onHeightMeasured]),
children: null
};
props2.children = [<ReanimatedRexport.View style={[styles.artHero, animatedStyle]}>
{memo != null && <Image2 source={{
uri: memo
}} style={styles.artHeroImage} />}
<Module4611 colors={["rgba(0,0,0,0.3)", styles.container.backgroundColor]} style={styles.artHeroGradient} />
</ReanimatedRexport.View>, <View style={styles.headerContent}>
<View style={styles.shadowContainer}>
<View {...memo2 != null ? {
style: styles.coverContainer,
children: <Image2 source={{
uri: memo2
}} style={styles.image} />
} : {
style: styles.iconContainer,
children: memo3 != null && <Image2 source={{
uri: memo3
}} style={styles.image} />
}} />
</View>
<View style={styles.titleContainer}>
{l30Rank != null && <GameProfileRankPill rank={l30Rank} />}
<Text variant="heading-xxl/semibold" color="text-overlay-light" lineClamp={2} style={styles.textShadow}>{name}</Text>
{r43 != null ? r43 !== "" ? <Text variant="text-md/normal" color="text-overlay-light" lineClamp={2} style={styles.textShadow}>{r43}</Text> : null : null}
</View>
</View>];
return <View {...props2} />;
};
@@ -0,0 +1,109 @@
// Metro module 8644 (f8645).
import { useCallback } from "react";
import { View } from "react-native";
import UserStore from "../../../../stores/UserStore";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import useStartAuthorize from "../../../application_account_linking/native/useStartAuthorize";
import { useStateFromStores } from "../../../../_bundle/Module589";
import { GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
import { Text } from "../../../../design/components/Text/native/Text";
import { intl, t } from "../../../../intl/index.native";
import FastImage from "../../../../components_native/common/FastImage";
import { Avatar, AvatarSizes } from "../../../../design/void/native";
import { Button } from "../../../../design/components/Button/native/Button.native";
import { ExperimentalGameControllerLinkIcon } from "../../../../design/components/Icon/native/redesign/generated/ExperimentalGameControllerLinkIcon";
const useStyles = createStyles({
container: {
gap: Module712.space.PX_8
},
headerText: {
paddingHorizontal: Module712.space.PX_8
},
card: {
borderRadius: Module712.radii.lg,
borderWidth: 1,
borderColor: Module712.colors.BORDER_SUBTLE,
backgroundColor: Module712.colors.BACKGROUND_BASE_LOW,
padding: Module712.space.PX_16,
gap: Module712.space.PX_16
},
cardImagesContainer: {
flexDirection: "row",
gap: Module712.space.PX_8,
alignItems: "center",
alignSelf: "center"
},
ellipseGroup: {
flexDirection: "row",
justifyContent: "space-between",
gap: Module712.space.PX_4
},
ellipse: {
width: 4,
height: 4,
backgroundColor: Module712.colors.MOBILE_TEXT_HEADING_PRIMARY,
opacity: 0.3,
borderRadius: Module712.radii.round
},
cardImageApplication: {
width: 48,
height: 48,
borderRadius: Module712.radii.sm
},
cardContent: {
gap: Module712.space.PX_4,
alignSelf: "center",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
paddingHorizontal: Module712.space.PX_24
},
cardText: {
textAlign: "center"
}
});
export default function GameProfileLinkAccount(props) {
const { game, trackAction, analyticsLocations } = props;
const styles = useStyles();
const startAuthorize = useStartAuthorize(game);
const { fetched, hasAlreadyLinked, canStartAuthorization, startAuthorization, connectionApp } = startAuthorize;
const stateFromStores = useStateFromStores([UserStore], () => UserStore.getCurrentUser());
const callback = useCallback(() => {
trackAction(GameProfileTrackActionActions.LinkAccount);
startAuthorization({
analyticsLocations
});
}, [trackAction, startAuthorization, analyticsLocations]);
if (fetched && connectionApp != null && canStartAuthorization && !hasAlreadyLinked && stateFromStores != null) {
const iconSource = connectionApp.getIconSource(48);
return <View style={styles.container}>
<Text variant="heading-sm/semibold" color="mobile-text-heading-primary" style={styles.headerText}>
{intl.string(t["VDAhr+"])}
</Text>
<View style={styles.card}>
{iconSource != null ? <View style={styles.cardImagesContainer}>
<FastImage source={iconSource} style={styles.cardImageApplication} />
<View style={styles.ellipseGroup}>
<View style={styles.ellipse} />
<View style={styles.ellipse} />
<View style={styles.ellipse} />
</View>
<Avatar size={AvatarSizes.LARGE_48} user={stateFromStores} guildId={void 0} />
</View> : null}
<View style={styles.cardContent}>
<Text variant="heading-md/semibold" color="mobile-text-heading-primary" style={styles.cardText}>
{intl.formatToPlainString(t.hUbQT2, {
gameName: connectionApp.name
})}
</Text>
<Text variant="text-sm/medium" color="text-default" style={styles.cardText}>
{intl.string(t["JKqu+4"])}
</Text>
</View>
<Button variant="secondary" size="md" text={intl.string(t.jynBQ5)} onPress={callback} icon={<ExperimentalGameControllerLinkIcon size="sm" />} />
</View>
</View>;
}
return null;
};
@@ -0,0 +1,236 @@
// Metro module 8519 (f8520).
import { useRef, useCallback, useState, useEffect, useMemo } from "react";
import { Image as Image2, Pressable, ScrollView, View } from "react-native";
import { NOOP } from "../../../../_bundle/Module505";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import { GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
import { openMediaModal } from "../../../media_viewer/native/components/openMediaModal";
import { createVideoControls, VideoComponent } from "../../../../components_native/common/Video";
import { isAndroid } from "../../../../_bundle/Module501";
import useWindowDimensions_native from "../../../screen/useWindowDimensions.native";
import { useObscuredSurface } from "../../../safety_common/ObscuredSurfaceContext";
import { getBestMediaProxySize, getDevicePixelRatio } from "../../../image_upload/ImageLoaderUtils";
import { getAssetURL } from "../../../../utils/StoreUtils";
import { HermesBuiltin } from "../../../../_hermes/prelude";
let width, useStyles, TrailerItem;
const ImageItem = function ImageItem(props) {
const { url, index, sources, trackAction, width: width4, height: height2, onScrollToIndex, setMediaModalOpen } = props;
const styles = useStyles();
const ref = useRef(null);
return <Pressable ref={ref} style={[styles.mediaItem, {
width: width4,
height: height2
}]} onPress={useCallback(() => {
trackAction(GameProfileTrackActionActions.ClickImage);
setMediaModalOpen(true);
openMediaModal({
initialSources: sources,
initialIndex: index,
originViewOrOriginLayout: ref.current,
analyticsSource: "game_profile",
openAs: "action-sheet",
onIndexChange: (a0) => onScrollToIndex(a0),
onClose: () => setMediaModalOpen(false)
});
}, [sources, index, trackAction, onScrollToIndex, setMediaModalOpen])}>
<Image2 source={{
uri: url
}} style={styles.mediaImage} />
</Pressable>;
};
TrailerItem = function TrailerItem(props) {
let ref4;
const { url, posterUrl, active, index: index2, sources: sources2, trackAction: trackAction2, width: width4, height: height2, onScrollToIndex: onScrollToIndex2, setMediaModalOpen: setMediaModalOpen2 } = props;
ref4 = void 0;
const styles = useStyles();
const ref2 = useRef(null);
const ref3 = useRef(0);
const [state, setState] = useState(0);
const callback2 = useCallback((a0) => {
ref3.current = a0;
}, []);
ref4 = useRef(createVideoControls(NOOP));
ref4.current.useSubscribe(callback2, NOOP, NOOP);
useEffect(() => {
if (isAndroid() && !active) {
setState((prevState) => prevState + 1);
} else {
ref4.current.seek(0);
}
}, [active]);
return <Pressable ref={ref2} style={[styles.mediaItem, {
width: width4,
height: height2
}]} onPress={useCallback(() => {
trackAction2(GameProfileTrackActionActions.ClickTrailer);
setMediaModalOpen2(true);
openMediaModal({
initialSources: sources2,
initialIndex: index2,
initialIndexVideoStartTime: ref3.current,
originViewOrOriginLayout: ref2.current,
analyticsSource: "game_profile",
openAs: "action-sheet",
onIndexChange: (a0) => onScrollToIndex2(a0),
onClose: () => setMediaModalOpen2(false)
});
}, [trackAction2, sources2, index2, onScrollToIndex2, setMediaModalOpen2])}>
<VideoComponent key={isAndroid() ? `render-${state}` : void 0} style={styles.mediaVideo} source={{
uri: url
}} poster={posterUrl} paused={!active} muted resizeMode="cover" pauseWhileAppInactive controls={ref4.current} />
</Pressable>;
};
width = 1920;
useStyles = createStyles({
container: {
gap: Module712.space.PX_12,
marginHorizontal: -Module712.space.PX_16
},
scrollView: {
flexDirection: "row",
overflow: "visible"
},
scrollViewContent: {
gap: Module712.space.PX_12,
paddingHorizontal: Module712.space.PX_16
},
mediaItem: {
maxWidth: 366,
maxHeight: 200,
borderRadius: Module712.radii.lg,
overflow: "hidden",
...Module712.shadows.SHADOW_HIGH
},
mediaImage: {
width: "100%",
height: "100%",
resizeMode: "cover"
},
mediaVideo: {
width: "100%",
height: "100%",
backgroundColor: Module712.colors.BLACK
}
});
export default function GameProfileMedia(props) {
let width3, height, memo, memo2, memo3, memo4, memo5, callback;
const { game, trackAction: trackAction3 } = props;
width3 = void 0;
height = void 0;
memo = void 0;
memo2 = void 0;
memo3 = void 0;
memo4 = void 0;
memo5 = void 0;
callback = void 0;
const styles = useStyles();
const width2 = useWindowDimensions_native().width;
const obscured = useObscuredSurface().obscured;
const [state, setState2] = useState(0);
const [state2, setState3] = useState(0);
const [state3, setState4] = useState(false);
const ref5 = useRef(null);
[width3, height] = useMemo(() => {
const bestMediaProxySize = getBestMediaProxySize(Math.min(width2, width) * getDevicePixelRatio());
return [bestMediaProxySize, bestMediaProxySize / 1.83];
}, [width2]);
const callback2 = useCallback((a0) => {
setState2(a0.nativeEvent.layout.width);
}, []);
memo = useMemo(() => {
let r10;
if (game == null) {
r10 = [];
} else {
let trailers = game.trailers;
if (trailers == null) {
trailers = [];
}
const r8 = trailers.map((trailer) => ({
type: "trailer",
url: getAssetURL(trailer.application_id, trailer.id, 1920, "mp4"),
thumbnailUrl: getAssetURL(trailer.application_id, trailer.id, Math.min(width2, width), "webp")
}));
r10 = [];
const r0 = HermesBuiltin.arraySpread(r10, r8, 0);
let screenshotUrls = game.screenshotUrls;
if (screenshotUrls == null) {
screenshotUrls = [];
}
HermesBuiltin.arraySpread(r10, screenshotUrls.map((screenshotUrl) => ({
type: "image",
url: screenshotUrl,
thumbnailUrl: screenshotUrl.replace.call(screenshotUrl, /size=\d+/g, `size=${width3}`)
})), r0);
}
return r10;
}, [game, width3, width2]);
memo2 = useMemo(() => Math.max(0, Math.min(366, state - Module712.space.PX_12 - 2 * Module712.space.PX_16)), [state]);
memo3 = useMemo(() => Math.min(200, memo2 / 1.83), [memo2]);
memo4 = useMemo(() => memo.map((item, index) => ({
uri: item.url,
videoURI: item.type === "trailer" ? item.url : void 0,
mediaIndex: index,
width,
height: 1080,
thumbnail: {
width: width3,
height,
uri: item.thumbnailUrl
},
accessoryType: "embed",
disableDownload: true
})), [memo, width3, height]);
memo5 = useMemo(() => {
let c26212_0 = (state - memo2 - 2 * Module712.space.PX_16) / 2;
let c26212_1 = memo2 + Module712.space.PX_12;
return memo.map((item, index) => Math.max(0, index * c26212_1 - c26212_0));
}, [memo, state, memo2]);
const callback3 = useCallback((a0) => {
let length;
if (memo5.length !== 0) {
const r11 = a0.nativeEvent.contentOffset.x;
const r20 = Math.abs(memo5[0] - r11);
const r6 = 1 < memo5.length;
let r2 = 1;
let r22 = r20;
let r1 = 0;
let r23 = 0;
if (r6) {
do {
const r28 = Math.abs(memo5[r2] - r11);
const r3 = r2;
let r29 = r22;
let r0 = r1;
if (r28 < r29) {
r29 = r28;
r0 = r3;
}
r2 = r3 + 1;
length = memo5.length;
r22 = r29;
r1 = r0;
r23 = r1;
} while (r2 < length);
}
setState3(r23);
}
}, [memo5]);
callback = useCallback((a0) => {
const current = ref5.current;
if (current != null) {
current.scrollTo({
x: memo5[a0],
y: 0,
animated: false
});
}
setState3(a0);
}, [memo5]);
return memo.length !== 0 ? <View style={styles.container} onLayout={callback2}>
<ScrollView ref={ref5} horizontal showsHorizontalScrollIndicator={false} style={styles.scrollView} contentContainerStyle={styles.scrollViewContent} decelerationRate="fast" snapToOffsets={memo5} snapToStart={false} snapToEnd={false} onMomentumScrollEnd={callback3}>
{memo.map((item, a1) => item.type === "trailer" ? <TrailerItem key={`${item.url}-${a1}`} url={item.url} posterUrl={item.thumbnailUrl} active={(obscured ? !obscured : !state3) && state2 === a1} index={a1} sources={memo4} trackAction={trackAction3} width={memo2} height={memo3} onScrollToIndex={callback} setMediaModalOpen={setState4} /> : <ImageItem key={`${item.url}-${a1}`} url={item.url} index={a1} sources={memo4} trackAction={trackAction3} width={memo2} height={memo3} onScrollToIndex={callback} setMediaModalOpen={setState4} />)}
</ScrollView>
</View> : null;
};
@@ -0,0 +1,119 @@
// Metro module 11946 (f11947).
import { useEffect, useMemo } from "react";
import { Image as Image2, StyleSheet, View } from "react-native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import ReanimatedRexport, { useSharedValue, useAnimatedStyle } from "../../../reanimated/ReanimatedRexport";
import { withTiming } from "../../../../design/animation/reanimated/timing/timing";
import { SUPPORTS_WEBP } from "../../../../utils/AvatarUtils";
import { BackgroundBlurFill } from "../../../../design/components/experimental/native";
import { Heading } from "../../../../design/components/Text/native/Text";
import GameProfileRankPill from "./GameProfileRankPill";
const useStyles = createStyles({
headerContainer: {
height: 56,
paddingHorizontal: Module712.space.PX_16,
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: Module712.colors.BORDER_SUBTLE,
overflow: "hidden",
justifyContent: "center"
},
headerRow: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_8
},
icon: {
width: 32,
height: 32,
borderRadius: Module712.radii.sm
},
titleContainer: {
flex: 1,
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_8,
minWidth: 0
},
headerRight: {
flexDirection: "row",
alignItems: "center"
},
rankPillContainer: {
flex: 1,
flexDirection: "row",
alignItems: "center"
}
});
const __initData = {
code: "function GameProfileNavigationHeaderTsx1(){const{headerRightProgress}=this.__closure;return{opacity:headerRightProgress.get()};}"
};
const __initData2 = {
code: "function GameProfileNavigationHeaderTsx2(){const{headerRightProgress}=this.__closure;return{opacity:1-headerRightProgress.get()};}"
};
export default function GameProfileNavigationHeader(props) {
const { game, application, headerRight } = props;
const styles = useStyles();
const r4 = headerRight != null;
let c19280_2 = r4;
const sharedValue = useSharedValue(r4 ? 1 : 0);
useEffect(() => {
sharedValue.set(withTiming(c19280_2 ? 1 : 0, {
duration: 200
}));
}, [r4, sharedValue]);
const x = () => ({
opacity: sharedValue.get()
});
x.__closure = {
headerRightProgress: sharedValue
};
x.__workletHash = 16001524280109;
x.__initData = __initData;
const animatedStyle = useAnimatedStyle(x);
const b = () => ({
opacity: 1 - sharedValue.get()
});
b.__closure = {
headerRightProgress: sharedValue
};
b.__workletHash = 5182160908530;
b.__initData = __initData2;
const animatedStyle2 = useAnimatedStyle(b);
const memo = useMemo(() => {
let r4 = game == null ? void 0 : game.getIconURL(32, SUPPORTS_WEBP ? "webp" : "png");
if (r4 == null) {
r4 = application == null ? void 0 : application.getIconURL(32, SUPPORTS_WEBP ? "webp" : "png");
}
if (r4 == null) {
r4 = null;
}
return r4;
}, [game, application]);
let r21 = game?.name;
if (r21 == null) {
r21 = application?.name;
}
const r55 = r21 == null;
const r56 = r55 ? null : <View style={styles.headerContainer}>
<BackgroundBlurFill />
<View style={styles.headerRow}>
{memo != null && <Image2 source={{
uri: memo
}} style={styles.icon} />}
<View style={styles.titleContainer}>
<Heading variant="redesign/heading-18/bold" color="mobile-text-heading-primary" lineClamp={1}>{r21}</Heading>
{game?.l30Rank != null && <View style={styles.rankPillContainer}>
<GameProfileRankPill rank={game.l30Rank} compact />
<ReanimatedRexport.View style={[StyleSheet.absoluteFill, animatedStyle2]}>
<GameProfileRankPill rank={game.l30Rank} />
</ReanimatedRexport.View>
</View>}
</View>
{headerRight != null && <ReanimatedRexport.View style={[styles.headerRight, animatedStyle]}>
{headerRight()}
</ReanimatedRexport.View>}
</View>
</View>;
return r56;
};
@@ -0,0 +1,39 @@
// Metro module 8518 (f8519).
import { View } from "react-native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import { TrophyIcon } from "../../../../design/components/Icon/native/redesign/generated/TrophyIcon";
import { Text } from "../../../../design/components/Text/native/Text";
import { intl, t } from "../../../../intl/index.native";
const useStyles = createStyles({
container: {
flex: 1,
flexDirection: "row",
alignItems: "flex-end"
},
gameRankPill: {
flexDirection: "row",
backgroundColor: Module712.colors.WHITE,
borderRadius: Module712.radii.round,
paddingHorizontal: Module712.space.PX_8,
alignItems: "center",
gap: Module712.space.PX_4,
...Module712.shadows.SHADOW_LOW
}
});
export default function GameProfileRankPill(props) {
const { rank, compact = false } = props;
const styles = useStyles();
return <View style={styles.container}>
<View style={styles.gameRankPill}>
<TrophyIcon size="xxs" color={Module712.colors.BLACK} />
<Text variant="text-xs/bold" color="text-overlay-dark">
{(compact ? intl.formatToPlainString(t.UA6RoE, {
rank
}) : intl.formatToPlainString(t.ehZXlZ, {
rank
})).toUpperCase()}
</Text>
</View>
</View>;
};
@@ -0,0 +1,19 @@
// Metro module 11942 (f11943).
import { useCallback } from "react";
import ActionSheetActionCreators from "../../../action_sheet/native/ActionSheetActionCreators";
import { GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
import ModalActionCreators from "../../../../actions/ModalActionCreators";
import { MODAL_KEY } from "./GameDetectionReportModal";
import { Button } from "../../../../design/components/Button/native/Button.native";
import { intl, t } from "../../../../intl/index.native";
export default function GameProfileReportButton(props) {
const { applicationId, trackAction } = props;
const callback = useCallback(() => {
ActionSheetActionCreators.hideActionSheet();
trackAction(GameProfileTrackActionActions.Feedback);
ModalActionCreators.pushLazy(import("./GameDetectionReportModal"), {
applicationId
}, MODAL_KEY);
}, [applicationId, trackAction]);
return <Button variant="secondary" size="md" text={intl.string(t.qP2cXd)} onPress={callback} />;
};
@@ -0,0 +1,227 @@
// Metro module 8521 (f8522).
import { useCallback } from "react";
import { Image as Image2, Pressable, View } from "react-native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import useOpenExternalUrlFromGameProfile from "../../hooks/useOpenExternalUrlFromGameProfile";
import Linking from "../../../../lib/native/Linking";
import { calculateSteamReviewScoreDescription } from "../../../game_detection/calculateSteamReviewScoreDescription";
import * as _GameProfileReviewUtils from "../../GameProfileReviewUtils";
import { getSteamReviewScoreDescriptionColor, getSteamReviewScoreDescriptionIntl } from "../../GameProfileReviewUtils";
import { GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
import { intl, t } from "../../../../intl/index.native";
import { SteamNeutralIcon } from "../../../../design/components/Icon/native/redesign/generated/SteamNeutralIcon";
import { Text } from "../../../../design/components/Text/native/Text";
import { SteamReviewScoreDescription } from "../../../game_detection/GameDetectionTypes";
import { getOpenCriticTierText, getOpenCriticCircleRatingColor, getOpenCriticTierImage } from "../../hooks/useGameProfileOpenCritic";
import OpenCriticRatingCircle from "./OpenCriticRatingCircle";
import { useSteamWebsiteUrl } from "../../hooks/useSteamWebsiteUrl";
import { SteamReleaseStatus } from "../../../../_bundle/Module8492";
let useStyles, OpenCriticReview;
const SteamReviewRow = function SteamReviewRow(props) {
const url = props.url;
let showBorderBottom = props.showBorderBottom;
const { trackAction, title, rating, ratingCount, isRecentRating } = props;
const styles = useStyles();
const openExternalUrlFromGameProfile = useOpenExternalUrlFromGameProfile(Linking.openURL);
let c16625_2 = openExternalUrlFromGameProfile;
const r11 = calculateSteamReviewScoreDescription(rating, ratingCount, isRecentRating);
const steamReviewScoreDescriptionColor = getSteamReviewScoreDescriptionColor(r11);
const props2 = {
onPress: useCallback(() => {
trackAction(GameProfileTrackActionActions.SteamReviews);
c16625_2(url);
}, [openExternalUrlFromGameProfile, url, trackAction]),
accessibilityRole: "link",
accessibilityLabel: intl.string(t.YNC5Di),
style: null,
children: null
};
const style = [styles.reviewRow, ,];
if (showBorderBottom) {
showBorderBottom = styles.reviewRowNotLast;
}
style[1] = showBorderBottom;
props2.style = style;
props2.children = [<View style={styles.steamNameContainer}>
<SteamNeutralIcon size="sm" color={Module712.colors.ICON_STRONG} />
<Text variant="heading-sm/medium" color="mobile-text-heading-primary">{title}</Text>
</View>, <View style={styles.steamRatingContainer}>
<Text variant="text-sm/medium" color={steamReviewScoreDescriptionColor}>
{getSteamReviewScoreDescriptionIntl(r11)}
</Text>
{ratingCount != null && r11 !== SteamReviewScoreDescription.NO_USER_REVIEWS && <Text variant="text-sm/medium" color="text-subtle">
{intl.format(t.sgIoin, {
rating_count: ratingCount.toLocaleString()
}).toString()}
</Text>}
</View>];
return <Pressable {...props2} />;
};
OpenCriticReview = function OpenCriticReview(props) {
const { game, url: url2, trackAction: trackAction2 } = props;
const styles = useStyles();
let r30 = game.reviews?.opencritic;
if (r30 == null) {
r30 = {
topCriticRating: void 0,
topCriticRatingCount: void 0,
tier: void 0
};
}
const tier = r30.tier;
let topCriticRating = r30.topCriticRating;
if (topCriticRating == null) {
topCriticRating = -1;
}
let topCriticRatingCount = r30.topCriticRatingCount;
if (topCriticRatingCount == null) {
topCriticRatingCount = -1;
}
const openExternalUrlFromGameProfile = useOpenExternalUrlFromGameProfile(Linking.openURL);
let c16626_2 = openExternalUrlFromGameProfile;
const callback = useCallback(() => {
trackAction2(GameProfileTrackActionActions.OpenCriticReviews);
c16626_2(url2);
}, [openExternalUrlFromGameProfile, url2, trackAction2]);
const accessibilityLabel = tier != null ? getOpenCriticTierText(tier) : "";
const r45 = tier != null ? getOpenCriticCircleRatingColor(tier) : {
foregroundColor: "",
backgroundColor: ""
};
const { foregroundColor, backgroundColor } = r45;
const props2 = {
onPress: callback,
accessibilityRole: "link",
accessibilityLabel: intl.string(t.aLNBAw),
style: styles.reviewRow,
children: null
};
const children = [<Text variant="heading-sm/medium" color="mobile-text-heading-primary">
{intl.string(t["UxvER+"])}
</Text>, ,];
const r89 = [tier != null ? <View style={styles.opencriticTopCriticContainer} accessibilityLabel={accessibilityLabel} accessibilityRole="image">
<Image2 source={{
uri: getOpenCriticTierImage(tier)
}} style={styles.opencriticTopCriticImage} accessible accessibilityLabel={accessibilityLabel} />
</View> : null, tier != null ? topCriticRating > 0 ? topCriticRatingCount > 0 ? <View style={[styles.opencriticTopCriticContainer, {
backgroundColor
}]} accessibilityLabel={intl.string(t.Ub4YR1)} accessibilityRole="image">
<OpenCriticRatingCircle rating={topCriticRating} strokeColor={foregroundColor} size={32} />
<View style={styles.opencriticTopCriticRatingContainer}>
<Text variant="text-xs/bold" color="text-overlay-light">
{Math.floor(topCriticRating)}
</Text>
</View>
</View> : null : null : null, topCriticRating <= 0 ? tier == null ? <Text variant="text-xs/medium" color={getSteamReviewScoreDescriptionColor(SteamReviewScoreDescription.NO_USER_REVIEWS)}>
{intl.string(t["0xYzpO"])}
</Text> : null : topCriticRatingCount <= 0 ? tier == null ? <Text variant="text-xs/medium" color={getSteamReviewScoreDescriptionColor(SteamReviewScoreDescription.NO_USER_REVIEWS)}>
{intl.string(t["0xYzpO"])}
</Text> : null : null];
children[1] = <View style={styles.opencriticRightContainer}>{r89}</View>;
props2.children = children;
return <Pressable {...props2} />;
};
useStyles = createStyles({
container: {
gap: Module712.space.PX_8
},
headerText: {
paddingHorizontal: Module712.space.PX_8
},
reviewContainer: {
borderRadius: Module712.radii.lg,
borderWidth: 1,
borderColor: Module712.colors.BORDER_SUBTLE,
overflow: "hidden"
},
reviewRow: {
height: 56,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
padding: Module712.space.PX_12
},
reviewRowNotLast: {
borderBottomWidth: 1,
borderBottomColor: Module712.colors.BACKGROUND_MOD_SUBTLE
},
steamNameContainer: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_8
},
steamRatingContainer: {
flexDirection: "row",
alignItems: "flex-end",
flexShrink: 1,
paddingLeft: Module712.space.PX_32,
gap: Module712.space.PX_4
},
opencriticRightContainer: {
flexDirection: "row",
alignItems: "center",
gap: Module712.space.PX_12
},
opencriticTopCriticContainer: {
width: 32,
height: 32,
borderRadius: Module712.radii.round,
backgroundColor: Module712.colors.BACKGROUND_SURFACE_HIGH,
alignItems: "center",
justifyContent: "center"
},
opencriticTopCriticImage: {
width: 32,
height: 32
},
opencriticTopCriticRatingContainer: {
position: "absolute",
top: 0,
left: 1,
right: 0,
bottom: 0,
alignItems: "center",
justifyContent: "center"
}
});
export default function GameProfileReviews(props) {
let r68;
const { game, trackAction: trackAction3 } = props;
const styles = useStyles();
const steamWebsiteUrl = useSteamWebsiteUrl(game?.id);
const opencriticUrl = game?.opencriticUrl;
if (game == null) {
return null;
}
const r4 = game.steamReleaseStatus !== SteamReleaseStatus.RETIRED_ABANDONED && steamWebsiteUrl != null;
const steam = game.reviews?.steam;
const r48 = calculateSteamReviewScoreDescription(steam?.recentRating, steam?.recentRatingCount, true);
const r3 = r4 ? r48 !== SteamReviewScoreDescription.NO_USER_REVIEWS : r4;
const canShowLocalizedSteamReview = _GameProfileReviewUtils.canShowLocalizedSteamReview(steam);
const r57 = steam == null;
const rating = canShowLocalizedSteamReview ? r57 ? void 0 : steam.localizedRating : r57 ? void 0 : steam.rating;
const r59 = steam == null;
const ratingCount = canShowLocalizedSteamReview ? r59 ? void 0 : steam.localizedRatingCount : r59 ? void 0 : steam.ratingCount;
const r25 = canShowLocalizedSteamReview ? t["aWb+V4"] : t["8e4LiB"];
const showBorderBottom = game.reviews?.opencritic != null && opencriticUrl != null;
L55: {
if (!r4 && !r3) {
r68 = null;
if (!showBorderBottom) {
break L55;
}
}
r68 = <View style={styles.container}>
<Text variant="heading-sm/semibold" color="mobile-text-heading-primary" style={styles.headerText}>
{intl.string(t.GaAQXP)}
</Text>
<View style={styles.reviewContainer}>
{r3 ? steamWebsiteUrl != null ? <SteamReviewRow url={steamWebsiteUrl} showBorderBottom={r4 || showBorderBottom} trackAction={trackAction3} title={intl.string(t.MQGNsN)} rating={steam?.recentRating} ratingCount={steam?.recentRatingCount} isRecentRating /> : null : null}
{r4 ? steamWebsiteUrl != null ? <SteamReviewRow url={steamWebsiteUrl} showBorderBottom={showBorderBottom} trackAction={trackAction3} title={intl.string(r25)} rating={rating} ratingCount={ratingCount} isRecentRating={false} /> : null : null}
{showBorderBottom ? opencriticUrl != null ? <OpenCriticReview game={game} url={opencriticUrl} trackAction={trackAction3} /> : null : null}
</View>
</View>;
}
return r68;
};
@@ -0,0 +1,297 @@
// Metro module 8481 (f8482).
import { useState, useRef, useCallback, useMemo, useEffect } from "react";
import { ActivityIndicator, View } from "react-native";
import GameProfileStore from "../../GameProfileStore";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import { Button } from "../../../../design/components/Button/native/Button.native";
import { intl, t } from "../../../../intl/index.native";
import { useBottomSheetRef } from "../../../../design/components/Sheet/native/useBottomSheetRef";
import useOpenExternalUrlFromGameProfile from "../../hooks/useOpenExternalUrlFromGameProfile";
import Linking from "../../../../lib/native/Linking";
import { generateViewId, getGuildIdAndVerifiedFromInvite, trackGameProfileAction, trackGameProfileOpen, GameProfileTypes, trackGameProfileClose } from "../../GameProfileAnalyticUtils";
import { useGame } from "../../../games/hooks/useGame";
import useGameProfileObscured from "../../hooks/useGameProfileObscured";
import * as _ReanimatedRexport from "../../../reanimated/ReanimatedRexport";
import ReanimatedRexport, { useSharedValue, useAnimatedReaction, useAnimatedStyle } from "../../../reanimated/ReanimatedRexport";
import useInAppBrowserReturn from "../hooks/useInAppBrowserReturn";
import * as _timing from "../../../../design/animation/reanimated/timing/timing";
import { useGameProfileStoreWebsites } from "../../hooks/useGameProfileStoreWebsites";
import getGameProfileStoreWebsiteData from "../utils/getGameProfileStoreWebsiteData";
import ActionSheetActionCreators, { showActionSheet } from "../../../action_sheet/native/ActionSheetActionCreators";
import GameProfileStoreLinksActionSheet, { ACTION_SHEET_KEY } from "./GameProfileStoreLinksActionSheet";
import { GameProfileSimilarGamesMobileExperiment } from "../../SimilarGamesExperiments";
import { BottomSheet } from "../../../../design/components/Sheet/native/BottomSheet.native";
import { BottomSheetScrollView } from "../../../../_bundle/Module5245";
import ObscuredSurface from "../../../safety_common/native/ObscuredSurface";
import GameProfileView from "./GameProfileView";
import GameProfileNavigationHeader from "./GameProfileNavigationHeader";
import { ActionSheetHeaderBar } from "../../../../design/components/Sheet/native/ActionSheetHeaderBar.native";
let useStyles, __initData, __initData2, __initData3, __initData4, __initData5;
const GetButton = function GetButton(props) {
const onPress = props.onPress;
return <Button variant="primary" size="sm" text={intl.string(t.l8JeHg)} onPress={onPress} accessibilityLabel={intl.string(t.Vsxqmz)} />;
};
useStyles = createStyles({
loadingContainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
minHeight: 300,
backgroundColor: Module712.colors.BACKGROUND_BASE_LOWEST
},
scrollView: {
flex: 1,
backgroundColor: Module712.colors.BACKGROUND_BASE_LOWEST
},
stickyHeader: {
position: "absolute",
top: 0,
left: 0,
right: 0
}
});
__initData = {
code: "function GameProfileScreenTsx1(){const{heroHeaderHeight,scrollY,STICKY_HEADER_HEIGHT}=this.__closure;return heroHeaderHeight.get()>0&&scrollY.get()>=heroHeaderHeight.get()-STICKY_HEADER_HEIGHT;}"
};
__initData2 = {
code: "function GameProfileScreenTsx2(isVisible,wasVisible){const{stickyHeaderVisible,withTiming}=this.__closure;if(isVisible!==wasVisible){stickyHeaderVisible.set(withTiming(isVisible?1:0,{duration:150}));}}"
};
__initData3 = {
code: "function GameProfileScreenTsx3(){const{interpolate,stickyHeaderVisible,STICKY_HEADER_HEIGHT}=this.__closure;return{transform:[{translateY:interpolate(stickyHeaderVisible.get(),[0,1],[-1*STICKY_HEADER_HEIGHT,0])}]};}"
};
__initData4 = {
code: "function GameProfileScreenTsx4(){const{scrollY,storeLinksSectionBottomY,STICKY_HEADER_HEIGHT}=this.__closure;return scrollY.get()>storeLinksSectionBottomY.get()-STICKY_HEADER_HEIGHT;}"
};
__initData5 = {
code: "function GameProfileScreenTsx5(shouldShow,prevShouldShow){const{runOnJS,setShowGetButton}=this.__closure;if(shouldShow!==prevShouldShow){runOnJS(setShowGetButton)(shouldShow);}}"
};
export default function GameProfileScreen(props) {
let ref, ref2, state2, name, sharedValue, ref3, sharedValue2, sharedValue3, sharedValue4, state3, setState, gameProfileStoreWebsites, memo, ref4, ref5, callback, callback2;
const { gameId, source, sourceUserId, initialScrollOffset = 0 } = props;
let c16611_3 = initialScrollOffset;
ref = void 0;
ref2 = void 0;
state2 = void 0;
name = void 0;
sharedValue = void 0;
ref3 = void 0;
sharedValue2 = void 0;
sharedValue3 = void 0;
sharedValue4 = void 0;
state3 = void 0;
setState = void 0;
gameProfileStoreWebsites = void 0;
memo = void 0;
ref4 = void 0;
ref5 = void 0;
callback = void 0;
callback2 = void 0;
const styles = useStyles();
const bottomSheetRef2 = useBottomSheetRef();
const { bottomSheetRef, bottomSheetClose } = bottomSheetRef2;
const openExternalUrlFromGameProfile = useOpenExternalUrlFromGameProfile(Linking.openURL);
let c16611_4 = openExternalUrlFromGameProfile;
const [state] = useState(() => generateViewId());
ref = useRef(null);
ref2 = useRef(0);
const game = useGame(gameId);
const { data, isLoading } = game;
const gameProfileObscured = useGameProfileObscured(data);
let onGuildInviteResolved;
[state2, onGuildInviteResolved] = useState(null);
name = data?.name;
sharedValue = useSharedValue(0);
const callback3 = useCallback((a0) => {
const current = a0.nativeEvent.contentOffset.y;
sharedValue.set(current);
ref2.current = current;
}, [sharedValue]);
ref3 = useRef(false);
const callback4 = useCallback(() => {
if (c16611_3 > 0 && !ref3.current) {
ref3.current = true;
const current = ref.current;
if (current != null) {
current.scrollTo({
y: c16611_3,
animated: false
});
}
}
}, [initialScrollOffset]);
useInAppBrowserReturn({
gameId: data?.id,
scrollOffsetRef: ref2
});
sharedValue2 = useSharedValue(0);
sharedValue3 = useSharedValue(0);
const U = () => sharedValue2.get() > 0 && sharedValue.get() >= sharedValue2.get() - 56;
U.__closure = {
heroHeaderHeight: sharedValue2,
scrollY: sharedValue,
STICKY_HEADER_HEIGHT: 56
};
U.__workletHash = 15395308691297;
U.__initData = __initData;
const j = function j(a0, a1) {
if (a0 !== a1) {
sharedValue3.set(_timing.withTiming(a0 ? 1 : 0, {
duration: 150
}));
}
};
j.__closure = {
stickyHeaderVisible: sharedValue3,
withTiming: _timing.withTiming
};
j.__workletHash = 3161097061646;
j.__initData = __initData2;
useAnimatedReaction(U, j);
const q = function q() {
return {
transform: [{
translateY: _ReanimatedRexport.interpolate(sharedValue3.get(), [0, 1], [-56, 0])
}]
};
};
q.__closure = {
interpolate: _ReanimatedRexport.interpolate,
stickyHeaderVisible: sharedValue3,
STICKY_HEADER_HEIGHT: 56
};
q.__workletHash = 16452163547712;
q.__initData = __initData3;
const animatedStyle = useAnimatedStyle(q);
sharedValue4 = useSharedValue(Infinity);
[state3, setState] = useState(false);
const X = () => sharedValue.get() > sharedValue4.get() - 56;
X.__closure = {
scrollY: sharedValue,
storeLinksSectionBottomY: sharedValue4,
STICKY_HEADER_HEIGHT: 56
};
X.__workletHash = 14521195063038;
X.__initData = __initData4;
const Q = function Q(a0, a1) {
if (a0 !== a1) {
_ReanimatedRexport.runOnJS(setState)(a0);
}
};
Q.__closure = {
runOnJS: _ReanimatedRexport.runOnJS,
setShowGetButton: setState
};
Q.__workletHash = 15045914286853;
Q.__initData = __initData5;
useAnimatedReaction(X, Q);
gameProfileStoreWebsites = useGameProfileStoreWebsites(data);
memo = useMemo(() => gameProfileStoreWebsites.map(getGameProfileStoreWebsiteData).filter((item) => item != null), [gameProfileStoreWebsites]);
ref4 = useRef(void 0);
ref5 = useRef(null);
useEffect(() => {
ref4.current = name;
}, [name]);
useEffect(() => {
ref5.current = state2;
}, [state2]);
callback = useCallback((a0, a1) => {
const guildIdAndVerifiedFromInvite = getGuildIdAndVerifiedFromInvite(ref5.current);
const { guildId, isVerified } = guildIdAndVerifiedFromInvite;
let current = ref4.current;
if (current == null) {
current = "";
}
trackGameProfileAction({
gameName: current,
gameId,
action: a0,
similarGameId: a1,
viewId: state,
guildId,
isVerified,
source
});
}, [gameId, state, source]);
callback2 = useCallback(() => {
if (memo.length === 1) {
const [r31] = memo;
callback(r31.action);
c16611_4(r31.url);
} else if (memo.length > 1) {
let current = ref4.current;
if (current == null) {
current = "";
}
showActionSheet({
key: ACTION_SHEET_KEY,
content: <GameProfileStoreLinksActionSheet gameName={current} websiteButtons={memo} trackAction={callback} />,
stackingBehavior: "stack"
});
}
}, [memo, callback, openExternalUrlFromGameProfile]);
useEffect(() => {
let current = ref4.current;
if (current == null) {
current = "";
}
trackGameProfileOpen({
source,
viewId: state,
gameId,
gameName: current,
authorId: sourceUserId,
profileType: GameProfileTypes.FullProfile
});
}, [gameId, source, sourceUserId, state]);
useEffect(() => () => {
let similarGames;
const guildIdAndVerifiedFromInvite = getGuildIdAndVerifiedFromInvite(ref5.current);
const { guildId, isVerified } = guildIdAndVerifiedFromInvite;
const enabled = GameProfileSimilarGamesMobileExperiment.getConfig({
location: "GameProfileScreenClose"
}).enabled;
let current = ref4.current;
if (current == null) {
current = "";
}
if (enabled) {
let r34 = GameProfileStore.getSimilarGames(gameId);
if (r34 == null) {
r34 = [];
}
similarGames = r34;
} else {
similarGames = [];
}
trackGameProfileClose({
viewId: state,
gameId,
gameName: current,
playedFriendIds: [],
playedFriendsData: [],
similarGames,
guildId,
isVerified
});
}, [gameId, source, sourceUserId, state]);
const callback5 = useCallback((a0) => {
sharedValue2.set(a0);
}, [sharedValue2]);
const callback6 = useCallback((a0) => {
sharedValue4.set(a0);
}, [sharedValue4]);
return <BottomSheet ref={bottomSheetRef} startExpanded scrollable handleDisabled onExpand={callback4}>
{!isLoading && data != null ? <BottomSheetScrollView ref={ref} style={styles.scrollView} onScroll={callback3}>
<ObscuredSurface obscured={gameProfileObscured}>
<GameProfileView game={data} invite={state2} viewId={state} source={source} trackAction={callback} onGuildInviteResolved={onGuildInviteResolved} closeModal={() => ActionSheetActionCreators.hideAllActionSheets()} scrollY={sharedValue} websiteButtons={memo} onStoreLinksMeasured={callback6} onHeaderHeightMeasured={callback5} scrollOffsetRef={ref2} />
</ObscuredSurface>
</BottomSheetScrollView> : <View style={styles.loadingContainer}>
<ActivityIndicator animating size="large" />
</View>}
<ReanimatedRexport.View style={[styles.stickyHeader, animatedStyle]} pointerEvents="box-none">
<GameProfileNavigationHeader game={data} headerRight={useMemo(() => memo.length > 0 ? state3 ? () => <GetButton onPress={callback2} /> : void 0 : void 0, [memo, state3, callback2])} />
</ReanimatedRexport.View>
<ActionSheetHeaderBar variant="overlay" onPress={bottomSheetClose} />
</BottomSheet>;
};
@@ -0,0 +1,82 @@
// Metro module 8659 (f8660).
import { useCallback } from "react";
import { View } from "react-native";
import CollectiblesCategoryStore from "../../../collectibles/CollectiblesCategoryStore";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import CollectiblesShopCardV2, { COLLECTIBLES_SHOP_CARD_GAP, COLLECTIBLES_SHOP_CARD_WIDTH } from "../../../collectibles/native/CollectiblesShopCardV2";
import { useGameProfileShopCollection } from "../../hooks/useGameProfileShopCollection";
import { useFetchCollectiblesProducts } from "../../../collectibles/hooks/useFetchCollectiblesProducts";
import { useStateFromStoresArray } from "../../../../_bundle/defaultAreStatesEqual";
import { GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
import { openCollectiblesShop } from "../../../collectibles/CollectiblesActionCreators";
import AnalyticsLocation from "../../../app_analytics/AnalyticsLocation";
import { Text } from "../../../../design/components/Text/native/Text";
import { intl, t } from "../../../../intl/index.native";
import { Button } from "../../../../design/components/Button/native/Button.native";
import { ChevronSmallRightIcon } from "../../../../design/components/Icon/native/redesign/generated/ChevronSmallRightIcon";
import { FlashList } from "../../../../_bundle/noop_6676";
let useStyles, GameProfileShopCarouselContent;
const HorizontalSpacing = function HorizontalSpacing() {
return <View style={{
width: COLLECTIBLES_SHOP_CARD_GAP
}} />;
};
GameProfileShopCarouselContent = function GameProfileShopCarouselContent(props) {
const { collectionId, closeModal, trackAction } = props;
const styles = useStyles();
const gameProfileShopCollection = useGameProfileShopCollection(collectionId);
useFetchCollectiblesProducts(gameProfileShopCollection);
const stateFromStoresArray = useStateFromStoresArray([CollectiblesCategoryStore], () => gameProfileShopCollection.map((item) => CollectiblesCategoryStore.getProduct(item)).filter((item) => item != null));
const callback = useCallback(() => {
trackAction(GameProfileTrackActionActions.DiscordCollectiblesShop);
closeModal();
openCollectiblesShop({
analyticsLocations: [AnalyticsLocation.GAME_PROFILE],
analyticsSource: AnalyticsLocation.GAME_PROFILE
});
}, [trackAction, closeModal]);
return stateFromStoresArray.length !== 0 ? <View style={styles.container}>
<View style={styles.header}>
<Text variant="heading-sm/semibold" color="mobile-text-heading-primary">
{intl.string(t["5DYPT8"])}
</Text>
<Button text={intl.string(t.budhsM)} variant="tertiary" size="sm" icon={<ChevronSmallRightIcon size="sm" />} iconPosition="end" onPress={callback} />
</View>
<FlashList key={collectionId} horizontal data={stateFromStoresArray} renderItem={({ item }) => <CollectiblesShopCardV2 solidBackground cardStyle={styles.card} product={item} hideWishlistButton hidePrice onPress={() => {
trackAction(GameProfileTrackActionActions.DiscordCollectiblesShop);
closeModal();
openCollectiblesShop({
analyticsLocations: [AnalyticsLocation.GAME_PROFILE],
analyticsSource: AnalyticsLocation.GAME_PROFILE,
initialProductSkuId: item.skuId
});
}} />} showsHorizontalScrollIndicator={false} ItemSeparatorComponent={HorizontalSpacing} ListHeaderComponent={HorizontalSpacing} ListFooterComponent={HorizontalSpacing} decelerationRate="fast" snapToInterval={COLLECTIBLES_SHOP_CARD_WIDTH + COLLECTIBLES_SHOP_CARD_GAP} />
</View> : null;
};
useStyles = createStyles({
container: {
gap: Module712.space.PX_8,
marginHorizontal: -1 * Module712.space.PX_16
},
header: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingHorizontal: Module712.space.PX_8,
marginHorizontal: Module712.space.PX_16
},
card: {
borderRadius: Module712.radii.lg
}
});
export default function GameProfileShopCarousel(props) {
const { game, closeModal: closeModal2, trackAction: trackAction2 } = props;
const r1 = game == null;
let collectionId = void 0;
if (!r1) {
const shopCollectionIds = game.shopCollectionIds;
collectionId = shopCollectionIds == null ? void 0 : shopCollectionIds[0];
}
return collectionId == null ? null : <GameProfileShopCarouselContent collectionId={collectionId} closeModal={closeModal2} trackAction={trackAction2} />;
};
@@ -0,0 +1,137 @@
// Metro module 11922 (f11923).
import { useCallback } from "react";
import { Image as Image2, Pressable, View } from "react-native";
import Module712 from "../../../../_bundle/Module712";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import useShouldOpenGameProfileModal from "../../hooks/useShouldOpenGameProfileModal";
import { GameProfileSources, GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
import GameProfileActionCreators_native from "../../GameProfileActionCreators.native";
import { intl, t } from "../../../../intl/index.native";
import { Text } from "../../../../design/components/Text/native/Text";
import { GameProfileSimilarGamesMobileExperiment } from "../../SimilarGamesExperiments";
import useSimilarGames from "../../hooks/useSimilarGames";
import useWindowDimensions_native from "../../../screen/useWindowDimensions.native";
import { FlashList } from "../../../../_bundle/noop_6676";
let PX_12, PX_16, PX_122, useStyles, ListPadding, SimilarGameCard, LoadingCard;
const Spacer = function Spacer() {
return <View style={{
width: PX_12
}} />;
};
ListPadding = function ListPadding() {
return <View style={{
width: Module712.space.PX_16
}} />;
};
SimilarGameCard = function SimilarGameCard(props) {
const { game, trackAction, cardWidth: cardWidth2 } = props;
const styles = useStyles();
const height = 1.34 * cardWidth2;
const coverURL = game.getCoverURL(Math.ceil(height));
const r10 = {
width: cardWidth2,
height
};
const shouldOpenGameProfileModal = useShouldOpenGameProfileModal({
gameId: game.id,
source: GameProfileSources.SimilarGames
});
const { shouldOpenGameProfile, gameId } = shouldOpenGameProfileModal;
return <Pressable style={[styles.card, {
width: cardWidth2
}]} onPress={useCallback(() => {
trackAction(GameProfileTrackActionActions.ClickSimilarGame, game.id);
let r14 = shouldOpenGameProfile;
if (shouldOpenGameProfile) {
r14 = gameId != null;
}
if (r14) {
GameProfileActionCreators_native.openGameProfileModal({
gameId,
gameProfileModalChecks: {
shouldOpenGameProfile: true,
gameId
},
source: GameProfileSources.SimilarGames
});
}
}, [game.id, trackAction, shouldOpenGameProfile, gameId])} accessibilityRole="button" accessibilityLabel={intl.formatToPlainString(t["8QLQB+"], {
gameName: game.name
})}>
{coverURL != null ? <Image2 source={{
uri: coverURL
}} style={[styles.coverArt, r10]} /> : <View style={[styles.coverArtFallback, r10]}>
<Text variant="text-xs/medium" color="text-overlay-light" lineClamp={3}>{game.name}</Text>
</View>}
</Pressable>;
};
LoadingCard = function LoadingCard(props) {
const cardWidth2 = props.cardWidth;
return <View style={{
width: cardWidth2
}}>
<View style={[useStyles().loadingArt, {
width: cardWidth2,
height: 1.34 * cardWidth2
}]} />
</View>;
};
PX_12 = Module712.space.PX_12;
PX_16 = Module712.space.PX_16;
PX_122 = Module712.space.PX_12;
useStyles = createStyles({
container: {
gap: Module712.space.PX_8,
marginHorizontal: -1 * Module712.space.PX_16
},
header: {
paddingHorizontal: Module712.space.PX_16
},
card: {
gap: Module712.space.PX_4
},
coverArt: {
borderRadius: Module712.radii.sm
},
coverArtFallback: {
borderRadius: Module712.radii.sm,
backgroundColor: Module712.colors.BACKGROUND_SURFACE_HIGH,
justifyContent: "center",
alignItems: "center",
padding: Module712.space.PX_8
},
loadingArt: {
borderRadius: Module712.radii.sm,
backgroundColor: Module712.colors.BACKGROUND_SURFACE_HIGH
}
});
export default function GameProfileSimilarGames(props) {
const { gameId: gameId2, trackAction: trackAction2 } = props;
const styles = useStyles();
const config = GameProfileSimilarGamesMobileExperiment.useConfig({
location: "GameProfileSimilarGames"
});
const { enabled, dense } = config;
const similarGames2 = useSimilarGames(gameId2, enabled);
const { isFetching, similarGames } = similarGames2;
const length = dense ? 4 : 3;
const cardWidth = (useWindowDimensions_native().width - 2 * PX_16 - (length - 1) * PX_12 - PX_122) / length;
const data = Array.from({
length
}, (a0, a1) => a1);
return isFetching ? <View style={styles.container}>
<View style={styles.header}>
<Text variant="heading-sm/semibold" color="mobile-text-heading-primary">
{intl.string(t["6rLyQB"])}
</Text>
</View>
<FlashList horizontal data={data} renderItem={() => <LoadingCard cardWidth={cardWidth} />} showsHorizontalScrollIndicator={false} ItemSeparatorComponent={Spacer} ListHeaderComponent={ListPadding} ListFooterComponent={ListPadding} />
</View> : similarGames.length !== 0 ? <View style={styles.container}>
<View style={styles.header}>
<Text variant="heading-sm/semibold" color="mobile-text-heading-primary">
{intl.string(t["6rLyQB"])}
</Text>
</View>
<FlashList horizontal data={similarGames} renderItem={(info) => <SimilarGameCard game={info.item} trackAction={trackAction2} cardWidth={cardWidth} />} showsHorizontalScrollIndicator={false} ItemSeparatorComponent={Spacer} ListHeaderComponent={ListPadding} ListFooterComponent={ListPadding} decelerationRate="fast" snapToInterval={cardWidth + PX_12} />
</View> : null;
};
@@ -0,0 +1,51 @@
// Metro module 8520 (f8521).
import { View } from "react-native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import useOpenExternalUrlFromGameProfile from "../../hooks/useOpenExternalUrlFromGameProfile";
import Linking from "../../../../lib/native/Linking";
import { Button } from "../../../../design/components/Button/native/Button.native";
import { intl, t } from "../../../../intl/index.native";
import { showActionSheet } from "../../../action_sheet/native/ActionSheetActionCreators";
import GameProfileStoreLinksActionSheet, { ACTION_SHEET_KEY } from "./GameProfileStoreLinksActionSheet";
import { GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
let useStyles;
const WebsiteGameStoreLinkButton = function WebsiteGameStoreLinkButton(props) {
const { data, trackAction } = props;
let c16623_2 = useOpenExternalUrlFromGameProfile(Linking.openURL);
return <Button variant="secondary" size="md" text={data.title} icon={data.icon} onPress={() => {
trackAction(data.action);
c16623_2(data.url);
}} />;
};
useStyles = createStyles({
container: {
flexDirection: "column",
gap: Module712.space.PX_8
}
});
export default function GameProfileStoreLinks(props) {
const { game, trackAction: trackAction2, websiteButtons } = props;
const styles = useStyles();
const name = game?.name;
if (websiteButtons.length !== 0 && name != null) {
if (websiteButtons.length === 1) {
return <WebsiteGameStoreLinkButton data={websiteButtons[0]} trackAction={trackAction2} />;
}
if (websiteButtons.length === 2) {
return <View style={styles.container}>
<WebsiteGameStoreLinkButton data={websiteButtons[0]} trackAction={trackAction2} />
<WebsiteGameStoreLinkButton data={websiteButtons[1]} trackAction={trackAction2} />
</View>;
}
const r35 = <Button variant="secondary" size="md" text={intl.string(t["/hMurx"])} onPress={() => showActionSheet({
key: ACTION_SHEET_KEY,
content: <GameProfileStoreLinksActionSheet gameName={name} websiteButtons={websiteButtons} trackAction={trackAction2} />
})} />;
return websiteButtons[0]?.action === GameProfileTrackActionActions.XboxGamePassStoreLink ? <View style={styles.container}>
<WebsiteGameStoreLinkButton data={websiteButtons[0]} trackAction={trackAction2} />
{r35}
</View> : r35;
}
return null;
};
@@ -0,0 +1,56 @@
// Metro module 8511 (f8512).
import { View } from "react-native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import useOpenExternalUrlFromGameProfile from "../../hooks/useOpenExternalUrlFromGameProfile";
import Linking from "../../../../lib/native/Linking";
import useSafeAreaInsets_native from "../../../safe_area/useSafeAreaInsets.native";
import { ActionSheet } from "../../../../design/components/Sheet/native/ActionSheet.native";
import { BottomSheetScrollView } from "../../../../_bundle/Module5245";
import { Text } from "../../../../design/components/Text/native/Text";
import { intl, t } from "../../../../intl/index.native";
import { Button } from "../../../../design/components/Button/native/Button.native";
import ActionSheetActionCreators from "../../../action_sheet/native/ActionSheetActionCreators";
const useStyles = createStyles({
header: {
gap: Module712.space.PX_8,
paddingTop: Module712.space.PX_8,
paddingHorizontal: Module712.space.PX_16,
paddingBottom: Module712.space.PX_24
},
headerText: {
textAlign: "center"
},
buttons: {
gap: Module712.space.PX_12
}
});
export default function GameProfileStoreLinksActionSheet(props) {
const { gameName, websiteButtons, trackAction } = props;
const styles = useStyles();
let c16617_1 = useOpenExternalUrlFromGameProfile(Linking.openURL);
return <ActionSheet>
<BottomSheetScrollView contentContainerStyle={{
paddingBottom: useSafeAreaInsets_native().bottom + Module712.space.PX_16
}}>
<View style={styles.header}>
<Text variant="heading-lg/semibold" color="mobile-text-heading-primary" style={styles.headerText}>
{intl.string(t["/4gj6r"])}
</Text>
<Text variant="text-md/medium" color="text-subtle" style={styles.headerText}>
{intl.format(t["0acM2Y"], {
gameName
})}
</Text>
</View>
<View style={styles.buttons}>
{websiteButtons.map(({ icon, title, url, action }) => <Button key={url} icon={icon} text={title} variant="secondary" size="md" onPress={() => {
ActionSheetActionCreators.hideActionSheet();
trackAction(action);
c16617_1(url);
}} />)}
</View>
</BottomSheetScrollView>
</ActionSheet>;
};
export const ACTION_SHEET_KEY = "game-profile-store-links";
@@ -0,0 +1,42 @@
// Metro module 8643 (f8644).
import { useState, useCallback } from "react";
import { Pressable, View } from "react-native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import { GameProfileTrackActionActions } from "../../GameProfileAnalyticUtils";
import { intl, t } from "../../../../intl/index.native";
import { Text } from "../../../../design/components/Text/native/Text";
const useStyles = createStyles({
container: {
flexDirection: "column"
}
});
export default function GameProfileSummary(props) {
const { game, trackAction } = props;
const styles = useStyles();
const [state, setState] = useState(false);
const [state2, setState2] = useState(null);
const callback2 = useCallback((a0) => {
if (state2 == null) {
setState2(a0.nativeEvent.lines.length > 3);
}
}, [state2]);
const callback = useCallback(() => {
const r1 = !state;
trackAction(state ? GameProfileTrackActionActions.ShowLess : GameProfileTrackActionActions.ShowMore);
setState(r1);
}, [state, trackAction]);
let r17 = game?.summaryLocalized;
if (r17 == null) {
r17 = game?.description;
}
if (r17 == null) {
return null;
}
const accessibilityLabel = intl.string(state ? t["6MwJo/"] : t.lBeKY2);
return <View style={styles.container}>
<Text variant="text-md/normal" color="interactive-text-active" lineClamp={state ? void 0 : state2 == null ? void 0 : 3} onTextLayout={callback2}>{r17}</Text>
{state2 ? <Pressable onPress={callback} accessibilityRole="button" accessibilityLabel={accessibilityLabel}>
<Text variant="text-md/medium" color="text-brand">{accessibilityLabel}</Text>
</Pressable> : null}
</View>;
};
@@ -0,0 +1,84 @@
// Metro module 8515 (f8516).
import { useRef, useCallback } from "react";
import { View } from "react-native";
import { createStyles } from "../../../../design/components/Styles/native/createStyles";
import Module712 from "../../../../_bundle/Module712";
import useAnalyticsLocations, { AnalyticsLocationProvider } from "../../../app_analytics/useAnalyticsLocations";
import AnalyticsLocation from "../../../app_analytics/AnalyticsLocation";
import GameProfileHeader from "./GameProfileHeader";
import GameProfileMedia from "./GameProfileMedia";
import GameProfileStoreLinks from "./GameProfileStoreLinks";
import GameProfileReviews from "./GameProfileReviews";
import GameProfileSummary from "./GameProfileSummary";
import GameProfileLinkAccount from "./GameProfileLinkAccount";
import GameProfileCommunity from "./GameProfileCommunity";
import GameProfileAnnouncements from "./GameProfileAnnouncements";
import GameProfileShopCarousel from "./GameProfileShopCarousel";
import GameProfileSimilarGames from "./GameProfileSimilarGames";
import GameProfileDetails from "./GameProfileDetails";
import GameProfileGameClaimCta from "./GameProfileGameClaimCta";
import GameProfileReportButton from "./GameProfileReportButton";
const useStyles = createStyles({
container: {
flex: 1,
backgroundColor: Module712.colors.BACKGROUND_BASE_LOWEST,
paddingBottom: Module712.space.PX_16
},
body: {
flexDirection: "column",
paddingVertical: Module712.space.PX_16,
paddingHorizontal: Module712.space.PX_16,
gap: Module712.space.PX_32,
maxWidth: 520,
alignSelf: "center",
width: "100%"
},
buttonsContainer: {
flexDirection: "column",
gap: Module712.space.PX_8
}
});
export default function GameProfileView(props) {
const { game, invite, viewId, source, trackAction, onGuildInviteResolved, closeModal, scrollY, websiteButtons, onStoreLinksMeasured, onHeaderHeightMeasured, scrollOffsetRef } = props;
const styles = useStyles();
const ref = useRef(null);
const ref2 = useRef(null);
const analyticsLocations = useAnalyticsLocations(AnalyticsLocation.GAME_PROFILE).analyticsLocations;
const callback = useCallback(() => {
const current = ref.current;
const current2 = ref2.current;
if (current != null && current2 != null && onStoreLinksMeasured != null) {
onStoreLinksMeasured(current + current2);
}
}, [onStoreLinksMeasured]);
return <AnalyticsLocationProvider value={analyticsLocations}>
<View style={styles.container}>
<GameProfileHeader game={game} scrollY={scrollY} onHeightMeasured={onHeaderHeightMeasured} />
<View style={styles.body} onLayout={(event) => {
ref.current = event.nativeEvent.layout.y;
callback();
}}>
<GameProfileMedia game={game} viewId={viewId} source={source} trackAction={trackAction} />
{websiteButtons.length > 0 && <View onLayout={(event) => {
const layout = event.nativeEvent.layout;
ref2.current = layout.y + layout.height;
callback();
}}>
<GameProfileStoreLinks game={game} websiteButtons={websiteButtons} trackAction={trackAction} />
</View>}
<GameProfileReviews game={game} trackAction={trackAction} />
<GameProfileSummary game={game} viewId={viewId} source={source} trackAction={trackAction} />
<GameProfileLinkAccount game={game} analyticsLocations={analyticsLocations} trackAction={trackAction} />
<GameProfileCommunity closeModal={closeModal} game={game} onInviteResolved={onGuildInviteResolved} trackAction={trackAction} />
<GameProfileAnnouncements gameId={game.id} invite={invite} closeModal={closeModal} trackAction={trackAction} scrollOffsetRef={scrollOffsetRef} />
<GameProfileShopCarousel game={game} closeModal={closeModal} trackAction={trackAction} />
<GameProfileSimilarGames gameId={game.id} trackAction={trackAction} />
<GameProfileDetails game={game} viewId={viewId} source={source} trackAction={trackAction} />
<View style={styles.buttonsContainer}>
<GameProfileGameClaimCta game={game} trackAction={trackAction} />
<GameProfileReportButton applicationId={game.id} trackAction={trackAction} />
</View>
</View>
</View>
</AnalyticsLocationProvider>;
};
@@ -0,0 +1,12 @@
// Metro module 8530 (f8531).
import Module8531, { Circle } from "../../../../_bundle/Module8531";
export default function OpenCriticRatingCircle(props) {
const { rating, strokeColor, size } = props;
const cx = size / 2;
const r4 = (size - 4) / 2;
const strokeDasharray = 2 * Math.PI * r4;
const r44 = 1 - Math.min(Math.max(rating, 0), 100) / 100;
return <Module8531 width={size} height={size}>
<Circle transform={`rotate(${360 * r44 / 2} ${cx} ${cx})`} cx={cx} cy={cx} r={r4} stroke={strokeColor} strokeWidth={2} fill="none" strokeDasharray={strokeDasharray} strokeDashoffset={strokeDasharray * r44} />
</Module8531>;
};