Compare commits

...

48 Commits

Author SHA1 Message Date
semantic-release-bot
24606190e0 chore(release): 3.11.0 [CI SKIP] 2022-11-18 18:00:30 +00:00
Lukas Senionis
ed98d14b37 feat(classes): add "appDetailsClasses" (#55) 2022-11-18 12:59:57 -05:00
semantic-release-bot
b882612dfa chore(release): 3.10.0 [CI SKIP] 2022-11-18 17:37:50 +00:00
Lukas Senionis
32291620b4 feat(classes): add appDetailsHeaderClasses (#54) 2022-11-18 12:37:16 -05:00
semantic-release-bot
9b368c5f11 chore(release): 3.9.0 [CI SKIP] 2022-11-16 20:45:13 +00:00
Lukas Senionis
e167ef5a13 feat(Dialog): add "focusable" button prop (#51) 2022-11-16 15:44:36 -05:00
semantic-release-bot
2f3df00967 chore(release): 3.8.0 [CI SKIP] 2022-11-11 21:05:54 +00:00
AAGaming
215156d316 feat(routerhook): add global components support 2022-11-11 16:05:05 -05:00
semantic-release-bot
47d75db690 chore(release): 3.7.14 [CI SKIP] 2022-11-05 01:47:25 +00:00
AAGaming
82768e0415 fix(Menu): fix on Steam beta 2022-11-04 21:46:39 -04:00
AAGaming
e44187fe4b fix(Modal): fix on Steam beta 2022-11-04 21:46:22 -04:00
semantic-release-bot
72af32436e chore(release): 3.7.13 [CI SKIP] 2022-11-02 16:56:44 +00:00
Lukas Senionis
e1f64a38de fix(useQuickAccessVisible): make it work in beta (#49)
* fix(useQuickAccessVisible): make it work in beta

* fix(useQuickAccessVisible): rename for consistency

* fix(useQuickAccessVisible): update the exports

* fix(useQuickAccessVisible): shut up typescript
2022-11-02 12:56:11 -04:00
TrainDoctor
82ed48761d Merge pull request #38 from Tormak9970/main
Added some of the SteamClient types
2022-10-30 19:36:12 -07:00
TrainDoctor
a81c342d2a Update src/deck-components/index.ts 2022-10-30 17:35:48 -07:00
TrainDoctor
68d630262d Merge pull request #45 from FrogTheFrog/patch-19
Extend CI for PRs
2022-10-29 15:16:22 -07:00
semantic-release-bot
0bb8c67cfa chore(release): 3.7.12 [CI SKIP] 2022-10-29 19:44:41 +00:00
Jonas Dellinger
edd29e6c5a Merge pull request #46 from FrogTheFrog/patch-20
fix(Item): change title and description types to ReactNode
2022-10-29 21:44:13 +02:00
Lukas Senionis
0ed054fae9 fix(Item): change title and description types to ReactNode 2022-10-29 13:25:30 +03:00
semantic-release-bot
0d912eac88 chore(release): 3.7.11 [CI SKIP] 2022-10-28 23:04:53 +00:00
AAGaming
789e16380f fix(package.json): train wtf 2022-10-28 19:04:25 -04:00
semantic-release-bot
88b50bbc1e chore(release): 3.7.10 [CI SKIP] 2022-10-28 22:56:58 +00:00
AAGaming
75f35882f2 fix(tabs): shut up typescript 2022-10-28 18:56:30 -04:00
semantic-release-bot
23af4c0bb4 chore(release): 3.7.9 [CI SKIP] 2022-10-28 22:43:16 +00:00
AAGaming
a074277bb5 fix(tabs): fix on stable for real this time i think 2022-10-28 18:42:28 -04:00
Lukas Senionis
9c72a55aff Remove prepack hook 2022-10-28 22:00:33 +03:00
Lukas Senionis
92ffc76075 Extend CI for PRs 2022-10-27 11:48:44 +03:00
semantic-release-bot
fb49d64fd3 chore(release): 3.7.8 [CI SKIP] 2022-10-26 21:54:08 +00:00
Lukas Senionis
cfef1dc320 fix(Field): fix this time for real (#44) 2022-10-26 17:53:41 -04:00
semantic-release-bot
f6b4d6b254 chore(release): 3.7.7 [CI SKIP] 2022-10-26 21:49:50 +00:00
Lukas Senionis
0010a1fcee fix(Field): remove incompatible properties (#42)
* fix(Field): remove incompatible properties

* fix(Field): remove the override
2022-10-26 17:49:14 -04:00
semantic-release-bot
28cbc1cfe1 chore(release): 3.7.6 [CI SKIP] 2022-10-26 21:42:37 +00:00
Lukas Senionis
fe75dfb5f4 fix(Field): add override for onClick type (#43) 2022-10-26 17:42:04 -04:00
semantic-release-bot
91c386a6cc chore(release): 3.7.5 [CI SKIP] 2022-10-26 12:19:45 +00:00
Lukas Senionis
bedb6b8bb9 fix(Field): add types for focusing field (#41) 2022-10-26 08:19:16 -04:00
Tormak
ce3860f73b added jsdoc and SteamClient global declaration 2022-10-17 08:39:37 -04:00
Tormak
d8b10a2133 ran prettier 2022-10-15 22:46:41 -05:00
Tormak
1581304dcb restyled 2022-10-15 22:44:58 -05:00
Travis Lane
60ddf474e0 Merge branch 'SteamDeckHomebrew:main' into main 2022-10-15 13:46:50 -05:00
Tormak
52ae328e2e added some of the SteamClient types 2022-10-15 14:35:57 -05:00
Tormak
aa0fad2ecf fixed typo 2022-09-29 13:24:15 -05:00
Tormak
dab9071d1e found name of static classes 2022-09-29 13:01:06 -05:00
Tormak
189a90ba31 Updated ScrollPanelClasses
marked the old variable as depreciated and moved the implementation to the new variable
2022-09-25 09:06:14 -05:00
Tormak
8509ae8f9a Merge branch 'main' of https://github.com/Tormak9970/decky-frontend-lib 2022-09-24 12:05:06 -05:00
Tormak
a6ebfdcd7d fixed includes 2022-09-24 12:05:04 -05:00
Tormak
5f7655baaf fixed bugs with static-classes and future proofing 2022-09-24 11:51:19 -05:00
Travis Lane
bca2dcc9bd Merge branch 'SteamDeckHomebrew:main' into main 2022-09-24 10:54:09 -05:00
Tormak
546a4da043 updated DialogButton props and added nav pref enum 2022-09-22 17:33:08 -05:00
16 changed files with 666 additions and 61 deletions

View File

@@ -1,6 +1,7 @@
name: Release
on:
pull_request:
push:
branches:
- main
@@ -20,9 +21,12 @@ jobs:
node-version: 16
- name: Setup | Dependencies
run: npm i -g pnpm && pnpm i --frozen-lockfile
- name: Build
run: pnpm run build
- name: Test
run: pnpm run test
- name: Release
if: github.event_name != 'pull_request'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -1,3 +1,102 @@
# [3.11.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.10.0...v3.11.0) (2022-11-18)
### Features
* **classes:** add "appDetailsClasses" ([#55](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/55)) ([ed98d14](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/ed98d14b37cf09500afd88e7c8e9c03749119b38))
# [3.10.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.9.0...v3.10.0) (2022-11-18)
### Features
* **classes:** add appDetailsHeaderClasses ([#54](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/54)) ([3229162](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/32291620b403f8b65cf378343454a3f2668fb6ee))
# [3.9.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.8.0...v3.9.0) (2022-11-16)
### Features
* **Dialog:** add "focusable" button prop ([#51](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/51)) ([e167ef5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e167ef5a138a3edc004db2365334f8455c177132))
# [3.8.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.14...v3.8.0) (2022-11-11)
### Features
* **routerhook:** add global components support ([215156d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/215156d31688faac9028627379e5a3ac4d64ec46))
## [3.7.14](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.13...v3.7.14) (2022-11-05)
### Bug Fixes
* **Menu:** fix on Steam beta ([82768e0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/82768e0415d084deb2af39beb3f9273a83e819de))
* **Modal:** fix on Steam beta ([e44187f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e44187fe4b9d3e3c9e94490669591599dc5246ba))
## [3.7.13](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.12...v3.7.13) (2022-11-02)
### Bug Fixes
* **useQuickAccessVisible:** make it work in beta ([#49](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/49)) ([e1f64a3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e1f64a38de85073e5cea74ecea4b9cde9a783ecc))
## [3.7.12](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.11...v3.7.12) (2022-10-29)
### Bug Fixes
* **Item:** change title and description types to ReactNode ([0ed054f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0ed054fae972ffd36299b142bd693f80388480a6))
## [3.7.11](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.10...v3.7.11) (2022-10-28)
### Bug Fixes
* **package.json:** train wtf ([789e163](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/789e16380fd01a6b46188c7a1174a55c18c8dead))
## [3.7.10](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.9...v3.7.10) (2022-10-28)
### Bug Fixes
* **tabs:** shut up typescript ([75f3588](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/75f35882f27252e1255208953a6e801c68d5dcec))
## [3.7.9](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.8...v3.7.9) (2022-10-28)
### Bug Fixes
* **tabs:** fix on stable for real this time i think ([a074277](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/a074277bb58428a64295154ebf96aceb96e654a7))
## [3.7.8](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.7...v3.7.8) (2022-10-26)
### Bug Fixes
* **Field:** fix this time for real ([#44](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/44)) ([cfef1dc](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/cfef1dc320a5f649d66c3af365cd6aa2d88e46ea))
## [3.7.7](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.6...v3.7.7) (2022-10-26)
### Bug Fixes
* **Field:** remove incompatible properties ([#42](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/42)) ([0010a1f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0010a1fceedc417aa25b709d066341da97d42444))
## [3.7.6](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.5...v3.7.6) (2022-10-26)
### Bug Fixes
* **Field:** add override for onClick type ([#43](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/43)) ([fe75dfb](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/fe75dfb5f4fb1ec9417cc07dc714c71820945748))
## [3.7.5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.4...v3.7.5) (2022-10-26)
### Bug Fixes
* **Field:** add types for focusing field ([#41](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/41)) ([bedb6b8](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/bedb6b8bb90e021a60e47a93709d6f48e0bd75c6))
## [3.7.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.3...v3.7.4) (2022-10-26)

View File

@@ -1,6 +1,6 @@
{
"name": "decky-frontend-lib",
"version": "3.7.4",
"version": "3.11.0",
"description": "A library for building decky plugins",
"main": "dist/index.js",
"types": "dist/index.d.ts",
@@ -10,7 +10,6 @@
"build": "shx rm -rf dist && tsc -b",
"dev": "tsc -b -w",
"docs": "typedoc --tsconfig ./tsconfig.json src/**/*",
"prepack": "npm run build",
"test": "echo 'No tests for now!'",
"prepare": "husky install",
"commit": "git-cz"
@@ -54,6 +53,7 @@
"husky": "^8.0.1",
"import-sort-style-module": "^6.0.0",
"jest": "^27.5.1",
"minimist": "^1.2.6",
"prettier": "^2.7.1",
"prettier-plugin-import-sort": "^0.0.7",
"semantic-release": "^19.0.3",
@@ -78,8 +78,5 @@
"style": "module",
"parser": "typescript"
}
},
"dependencies": {
"minimist": "^1.2.6"
}
}

5
pnpm-lock.yaml generated
View File

@@ -25,9 +25,6 @@ specifiers:
typedoc-plugin-missing-exports: ^1.0.0
typescript: ^4.6.3
dependencies:
minimist: 1.2.6
devDependencies:
'@commitlint/cli': 17.0.2
'@commitlint/config-conventional': 17.0.2
@@ -41,6 +38,7 @@ devDependencies:
husky: 8.0.1
import-sort-style-module: 6.0.0
jest: 27.5.1
minimist: 1.2.6
prettier: 2.7.1
prettier-plugin-import-sort: 0.0.7_prettier@2.7.1
semantic-release: 19.0.3
@@ -3735,6 +3733,7 @@ packages:
/minimist/1.2.6:
resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==}
dev: true
/modify-values/1.0.1:
resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==}

View File

@@ -1 +1 @@
export * from './usequickaccessvisible';
export * from './useQuickAccessVisible';

View File

@@ -4,6 +4,16 @@ declare global {
var FocusNavController: any;
}
function getQuickAccessWindow(): Window | null {
try {
const navTrees = FocusNavController?.m_ActiveContext?.m_rgGamepadNavigationTrees || FocusNavController?.m_rgGamepadNavigationTrees;
return navTrees?.find((tree: any) => tree?.id === "QuickAccess-NA")?.m_Root?.m_element?.ownerDocument.defaultView ?? null;
} catch (error) {
console.error(error);
return null;
}
}
/**
* Returns state indicating the visibility of quick access menu.
*
@@ -42,12 +52,10 @@ declare global {
* };
*/
export function useQuickAccessVisible(): boolean {
// Assuming that the component is rendered in QAM already, so true by default...
const [isVisible, setIsVisible] = useState(true);
const [isVisible, setIsVisible] = useState(getQuickAccessWindow()?.document.hasFocus() ?? true);
useEffect(() => {
const quickAccessWindow: Window | null =
FocusNavController?.GetGamepadNavTreeByID('QuickAccess-NA')?.m_Root?.m_element?.ownerDocument.defaultView ?? null;
const quickAccessWindow = getQuickAccessWindow();
if (quickAccessWindow === null) {
console.error('Could not get window of QuickAccess menu!');
return;

View File

@@ -9,8 +9,35 @@ export interface DialogCommonProps extends RefAttributes<HTMLDivElement> {
}
export interface DialogButtonProps extends DialogCommonProps, FooterLegendProps {
/**
* Enables/disables the focus around the button.
*
* @note
* Default value depends on context, so setting it to `false` will enable it.
*/
noFocusRing?: boolean;
/**
* Disables the button - assigned `on*` methods will not be invoked if clicked.
*
* @note
* Depending on where it is, it might still get focus. In such case it can be
* partially disabled separately.
*
* @see focusable.
*/
disabled?: boolean;
/**
* Enables/disables the navigation based focus on button - you won't be able to navigate to
* it via the gamepad or keyboard.
*
* @note
* If set to `false`, it still can be clicked and **WILL** become focused until navigated away.
* Depending on the context of where the button is, even a disabled button can focused.
*/
focusable?: boolean;
onClick?(e: MouseEvent): void;
onPointerDown?(e: PointerEvent): void;
onPointerUp?(e: PointerEvent): void;

View File

@@ -1,9 +1,9 @@
import { FC, HTMLAttributes, ReactNode, RefAttributes } from 'react';
import { FC, ReactNode, RefAttributes } from 'react';
import { findModuleChild } from '../webpack';
import { FooterLegendProps } from './FooterLegend';
export interface FieldProps extends HTMLAttributes<HTMLDivElement>, FooterLegendProps {
export interface FieldProps extends FooterLegendProps {
label?: ReactNode;
bottomSeparator?: 'standard' | 'thick' | 'none';
description?: ReactNode;
@@ -18,6 +18,9 @@ export interface FieldProps extends HTMLAttributes<HTMLDivElement>, FooterLegend
highlightOnFocus?: boolean;
indentLevel?: number;
verticalAlignment?: 'center' | 'none'; // Alligns inline label with children
focusable?: boolean; // Allows to get focus without any focusable children or on* callbacks
onActivate?: (e: CustomEvent | MouseEvent) => void;
onClick?: (e: CustomEvent | MouseEvent) => void;
}
export const Field = findModuleChild((m) => {

View File

@@ -1,8 +1,8 @@
import { ReactNode } from 'react';
export interface ItemProps {
label?: string;
description?: string;
label?: ReactNode;
description?: ReactNode;
layout?: 'below' | 'inline';
icon?: ReactNode;
bottomSeparator?: 'standard' | 'thick' | 'none';

View File

@@ -1,5 +1,6 @@
import { FC, ReactNode } from 'react';
import { fakeRenderComponent } from '../utils';
import { findModuleChild } from '../webpack';
export const showContextMenu: (children: ReactNode, parent?: EventTarget) => void = findModuleChild((m) => {
@@ -38,7 +39,11 @@ export const MenuGroup: FC<MenuGroupProps> = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (m[prop]?.prototype?.RenderSubMenu && m[prop]?.prototype?.ShowSubMenu) {
if (
(m[prop]?.toString()?.includes('bInGamepadUI:') &&
fakeRenderComponent(() => m[prop]())?.type?.prototype?.RenderSubMenu) ||
(m[prop]?.prototype?.RenderSubMenu && m[prop]?.prototype?.ShowSubMenu)
) {
return m[prop];
}
}
@@ -54,7 +59,10 @@ export const MenuItem: FC<MenuItemProps> = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (m[prop]?.prototype?.OnOKButton && m[prop]?.prototype?.OnMouseEnter) {
if (
m[prop]?.render?.toString()?.includes('bPlayAudio:') ||
(m[prop]?.prototype?.OnOKButton && m[prop]?.prototype?.OnMouseEnter)
) {
return m[prop];
}
}

View File

@@ -1,7 +1,7 @@
import { FC, ReactNode } from 'react';
import { findSP } from '../utils';
import { findModuleChild } from '../webpack';
import { findModule, findModuleChild } from '../webpack';
// All of the popout options + strTitle are related. Proper usage is not yet known...
export interface ShowModalProps {
@@ -29,18 +29,57 @@ export interface ShowModalResult {
Update: (modal: ReactNode) => void;
}
const showModalRaw: (modal: ReactNode, parent?: EventTarget, props?: ShowModalProps) => Promise<ShowModalResult> =
findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (typeof m[prop] === 'function' && m[prop].toString().includes('bHideMainWindowForPopouts:!0')) {
return m[prop];
}
const showModalRaw:
| ((
modal: ReactNode,
parent?: EventTarget,
title?: string,
props?: ShowModalProps,
unknown1?: unknown,
hideActions?: { bHideActions?: boolean },
modalManager?: unknown,
) => Promise<ShowModalResult>)
| void = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (
typeof m[prop] === 'function' &&
m[prop].toString().includes('props.bDisableBackgroundDismiss') &&
!m[prop]?.prototype?.Cancel
) {
return m[prop];
}
});
}
});
export const showModal = (modal: ReactNode, parent?: EventTarget, props?: ShowModalProps): Promise<ShowModalResult> => {
return showModalRaw(modal, parent || findSP(), props);
const oldShowModalRaw:
| ((modal: ReactNode, parent?: EventTarget, props?: ShowModalProps) => Promise<ShowModalResult>)
| void = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (typeof m[prop] === 'function' && m[prop].toString().includes('bHideMainWindowForPopouts:!0')) {
return m[prop];
}
}
});
export const showModal = (
modal: ReactNode,
parent?: EventTarget,
props: ShowModalProps = {
strTitle: 'Decky Dialog',
bHideMainWindowForPopouts: false,
},
): Promise<ShowModalResult> => {
if (showModalRaw) {
return showModalRaw(modal, parent || findSP(), props.strTitle, props, undefined, {
bHideActions: props.bHideActionIcons,
});
} else if (oldShowModalRaw) {
return oldShowModalRaw(modal, parent || findSP(), props);
} else {
throw new Error('[DFL:Modals]: Cannot find showModal function');
}
};
export interface ModalRootProps {
@@ -79,11 +118,26 @@ export const ConfirmModal = findModuleChild((m) => {
}
}) as FC<ConfirmModalProps>;
export const ModalRoot = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (m[prop]?.prototype?.OK && m[prop]?.prototype?.Cancel && m[prop]?.prototype?.render) {
return m[prop];
// new
export const ModalRoot = (Object.values(
findModule((m: any) => {
if (typeof m !== 'object') return false;
for (let prop in m) {
if (m[prop]?.toString()?.includes('"ModalManager","DialogWrapper"')) {
return true;
}
}
}
}) as FC<ModalRootProps>;
return false;
}) || {},
)?.find((x: any) => x?.type?.toString()?.includes('((function(){')) ||
// old
findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (m[prop]?.prototype?.OK && m[prop]?.prototype?.Cancel && m[prop]?.prototype?.render) {
return m[prop];
}
}
})) as FC<ModalRootProps>;

View File

@@ -0,0 +1,300 @@
export interface Apps {
RegisterForAppOverviewChanges: any;
RegisterForAppDetails: any;
RegisterForLocalizationChanges: any;
RegisterForWorkshopChanges: any;
RegisterForWorkshopItemDownloads: any;
GetLibraryBootstrapData: any;
RegisterForAchievementChanges: any;
GetFriendAchievementsForApp: any;
GetMyAchievementsForApp: any;
AddUserTagToApps: any;
RemoveUserTagFromApps: any;
ClearUserTagsOnApps: any;
ClearAndSetUserTagsOnApp: any;
SetAppHidden: any;
ResetHiddenState: any;
SetAppLaunchOptions: any;
SetAppResolutionOverride: any;
SetAppCurrentLanguage: any;
SetAppAutoUpdateBehavior: any;
SetAppBackgroundDownloadsBehavior: any;
ToggleAppFamilyBlockedState: any;
ToggleAppSteamCloudEnabled: any;
ToggleAppSteamCloudSyncOnSuspendEnabled: any;
ToggleOverrideResolutionForInternalDisplay: any;
ToggleEnableSteamOverlayForApp: any;
ToggleEnableDesktopTheatreForApp: any;
BrowseLocalFilesForApp: any;
BrowseScreenshotsForApp: any;
BrowseScreenshotForApp: any;
BackupFilesForApp: any;
VerifyFilesForApp: any;
CreateDesktopShortcutForApp: any;
JoinAppContentBeta: any;
JoinAppContentBetaByPassword: any;
GetAchievementsInTimeRange: any;
GetSubscribedWorkshopItems: any;
SubscribeWorkshopItem: any;
GetDownloadedWorkshopItems: any;
DownloadWorkshopItem: any;
SetLocalScreenshotCaption: any;
SetLocalScreenshotSpoiler: any;
GetDetailsForScreenshotUpload: any;
UploadLocalScreenshot: any;
DeleteLocalScreenshot: any;
GetScreenshotsInTimeRange: any;
GetFriendsWhoPlay: any;
RequestLegacyCDKeysForApp: any;
GetSoundtrackDetails: any;
GetStoreTagLocalization: any;
GetLaunchOptionsForApp: any;
GetResolutionOverrideForApp: any;
ScanForShortcuts: any;
GetAllShortcuts: any;
GetShortcutData: any;
AddShortcut: any;
RemoveShortcut: any;
InstallFlatpakAppAndCreateShortcut: any;
ListFlatpakApps: any;
UninstallFlatpakApp: any;
ShowControllerConfigurator: any;
SetThirdPartyControllerConfiguration: any;
ToggleAllowDesktopConfiguration: any;
SetControllerRumblePreference: any;
GetCachedAppDetails: any;
SetCachedAppDetails: any;
ReportLibraryAssetCacheMiss: any;
SaveAchievementProgressCache: any;
SetStreamingClientForApp: any;
SetCustomArtworkForApp: any;
ClearCustomArtworkForApp: any;
SetCustomLogoPositionForApp: any;
ClearCustomLogoPositionForApp: any;
RequestIconDataForApp: any;
SpecifyCompatTool: any;
GetAvailableCompatTools: any;
SetShortcutName: any;
SetShortcutExe: any;
SetShortcutStartDir: any;
SetShortcutLaunchOptions: any;
SetShortcutIsVR: any;
PromptToChangeShortcut: any;
PromptToSelectShortcutIcon: any;
InstallApp: any;
RunGame: any;
VerifyApp: any;
StreamGame: any;
CancelLaunch: any;
TerminateApp: any;
UninstallApps: any;
ShowStore: any;
SetDLCEnabled: any;
ContinueGameAction: any;
CancelGameAction: any;
GetActiveGameActions: any;
GetGameActionDetails: any;
GetGameActionForApp: any;
SkipShaderProcessing: any;
MarkEulaAccepted: any;
MarkEulaRejected: any;
LoadEula: any;
GetConflictingFileTimestamps: any;
GetCloudPendingRemoteOperations: any;
ClearProton: any;
RegisterForMarketingMessages: any;
FetchMarketingMessages: any;
MarkMarketingMessageSeen: any;
ReportMarketingMessageSeen: any;
RegisterForGameActionStart: any;
RegisterForGameActionEnd: any;
RegisterForGameActionTaskChange: any;
RegisterForGameActionUserRequest: any;
RegisterForGameActionShowError: any;
RegisterForGameActionShowUI: any;
OpenAppSettingsDialog: any;
}
export interface Window {
RegisterForExternalDisplayChanged: any;
SetManualDisplayScaleFactor: any;
SetAutoDisplayScale: any;
Minimize: any;
ProcessShuttingDown: any;
ToggleMaximize: any;
MoveTo: any;
ResizeTo: any;
SetMinSize: any;
SetResizeGrip: any;
SetComposition: any;
GamescopeBlur: any;
BringToFront: any;
SetForegroundWindow: any;
SetKeyFocus: any;
FlashWindow: any;
StopFlashWindow: any;
ShowWindow: any;
HideWindow: any;
SetWindowIcon: any;
GetWindowDimensions: any;
GetWindowRestoreDetails: any;
PositionWindowRelative: any;
GetMousePositionDetails: any;
IsWindowMinimized: any;
GetBrowserID: any;
}
export interface SteamClient {
Apps: Apps;
Browser: any;
BrowserView: any;
ClientNotifications: any;
Cloud: any;
Console: any;
Downloads: any;
FamilySharing: any;
FriendSettings: any;
Friends: any;
GameSessions: any;
Input: any;
InstallFolder: any;
Installs: any;
MachineStorage: any;
Messaging: any;
Notifications: any;
OpenVR: any;
Overlay: any;
Parental: any;
RegisterIFrameNavigatedCallback: any;
RemotePlay: any;
RoamingStorage: any;
Screenshots: any;
Settings: any;
SharedConnection: any;
Stats: any;
Storage: any;
Streaming: any;
System: any;
UI: any;
URL: any;
Updates: any;
User: any;
WebChat: any;
Window: Window;
}
export interface SteamShortcut {
appid: number;
data: {
bIsApplication: boolean;
strAppName: string;
strExePath: string;
strArguments: string;
strShortcutPath: string;
strSortAs: string;
};
}
/**
* @prop unAppID is not properly set by Steam for non-steam game shortcuts, so it defaults to 0 for them
*/
export interface LifetimeNotification {
unAppID: number;
nInstanceID: number;
bRunning: boolean;
}
export type AppAchievements = {
nAchieved: number;
nTotal: number;
vecAchievedHidden: any[];
vecHighlight: any[];
vecUnachieved: any[];
};
export type AppLanguages = {
strDisplayName: string;
strShortName: string;
};
export interface AppDetails {
achievements: AppAchievements;
bCanMoveInstallFolder: boolean;
bCloudAvailable: boolean;
bCloudEnabledForAccount: boolean;
bCloudEnabledForApp: boolean;
bCloudSyncOnSuspendAvailable: boolean;
bCloudSyncOnSuspendEnabled: boolean;
bCommunityMarketPresence: boolean;
bEnableAllowDesktopConfiguration: boolean;
bFreeRemovableLicense: boolean;
bHasAllLegacyCDKeys: boolean;
bHasAnyLocalContent: boolean;
bHasLockedPrivateBetas: boolean;
bIsExcludedFromSharing: boolean;
bIsSubscribedTo: boolean;
bOverlayEnabled: boolean;
bOverrideInternalResolution: boolean;
bRequiresLegacyCDKey: boolean;
bShortcutIsVR: boolean;
bShowCDKeyInMenus: boolean;
bShowControllerConfig: boolean;
bSupportsCDKeyCopyToClipboard: boolean;
bVRGameTheatreEnabled: boolean;
bWorkshopVisible: boolean;
eAppOwnershipFlags: number;
eAutoUpdateValue: number;
eBackgroundDownloads: number;
eCloudSync: number;
eControllerRumblePreference: number;
eDisplayStatus: number;
eEnableThirdPartyControllerConfiguration: number;
eSteamInputControllerMask: number;
iInstallFolder: number;
lDiskUsageBytes: number;
lDlcUsageBytes: number;
nBuildID: number;
nCompatToolPriority: number;
nPlaytimeForever: number;
nScreenshots: number;
rtLastTimePlayed: number;
rtLastUpdated: number;
rtPurchased: number;
selectedLanguage: {
strDisplayName: string;
strShortName: string;
};
strCloudBytesAvailable: string;
strCloudBytesUsed: string;
strCompatToolDisplayName: string;
strCompatToolName: string;
strDeveloperName: string;
strDeveloperURL: string;
strDisplayName: string;
strExternalSubscriptionURL: string;
strFlatpakAppID: string;
strHomepageURL: string;
strLaunchOptions: string;
strManualURL: string;
strOwnerSteamID: string;
strResolutionOverride: string;
strSelectedBeta: string;
strShortcutExe: string;
strShortcutLaunchOptions: string;
strShortcutStartDir: string;
strSteamDeckBlogURL: string;
unAppID: number;
vecBetas: any[];
vecDLC: any[];
vecDeckCompatTestResults: any[];
vecLanguages: AppLanguages[];
vecLegacyCDKeys: any[];
vecMusicAlbums: any[];
vecPlatforms: string[];
vecScreenShots: any[];
}
export interface SteamAppOverview {
display_name: string;
gameid: string;
}

View File

@@ -65,16 +65,11 @@ export interface TabsProps {
autoFocusContents?: boolean;
}
declare global {
interface Window {
DeckyPluginLoader: any;
}
}
let tabsComponent: any;
const getTabs = async () => {
if (tabsComponent) return tabsComponent;
// @ts-ignore
while (!window?.DeckyPluginLoader?.routerHook?.routes) {
console.debug('[DFL:Tabs]: Waiting for Decky router...');
await sleep(500);
@@ -83,6 +78,7 @@ const getTabs = async () => {
() => {
return findInReactTree(
findInReactTree(
// @ts-ignore
window.DeckyPluginLoader.routerHook.routes
.find((x: any) => x.props.path == '/library/app/:appid/achievements')
.props.children.type(),
@@ -109,27 +105,30 @@ try {
}
return false;
});
if (oldTabsModule) oldTabs = Object.values(oldTabsModule).find((x: any) => x?.type?.toString()?.includes("((function(") && x?.type?.toString()?.includes("[\"tabs\""));
if (oldTabsModule)
oldTabs = Object.values(oldTabsModule).find((x: any) => x?.type?.toString()?.includes('((function(){'));
} catch (e) {
console.error("Error finding oldTabs:", e)
console.error('Error finding oldTabs:', e);
}
/**
* Tabs component as used in the library and media tabs. See {@link TabsProps}
* Unlike other components in `decky-frontend-lib`, this requires Decky Loader to be running.
*/
export const Tabs = oldTabs || ((props: TabsProps) => {
const found = tabsComponent;
const [tc, setTC] = useState<FC<TabsProps>>(found);
useEffect(() => {
if (found) return;
(async () => {
console.debug('[DFL:Tabs]: Finding component...');
const t = await getTabs();
console.debug('[DFL:Tabs]: Found!');
setTC(t);
})();
}, []);
console.log('tc', tc);
return tc ? createElement(tc, props) : <SteamSpinner />;
}) as FC<TabsProps>;
export const Tabs =
oldTabs ||
(((props: TabsProps) => {
const found = tabsComponent;
const [tc, setTC] = useState<FC<TabsProps>>(found);
useEffect(() => {
if (found) return;
(async () => {
console.debug('[DFL:Tabs]: Finding component...');
const t = await getTabs();
console.debug('[DFL:Tabs]: Found!');
setTC(t);
})();
}, []);
console.log('tc', tc);
return tc ? createElement(tc, props) : <SteamSpinner />;
}) as FC<TabsProps>);

View File

@@ -21,3 +21,10 @@ export * from './Tabs';
export * from './TextField';
export * from './Toggle';
export * from './ToggleField';
export * from './SteamClient';
import {SteamClient} from './SteamClient'
declare global {
var SteamClient: SteamClient;
}

View File

@@ -349,6 +349,98 @@ type GamepadSliderClasses = Record<
string
>;
type AppDetailsHeaderClasses = Record<
| 'AddBoxSizer'
| 'Background'
| 'Bottom'
| 'BottomCenter'
| 'BottomLeft'
| 'BottomRight'
| 'BoxSizer'
| 'BoxSizerButtonContainer'
| 'BoxSizerContainer'
| 'BoxSizerDelete'
| 'BoxSizerDragBox'
| 'BoxSizerEdge'
| 'BoxSizerGridBox'
| 'BoxSizerInfo'
| 'BoxSizerSettings'
| 'BoxSizerValidRegion'
| 'CenterCenter'
| 'DialogButton'
| 'EdgeDown'
| 'FallbackArt'
| 'Features'
| 'FullscreenEnterActive'
| 'FullscreenEnterDone'
| 'FullscreenEnterStart'
| 'FullscreenExitActive'
| 'FullscreenExitDone'
| 'FullscreenExitStart'
| 'HeaderBackgroundImage'
| 'ImgBlur'
| 'ImgBlurBackdrop'
| 'ImgContainer'
| 'ImgSrc'
| 'Left'
| 'Loaded'
| 'Middle'
| 'NoArt'
| 'PinBox'
| 'Right'
| 'SVGTitle'
| 'SaveBoxSizer'
| 'TextNameSpace'
| 'TitleImageContainer'
| 'TitleLogo'
| 'TitleSection'
| 'Top'
| 'TopCapsule'
| 'TopGradient'
| 'TopLeft'
| 'TopRight'
| 'UpperCenter'
| 'UpperLeft'
| 'duration-app-launch',
string
>;
type AppDetailsClasses = Record<
| 'BreakNarrow'
| 'BreakShort'
| 'BreakTall'
| 'BreakUltraWide'
| 'BreakWide'
| 'Container'
| 'GamepadUIBreakNarrow'
| 'GamepadUIBreakShort'
| 'GamepadUIBreakWide'
| 'Glassy'
| 'Header'
| 'HeaderLoaded'
| 'InnerContainer'
| 'ItemFocusAnim-darkGrey'
| 'ItemFocusAnim-darkerGrey'
| 'ItemFocusAnim-darkerGrey-nocolor'
| 'ItemFocusAnim-green'
| 'ItemFocusAnim-grey'
| 'ItemFocusAnimBorder-darkGrey'
| 'PlayBar'
| 'PreventScrolling'
| 'RightBreakNarrow'
| 'RightBreakUltraNarrow'
| 'RightBreakUltraWide'
| 'RightBreakWide'
| 'ScrollContainer'
| 'ShowPlayBar'
| 'Throbber'
| 'duration-app-launch'
| 'fadein'
| 'focusAnimation'
| 'hoverAnimation',
string
>;
export const quickAccessMenuClasses: QuickAccessMenuClasses = findModule(
(mod) => typeof mod === 'object' && mod?.Title?.includes('quickaccessmenu'),
);
@@ -378,3 +470,9 @@ export const playSectionClasses: PlaySectionClasses = findModule(
export const gamepadSliderClasses: GamepadSliderClasses = findModule(
(mod) => typeof mod === 'object' && mod?.SliderControlPanelGroup?.includes('gamepadslider'),
);
export const appDetailsHeaderClasses: AppDetailsHeaderClasses = findModule(
(mod) => typeof mod === 'object' && mod?.TopCapsule?.includes('sharedappdetailsheader'),
);
export const appDetailsClasses: AppDetailsClasses = findModule(
(mod) => typeof mod === 'object' && mod?.HeaderLoaded?.includes('appdetails_'),
);

View File

@@ -26,8 +26,10 @@ export type RoutePatch = (route: RouteProps) => RouteProps;
export interface RouterHook {
addRoute(path: string, component: ComponentType, props?: Omit<RouteProps, 'path' | 'children'>): void;
addPatch(path: string, patch: RoutePatch): RoutePatch;
removePatch(path: string, patch: RoutePatch): void;
addGlobalComponent(name: string, component: ComponentType): void;
removeRoute(path: string): void;
removePatch(path: string, patch: RoutePatch): void;
removeGlobalComponent(name: string): void;
}
export interface ToastData {