PluginSettings: Try to improve performance

This commit is contained in:
Vendicated 2023-01-09 15:57:02 +01:00
parent ae9fe7fcfd
commit 95df164e44
No known key found for this signature in database
GPG Key ID: A1DC0CFB5615D905

@ -198,7 +198,13 @@ function PluginCard({ plugin, disabled, onRestartNeeded, onMouseEnter, onMouseLe
); );
} }
export default ErrorBoundary.wrap(function Settings() { enum SearchStatus {
ALL,
ENABLED,
DISABLED
}
export default ErrorBoundary.wrap(function PluginSettings() {
const settings = useSettings(); const settings = useSettings();
const changes = React.useMemo(() => new ChangeList<string>(), []); const changes = React.useMemo(() => new ChangeList<string>(), []);
@ -239,21 +245,19 @@ export default ErrorBoundary.wrap(function Settings() {
const sortedPlugins = React.useMemo(() => Object.values(Plugins) const sortedPlugins = React.useMemo(() => Object.values(Plugins)
.sort((a, b) => a.name.localeCompare(b.name)), []); .sort((a, b) => a.name.localeCompare(b.name)), []);
const [searchValue, setSearchValue] = React.useState({ value: "", status: "all" }); const [searchValue, setSearchValue] = React.useState({ value: "", status: SearchStatus.ALL });
const onSearch = (query: string) => setSearchValue(prev => ({ ...prev, value: query })); const onSearch = (query: string) => setSearchValue(prev => ({ ...prev, value: query }));
const onStatusChange = (status: string) => setSearchValue(prev => ({ ...prev, status })); const onStatusChange = (status: SearchStatus) => setSearchValue(prev => ({ ...prev, status }));
const pluginFilter = (plugin: typeof Plugins[keyof typeof Plugins]) => { const pluginFilter = (plugin: typeof Plugins[keyof typeof Plugins]) => {
const showEnabled = searchValue.status === "enabled" || searchValue.status === "all";
const showDisabled = searchValue.status === "disabled" || searchValue.status === "all";
const enabled = settings.plugins[plugin.name]?.enabled || plugin.started; const enabled = settings.plugins[plugin.name]?.enabled || plugin.started;
if (enabled && searchValue.status === SearchStatus.DISABLED) return false;
if (!enabled && searchValue.status === SearchStatus.ENABLED) return false;
if (!searchValue.value.length) return true;
return ( return (
((showEnabled && enabled) || (showDisabled && !enabled)) && plugin.name.toLowerCase().includes(searchValue.value.toLowerCase()) ||
( plugin.description.toLowerCase().includes(searchValue.value.toLowerCase())
plugin.name.toLowerCase().includes(searchValue.value.toLowerCase()) ||
plugin.description.toLowerCase().includes(searchValue.value.toLowerCase())
)
); );
}; };
@ -274,6 +278,52 @@ export default ErrorBoundary.wrap(function Settings() {
return window._.isEqual(newPlugins, sortedPluginNames) ? [] : newPlugins; return window._.isEqual(newPlugins, sortedPluginNames) ? [] : newPlugins;
})); }));
type P = JSX.Element | JSX.Element[];
let plugins: P, requiredPlugins: P;
if (sortedPlugins?.length) {
plugins = [];
requiredPlugins = [];
for (const p of sortedPlugins) {
if (!pluginFilter(p)) continue;
const isRequired = p.required || depMap[p.name]?.some(d => Settings.plugins[d].enabled);
if (isRequired) {
const tooltipText = p.required
? "This plugin is required for Vencord to function."
: makeDependencyList(depMap[p.name]?.filter(d => settings.plugins[d].enabled));
requiredPlugins.push(
<Tooltip text={tooltipText} key={p.name}>
{({ onMouseLeave, onMouseEnter }) => (
<PluginCard
onMouseLeave={onMouseLeave}
onMouseEnter={onMouseEnter}
onRestartNeeded={name => changes.handleChange(name)}
disabled={true}
plugin={p}
/>
)}
</Tooltip>
);
} else {
plugins.push(
<PluginCard
onRestartNeeded={name => changes.handleChange(name)}
disabled={false}
plugin={p}
isNew={newPlugins?.includes(p.name)}
key={p.name}
/>
);
}
}
} else {
plugins = requiredPlugins = <Text variant="text-md/normal">No plugins meet search criteria.</Text>;
}
return ( return (
<Forms.FormSection> <Forms.FormSection>
<Forms.FormTitle tag="h5" className={classes(Margins.marginTop20, Margins.marginBottom8)}> <Forms.FormTitle tag="h5" className={classes(Margins.marginTop20, Margins.marginBottom8)}>
@ -288,9 +338,9 @@ export default ErrorBoundary.wrap(function Settings() {
<Select <Select
className={InputStyles.inputDefault} className={InputStyles.inputDefault}
options={[ options={[
{ label: "Show All", value: "all", default: true }, { label: "Show All", value: SearchStatus.ALL, default: true },
{ label: "Show Enabled", value: "enabled" }, { label: "Show Enabled", value: SearchStatus.ENABLED },
{ label: "Show Disabled", value: "disabled" } { label: "Show Disabled", value: SearchStatus.DISABLED }
]} ]}
serialize={String} serialize={String}
select={onStatusChange} select={onStatusChange}
@ -303,49 +353,14 @@ export default ErrorBoundary.wrap(function Settings() {
<Forms.FormTitle className={Margins.marginTop20}>Plugins</Forms.FormTitle> <Forms.FormTitle className={Margins.marginTop20}>Plugins</Forms.FormTitle>
<div className={cl("grid")}> <div className={cl("grid")}>
{sortedPlugins?.length ? sortedPlugins {plugins}
.filter(a => !a.required && !dependencyCheck(a.name, depMap).length && pluginFilter(a))
.map(plugin => {
const enabledDependants = depMap[plugin.name]?.filter(d => settings.plugins[d].enabled);
const dependency = enabledDependants?.length;
return <PluginCard
onRestartNeeded={name => changes.add(name)}
disabled={plugin.required || !!dependency}
plugin={plugin}
isNew={newPlugins?.includes(plugin.name)}
key={plugin.name}
/>;
})
: <Text variant="text-md/normal">No plugins meet search criteria.</Text>
}
</div> </div>
<Forms.FormDivider /> <Forms.FormDivider />
<Forms.FormTitle tag="h5" className={classes(Margins.marginTop20, Margins.marginBottom8)}> <Forms.FormTitle tag="h5" className={classes(Margins.marginTop20, Margins.marginBottom8)}>
Required Plugins Required Plugins
</Forms.FormTitle> </Forms.FormTitle>
<div className={cl("grid")}> <div className={cl("grid")}>
{sortedPlugins?.length ? sortedPlugins {requiredPlugins}
.filter(a => a.required || dependencyCheck(a.name, depMap).length && pluginFilter(a))
.map(plugin => {
const enabledDependants = depMap[plugin.name]?.filter(d => settings.plugins[d].enabled);
const dependency = enabledDependants?.length;
const tooltipText = plugin.required
? "This plugin is required for Vencord to function."
: makeDependencyList(dependencyCheck(plugin.name, depMap));
return <Tooltip text={tooltipText} key={plugin.name}>
{({ onMouseLeave, onMouseEnter }) => (
<PluginCard
onMouseLeave={onMouseLeave}
onMouseEnter={onMouseEnter}
onRestartNeeded={name => changes.handleChange(name)}
disabled={plugin.required || !!dependency}
plugin={plugin}
/>
)}
</Tooltip>;
})
: <Text variant="text-md/normal">No plugins meet search criteria.</Text>
}
</div> </div>
</Forms.FormSection > </Forms.FormSection >
); );
@ -362,7 +377,3 @@ function makeDependencyList(deps: string[]) {
</React.Fragment> </React.Fragment>
); );
} }
function dependencyCheck(pluginName: string, depMap: Record<string, string[]>): string[] {
return depMap[pluginName]?.filter(d => Settings.plugins[d].enabled) || [];
}