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

283 lines
12 KiB
TypeScript

// Metro module 11958 (f11959).
import { useCallback } from "react";
import { View } from "react-native";
import LocaleStore from "../../user_settings/LocaleStore";
import GuildMemberStore from "../../../stores/GuildMemberStore";
import GuildStore from "../../../stores/GuildStore";
import { DIVIDER_DOT, UserProfileThemeTypes } from "./Constants";
import { Routes } from "../../../Constants";
import { AppLauncherRouteName } from "../../app_launcher/native/AppLauncherNativeConstants";
import { createStyles } from "../../../design/components/Styles/native/createStyles";
import { useToken } from "../../../design/tokens/native/useToken";
import Module712 from "../../../_bundle/Module712";
import { Text } from "../../../design/components/Text/native/Text";
import { intl, t } from "../../../intl/index.native";
import BioText from "../../profile_customization/native/BioText";
import { useStateFromStores } from "../../../_bundle/Module589";
import { getCreatedAtDate } from "../../connections/ConnectionsUtils";
import SnowflakeUtils from "../../../utils/SnowflakeUtils";
import { ClydeIcon } from "../../../design/components/Icon/native/redesign/generated/ClydeIcon";
import GuildIcon, { GuildIconSizes } from "../../guild/native/GuildIcon";
import { useFriendsSinceDate } from "../hooks/useFriendsSinceDate";
import { PressableOpacity } from "../../../design/void/native";
import { handleClick } from "../../../utils/MaskedLinkUtils";
import useAnalyticsLocations from "../../app_analytics/useAnalyticsLocations";
import { useUserProfileAnalyticsContext } from "../UserProfileAnalyticsContext";
import useBotProfileCommands from "../useBotProfileCommands";
import showUserProfileActionSheet, { getUserProfileActionSheetKey } from "./showUserProfileActionSheet";
import ActionSheetActionCreators from "../../action_sheet/native/ActionSheetActionCreators";
import { getRootNavigationRef } from "../../main_tabs_v2/RootNavigationRef.native";
import { transitionTo } from "../../routing/router_utils";
import { runAfterInteractions } from "../../../utils/native/RunAfterInteractionsUtils";
import { getBestActiveInput } from "../../../utils/native/ChatInputUtils";
import { KeyboardTypes } from "../../keyboard/native/KeyboardTypes";
import UserProfileAboutMeCardCommand from "./UserProfileAboutMeCardCommand";
import { Button } from "../../../design/components/Button/native/Button.native";
import UserProfileCard from "./UserProfileCard";
let c8202_14, c8202_15, useStyles, TextWithIcon, Bio, MemberJoinDates, FriendsSinceDate, PolicyLinks, PolicyLink, BotSlashCommands;
const Heading = function Heading(props) {
const { children, themeType } = props;
let r4 = themeType != null ? c8202_15[themeType] : void 0;
if (r4 == null) {
r4 = c8202_14;
}
const { headingVariant, headingSpacing } = r4;
let variant = useToken(Module712.modules.mobile.USER_PROFILE_ABOUT_ME_HEADING_TEXT_STYLE);
if (variant == null) {
variant = headingVariant;
}
return <Text accessibilityRole="header" variant={variant} color="user-profile-about-me-heading-text" style={{
marginBottom: headingSpacing
}}>{children}</Text>;
};
TextWithIcon = function TextWithIcon(props) {
const { icon, children, themeType, accessibilityLabel } = props;
const styles = useStyles();
let r15 = themeType != null ? c8202_15[themeType] : void 0;
if (r15 == null) {
r15 = c8202_14;
}
return <View style={[styles.textWithIcon, {
columnGap: r15.columnGap
}]} accessible accessibilityLabel={accessibilityLabel}>
{icon}
<Text variant={r15.textVariant} color="text-default">{children}</Text>
</View>;
};
Bio = function Bio(props) {
const { userId: userId2, displayProfile, pendingBio, themeType, lineClamp } = props;
let r20 = themeType != null ? c8202_15[themeType] : void 0;
if (r20 == null) {
r20 = c8202_14;
}
const textVariant = r20.textVariant;
const bio = displayProfile == null ? void 0 : displayProfile.getPreviewBio(pendingBio);
return bio == null ? null : bio !== "" ? <View>
<Heading themeType={themeType}>
{intl.string(t.ZzAR2Y)}
</Heading>
<BioText bio={bio} userId={userId2} textVariant={textVariant} lineClamp={lineClamp} />
</View> : null;
};
MemberJoinDates = function MemberJoinDates(props) {
const { userId, guildId, themeType } = props;
const styles = useStyles();
let r25 = themeType != null ? c8202_15[themeType] : void 0;
if (r25 == null) {
r25 = c8202_14;
}
const { textVariant, columnGap } = r25;
const stateFromStores2 = useStateFromStores([LocaleStore], () => LocaleStore.locale);
const stateFromStores = useStateFromStores([GuildStore], () => guildId != null ? GuildStore.getGuild(guildId) : null);
const stateFromStores3 = useStateFromStores([GuildMemberStore], () => guildId != null ? GuildMemberStore.getMember(guildId, userId) : null);
const createdAtDate2 = getCreatedAtDate(SnowflakeUtils.extractTimestamp(userId), stateFromStores2);
const createdAtDate = getCreatedAtDate(stateFromStores3?.joinedAt, stateFromStores2);
return <View>
<Heading themeType={themeType}>
{intl.string(t.a6XYD9)}
</Heading>
<View style={[styles.memberJoinDates, {
columnGap
}]}>
<TextWithIcon themeType={themeType} icon={<ClydeIcon size="xs" />} accessibilityLabel={intl.formatToPlainString(t["9t7w53"], {
date: createdAtDate2
})}>{createdAtDate2}</TextWithIcon>
{stateFromStores != null && createdAtDate != null && <>
<Text variant={textVariant} color="text-default" accessibilityElementsHidden importantForAccessibility="no-hide-descendants">{DIVIDER_DOT}</Text>
<TextWithIcon themeType={themeType} icon={<GuildIcon guild={stateFromStores} size={GuildIconSizes.XXSMALL} />} accessibilityLabel={intl.formatToPlainString(t.FdLNDK, {
guildName: stateFromStores.name,
date: createdAtDate
})}>{createdAtDate}</TextWithIcon>
</>}
</View>
</View>;
};
FriendsSinceDate = function FriendsSinceDate(props) {
const { userId: userId2, themeType } = props;
let r3 = themeType != null ? c8202_15[themeType] : void 0;
if (r3 == null) {
r3 = c8202_14;
}
const textVariant = r3.textVariant;
const friendsSinceDate = useFriendsSinceDate(userId2);
return friendsSinceDate == null ? null : <View>
<Heading themeType={themeType}>
{intl.string(t.wlTO8v)}
</Heading>
<Text variant={textVariant} color="text-default">{friendsSinceDate}</Text>
</View>;
};
PolicyLinks = function PolicyLinks(props) {
let r21, r29;
const { termsOfServiceUrl, privacyPolicyUrl, themeType } = props;
const styles = useStyles();
if (termsOfServiceUrl == null) {
const r2 = privacyPolicyUrl == null;
r21 = null;
if (!r2) {
r29 = [<Heading themeType={themeType}>
{intl.string(t.l6DP2n)}
</Heading>, <View style={styles.policyLinks}>
{termsOfServiceUrl != null && <PolicyLink url={termsOfServiceUrl} label={intl.string(t.s7STcY)} themeType={themeType} />}
{privacyPolicyUrl != null && <PolicyLink url={privacyPolicyUrl} label={intl.string(t.kH3JR5)} themeType={themeType} />}
</View>];
r21 = <View>{r29}</View>;
}
} else {
r29 = [<Heading themeType={themeType}>
{intl.string(t.l6DP2n)}
</Heading>, <View style={styles.policyLinks}>
{termsOfServiceUrl != null && <PolicyLink url={termsOfServiceUrl} label={intl.string(t.s7STcY)} themeType={themeType} />}
{privacyPolicyUrl != null && <PolicyLink url={privacyPolicyUrl} label={intl.string(t.kH3JR5)} themeType={themeType} />}
</View>];
r21 = <View>{r29}</View>;
}
return r21;
};
PolicyLink = function PolicyLink(props) {
const { url, label, themeType } = props;
let r11 = themeType != null ? c8202_15[themeType] : void 0;
if (r11 == null) {
r11 = c8202_14;
}
return <PressableOpacity accessibilityRole="link" onPress={() => handleClick({
href: url
})}>
<Text variant={r11.textVariant} color="text-link">{label}</Text>
</PressableOpacity>;
};
BotSlashCommands = function BotSlashCommands(props) {
const { applicationId, channel, commandIds, themeType } = props;
const styles = useStyles();
const analyticsLocations = useAnalyticsLocations().analyticsLocations;
const context = useUserProfileAnalyticsContext().context;
const botProfileCommands = useBotProfileCommands(channel, applicationId, commandIds);
const { commands, application } = botProfileCommands;
const callback = useCallback(() => {
if (application != null && application.bot != null) {
const id = application.bot.id;
ActionSheetActionCreators.hideActionSheet(getUserProfileActionSheetKey(id));
const rootNavigationRef = getRootNavigationRef();
if (rootNavigationRef != null && rootNavigationRef.isReady()) {
const state = rootNavigationRef.getState();
let r36 = state == null ? void 0 : state.routes?.length;
if (r36 == null) {
r36 = 0;
}
while (r36 > 1) {
rootNavigationRef.goBack();
r36 = r36 - 1;
}
transitionTo(Routes.CHANNEL(channel.guild_id, channel.id));
}
runAfterInteractions(() => {
const bestActiveInput = getBestActiveInput();
if (bestActiveInput != null) {
bestActiveInput.openCustomKeyboard({
type: KeyboardTypes.APP_LAUNCHER,
context: {
initialRouteName: AppLauncherRouteName.APPLICATION_VIEW,
initiallyExpanded: true,
application,
onPressBack: () => {
showUserProfileActionSheet({
...context,
userId: id,
channelId: channel.id,
sourceAnalyticsLocations: analyticsLocations
});
}
}
});
}
});
}
}, [application, channel.id, channel.guild_id, context, analyticsLocations]);
return commands == null ? null : commands.length !== 0 ? <View>
<Heading themeType={themeType}>
{intl.string(t["0hKkS+"])}
</Heading>
<View style={styles.slashCommands}>
{commands.map((a0) => <UserProfileAboutMeCardCommand key={a0.id} application={application} channel={channel} command={a0} />)}
</View>
{application != null && application.bot != null && <Button size="sm" variant="tertiary" text={intl.string(t.VEfKyb)} onPress={callback} />}
</View> : null;
};
c8202_14 = {
headingVariant: "text-sm/semibold",
textVariant: "text-md/normal",
headingSpacing: 8,
rowGap: 24,
columnGap: 6
};
const r48 = {};
r48[UserProfileThemeTypes.PREVIEW] = {
headingVariant: "text-xs/semibold",
textVariant: "text-sm/normal",
headingSpacing: 4,
rowGap: 12,
columnGap: 3
};
c8202_15 = r48;
useStyles = createStyles({
card: {
flexDirection: "column"
},
textWithIcon: {
flexDirection: "row",
alignItems: "center"
},
memberJoinDates: {
flexDirection: "row",
flexWrap: "wrap"
},
slashCommands: {
flex: 1,
flexDirection: "row",
flexWrap: "wrap",
marginBottom: 12
},
policyLinks: {
rowGap: 8
}
});
export default function UserProfileAboutMeCard(props) {
const { userId: userId2, displayProfile, channel: channel2, pendingBio, bioLineClamp, themeType, style } = props;
const styles = useStyles();
let r19 = themeType != null ? c8202_15[themeType] : void 0;
if (r19 == null) {
r19 = c8202_14;
}
const rowGap = r19.rowGap;
const application2 = displayProfile?.application;
return <UserProfileCard style={[styles.card, {
rowGap
}, style]}>
<Bio userId={userId2} displayProfile={displayProfile} pendingBio={pendingBio} themeType={themeType} lineClamp={bioLineClamp} />
<MemberJoinDates userId={userId2} guildId={displayProfile?.guildId} themeType={themeType} />
<FriendsSinceDate userId={userId2} themeType={themeType} />
<PolicyLinks termsOfServiceUrl={application2?.termsOfServiceUrl} privacyPolicyUrl={application2?.privacyPolicyUrl} themeType={themeType} />
{application2?.popularApplicationCommandIds != null && channel2 != null && <BotSlashCommands applicationId={application2.id} channel={channel2} commandIds={application2.popularApplicationCommandIds} themeType={themeType} />}
</UserProfileCard>;
};