summaryrefslogtreecommitdiff
path: root/frontend/src/components/settings/pages
diff options
context:
space:
mode:
authorNihaal Sangha <nihaal.git@gmail.com>2026-09-25 21:32:11 +0100
committerGitHub <noreply@github.com>2026-09-25 16:32:11 -0400
commit84288115c8db0abe40061df0612567ab4ac81967 (patch)
tree216215d9aa6f709e329cd5033ea1c9fedbbf9110 /frontend/src/components/settings/pages
parentb73a094ae148ca39de5a349432f45f1bf29c0131 (diff)
downloaddecky-loader-84288115c8db0abe40061df0612567ab4ac81967.tar.gz
decky-loader-84288115c8db0abe40061df0612567ab4ac81967.zip
Add sort plugins setting (#859)
Diffstat (limited to 'frontend/src/components/settings/pages')
-rw-r--r--frontend/src/components/settings/pages/general/index.tsx13
-rw-r--r--frontend/src/components/settings/pages/plugin_list/index.tsx35
2 files changed, 40 insertions, 8 deletions
diff --git a/frontend/src/components/settings/pages/general/index.tsx b/frontend/src/components/settings/pages/general/index.tsx
index 84ad88f1..9bd5616d 100644
--- a/frontend/src/components/settings/pages/general/index.tsx
+++ b/frontend/src/components/settings/pages/general/index.tsx
@@ -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>
diff --git a/frontend/src/components/settings/pages/plugin_list/index.tsx b/frontend/src/components/settings/pages/plugin_list/index.tsx
index 75365ba5..71a7df6c 100644
--- a/frontend/src/components/settings/pages/plugin_list/index.tsx
+++ b/frontend/src/components/settings/pages/plugin_list/index.tsx
@@ -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>
);