Add sort plugins setting (#859)

This commit is contained in:
Nihaal Sangha
2026-09-25 21:32:11 +01:00
committed by GitHub
parent b73a094ae1
commit 84288115c8
6 changed files with 67 additions and 10 deletions
+3
View File
@@ -217,6 +217,9 @@
"developer_mode": {
"label": "Developer mode"
},
"sort_plugins": {
"label": "Sort plugins alphabetically"
},
"notifications": {
"decky_updates_label": "Decky update available",
"header": "Notifications",
+11
View File
@@ -10,6 +10,7 @@ interface PublicDeckyState {
disabledPlugins: DisabledPlugin[];
installedPlugins: (Plugin | DisabledPlugin)[];
pluginOrder: string[];
sortPlugins: boolean;
frozenPlugins: string[];
hiddenPlugins: string[];
activePlugin: Plugin | null;
@@ -31,6 +32,7 @@ export class DeckyState {
private _disabledPlugins: DisabledPlugin[] = [];
private _installedPlugins: (Plugin | DisabledPlugin)[] = [];
private _pluginOrder: string[] = [];
private _sortPlugins: boolean = false;
private _frozenPlugins: string[] = [];
private _hiddenPlugins: string[] = [];
private _activePlugin: Plugin | null = null;
@@ -49,6 +51,7 @@ export class DeckyState {
disabledPlugins: this._disabledPlugins,
installedPlugins: this._installedPlugins,
pluginOrder: this._pluginOrder,
sortPlugins: this._sortPlugins,
frozenPlugins: this._frozenPlugins,
hiddenPlugins: this._hiddenPlugins,
activePlugin: this._activePlugin,
@@ -83,6 +86,11 @@ export class DeckyState {
this.notifyUpdate();
}
setSortPlugins(sortPlugins: boolean) {
this._sortPlugins = sortPlugins;
this.notifyUpdate();
}
setFrozenPlugins(frozenPlugins: string[]) {
this._frozenPlugins = frozenPlugins;
this.notifyUpdate();
@@ -139,6 +147,7 @@ interface DeckyStateContext extends PublicDeckyState {
setActivePlugin(name: string): void;
setPluginOrder(pluginOrder: string[]): void;
setDisabledPlugins(disabled: DisabledPlugin[]): void;
setSortPlugins(sortPlugins: boolean): void;
closeActivePlugin(): void;
}
@@ -178,6 +187,7 @@ export const DeckyStateContextProvider: FC<Props> = ({ children, deckyState }) =
const closeActivePlugin = deckyState.closeActivePlugin.bind(deckyState);
const setPluginOrder = deckyState.setPluginOrder.bind(deckyState);
const setDisabledPlugins = deckyState.setDisabledPlugins.bind(deckyState);
const setSortPlugins = deckyState.setSortPlugins.bind(deckyState);
return (
<DeckyStateContext.Provider
@@ -189,6 +199,7 @@ export const DeckyStateContextProvider: FC<Props> = ({ children, deckyState }) =
closeActivePlugin,
setPluginOrder,
setDisabledPlugins,
setSortPlugins,
}}
>
{children}
+7 -2
View File
@@ -16,6 +16,7 @@ const PluginView: FC = () => {
updates,
activePlugin,
pluginOrder,
sortPlugins,
setActivePlugin,
closeActivePlugin,
} = useDeckyState();
@@ -26,10 +27,14 @@ const PluginView: FC = () => {
console.log('updating PluginView after changes');
return [...plugins]
.sort((a, b) => pluginOrder.indexOf(a.name) - pluginOrder.indexOf(b.name))
.sort((a, b) =>
sortPlugins
? a.name.localeCompare(b.name, undefined, { sensitivity: 'base' })
: pluginOrder.indexOf(a.name) - pluginOrder.indexOf(b.name),
)
.filter((p) => p.content)
.filter(({ name }) => !hiddenPlugins.includes(name));
}, [plugins, pluginOrder, hiddenPlugins]);
}, [plugins, pluginOrder, sortPlugins, hiddenPlugins]);
const numberOfHidden = hiddenPlugins.filter((name) => !!plugins.find((p) => p.name === name)).length;
@@ -1,6 +1,7 @@
import { DialogBody, DialogControlsSection, DialogControlsSectionHeader, Field, Toggle } from '@decky/ui';
import { useTranslation } from 'react-i18next';
import { useSetting } from '../../../../utils/hooks/useSetting';
import { useDeckyState } from '../../../DeckyState';
import BranchSelect from './BranchSelect';
import NotificationSettings from './NotificationSettings';
@@ -14,7 +15,8 @@ export default function GeneralSettings({
isDeveloper: boolean;
setIsDeveloper: (val: boolean) => void;
}) {
const { versionInfo } = useDeckyState();
const { versionInfo, sortPlugins, setSortPlugins } = useDeckyState();
const [_, setSortPluginsSetting] = useSetting<boolean>('sortPlugins', false);
const { t } = useTranslation();
return (
@@ -42,6 +44,15 @@ export default function GeneralSettings({
}}
/>
</Field>
<Field label={t('SettingsGeneralIndex.sort_plugins.label')}>
<Toggle
value={sortPlugins}
onChange={(toggleValue) => {
setSortPlugins(toggleValue);
setSortPluginsSetting(toggleValue);
}}
/>
</Field>
</DialogControlsSection>
<DialogControlsSection>
<DialogControlsSectionHeader>{t('SettingsGeneralIndex.about.header')}</DialogControlsSectionHeader>
@@ -11,7 +11,7 @@ import {
ReorderableList,
showContextMenu,
} from '@decky/ui';
import { useEffect, useState } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { FaDownload, FaEllipsisH, FaRecycle } from 'react-icons/fa';
@@ -171,9 +171,16 @@ type PluginData = {
};
export default function PluginList({ isDeveloper }: { isDeveloper: boolean }) {
const { installedPlugins, disabledPlugins, updates, pluginOrder, setPluginOrder, frozenPlugins, hiddenPlugins } =
useDeckyState();
const {
installedPlugins,
disabledPlugins,
updates,
pluginOrder,
setPluginOrder,
frozenPlugins,
hiddenPlugins,
sortPlugins,
} = useDeckyState();
const [_, setPluginOrderSetting] = useSetting<string[]>(
'pluginOrder',
installedPlugins.map((plugin) => plugin.name),
@@ -188,6 +195,12 @@ export default function PluginList({ isDeveloper }: { isDeveloper: boolean }) {
const hiddenPluginsService = DeckyPluginLoader.hiddenPluginsService;
const frozenPluginsService = DeckyPluginLoader.frozenPluginsService;
const sortedPlugins = useMemo(() => {
return sortPlugins
? [...installedPlugins].sort((a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }))
: installedPlugins;
}, [installedPlugins, sortPlugins]);
useEffect(() => {
setPluginEntries(
installedPlugins.map(({ name, version }) => {
@@ -204,7 +217,7 @@ export default function PluginList({ isDeveloper }: { isDeveloper: boolean }) {
disabled={disabledPlugins.find((p) => p.name == name) !== undefined}
/>
),
position: pluginOrder.indexOf(name),
position: sortPlugins ? sortedPlugins.findIndex((p) => p.name === name) : pluginOrder.indexOf(name),
data: {
name,
disabled: disabledPlugins.some((disabledPlugin) => disabledPlugin.name === name),
@@ -221,7 +234,7 @@ export default function PluginList({ isDeveloper }: { isDeveloper: boolean }) {
};
}),
);
}, [installedPlugins, updates, hiddenPlugins, disabledPlugins]);
}, [installedPlugins, updates, hiddenPlugins, disabledPlugins, sortPlugins, sortedPlugins]);
if (installedPlugins.length === 0) {
return (
@@ -232,6 +245,9 @@ export default function PluginList({ isDeveloper }: { isDeveloper: boolean }) {
}
function onSave(entries: ReorderableEntry<PluginTableData>[]) {
if (sortPlugins) {
return;
}
const newOrder = entries.map((entry) => entry.data!.name);
console.log(newOrder);
setPluginOrder(newOrder);
@@ -265,7 +281,12 @@ export default function PluginList({ isDeveloper }: { isDeveloper: boolean }) {
</DialogButton>
)}
<DialogControlsSection style={{ marginTop: 0 }}>
<ReorderableList<PluginTableData> entries={pluginEntries} onSave={onSave} interactables={PluginInteractables} />
<ReorderableList<PluginTableData>
entries={pluginEntries}
onSave={onSave}
interactables={PluginInteractables}
disableReordering={sortPlugins}
/>
</DialogControlsSection>
</DialogBody>
);
+6
View File
@@ -360,6 +360,12 @@ class PluginLoader extends Logger {
this.deckyState.setPluginOrder(pluginOrder);
});
// Grab and set sort plugins setting
getSetting<boolean>('sortPlugins', false).then((sortPlugins) => {
this.debug('sortPlugins: ', sortPlugins);
this.deckyState.setSortPlugins(sortPlugins);
});
this.frozenPluginsService.init();
this.hiddenPluginsService.init();
this.notificationService.init();