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,
})
}