mirror of
https://github.com/Droid-Deck/decky-loader.git
synced 2026-11-07 10:25:58 -10:00
Merge remote-tracking branch 'upstream/main' into HEAD
This commit is contained in:
commit
fab65e4ca4
8 files changed
+85
-24
No files matched your search
@@ -217,6 +217,9 @@
|
||||
"developer_mode": {
|
||||
"label": "Developer mode"
|
||||
},
|
||||
"sort_plugins": {
|
||||
"label": "Sort plugins alphabetically"
|
||||
},
|
||||
"notifications": {
|
||||
"decky_updates_label": "Decky update available",
|
||||
"header": "Notifications",
|
||||
|
||||
@@ -333,20 +333,24 @@ class Utilities:
|
||||
|
||||
#Resolving all files/folders in the requested directory
|
||||
for file in path_obj.iterdir():
|
||||
if file.exists():
|
||||
filest = file.stat()
|
||||
is_hidden = file.name.startswith('.')
|
||||
if ON_WINDOWS and not is_hidden:
|
||||
is_hidden = bool(filest.st_file_attributes & FILE_ATTRIBUTE_HIDDEN) # type: ignore
|
||||
if include_folders and file.is_dir():
|
||||
if (is_hidden and include_hidden) or not is_hidden:
|
||||
folders.append({"file": file, "filest": filest, "is_dir": True})
|
||||
elif include_files:
|
||||
# Handle requested extensions if present
|
||||
if include_ext == None or len(include_ext) == 0 or 'all_files' in include_ext \
|
||||
or splitext(file.name)[1].lstrip('.').upper() in (ext.upper() for ext in include_ext):
|
||||
try:
|
||||
if file.exists():
|
||||
filest = file.stat()
|
||||
is_hidden = file.name.startswith('.')
|
||||
if ON_WINDOWS and not is_hidden:
|
||||
is_hidden = bool(filest.st_file_attributes & FILE_ATTRIBUTE_HIDDEN) # type: ignore
|
||||
if include_folders and file.is_dir():
|
||||
if (is_hidden and include_hidden) or not is_hidden:
|
||||
files.append({"file": file, "filest": filest, "is_dir": False})
|
||||
folders.append({"file": file, "filest": filest, "is_dir": True})
|
||||
elif include_files:
|
||||
# Handle requested extensions if present
|
||||
if include_ext == None or len(include_ext) == 0 or 'all_files' in include_ext \
|
||||
or splitext(file.name)[1].lstrip('.').upper() in (ext.upper() for ext in include_ext):
|
||||
if (is_hidden and include_hidden) or not is_hidden:
|
||||
files.append({"file": file, "filest": filest, "is_dir": False})
|
||||
except (PermissionError, OSError):
|
||||
self.logger.debug(f"Skipping inaccessible file picker entry: {file}")
|
||||
continue
|
||||
# Filter logic
|
||||
if filter_for is not None:
|
||||
try:
|
||||
|
||||
@@ -9,7 +9,7 @@ a = Analysis(
|
||||
('decky_loader/locales', 'decky_loader/locales'),
|
||||
('decky_loader/static', 'decky_loader/static'),
|
||||
] + copy_metadata('decky_loader'),
|
||||
hiddenimports=['logging.handlers', 'sqlite3', 'decky_plugin', 'decky'],
|
||||
hiddenimports=['logging.handlers', 'sqlite3', 'http.server', 'socketserver', 'configparser', 'decky_plugin', 'decky'],
|
||||
)
|
||||
pyz = PYZ(a.pure, a.zipped_data)
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user