import { getAssetIdByName } from '@revenge-mod/assets' import { FormSwitch, TableRowAssetIcon } from '@revenge-mod/components' import { ActionSheetActionCreators, ToastActionCreators, } from '@revenge-mod/discord/actions' import { Design } from '@revenge-mod/discord/design' import { Clipboard } from '@revenge-mod/externals/react-native-clipboard' import { getInternalPluginMeta, InternalPluginFlags, isPluginEssential, } from '@revenge-mod/plugins/_' import { PluginFlags, PluginStatus } from '@revenge-mod/plugins/constants' import { lookupGeneratedIconComponent } from '@revenge-mod/utils/discord' import { getErrorStack } from '@revenge-mod/utils/error' import { Pressable } from 'react-native' import { ClickOutsideProvider } from 'react-native-click-outside' import { handleDisablePlugin, handleEnablePlugin } from '../utils/actions' import { openPluginSettings, showPluginClearDataConfirmation, } from '../utils/alerts' import { PluginInfo } from './PluginCard' import { usePluginEnabled, usePluginStatus } from './PluginStateProvider' import { EnablePluginTooltipProvider, useClickOutsideTooltip, useEnablePluginTooltip, } from './TooltipProvider' import type { AnyPlugin } from '@revenge-mod/plugins/_' export interface PluginOptionsActionSheetProps { plugin: AnyPlugin sheetKey: string } const { ActionSheet, IconButton, TableRowGroup, TableRow, Stack } = Design const FileWarningIcon = getAssetIdByName('FileWarningIcon', 'png')! const SettingsIcon = getAssetIdByName('SettingsIcon', 'png')! export default function PluginOptionsActionSheet({ plugin, sheetKey, }: PluginOptionsActionSheetProps) { const status = usePluginStatus(plugin) const enabled = usePluginEnabled(plugin) const meta = getInternalPluginMeta(plugin) const { dependencies, dependents } = meta! const essential = isPluginEssential(meta) const { manifest: { id, name, author, description, icon }, errors, flags, } = plugin return ( { if (v) handleEnablePlugin(plugin) else handleDisablePlugin(plugin) }} /> ) } /> { ActionSheetActionCreators.hideActionSheet( sheetKey, ) }} /> } label="Status (TODO)" subLabel={bitFieldToString(PluginStatus, status)} /> {errors.length && ( } subLabel={`${errors.length} errors. Tap to copy.`} onPress={() => { Clipboard.setString( errors.map(getErrorStack).join('\n'), ) showCopiedToClipboardToast() }} /> )} } label="ID" subLabel={id} onPress={() => { Clipboard.setString(id) showCopiedToClipboardToast() }} /> } label="Flags" subLabel={bitFieldToString(PluginFlags, flags)} /> {meta.iflags && ( } label="Internal Flags" subLabel={bitFieldToString( InternalPluginFlags, meta.iflags, )} /> )} {dependencies?.length && ( } label="Dependencies (TODO)" subLabel={`${name} depends on ${dependencies.length} other plugins`} /> )} {dependents?.length && ( } label="Dependents (TODO)" subLabel={`${dependents.length} other plugins depend on ${name}`} /> )} ) } function bitFieldToString(map: Record, bitField: number) { return ( Object.entries(map) .filter(([, value]) => bitField & value) .map(([key]) => key) .join(', ') || '-' ) } function PluginActions({ plugin, closeSheet, }: { plugin: AnyPlugin closeSheet: () => void }) { const enabled = usePluginEnabled(plugin) const enableTooltip = useEnablePluginTooltip() const settingsRef = useClickOutsideTooltip(useEnablePluginTooltip, () => {}) return ( { showPluginClearDataConfirmation(plugin, closeSheet) }} /> {plugin.SettingsComponent && ( { if (enabled) return requestAnimationFrame(() => { enableTooltip.targetRef.current = settingsRef.current enableTooltip.setVisible(true) }) }} > { openPluginSettings(plugin) closeSheet() }} /> )} ) } const CopyIcon = lookupGeneratedIconComponent('CopyIcon')! function showCopiedToClipboardToast() { ToastActionCreators.open({ key: 'REVENGE_PLUGIN_SETTINGS_COPIED', content: 'Copied to clipboard', IconComponent: CopyIcon, }) }