import { ReactNative as RN, stylesheet, constants, NavigationNative } from "@metro/common"; import { findByProps } from "@metro/filters"; import { Forms, General } from "@ui/components"; import { Plugin } from "@types"; import { getAssetIDByName } from "@ui/assets"; import { showToast } from "@ui/toasts"; import { removePlugin, startPlugin, stopPlugin, getSettings } from "@lib/plugins"; import copyText from "@utils/copyText"; //! This module is only found on 165.0+, under the assumption that iOS 165.0 is the same as Android 165.0. //* In 167.1 (Android alpha at the time of writing), stylesheet.ThemeColorMap is gone, and constants.ThemeColorMap has broken behaviour. //? SemanticColor is effectively ThemeColorMap //? RawColor is effectively Colors // TODO: Should this hotfix be moved elsewhere? Maybe a prop on window object, for plugins to use. const colorModule = findByProps("SemanticColorsByThemeTable"); const colorMap = (colorModule?.SemanticColor ?? constants.ThemeColorMap); // TODO: Replace with our eventual dialog API const Dialog = findByProps("show", "openLazy", "close"); const { FormRow, FormSwitch } = Forms; const { TouchableOpacity, Image } = General; // TODO: These styles work weirdly. iOS has cramped text, Android with low DPI probably does too. Fix? const styles = stylesheet.createThemedStyleSheet({ card: { backgroundColor: colorMap?.BACKGROUND_SECONDARY, borderRadius: 5, marginHorizontal: 10, marginBottom: 10, }, header: { padding: 0, backgroundColor: colorMap?.BACKGROUND_TERTIARY, borderTopLeftRadius: 5, borderTopRightRadius: 5, }, actions: { flexDirection: "row-reverse", alignItems: "center", }, icon: { width: 22, height: 22, marginLeft: 5, tintColor: colorMap?.INTERACTIVE_NORMAL, } }) interface PluginCardProps { plugin: Plugin; } export default function PluginCard({ plugin }: PluginCardProps) { const settings = getSettings(plugin.id); const navigation = NavigationNative.useNavigation(); const [removed, setRemoved] = React.useState(false); // This is needed because of Reactâ„¢ if (removed) return null; return ( i.name).join(", ")}`} leading={} trailing={ { if (v) startPlugin(plugin.id); else stopPlugin(plugin.id); }} /> } /> Dialog.show({ title: "Wait!", body: `Are you sure you wish to delete ${plugin.manifest.name}?`, confirmText: "Delete", cancelText: "Cancel", confirmColor: "red", onConfirm: () => { removePlugin(plugin.id); setRemoved(true); } })} > { copyText(plugin.id); showToast("Copied plugin URL to clipboard.", getAssetIDByName("toast_copy_link")); }} > { plugin.update = !plugin.update; showToast(`${plugin.update ? "Enabled" : "Disabled"} updates for ${plugin.manifest.name}.`, getAssetIDByName("toast_image_saved")); }} > {settings && navigation.push("VendettaCustomPage", { title: plugin.manifest.name, render: settings, })}> } } /> ) }