import React from "react"; import { View, Text, Animated, Pressable, Image, ViewStyle, StyleSheet } from "react-native"; import { getAssetIDByName } from "@vendetta/ui/assets"; import { storage } from "@vendetta/plugin"; import { useProxy } from "@vendetta/storage"; import { useFolderExpanded, GuildNode } from "../utils/theme"; import { lazy } from "../lib/lazy"; import { rawFindByFunctionProps, rawFindByStoreName } from "../lib/rawFind"; import { getFlux } from "../lib/commonModules"; import GuildIcon from "./GuildIcon"; import GuildItem from "./GuildItem"; const getGuildActions = lazy(() => rawFindByFunctionProps("toggleGuildFolderExpand")); const getGuildReadStateStore = lazy(() => rawFindByStoreName("GuildReadStateStore")); const ICON = 48; const MINI = 16; const POS: ViewStyle[] = [ { top: 6, left: 6 }, { top: 6, right: 6 }, { bottom: 6, left: 6 }, { bottom: 6, right: 6 }, ]; const FOLDER_ASSET = getAssetIDByName("FolderIcon"); function folderColor(color?: number | null): string { if (color == null) return "#5865f2"; return `#${color.toString(16).padStart(6, "0")}`; } function FolderBadge({ node }: { node: GuildNode }) { const Flux = getFlux(); const GuildReadStateStore = getGuildReadStateStore(); // Guards against an undefined store, not just a falsy return value - confirmed live that // passing [undefined] into useStateFromStores throws rather than failing safely, which used to // take the whole drawer down (this only ever runs when there's an actual folder to render, so // an account with folders showed nothing at all while one without rendered fine). const total = (Flux?.useStateFromStores && GuildReadStateStore) ? Flux.useStateFromStores( [GuildReadStateStore], () => { let sum = 0; for (const child of node.children) { sum += GuildReadStateStore?.getMentionCount?.(child.id) ?? 0; } return sum; }, [node.children], ) : 0; if (total > 0) { return ( {total > 99 ? "99+" : String(total)} ); } return null; } function FolderCover({ node }: { node: GuildNode }) { useProxy(storage); const col = folderColor(node.color); return ( {storage.hideFolderIcons ? ( ) : ( node.children.slice(0, 4).map((ch, i) => ( )) )} ); } const fc = StyleSheet.create({ outer: { width: ICON, height: ICON }, icon: { width: ICON, height: ICON, borderRadius: 16, overflow: "hidden" }, cell: { position: "absolute", width: MINI, height: MINI, borderRadius: 8, overflow: "hidden" }, plainIcon: { width: ICON, height: ICON, alignItems: "center", justifyContent: "center" }, }); function FadeIn({ children }: { children: React.ReactNode }) { const opacity = React.useRef(new Animated.Value(0)).current; React.useEffect(() => { Animated.timing(opacity, { toValue: 1, duration: 180, useNativeDriver: true }).start(); }, []); return {children}; } export default function FolderItem({ node, onPick }: { node: GuildNode; onPick: (id: string) => void }) { const open = useFolderExpanded(node.id); const toggle = () => { getGuildActions()?.toggleGuildFolderExpand?.(node.id); }; if (open) { return ( <> {node.children.map((ch) => ( ))} ); } return ( ); } const fo = StyleSheet.create({ openIcon: { width: ICON, height: ICON, borderRadius: 16, alignItems: "center", justifyContent: "center", }, folderImg: { width: 24, height: 24 }, }); const fbd = StyleSheet.create({ outline: { position: "absolute", bottom: -3, right: -3, minWidth: 23, minHeight: 23, borderRadius: 12, backgroundColor: "#1a1a2e", alignItems: "center", justifyContent: "center", }, badge: { minWidth: 19, height: 19, borderRadius: 9, backgroundColor: "#ed4245", alignItems: "center", justifyContent: "center", paddingHorizontal: 5, }, text: { color: "#fff", fontSize: 10, fontWeight: "700", lineHeight: 19, }, });