From 813bd56fab297bd303cd4e2605a1fcf3625ad14e Mon Sep 17 00:00:00 2001 From: Tormak <63308171+Tormak9970@users.noreply.github.com> Date: Sun, 7 Jan 2024 20:56:25 -0500 Subject: [PATCH] chore: renamed snapshots to tab groups --- main.py | 18 ++--- src/components/QuickAccessContent.tsx | 8 +- .../{menus => context-menus}/LibraryMenu.tsx | 6 +- .../{menus => context-menus}/PresetMenu.tsx | 0 src/components/context-menus/TabGroupMenu.tsx | 78 +++++++++++++++++++ src/components/filters/FilterSelect.tsx | 3 + src/components/menus/SnapshotMenu.tsx | 65 ---------------- ...{SnapshotModals.tsx => TabGroupModals.tsx} | 18 ++--- src/index.tsx | 3 - src/lib/controllers/PluginController.tsx | 7 ++ src/lib/controllers/PythonInterop.ts | 16 ++-- src/lib/controllers/SteamController.ts | 9 +++ src/patches/LibraryPatch.tsx | 2 +- src/state/SnapshotManager.tsx | 29 ------- src/state/TabGroupManager.tsx | 45 +++++++++++ src/state/TabMasterManager.tsx | 8 +- 16 files changed, 180 insertions(+), 135 deletions(-) rename src/components/{menus => context-menus}/LibraryMenu.tsx (97%) rename src/components/{menus => context-menus}/PresetMenu.tsx (100%) create mode 100644 src/components/context-menus/TabGroupMenu.tsx delete mode 100644 src/components/menus/SnapshotMenu.tsx rename src/components/modals/{SnapshotModals.tsx => TabGroupModals.tsx} (61%) delete mode 100644 src/state/SnapshotManager.tsx create mode 100644 src/state/TabGroupManager.tsx diff --git a/main.py b/main.py index ecd256c..f45b436 100644 --- a/main.py +++ b/main.py @@ -148,18 +148,18 @@ async def get_friends_games(self) -> dict[int, list[int]] | None: log(f"Got {len(friends_games)} friendsGames") return friends_games or {} - async def get_snapshots(self) -> dict[str, list[str]] | None: + async def get_tab_groups(self) -> dict[str, list[str]] | None: """ - Waits until users_dict is loaded, then returns snapshots + Waits until users_dict is loaded, then returns the tab groups - :return: Users tab visibility snapshots + :return: User's tab groups """ while Plugin.users_dict is None: await asyncio.sleep(0.1) - snapshots = Plugin.users_dict[Plugin.user_id]["snapshots"] - log(f"Got snapshots {snapshots}") - return snapshots or {} + tab_groups = Plugin.users_dict[Plugin.user_id]["tabGroups"] + log(f"Got tab groups {tab_groups}") + return tab_groups or {} # Plugin settings setters async def set_tabs(self, tabs: dict[str, dict]): @@ -167,7 +167,7 @@ async def set_tabs(self, tabs: dict[str, dict]): await Plugin.set_setting(self, "usersDict", Plugin.users_dict) async def set_tags(self, tags: list[dict]): - Plugin.tags= tags + Plugin.tags = tags await Plugin.set_setting(self, "tags", Plugin.tags) async def set_friends(self, friends: list[dict]): @@ -178,8 +178,8 @@ async def set_friends_games(self, friends_games: dict[str, list[int]]): Plugin.users_dict[Plugin.user_id]["friendsGames"] = friends_games await Plugin.set_setting(self, "usersDict", Plugin.users_dict) - async def set_snapshots(self, snapshots: dict[str, list[str]]): - Plugin.users_dict[Plugin.user_id]["snapshots"] = snapshots + async def set_tab_groups(self, tab_groups: dict[str, list[str]]): + Plugin.users_dict[Plugin.user_id]["tabGroups"] = tab_groups await Plugin.set_setting(self, "usersDict", Plugin.users_dict) async def get_docs(self): diff --git a/src/components/QuickAccessContent.tsx b/src/components/QuickAccessContent.tsx index e674061..5262cc1 100644 --- a/src/components/QuickAccessContent.tsx +++ b/src/components/QuickAccessContent.tsx @@ -22,12 +22,12 @@ import { QamStyles } from "./styles/QamStyles"; import { showModalNewTab } from "./modals/EditTabModal"; import { TabActionsButton } from "./TabActions"; import { LogController } from "../lib/controllers/LogController"; -import { PresetMenu } from './menus/PresetMenu'; +import { PresetMenu } from './context-menus/PresetMenu'; import { TabListLabel } from './TabListLabel'; import { MicroSDeckInstallState, MicroSDeckInterop, microSDeckLibVersion } from '../lib/controllers/MicroSDeckInterop'; import { MicroSDeckNotice } from './MicroSDeckNotice'; import { CustomTabContainer } from './CustomTabContainer'; -import { SnapshotMenu } from './menus/SnapshotMenu'; +import { TabGroupsMenu } from './context-menus/TabGroupMenu'; export type TabIdEntryType = { @@ -103,11 +103,11 @@ export const QuickAccessContent: VFC<{}> = ({ }) => { { if(evt.detail.button === GamepadButton.SELECT) { - showContextMenu(); + showContextMenu(); } }} onMenuButton={() => { Navigation.CloseSideMenus(); Navigation.Navigate("/tab-master-docs"); }} diff --git a/src/components/menus/LibraryMenu.tsx b/src/components/context-menus/LibraryMenu.tsx similarity index 97% rename from src/components/menus/LibraryMenu.tsx rename to src/components/context-menus/LibraryMenu.tsx index dc9b302..005c159 100644 --- a/src/components/menus/LibraryMenu.tsx +++ b/src/components/context-menus/LibraryMenu.tsx @@ -1,7 +1,6 @@ import { Menu, MenuItem, showModal, Focusable, MenuGroup, ReorderableEntry, ReorderableList, MenuItemProps } from 'decky-frontend-lib'; import { FC, Fragment, VFC, useState } from 'react'; import { TabMasterManager } from '../../state/TabMasterManager'; -import { TabIdEntryType } from '../..'; import { TabMasterContextProvider, useTabMasterContext } from '../../state/TabMasterContext'; import { showModalEditTab, showModalNewTab } from '../modals/EditTabModal'; import { LibraryMenuStyles } from '../styles/LibraryMenuStyles'; @@ -11,7 +10,8 @@ import { PresetMenuItems } from './PresetMenu'; import { CustomTabContainer } from '../CustomTabContainer'; import { TabListLabel } from '../TabListLabel'; import { MicroSDeckInterop } from '../../lib/controllers/MicroSDeckInterop'; -import { ApplySnapshotMenuGroup } from './SnapshotMenu'; +import { TabGroupsSubMenu } from './TabGroupMenu'; +import { TabIdEntryType } from "../QuickAccessContent"; export interface LibraryMenuProps { closeMenu: () => void; @@ -66,7 +66,7 @@ const LibraryMenuItems: VFC = ({ selectedTabId, closeMenu
- + diff --git a/src/components/menus/PresetMenu.tsx b/src/components/context-menus/PresetMenu.tsx similarity index 100% rename from src/components/menus/PresetMenu.tsx rename to src/components/context-menus/PresetMenu.tsx diff --git a/src/components/context-menus/TabGroupMenu.tsx b/src/components/context-menus/TabGroupMenu.tsx new file mode 100644 index 0000000..8a28c96 --- /dev/null +++ b/src/components/context-menus/TabGroupMenu.tsx @@ -0,0 +1,78 @@ +import { Menu, MenuGroup, MenuItem, showModal } from 'decky-frontend-lib'; +import { VFC, Fragment } from 'react'; +import { TabMasterManager } from '../../state/TabMasterManager'; +import { CreateTabGroupModal, OverwriteTabGroupModal } from '../modals/TabGroupModals'; + +interface TabsGroupMenuProps { + tabMasterManager: TabMasterManager, +} + +/** + * Context menu for managing Tab Groups. + */ +export const TabGroupsMenu: VFC = ({ tabMasterManager }) => { + return + + ; +}; + +/** + * Context menu sub-menu for managing Tab Groups. + */ +export const TabGroupsSubMenu: VFC = ({ tabMasterManager }) => { + return + + ; +}; + +/** + * Menu items for the Tab Group context menu. + */ +const TabGroupMenuItems: VFC = ({ tabMasterManager }) => { + return ( + <> + showModal()}> + Create Group + + + {/*
*/} + + + ); +}; + +/** + * The overwrite menu for Tab Groups. + */ +const OverwriteTabGroupMenu: VFC = ({ tabMasterManager }) => { + return ( + + {Object.keys(tabMasterManager.tabGroupManager?.snapshots ?? {}).map(snapshotName => { + return ( + showModal()}> + {snapshotName} + + ); + })} + + ); +}; + +/** + * The apply menu for Tab Groups. + */ +const ApplyTabGroupMenu: VFC = ({ tabMasterManager }) => { + return ( + + {Object.keys(tabMasterManager.tabGroupManager?.snapshots ?? {}).map(snapshotName => { + return ( + tabMasterManager.tabGroupManager?.apply(snapshotName, tabMasterManager)}> + {snapshotName} + + ); + })} + + ); +}; + + diff --git a/src/components/filters/FilterSelect.tsx b/src/components/filters/FilterSelect.tsx index 474e171..7d81902 100644 --- a/src/components/filters/FilterSelect.tsx +++ b/src/components/filters/FilterSelect.tsx @@ -54,12 +54,15 @@ interface FilterSelectElement { const FilterSelectElement: VFC = ({ filterType, focusable, onClick }) => { let disabled = false; let requiredMicroSDeckVer = ''; + if (filterType === 'sd card') { disabled = !MicroSDeckInterop.isInstallOk(); const [major, minor, patch] = microSDeckLibVersion.split(/[.+-]/, 3); + if (+major > 0) requiredMicroSDeckVer = major + '.x.x'; if (+major === 0) requiredMicroSDeckVer = `0.${minor}.${patch}`; } + const canFocus = focusable && !disabled; return ( diff --git a/src/components/menus/SnapshotMenu.tsx b/src/components/menus/SnapshotMenu.tsx deleted file mode 100644 index 453f3a1..0000000 --- a/src/components/menus/SnapshotMenu.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { Menu, MenuGroup, MenuItem, showModal } from 'decky-frontend-lib'; -import { VFC, Fragment } from 'react'; -import { TabMasterManager } from '../../state/TabMasterManager'; -import { CreateSnapshotModal, OverwriteSnapshotModal } from '../modals/SnapshotModals'; -import { gamepadContextMenuClasses } from '../../lib/GamepadContextMenuClasses'; - -interface SnapshotMenuProps { - tabMasterManager: TabMasterManager, -} - -export const SnapshotMenu: VFC = ({ tabMasterManager }) => { - return - - ; -}; - - -export const SnapshotMenuItems: VFC = ({ tabMasterManager }) => { - return ( - <> - showModal()}> - New - - -
- - - ); -}; - -export const OverwriteSnapshotMenuGroup: VFC = ({ tabMasterManager }) => { - - return ( - - {Object.keys(tabMasterManager.snapshotManager?.snapshots ?? {}).map(snapshotName => { - return ( - showModal()}> - {snapshotName} - - ); - })} - - ); -}; - -interface ApplySnapshotMenuGroupProps extends SnapshotMenuProps { - label: string; -} - -export const ApplySnapshotMenuGroup: VFC = ({ label, tabMasterManager }) => { - - return ( - - {Object.keys(tabMasterManager.snapshotManager?.snapshots ?? {}).map(snapshotName => { - return ( - tabMasterManager.snapshotManager?.apply(snapshotName, tabMasterManager)}> - {snapshotName} - - ); - })} - - ); -}; - - diff --git a/src/components/modals/SnapshotModals.tsx b/src/components/modals/TabGroupModals.tsx similarity index 61% rename from src/components/modals/SnapshotModals.tsx rename to src/components/modals/TabGroupModals.tsx index ed66455..cb0c768 100644 --- a/src/components/modals/SnapshotModals.tsx +++ b/src/components/modals/TabGroupModals.tsx @@ -2,41 +2,41 @@ import { ConfirmModal, TextField } from 'decky-frontend-lib'; import { VFC, useState } from 'react'; import { TabMasterManager } from '../../state/TabMasterManager'; -export interface CreateSnapshotModalProps { +export interface CreateTabGroupModalProps { tabMasterManager: TabMasterManager, closeModal?: () => void, } -export const CreateSnapshotModal: VFC = ({ tabMasterManager, closeModal }) => { +export const CreateTabGroupModal: VFC = ({ tabMasterManager, closeModal }) => { const [name, setName] = useState(''); const visibleTabs = tabMasterManager.getTabs().visibleTabsList; return ( { - tabMasterManager.snapshotManager?.write(name, visibleTabs.map(tabContainer => tabContainer.id)); + tabMasterManager.tabGroupManager?.write(name, visibleTabs.map(tabContainer => tabContainer.id)); closeModal!(); }} onCancel={() => closeModal!()} > - setName(e?.target.value)} /> + setName(e?.target.value)} /> {visibleTabs.map(tabContainer =>
{tabContainer.title}
)}
); }; -export interface OverwriteSnapshotModalProps extends CreateSnapshotModalProps { - snapshotName: string; +export interface OverwriteTabGroupModalProps extends CreateTabGroupModalProps { + groupName: string; } -export const OverwriteSnapshotModal: VFC = ({ snapshotName, tabMasterManager, closeModal }) => { +export const OverwriteTabGroupModal: VFC = ({ groupName, tabMasterManager, closeModal }) => { const { visibleTabsList, tabsMap } = tabMasterManager.getTabs(); - const existingTabs = tabMasterManager.snapshotManager!.snapshots[snapshotName].map(tabId => tabsMap.get(tabId)); + const existingTabs = tabMasterManager.tabGroupManager!.tabGroups[groupName].map(tabId => tabsMap.get(tabId)); return ( { - tabMasterManager.snapshotManager?.write(snapshotName, visibleTabsList.map(tabContainer => tabContainer.id)); + tabMasterManager.tabGroupManager?.write(groupName, visibleTabsList.map(tabContainer => tabContainer.id)); closeModal!(); }} onCancel={() => closeModal!()} diff --git a/src/index.tsx b/src/index.tsx index 1ad60c6..a27b293 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -52,8 +52,6 @@ export default definePlugin((serverAPI: ServerAPI) => { settingsPatch = patchSettings(serverAPI, tabMasterManager); }); - const onWakeUnregister = SteamClient.System.RegisterForOnResumeFromSuspend(PluginController.onWakeFromSleep.bind(PluginController)).unregister; - PythonInterop.getDocs().then((pages: DocPages | Error) => { if (pages instanceof Error) { LogController.error(pages); @@ -79,7 +77,6 @@ export default definePlugin((serverAPI: ServerAPI) => { serverAPI.routerHook.removeRoute("/tab-master-docs"); loginUnregisterer.unregister(); - onWakeUnregister(); PluginController.dismount(); }, }; diff --git a/src/lib/controllers/PluginController.tsx b/src/lib/controllers/PluginController.tsx index 0cdb841..18c5ab9 100644 --- a/src/lib/controllers/PluginController.tsx +++ b/src/lib/controllers/PluginController.tsx @@ -46,6 +46,8 @@ export class PluginController { private static steamController: SteamController; + private static onWakeSub: Unregisterer; + /** * Sets the plugin's serverAPI. * @param server The serverAPI to use. @@ -79,6 +81,8 @@ export class PluginController { */ static async init(): Promise { LogController.log("PluginController initialized."); + + this.onWakeSub = this.steamController.registerForOnResumeFromSuspend(this.onWakeFromSleep.bind(this)); // @ts-ignore return new Promise(async (resolve, reject) => { @@ -121,7 +125,10 @@ export class PluginController { * Function to run when the plugin dismounts. */ static dismount(): void { + if (this.onWakeSub) this.onWakeSub.unregister(); + this.tabMasterManager.disposeReactions(); + LogController.log("PluginController dismounted."); } } diff --git a/src/lib/controllers/PythonInterop.ts b/src/lib/controllers/PythonInterop.ts index 3249f17..8ed96f9 100644 --- a/src/lib/controllers/PythonInterop.ts +++ b/src/lib/controllers/PythonInterop.ts @@ -1,6 +1,6 @@ import { ServerAPI } from "decky-frontend-lib"; import { validateTabs } from "../Utils"; -import { SnapshotDictionary } from '../../state/SnapshotManager'; +import { TabGroupDictionary } from '../../state/TabGroupManager'; /** * Class for frontend -> backend communication. @@ -185,8 +185,8 @@ export class PythonInterop { * Gets the visible tab snapshots. * @returns A promise resolving the snapshots. */ - static async getSnapshots(): Promise { - let result = await PythonInterop.serverAPI.callPluginMethod<{}, SnapshotDictionary>("get_snapshots", {}); + static async getSnapshots(): Promise { + let result = await PythonInterop.serverAPI.callPluginMethod<{}, TabGroupDictionary>("get_snapshots", {}); if (result.success) { return result.result; @@ -267,12 +267,12 @@ export class PythonInterop { } /** - * Sets the visible tab snapshots. - * @param snapshots The snapshots. - * @returns A promise resolving to whether or not the snapshots were successfully set. + * Sets the tab groups. + * @param tabGroups The tab groups. + * @returns A promise resolving to whether or not the tab groups were successfully set. */ - static async setSnapshots(snapshots: SnapshotDictionary): Promise { - let result = await PythonInterop.serverAPI.callPluginMethod<{ snapshots: SnapshotDictionary }, void>("set_snapshots", { snapshots: snapshots }); + static async setTabGroups(tabGroups: TabGroupDictionary): Promise { + let result = await PythonInterop.serverAPI.callPluginMethod<{ tab_groups: TabGroupDictionary }, void>("set_tab_groups", { tab_groups: tabGroups }); if (result.success) { return result.result; diff --git a/src/lib/controllers/SteamController.ts b/src/lib/controllers/SteamController.ts index 666918a..fe2c6d6 100644 --- a/src/lib/controllers/SteamController.ts +++ b/src/lib/controllers/SteamController.ts @@ -69,6 +69,15 @@ export class SteamController { })) ?? false; } + /** + * Register a function for when the Steamdeck resumes from sleep. + * @param callback The callback to register. + * @returns A function that unsubscribes the callback. + */ + registerForOnResumeFromSuspend(callback: () => void): Unregisterer { + return SteamClient.System.RegisterForOnResumeFromSuspend(callback); + } + /** * Gets the localized tags from a list of ids. * @param tags The list of tag ids. diff --git a/src/patches/LibraryPatch.tsx b/src/patches/LibraryPatch.tsx index 929db98..e481a5b 100644 --- a/src/patches/LibraryPatch.tsx +++ b/src/patches/LibraryPatch.tsx @@ -11,7 +11,7 @@ import { ReactElement, useEffect, useState } from "react"; import { TabMasterManager } from "../state/TabMasterManager"; import { CustomTabContainer } from "../components/CustomTabContainer"; import { LogController } from "../lib/controllers/LogController"; -import { LibraryMenu } from '../components/menus/LibraryMenu'; +import { LibraryMenu } from '../components/context-menus/LibraryMenu'; import { MicroSDeckInterop } from '../lib/controllers/MicroSDeckInterop'; /** diff --git a/src/state/SnapshotManager.tsx b/src/state/SnapshotManager.tsx deleted file mode 100644 index 3bf8b97..0000000 --- a/src/state/SnapshotManager.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { PythonInterop } from '../lib/controllers/PythonInterop'; -import { TabMasterManager } from './TabMasterManager'; - -export type SnapshotDictionary = { - [name: string]: string[]; //array of ordered tab ids -}; - -export class SnapshotManager { - snapshots: SnapshotDictionary; - - constructor(snapshots: SnapshotDictionary) { - this.snapshots = snapshots; - } - - write(snapshotName: string, tabIds: string[]) { - this.snapshots[snapshotName] = tabIds; - this.save(); - } - - - apply(snapshotName: string, tabMasterManager: TabMasterManager) { - tabMasterManager.getTabs().tabsMap.forEach(tabContainer => tabContainer.position = -1); - tabMasterManager.reorderTabs(this.snapshots[snapshotName]); - } - - private save() { - PythonInterop.setSnapshots(this.snapshots); - } -} diff --git a/src/state/TabGroupManager.tsx b/src/state/TabGroupManager.tsx new file mode 100644 index 0000000..a93583e --- /dev/null +++ b/src/state/TabGroupManager.tsx @@ -0,0 +1,45 @@ +import { PythonInterop } from '../lib/controllers/PythonInterop'; +import { TabMasterManager } from './TabMasterManager'; + +export type TabGroupDictionary = { + [name: string]: string[]; //array of ordered tab ids +}; + +export class TabGroupManager { + tabGroups: TabGroupDictionary; + + /** + * Creates a new TabGroupManager. + * @param tabGroups The existing tab groups the current user has. + */ + constructor(tabGroups: TabGroupDictionary) { + this.tabGroups = tabGroups; + } + + /** + * Writes a tab group. + * @param tabGroupName The name of the tab group to write. + * @param tabIds The list of ids of the tabs that are included in this group. + */ + write(tabGroupName: string, tabIds: string[]) { + this.tabGroups[tabGroupName] = tabIds; + this.save(); + } + + /** + * Applies a tab group. + * @param tabGroupName The name of the tab group to apply. + * @param tabMasterManager The plugin manager. + */ + apply(tabGroupName: string, tabMasterManager: TabMasterManager) { + tabMasterManager.getTabs().tabsMap.forEach(tabContainer => tabContainer.position = -1); + tabMasterManager.reorderTabs(this.tabGroups[tabGroupName]); + } + + /** + * Saves all changes made to the tab groups. + */ + private save() { + PythonInterop.setTabGroups(this.tabGroups); + } +} diff --git a/src/state/TabMasterManager.tsx b/src/state/TabMasterManager.tsx index 3fab7ba..893ba44 100644 --- a/src/state/TabMasterManager.tsx +++ b/src/state/TabMasterManager.tsx @@ -9,7 +9,7 @@ import { LogController } from "../lib/controllers/LogController"; import { PresetName, PresetOptions, getPreset } from '../presets/presets'; import { MicroSDeckInterop } from '../lib/controllers/MicroSDeckInterop'; import { TabErrorController } from '../lib/controllers/TabErrorController'; -import { SnapshotDictionary, SnapshotManager } from './SnapshotManager'; +import { TabGroupDictionary, TabGroupManager } from './TabGroupManager'; /** * Converts a list of filters into a 1D array. @@ -67,7 +67,7 @@ export class TabMasterManager { private collectionRemoveReaction: IReactionDisposer | undefined; - public snapshotManager: SnapshotManager | undefined; + public tabGroupManager: TabGroupManager | undefined; /** * Creates a new TabMasterManager. @@ -523,12 +523,12 @@ export class TabMasterManager { } } }); - PythonInterop.getSnapshots().then((res: SnapshotDictionary | Error) => { + PythonInterop.getSnapshots().then((res: TabGroupDictionary | Error) => { if (res instanceof Error) { LogController.log("TabMaster couldn't load tab visibilty snapshots"); LogController.error(res.message); } else { - this.snapshotManager = new SnapshotManager(res); + this.tabGroupManager = new TabGroupManager(res); } });