From c2ebc78836cafc96f03546e6dba5acfa86795d65 Mon Sep 17 00:00:00 2001 From: Andrew Moore Date: Wed, 14 Feb 2024 23:45:55 -0500 Subject: [Feature] Freeze updates for devs (#582) --- frontend/src/components/DeckyState.tsx | 8 ++++ .../src/components/modals/PluginUninstallModal.tsx | 1 + frontend/src/components/settings/index.tsx | 2 +- .../settings/pages/plugin_list/PluginListLabel.tsx | 22 ++++++++-- .../settings/pages/plugin_list/index.tsx | 30 ++++++++++--- frontend/src/frozen-plugins-service.tsx | 49 ++++++++++++++++++++++ frontend/src/plugin-loader.tsx | 7 +++- 7 files changed, 109 insertions(+), 10 deletions(-) create mode 100644 frontend/src/frozen-plugins-service.tsx (limited to 'frontend') diff --git a/frontend/src/components/DeckyState.tsx b/frontend/src/components/DeckyState.tsx index d20c8d86..749e27ce 100644 --- a/frontend/src/components/DeckyState.tsx +++ b/frontend/src/components/DeckyState.tsx @@ -8,6 +8,7 @@ import { VerInfo } from '../updater'; interface PublicDeckyState { plugins: Plugin[]; pluginOrder: string[]; + frozenPlugins: string[]; hiddenPlugins: string[]; activePlugin: Plugin | null; updates: PluginUpdateMapping | null; @@ -26,6 +27,7 @@ export interface UserInfo { export class DeckyState { private _plugins: Plugin[] = []; private _pluginOrder: string[] = []; + private _frozenPlugins: string[] = []; private _hiddenPlugins: string[] = []; private _activePlugin: Plugin | null = null; private _updates: PluginUpdateMapping | null = null; @@ -41,6 +43,7 @@ export class DeckyState { return { plugins: this._plugins, pluginOrder: this._pluginOrder, + frozenPlugins: this._frozenPlugins, hiddenPlugins: this._hiddenPlugins, activePlugin: this._activePlugin, updates: this._updates, @@ -67,6 +70,11 @@ export class DeckyState { this.notifyUpdate(); } + setFrozenPlugins(frozenPlugins: string[]) { + this._frozenPlugins = frozenPlugins; + this.notifyUpdate(); + } + setHiddenPlugins(hiddenPlugins: string[]) { this._hiddenPlugins = hiddenPlugins; this.notifyUpdate(); diff --git a/frontend/src/components/modals/PluginUninstallModal.tsx b/frontend/src/components/modals/PluginUninstallModal.tsx index 3fc0a71f..087b634c 100644 --- a/frontend/src/components/modals/PluginUninstallModal.tsx +++ b/frontend/src/components/modals/PluginUninstallModal.tsx @@ -19,6 +19,7 @@ const PluginUninstallModal: FC = ({ name, title, butt await uninstallPlugin(name); // uninstalling a plugin resets the hidden setting for it server-side // we invalidate here so if you re-install it, you won't have an out-of-date hidden filter + await DeckyPluginLoader.frozenPluginsService.invalidate(); await DeckyPluginLoader.hiddenPluginsService.invalidate(); }} strTitle={title} diff --git a/frontend/src/components/settings/index.tsx b/frontend/src/components/settings/index.tsx index 568a0a49..80400058 100644 --- a/frontend/src/components/settings/index.tsx +++ b/frontend/src/components/settings/index.tsx @@ -25,7 +25,7 @@ export default function SettingsPage() { }, { title: t('SettingsIndex.plugins_title'), - content: , + content: , route: '/decky/settings/plugins', icon: , }, diff --git a/frontend/src/components/settings/pages/plugin_list/PluginListLabel.tsx b/frontend/src/components/settings/pages/plugin_list/PluginListLabel.tsx index a49f808f..fec03e56 100644 --- a/frontend/src/components/settings/pages/plugin_list/PluginListLabel.tsx +++ b/frontend/src/components/settings/pages/plugin_list/PluginListLabel.tsx @@ -1,18 +1,34 @@ import { FC } from 'react'; import { useTranslation } from 'react-i18next'; -import { FaEyeSlash } from 'react-icons/fa'; +import { FaEyeSlash, FaLock } from 'react-icons/fa'; interface PluginListLabelProps { + frozen: boolean; hidden: boolean; name: string; version?: string; } -const PluginListLabel: FC = ({ name, hidden, version }) => { +const PluginListLabel: FC = ({ name, frozen, hidden, version }) => { const { t } = useTranslation(); return (
-
{version ? `${name} - ${version}` : name}
+
+ {name} + {version && ( + <> + {' - '} + + {frozen && ( + <> + {' '} + + )} + {version} + + + )} +
{hidden && (
('loader/reload_plugin'); @@ -45,7 +54,7 @@ function PluginInteractables(props: { entry: ReorderableEntry } return null; } - const { name, update, version, onHide, onShow, hidden } = props.entry.data; + const { name, update, version, onHide, onShow, hidden, onFreeze, onUnfreeze, frozen, isDeveloper } = props.entry.data; const showCtxMenu = (e: MouseEvent | GamepadEvent) => { showContextMenu( @@ -80,6 +89,11 @@ function PluginInteractables(props: { entry: ReorderableEntry } ) : ( {t('PluginListIndex.hide')} )} + {frozen ? ( + {t('PluginListIndex.unfreeze')} + ) : ( + isDeveloper && {t('PluginListIndex.freeze')} + )} , e.currentTarget ?? window, ); @@ -134,8 +148,8 @@ type PluginData = { version?: string; }; -export default function PluginList() { - const { plugins, updates, pluginOrder, setPluginOrder, hiddenPlugins } = useDeckyState(); +export default function PluginList({ isDeveloper }: { isDeveloper: boolean }) { + const { plugins, updates, pluginOrder, setPluginOrder, frozenPlugins, hiddenPlugins } = useDeckyState(); const [_, setPluginOrderSetting] = useSetting( 'pluginOrder', plugins.map((plugin) => plugin.name), @@ -148,20 +162,26 @@ export default function PluginList() { const [pluginEntries, setPluginEntries] = useState[]>([]); const hiddenPluginsService = DeckyPluginLoader.hiddenPluginsService; + const frozenPluginsService = DeckyPluginLoader.frozenPluginsService; useEffect(() => { setPluginEntries( plugins.map(({ name, version }) => { + const frozen = frozenPlugins.includes(name); const hidden = hiddenPlugins.includes(name); return { - label: