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

260 lines
10 KiB
TypeScript

// Metro module 12531 (f12532).
import { useMemo, useEffect } from "react";
import { Image as Image2, View } from "react-native";
import ThemeStore from "../../user_settings/ThemeStore";
import GuildStore from "../../../stores/GuildStore";
import GuildBoostSlotStore from "../../../stores/billing/GuildBoostSlotStore";
import SubscriptionStore from "../../../stores/billing/SubscriptionStore";
import { Fonts } from "../../../Constants";
import { createStyles } from "../../../design/components/Styles/native/createStyles";
import Module712 from "../../../_bundle/Module712";
import TextStyles from "../../rebrand/native/TextStyles";
import useCountdown from "../../../hooks/useCountdown";
import { Text } from "../../../design/components/Text/native/Text";
import { intl, t } from "../../../intl/index.native";
import SnowflakeUtils from "../../../utils/SnowflakeUtils";
import { PressableOpacity } from "../../../design/void/Pressables/native/Pressables";
import { openTransferModal, openApplyBoostModal } from "../../../actions/native/BoostingActionCreators";
import GuildIcon, { GuildIconSizes } from "../../guild/native/GuildIcon";
import Module12532 from "../../../_bundle/Module12532";
import { useStateFromStores } from "../../../_bundle/Module589";
import AvatarUtils from "../../../utils/AvatarUtils";
import { useSubscriptionPlaceholderPatternSource } from "../../../design/components/Illustration/native/redesign/generated/SubscriptionPlaceholderPattern";
import BoostedGuildTierProgressCircle from "./BoostedGuildTierProgressCircle";
import { fetchSubscriptions } from "../../billing/actions/BillingActionCreators";
import { fetchGuildBoostSlots } from "../../../actions/BoostingActionCreators";
import Module12 from "../../../_bundle/Module12";
let useStyles, GuildBoostSlotsInventoryRow, GuildBoostSlot, UnusedGuildBoostSlots, BoostedGuildInfo, BoostedGuild;
const GuildBoostSlotCooldown = function GuildBoostSlotCooldown(props) {
const cooldownEndsAt = props.cooldownEndsAt;
const styles = useStyles();
const memo = useMemo(() => new Date(cooldownEndsAt), [cooldownEndsAt]);
const countdown = useCountdown(memo, 15000);
const { days, hours, minutes } = countdown;
return memo.valueOf() <= Date.now() ? null : <Text style={styles.subscriptionSlotInfoCooldown} variant="text-xs/medium" color="text-muted">
{intl.format(t.NffSH8, {
days,
hours,
minutes
})}
</Text>;
};
GuildBoostSlotsInventoryRow = function GuildBoostSlotsInventoryRow(props) {
const { title, subtitle, action, isLast } = props;
const styles = useStyles();
return <View style={styles.subscriptionSlot}>
<View style={styles.subscriptionSlotInner}>
<View style={styles.subscriptionSlotInfo}>
<Text style={styles.subscriptionSlotInfoTitle} lineClamp={1} variant="text-md/semibold" color="interactive-text-active">{title}</Text>
{subtitle}
</View>
{action}
</View>
{isLast ? null : <View style={styles.subscriptionSlotBorder} />}
</View>;
};
GuildBoostSlot = function GuildBoostSlot(props) {
const { guild, guildBoostSlot, isLast } = props;
if (guild == null) {
return null;
}
const r4 = guildBoostSlot.premiumGuildSubscription != null ? guildBoostSlot.premiumGuildSubscription.id : null;
const r15 = r4 != null ? SnowflakeUtils.extractTimestamp(r4) : null;
return <GuildBoostSlotsInventoryRow title={r15 != null ? intl.formatToPlainString(t["ePe+Xh"], {
date: new Date(r15)
}) : null} subtitle={guildBoostSlot.cooldownEndsAt != null ? <GuildBoostSlotCooldown cooldownEndsAt={guildBoostSlot.cooldownEndsAt} /> : null} action={guildBoostSlot.isOnCooldown() ? null : <PressableOpacity accessibilityRole="button" onPress={() => openTransferModal({
guildBoostSlots: [guildBoostSlot]
})}>
<Text variant="text-md/medium" color="control-brand-foreground">
{intl.string(t.jqqLb6)}
</Text>
</PressableOpacity>} isLast={isLast} />;
};
UnusedGuildBoostSlots = function UnusedGuildBoostSlots(props) {
let c19894_0;
const unusedSlots = props.unusedSlots;
c19894_0 = void 0;
const styles = useStyles();
const r9 = unusedSlots.filter(({ cooldownEndsAt: cooldownEndsAt2 }) => cooldownEndsAt2 != null && new Date(cooldownEndsAt2).valueOf() > Date.now());
c19894_0 = r9;
const r18 = unusedSlots.filter(({ cooldownEndsAt: cooldownEndsAt2 }) => cooldownEndsAt2 == null || new Date(cooldownEndsAt2).valueOf() <= Date.now());
return <View style={styles.unusedSlots}>
{r18.length > 0 ? <GuildBoostSlotsInventoryRow title={intl.formatToPlainString(t.ewI23O, {
numSubscriptions: r18.length
})} action={<PressableOpacity accessibilityRole="button" onPress={() => openApplyBoostModal()}>
<Text variant="text-md/medium" color="text-link">
{intl.string(t["7KyPor"])}
</Text>
</PressableOpacity>} isLast={r9.length === 0} /> : null}
{r9.map((item, index) => <GuildBoostSlotsInventoryRow key={item.id} title={intl.formatToPlainString(t.gDsyB9, {
numSubscriptions: 1
})} subtitle={item.cooldownEndsAt != null ? <GuildBoostSlotCooldown cooldownEndsAt={item.cooldownEndsAt} /> : null} isLast={index === c19894_0.length - 1} />)}
</View>;
};
BoostedGuildInfo = function BoostedGuildInfo(props) {
const { guild, numGuildBoostSlots } = props;
const styles = useStyles();
return guild != null ? <View style={styles.guildInfo}>
<View style={styles.guildInfoIcon}>
<GuildIcon guild={guild} size={GuildIconSizes.NORMAL} selected={false} />
</View>
<View>
<Text style={styles.guildInfoName} variant="heading-lg/extrabold" color="interactive-text-active">{guild.name}</Text>
<View style={styles.guildInfoRowBottom}>
<Image2 source={Module12532} style={styles.guildInfoRowIcon} />
<Text style={styles.guildInfoSubscriptionCount} variant="text-xs/semibold" color="interactive-text-active">
{intl.format(t.bexfNy, {
numSubscriptions: numGuildBoostSlots
})}
</Text>
</View>
</View>
</View> : null;
};
BoostedGuild = function BoostedGuild(props) {
const { guildId, guildBoostSlots } = props;
const styles = useStyles();
const stateFromStores = useStateFromStores([GuildStore], () => GuildStore.getGuild(guildId));
const stateFromStores2 = useStateFromStores([ThemeStore], () => ThemeStore.theme);
const r16 = stateFromStores != null ? stateFromStores.banner != null ? AvatarUtils.getGuildBannerSource(stateFromStores) : null : null;
let source = useSubscriptionPlaceholderPatternSource();
if (r16 != null) {
source = r16;
}
return <View style={styles.boostedGuild}>
<View style={styles.subscriptionBody}>
<View style={styles.subscriptionImageView}>
<Image2 source={source} style={[styles.subscriptionImage, r16 == null ? styles.subscriptionImageFallback : null]} />
{r16 != null ? <View style={styles.subscriptionImageOverlay} /> : null}
<BoostedGuildTierProgressCircle guild={stateFromStores} theme={stateFromStores2} />
</View>
<BoostedGuildInfo guild={stateFromStores} numGuildBoostSlots={guildBoostSlots.length} />
</View>
<View>
{guildBoostSlots.map((a0, index) => <GuildBoostSlot key={a0.id} guild={stateFromStores} guildBoostSlot={a0} isLast={index === guildBoostSlots.length - 1} />)}
</View>
</View>;
};
useStyles = createStyles({
inventory: {
marginBottom: 32
},
header: {
marginHorizontal: 16,
marginBottom: 16
},
boostedGuild: {
borderRadius: Module712.radii.xs,
marginBottom: 16
},
subscriptionBody: {
backgroundColor: Module712.colors.BACKGROUND_BASE_LOWEST
},
subscriptionImageView: {
backgroundColor: Module712.colors.BACKGROUND_MOD_NORMAL,
width: "100%",
height: 112,
overflow: "hidden",
alignItems: "center",
justifyContent: "center"
},
subscriptionImage: {
position: "absolute",
width: "100%",
height: "100%"
},
subscriptionImageFallback: {
opacity: 0.4
},
subscriptionImageOverlay: {
position: "absolute",
width: "100%",
height: "100%",
backgroundColor: Module712.colors.BLACK,
opacity: 0.4
},
guildInfo: {
flexDirection: "row",
padding: 16
},
guildInfoIcon: {
marginRight: 8
},
guildInfoName: {
...TextStyles(Fonts.DISPLAY_EXTRABOLD, Module712.colors.INTERACTIVE_TEXT_ACTIVE, 20),
marginBottom: 4
},
guildInfoRowBottom: {
flexDirection: "row",
alignItems: "center"
},
guildInfoRowIcon: {
height: 12,
width: 8,
marginLeft: 2,
marginRight: 8
},
guildInfoSubscriptionCount: {
lineHeight: 16
},
subscriptionSlot: {
backgroundColor: Module712.colors.BACKGROUND_SURFACE_HIGH,
paddingLeft: 16
},
subscriptionSlotInner: {
alignItems: "center",
flexDirection: "row",
paddingRight: 16,
paddingVertical: 12
},
subscriptionSlotBorder: {
backgroundColor: Module712.colors.BORDER_SUBTLE,
height: 1
},
subscriptionSlotInfo: {
flexShrink: 1,
flexGrow: 1
},
subscriptionSlotInfoTitle: {
lineHeight: 24
},
subscriptionSlotInfoCooldown: {
lineHeight: 16
},
unusedSlots: {
marginBottom: 32
}
});
export default function GuildBoostSlotsInventory() {
let r51;
let c19896_0;
L9: {
const styles = useStyles();
useEffect(() => {
fetchSubscriptions();
fetchGuildBoostSlots();
}, []);
const stateFromStores2 = useStateFromStores([SubscriptionStore], () => SubscriptionStore.getPremiumTypeSubscription());
const r43 = Module12(useStateFromStores([GuildBoostSlotStore], () => GuildBoostSlotStore.boostSlots)).groupBy(({ premiumGuildSubscription }) => premiumGuildSubscription != null ? premiumGuildSubscription.guildId : "0").value();
c19896_0 = r43;
const unusedSlots = r43[0];
const r14 = Object.keys(r43).filter((item) => item !== "0");
if (r14.length === 0) {
r51 = null;
if (unusedSlots == null) {
break L9;
}
}
r51 = stateFromStores2 == null ? null : <View style={styles.inventory}>
{unusedSlots != null ? unusedSlots.length > 0 ? <UnusedGuildBoostSlots unusedSlots={unusedSlots} /> : null : null}
{r14.length > 0 ? <>
<Text style={styles.header} variant="eyebrow" color="text-default">
{intl.string(t.gB9oQ7)}
</Text>
{r14.map((item) => <BoostedGuild key={item} guildId={item} guildBoostSlots={c19896_0[item]} />)}
</> : null}
</View>;
}
return r51;
};