From 01fa79f50ce339f43d1ee210479c3973ee3a95df Mon Sep 17 00:00:00 2001 From: Jesse Bofill Date: Thu, 27 Jun 2024 13:54:31 -0600 Subject: [PATCH 1/6] fix: tabmaster now loads on latest steam client beta --- src/components/CustomTabContainer.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/CustomTabContainer.tsx b/src/components/CustomTabContainer.tsx index ce46770..f7a0ae5 100644 --- a/src/components/CustomTabContainer.tsx +++ b/src/components/CustomTabContainer.tsx @@ -101,9 +101,8 @@ export class CustomTabContainer implements TabContainer { this.collection.allApps = appsList; this.collection.visibleApps = [...appsList]; - const allAppsMap = collectionStore.allAppsCollection.apps; const appMap = new Map(); - appsList.forEach((appItem: SteamAppOverview) => appMap.set(appItem.appid, allAppsMap.get(appItem.appid)!)); + appsList.forEach((appItem: SteamAppOverview) => appMap.set(appItem.appid, appItem)); this.collection.apps = appMap; } From d3454859677f7f2342e4fd8d9e725bc831e91be5 Mon Sep 17 00:00:00 2001 From: Jesse Bofill Date: Thu, 27 Jun 2024 14:42:58 -0600 Subject: [PATCH 2/6] chore: add null check to temporarily work around component not being found in settings patch --- src/patches/SettingsPatch.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patches/SettingsPatch.tsx b/src/patches/SettingsPatch.tsx index acac2b7..898ce5c 100644 --- a/src/patches/SettingsPatch.tsx +++ b/src/patches/SettingsPatch.tsx @@ -20,7 +20,7 @@ export const patchSettings = (serverAPI: ServerAPI, tabMasterManager: TabMasterM } afterPatch(ret1, 'type', (_: any, ret2: any) => { - const homeElement = ret2?.props?.children?.props?.pages?.find((obj: any) => obj.route === '/settings/home')?.content?.props?.children[1]; + const homeElement = ret2?.props?.children?.props?.pages?.find((obj: any) => obj.route === '/settings/home')?.content?.props?.children?.[1]; if (homeElement === undefined) { LogController.raiseError("Couldn't find home element to patch in settings"); return ret2; From 25bbf21b6d150bd79a31afbb5de5e0080550e10a Mon Sep 17 00:00:00 2001 From: Jesse Bofill Date: Thu, 27 Jun 2024 15:01:31 -0600 Subject: [PATCH 3/6] chore: raise errors that occur during plugin load --- src/components/QuickAccessContent.tsx | 4 +-- src/state/TabMasterManager.tsx | 37 +++++++++++++-------------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/components/QuickAccessContent.tsx b/src/components/QuickAccessContent.tsx index aa8bbc5..f886637 100644 --- a/src/components/QuickAccessContent.tsx +++ b/src/components/QuickAccessContent.tsx @@ -64,7 +64,7 @@ export const QuickAccessContent: VFC<{}> = ({ }) => { return (
- {LogController.errorFlag &&
+ {LogController.errorFlag && {}}>

Tab Master encountered an error @@ -80,7 +80,7 @@ export const QuickAccessContent: VFC<{}> = ({ }) => {
for support.

-
} + } {hasSdTabs && !isMicroSDeckInstalled && !microSDeckNoticeHidden && (
diff --git a/src/state/TabMasterManager.tsx b/src/state/TabMasterManager.tsx index a3cbac0..6962e4b 100644 --- a/src/state/TabMasterManager.tsx +++ b/src/state/TabMasterManager.tsx @@ -513,8 +513,7 @@ export class TabMasterManager { asyncLoadOther() { PythonInterop.getTags().then((res: TagResponse[] | Error) => { if (res instanceof Error) { - LogController.log("TabMaster couldn't load tags settings"); - LogController.error(res.message); + LogController.raiseError(`Error loading tags \n ${res.message}`) } else { if (this.allStoreTags.length === 0) { this.allStoreTags = res; @@ -523,8 +522,7 @@ export class TabMasterManager { }); PythonInterop.getFriends().then((res: FriendEntry[] | Error) => { if (res instanceof Error) { - LogController.log("TabMaster couldn't load friends settings"); - LogController.error(res.message); + LogController.raiseError(`Error loading friends \n ${res.message}`) } else { if (this.currentUsersFriends.length === 0) { this.currentUsersFriends = res; @@ -533,8 +531,7 @@ export class TabMasterManager { }); PythonInterop.getFriendsGames().then((res: Map | Error) => { if (res instanceof Error) { - LogController.log("TabMaster couldn't load friends games settings"); - LogController.error(res.message); + LogController.raiseError(`Error loading friends games \n ${res.message}`) } else { if (this.friendsGameMap.size === 0) { this.friendsGameMap = res; @@ -552,20 +549,22 @@ export class TabMasterManager { const profiles = await PythonInterop.getTabProfiles(); this.asyncLoadOther(); - - if (settings instanceof Error) { - LogController.log("TabMaster couldn't load tab settings"); - LogController.error(settings.message); - return; - } - if (profiles instanceof Error) { - LogController.log("TabMaster couldn't load tab profiles"); - LogController.error(profiles.message); - return; + try { + if (settings instanceof Error) { + throw new Error(`Error loading tab settings \n ${settings.message}`) + } + if (profiles instanceof Error) { + throw new Error(`Error loading tab profiles \n ${profiles.message}`) + } + + this.tabProfileManager = new TabProfileManager(profiles); + TabErrorController.validateSettingsOnLoad((Object.keys(settings).length > 0) ? settings : defaultTabsSettings, this, this.finishLoadingTabs.bind(this)); + + } catch(e) { + if(e instanceof Error) { + LogController.raiseError(`Encountered an error while loading \n ${e.message}`) + } } - - this.tabProfileManager = new TabProfileManager(profiles); - TabErrorController.validateSettingsOnLoad((Object.keys(settings).length > 0) ? settings : defaultTabsSettings, this, this.finishLoadingTabs.bind(this)); }; /** From 7d837ca2f2092629b6bd6ea3efacfabdcd08fb22 Mon Sep 17 00:00:00 2001 From: Tormak <63308171+Tormak9970@users.noreply.github.com> Date: Thu, 27 Jun 2024 16:13:55 -0500 Subject: [PATCH 4/6] fix: settings page patches properly on beta --- src/patches/SettingsPatch.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/patches/SettingsPatch.tsx b/src/patches/SettingsPatch.tsx index 898ce5c..6e06f3a 100644 --- a/src/patches/SettingsPatch.tsx +++ b/src/patches/SettingsPatch.tsx @@ -20,7 +20,7 @@ export const patchSettings = (serverAPI: ServerAPI, tabMasterManager: TabMasterM } afterPatch(ret1, 'type', (_: any, ret2: any) => { - const homeElement = ret2?.props?.children?.props?.pages?.find((obj: any) => obj.route === '/settings/home')?.content?.props?.children?.[1]; + const homeElement = ret2?.props?.children?.props?.pages?.find((obj: any) => obj.route === '/settings/home')?.content; if (homeElement === undefined) { LogController.raiseError("Couldn't find home element to patch in settings"); return ret2; @@ -44,8 +44,6 @@ export const patchSettings = (serverAPI: ServerAPI, tabMasterManager: TabMasterM } afterPatch(buttonElementContainer, 'type', (_: any, ret4: any) => { - console.log('ret 4', ret4); - //* if ret exists but cannot find onClick then raise error because it is assumed valve has changed something if (ret4 && !ret4.props?.onClick) { LogController.raiseError("Couldn't patch button onClick fn in settings"); From 18fbf6bf0c71f1b12090748ae956f106043155cd Mon Sep 17 00:00:00 2001 From: Tormak <63308171+Tormak9970@users.noreply.github.com> Date: Thu, 27 Jun 2024 16:37:02 -0500 Subject: [PATCH 5/6] chore: initial implementation of family sharing filter done --- src/components/filters/FilterOptions.tsx | 19 +++++++++++++++++++ src/components/filters/FilterPreview.tsx | 6 ++++++ src/components/filters/Filters.tsx | 18 ++++++++++++++++-- src/patches/SettingsPatch.tsx | 2 -- src/types/stores/collectionStore.d.ts | 1 + 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/components/filters/FilterOptions.tsx b/src/components/filters/FilterOptions.tsx index f3426f2..370c9e0 100644 --- a/src/components/filters/FilterOptions.tsx +++ b/src/components/filters/FilterOptions.tsx @@ -727,6 +727,23 @@ const LastPlayedFilterOptions: VFC> = ({ index ); }; +/** + * The options for a family sharing filter. + */ +const FamilySharingFilterOptions: VFC> = ({ index, setContainingGroupFilters, filter, containingGroupFilters }) => { + function onChange(checked: boolean) { + const updatedFilter = { ...filter }; + updatedFilter.params.isFamilyShared = checked ?? false; + const updatedFilters = [...containingGroupFilters]; + updatedFilters[index] = updatedFilter; + setContainingGroupFilters(updatedFilters); + } + + return ( + + ); +}; + /** * The options for a demo filter. */ @@ -899,6 +916,8 @@ export const FilterOptions: VFC> = ({ index, filt return } containingGroupFilters={containingGroupFilters} setContainingGroupFilters={setContainingGroupFilters} />; case "last played": return } containingGroupFilters={containingGroupFilters} setContainingGroupFilters={setContainingGroupFilters} />; + case "family sharing": + return } containingGroupFilters={containingGroupFilters} setContainingGroupFilters={setContainingGroupFilters} />; case "demo": return } containingGroupFilters={containingGroupFilters} setContainingGroupFilters={setContainingGroupFilters} />; case "streamable": diff --git a/src/components/filters/FilterPreview.tsx b/src/components/filters/FilterPreview.tsx index 5b59832..b515497 100644 --- a/src/components/filters/FilterPreview.tsx +++ b/src/components/filters/FilterPreview.tsx @@ -110,6 +110,10 @@ const LastPlayedFilterPreview: VFC> = ({ filte return ; }; +const FamilySharingFilterPreview: VFC> = ({ filter }) => { + return ; +}; + const DemoFilterPreview: VFC> = ({ filter }) => { return ; }; @@ -169,6 +173,8 @@ export const FilterPreview: VFC> = ({ filter }) = return } />; case "last played": return } />; + case "family sharing": + return } />; case "demo": return } />; case "streamable": diff --git a/src/components/filters/Filters.tsx b/src/components/filters/Filters.tsx index 14d1543..0775014 100644 --- a/src/components/filters/Filters.tsx +++ b/src/components/filters/Filters.tsx @@ -6,11 +6,11 @@ import { STEAM_FEATURES_ID_MAP } from "./SteamFeatures"; import { FaCheckCircle, FaHdd, FaSdCard, FaTrophy, FaUserFriends } from "react-icons/fa"; import { IoGrid } from "react-icons/io5"; import { SiSteamdeck } from "react-icons/si"; -import { FaAward, FaBan, FaCalendarDays, FaCloudArrowDown, FaCompactDisc, FaListCheck, FaPlay, FaRegClock, FaSteam, FaTags } from "react-icons/fa6"; +import { FaAward, FaBan, FaCalendarDays, FaCloudArrowDown, FaCompactDisc, FaListCheck, FaPlay, FaRegClock, FaSteam, FaTags, FaUserPlus } from "react-icons/fa6"; import { BsClockHistory, BsRegex } from "react-icons/bs"; import { LuCombine } from "react-icons/lu"; -export type FilterType = 'collection' | 'installed' | 'regex' | 'friends' | 'tags' | 'whitelist' | 'blacklist' | 'merge' | 'platform' | 'deck compatibility' | 'review score' | 'time played' | 'size on disk' | 'release date' | 'last played' | 'demo' | 'streamable' | 'steam features' | 'achievements' | 'sd card'; +export type FilterType = 'collection' | 'installed' | 'regex' | 'friends' | 'tags' | 'whitelist' | 'blacklist' | 'merge' | 'platform' | 'deck compatibility' | 'review score' | 'time played' | 'size on disk' | 'release date' | 'last played' | 'family sharing' | 'demo' | 'streamable' | 'steam features' | 'achievements' | 'sd card'; export type TimeUnit = 'minutes' | 'hours' | 'days'; export type ThresholdCondition = 'above' | 'below'; @@ -41,6 +41,7 @@ type TimePlayedFilterParams = { timeThreshold: number, condition: ThresholdCondi type SizeOnDiskFilterParams = { gbThreshold: number, condition: ThresholdCondition }; type ReleaseDateFilterParams = { date?: DateObj, daysAgo?: number, condition: ThresholdCondition }; type LastPlayedFilterParams = { date?: DateObj, daysAgo?: number, condition: ThresholdCondition }; +type FamilySharingFilterParams = { isFamilyShared: boolean }; type DemoFilterParams = { isDemo: boolean }; type StreamableFilterParams = { isStreamable: boolean }; type SteamFeaturesFilterParams = { features: number[], mode: LogicalMode }; @@ -63,6 +64,7 @@ export type FilterParams = T extends 'size on disk' ? SizeOnDiskFilterParams : T extends 'release date' ? ReleaseDateFilterParams : T extends 'last played' ? LastPlayedFilterParams : + T extends 'family sharing' ? FamilySharingFilterParams : T extends 'demo' ? DemoFilterParams : T extends 'streamable' ? StreamableFilterParams : T extends 'steam features' ? SteamFeaturesFilterParams : @@ -99,6 +101,7 @@ export const FilterDefaultParams: { [key in FilterType]: FilterParams } = { "size on disk": { gbThreshold: 10, condition: 'above' }, "release date": { date: undefined, condition: 'above' }, "last played": { date: undefined, condition: 'above' }, + "family sharing": { isFamilyShared: true }, "demo": { isDemo: true }, "streamable": { isStreamable: true }, "steam features": { features: [], mode: 'and' }, @@ -125,6 +128,7 @@ export const FilterDescriptions: { [filterType in FilterType]: string } = { "size on disk": "Selects apps based on their install size.", "release date": "Selects apps based on their release date.", "last played": "Selects apps based on when they were last played.", + "family sharing": "Selects apps that are/aren't shared from family members.", demo: "Selects apps that are/aren't demos.", streamable: "Selects apps that can/can't be streamed from another computer.", achievements: "Selects apps based on their completion percentage.", @@ -151,6 +155,7 @@ export const FilterIcons: { [filterType in FilterType]: IconType } = { "size on disk": FaHdd, "release date": FaCalendarDays, "last played": BsClockHistory, + "family sharing": FaUserPlus, demo: FaCompactDisc, streamable: FaCloudArrowDown, "steam features": FaListCheck, @@ -186,6 +191,7 @@ export function canBeInverted(filter: TabFilterSettings): boolean { case "release date": case "last played": case "demo": + case "family sharing": case "streamable": return false; } @@ -225,6 +231,7 @@ export function isValidParams(filter: TabFilterSettings): boolean { case "review score": case "time played": case "demo": + case "family sharing": case "streamable": case "achievements": case "sd card": @@ -374,6 +381,7 @@ export function validateFilter(filter: TabFilterSettings): Validatio case "release date": case "last played": case "demo": + case "family sharing": case "streamable": case "steam features": case "achievements": @@ -512,6 +520,12 @@ export class Filter { lastPlayedTimeMs < new Date(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate() + 1 - params.daysAgo!).getTime(); } }, + 'family sharing': (params: FilterParams<'family sharing'>, appOverview: SteamAppOverview) => { + const isInSharedCollection = collectionStore.sharedLibrariesCollections.some((collection) => { + return collection.allApps.includes(appOverview); + }); + return params.isFamilyShared ? isInSharedCollection : !isInSharedCollection; + }, demo: (params: FilterParams<'demo'>, appOverview: SteamAppOverview) => { return params.isDemo ? appOverview.app_type === 8 : appOverview.app_type !== 8; }, diff --git a/src/patches/SettingsPatch.tsx b/src/patches/SettingsPatch.tsx index 6e06f3a..67bcad5 100644 --- a/src/patches/SettingsPatch.tsx +++ b/src/patches/SettingsPatch.tsx @@ -32,8 +32,6 @@ export const patchSettings = (serverAPI: ServerAPI, tabMasterManager: TabMasterM } afterPatch(homeElement, 'type', (_: any, ret3: any) => { - console.log('ret 3', ret3); - const buttonElementContainer = ret3?.props?.children?.find((elt: React.ReactElement) => { return elt?.type?.toString?.().includes('HomeSettings'); }); diff --git a/src/types/stores/collectionStore.d.ts b/src/types/stores/collectionStore.d.ts index ebae36f..caeecfa 100644 --- a/src/types/stores/collectionStore.d.ts +++ b/src/types/stores/collectionStore.d.ts @@ -7,6 +7,7 @@ type CollectionStore = { userCollections: SteamCollection[], allGamesCollection: Collection, deckDesktopApps: Collection | null, + sharedLibrariesCollections: Collection[], userCollections: Collection[], localGamesCollection: Collection, allAppsCollection: Collection, From 47940d42e19e06e68ce62a534b17ab77385f3537 Mon Sep 17 00:00:00 2001 From: Tormak <63308171+Tormak9970@users.noreply.github.com> Date: Sat, 29 Jun 2024 12:34:17 -0500 Subject: [PATCH 6/6] feat: added family sharing filter --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d085810..33b914a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tabmaster", - "version": "2.5.5", + "version": "2.5.6", "description": "Gives you full control over your Steam library! Support for customizing, adding, and hiding Library Tabs.", "scripts": { "build": "shx rm -rf dist && rollup -c",