mirror of
https://github.com/SteamDeckHomebrew/decky-frontend-lib.git
synced 2026-05-22 19:08:46 +02:00
Compare commits
1 Commits
v3.21.5
...
aa/menu-ho
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6e399fa46 |
189
CHANGELOG.md
189
CHANGELOG.md
@@ -1,192 +1,3 @@
|
|||||||
## [3.21.5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.21.4...v3.21.5) (2023-06-22)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* missing parameter ([8b54ee9](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/8b54ee990ee4d9b51174737979c35ab7ad92ed7a))
|
|
||||||
|
|
||||||
## [3.21.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.21.3...v3.21.4) (2023-06-22)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* move the new file picker api as v2 ([8bfeae4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/8bfeae4b3593b2efa0aa075a0d9e0b5926cdf169))
|
|
||||||
|
|
||||||
## [3.21.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.21.2...v3.21.3) (2023-06-22)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* total is not needed as a return value to plugins ([979a630](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/979a630f2b02ac4a1ac19e38002244f9dfe97177))
|
|
||||||
|
|
||||||
## [3.21.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.21.1...v3.21.2) (2023-06-18)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **SidebarNavigation:** allow ReactNode for page title ([44d9b90](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/44d9b90cdcfb9e6441fdb1e4b21fe844f1f29fd5))
|
|
||||||
|
|
||||||
## [3.21.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.21.0...v3.21.1) (2023-05-28)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **reorderable-list:** open label type from string to ReactNode ([fb5f043](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/fb5f043ba9eeed0209960c8ae4ae597c2831b8c8))
|
|
||||||
|
|
||||||
# [3.21.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.20.7...v3.21.0) (2023-05-19)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **Utils:** return null when SP not found ([18d341f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/18d341f82acf843ff830d1bf3d44678f3f2eda52))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **StaticClasses:** add new GamepadUI classes ([3ca8c43](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/3ca8c43a542b1049c4e203ad186e555401fbfbfe))
|
|
||||||
|
|
||||||
## [3.20.7](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.20.6...v3.20.7) (2023-05-10)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **decky:** fix decky on latest beta ([74a7cba](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/74a7cbaf94538c68a01f5fa707935c4d21570c5f))
|
|
||||||
|
|
||||||
## [3.20.6](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.20.5...v3.20.6) (2023-04-29)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **QuickAccessTab:** set decky tab ID to 999 ([5d5cb31](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/5d5cb31638070deae9970a93c587b447d5e56559))
|
|
||||||
|
|
||||||
## [3.20.5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.20.4...v3.20.5) (2023-04-04)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* reorderable list no longer toggles on backout ([7e1182a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/7e1182a83f7fafbec6fe115a72f8b64b71c119a4))
|
|
||||||
|
|
||||||
## [3.20.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.20.3...v3.20.4) (2023-04-04)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **SteamSpinner:** oh apparently the class was moved outside the component for some reason?????? ([b8ddf3d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/b8ddf3d927401d04c0fde8ebc8960639369b8ad3))
|
|
||||||
|
|
||||||
## [3.20.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.20.2...v3.20.3) (2023-04-04)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **SteamSpinner:** fix the fix ([79d229b](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/79d229be50d26e2510af0ea16cdf6644371a5967))
|
|
||||||
|
|
||||||
## [3.20.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.20.1...v3.20.2) (2023-04-04)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **SteamSpinner:** dont error on latest desktop beta ([19819b7](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/19819b7a5bc9434fa802f4e8dca4f4cb6921df07))
|
|
||||||
|
|
||||||
## [3.20.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.20.0...v3.20.1) (2023-04-03)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **useQuickAccessVisible:** make it work again ([7dacb23](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/7dacb23e8be7b1f076cdd0869a4e3a3902b07ec5))
|
|
||||||
|
|
||||||
# [3.20.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.19.2...v3.20.0) (2023-04-03)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **Field:** remove style ([53faf55](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/53faf55df1484204e276cd21a32703c2d7809332))
|
|
||||||
* fixed missing export ([b480d39](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/b480d397c4251f42c1f24ff5e74322d22e313f05))
|
|
||||||
* list didn't update on prop change ([b146eab](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/b146eab8d7e1338afa54a168a2fd895e716c2bb2))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* added doc comments ([dfcb3be](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/dfcb3bec19900e099ae3766771e120dbd4f229f5))
|
|
||||||
* added reorderable list and updated fieldProps ([3c171cf](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/3c171cfb8ff18ed02eeb569a183c9d43fd0b4f57))
|
|
||||||
* changed ReorderableList to working version ([5b166d6](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/5b166d6db879200b049e872cba327957ba5fb705))
|
|
||||||
* made requested changes and ran prettier ([b1b2f4f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/b1b2f4fa2da755efd65b82b15b52196f89fb09c0))
|
|
||||||
* refactoring mostly complete ([cea315a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/cea315a52c285b31ad4e5d0a03104c674ae4f7f5))
|
|
||||||
* reorderable list now saves on backout ([b1591f8](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/b1591f86bbd36e160818626760e0717ee50878e0))
|
|
||||||
* **ReorderableList:** add animations, clean up ([26fae13](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/26fae13c8ebd3f11f134c3bc0edfc971afd42fff))
|
|
||||||
* support for non-interactable reordering ([dbd01b1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/dbd01b11cafe9b102cc371b9812f99aec718d106))
|
|
||||||
* support for user specified icon ([47a6fdd](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/47a6fddc89b8f9110252c5e19a6e95152c367dbf))
|
|
||||||
|
|
||||||
## [3.19.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.19.1...v3.19.2) (2023-03-07)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **Item:** add highlightOnFocus prop ([c53f87b](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/c53f87b4a9273b377853bfff1d27474ebd6e564a))
|
|
||||||
|
|
||||||
## [3.19.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.19.0...v3.19.1) (2023-02-23)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* refactoring to fix for feb 22 2023 beta ([0b6dc24](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0b6dc24c0da2d7644e185425e975787657f8bba1))
|
|
||||||
|
|
||||||
# [3.19.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.11...v3.19.0) (2023-02-22)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* added reorderable list and updated fieldProps ([#57](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/57)) ([5a074b5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/5a074b5bb68c675c484a7b693f67a67488be9bcf))
|
|
||||||
|
|
||||||
## [3.18.11](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.10...v3.18.11) (2023-02-18)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **Navigation:** fix NavigateToExternalWeb ([82214fe](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/82214fef4c0a383776631fbb754550fe69f9000d))
|
|
||||||
* **Navigation:** fix NavigateToExternalWeb ([c53d7f8](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/c53d7f8448d8aad76dc699f1f309bdd547ee14df))
|
|
||||||
|
|
||||||
## [3.18.10](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.9...v3.18.10) (2023-01-17)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **SuspensefulImage:** fix changing src ([9723854](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/9723854ddca53d7708e1effbddec9e5ead22d5de))
|
|
||||||
|
|
||||||
## [3.18.9](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.8...v3.18.9) (2023-01-16)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **Navigation:** fix on stable ([4affd4a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/4affd4aaec088f01d0f30af48cb4daa34acf26b1))
|
|
||||||
|
|
||||||
## [3.18.8](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.7...v3.18.8) (2023-01-16)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **Navigation:** fix timing issue in decky-loader ([58b69f0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/58b69f0d6c43356c4f0ed183802d5bf7fb80e978))
|
|
||||||
|
|
||||||
## [3.18.7](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.6...v3.18.7) (2023-01-16)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* un-break navigation on stable ([2e66e5a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/2e66e5a555f44009d24e332eca82453ba930baf7))
|
|
||||||
|
|
||||||
## [3.18.6](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.5...v3.18.6) (2023-01-13)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **Router:** fix Navigation for the millionth time ([aac2d52](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/aac2d520a68b1074ba1ae988d6c92f7881a296d7))
|
|
||||||
|
|
||||||
## [3.18.5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.4...v3.18.5) (2022-12-21)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* fixed prop interfaces ([#70](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/70)) ([0b50f2c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0b50f2cf0baa76fc00aa0a41a8435d7a512bff19))
|
|
||||||
|
|
||||||
## [3.18.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.3...v3.18.4) (2022-12-16)
|
## [3.18.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.3...v3.18.4) (2022-12-16)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
Library used to develop plugins used for use with [decky-loader](https://github.com/SteamDeckHomebrew/decky-loader).
|
Library used to develop plugins used for use with [decky-loader](https://github.com/SteamDeckHomebrew/decky-loader).
|
||||||
|
|
||||||
## Decky Loader Discord [](https://deckbrew.xyz/discord)
|
## Decky Loader Discord [](https://discord.gg/ZU74G2NJzk)
|
||||||
|
|
||||||
Please [contact the developers here](https://deckbrew.xyz/discord) for questions and support that cannot be addressed via a Github issue.
|
Please contact the developers here for questions and support that cannot be addressed via a Github issue.
|
||||||
|
|
||||||
## Developers and Contributors
|
## Developers and Contributors
|
||||||
|
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "decky-frontend-lib",
|
"name": "decky-frontend-lib",
|
||||||
"version": "3.21.5",
|
"version": "3.18.4",
|
||||||
"description": "A library for building decky plugins",
|
"description": "A library for building decky plugins",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "shx rm -rf dist && tsc -b",
|
"build": "shx rm -rf dist && tsc -b",
|
||||||
"dev": "tsc -b -w",
|
"dev": "tsc -b -w",
|
||||||
"docs": "typedoc --theme wiki-js --tsconfig ./tsconfig.json src/**/*",
|
"docs": "typedoc --tsconfig ./tsconfig.json src/**/*",
|
||||||
"test": "echo 'No tests for now!'",
|
"test": "echo 'No tests for now!'",
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
"commit": "git-cz"
|
"commit": "git-cz"
|
||||||
@@ -59,11 +59,11 @@
|
|||||||
"semantic-release": "^19.0.3",
|
"semantic-release": "^19.0.3",
|
||||||
"shx": "^0.3.4",
|
"shx": "^0.3.4",
|
||||||
"ts-jest": "^27.1.4",
|
"ts-jest": "^27.1.4",
|
||||||
"typedoc": "^0.23.24",
|
"typedoc": "^0.23.15",
|
||||||
|
"typedoc-plugin-markdown": "^3.13.6",
|
||||||
"typedoc-plugin-mdn-links": "^2.0.0",
|
"typedoc-plugin-mdn-links": "^2.0.0",
|
||||||
"typedoc-plugin-missing-exports": "^1.0.0",
|
"typedoc-plugin-missing-exports": "^1.0.0",
|
||||||
"typedoc-wikijs-theme": "^1.0.5",
|
"typescript": "^4.6.3"
|
||||||
"typescript": "^4.9.5"
|
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"peerDependencyRules": {
|
"peerDependencyRules": {
|
||||||
|
|||||||
3072
pnpm-lock.yaml
generated
3072
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,183 +0,0 @@
|
|||||||
import { Fragment, JSXElementConstructor, ReactElement, ReactNode, useEffect, useState } from 'react';
|
|
||||||
|
|
||||||
import { Field, FieldProps, Focusable, GamepadButton } from '../deck-components';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A ReorderableList entry of type <T>.
|
|
||||||
* @param label The name of this entry in the list.
|
|
||||||
* @param data Optional data to connect to this entry.
|
|
||||||
* @param position The position of this entry in the list.
|
|
||||||
*/
|
|
||||||
export type ReorderableEntry<T> = {
|
|
||||||
label: ReactNode;
|
|
||||||
data?: T;
|
|
||||||
position: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Properties for a ReorderableList component of type <T>.
|
|
||||||
*
|
|
||||||
* @param animate If the list should animate. @default true
|
|
||||||
*/
|
|
||||||
export type ReorderableListProps<T> = {
|
|
||||||
entries: ReorderableEntry<T>[];
|
|
||||||
onSave: (entries: ReorderableEntry<T>[]) => void;
|
|
||||||
interactables?: JSXElementConstructor<{ entry: ReorderableEntry<T> }>;
|
|
||||||
fieldProps?: FieldProps;
|
|
||||||
animate?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A component for creating reorderable lists.
|
|
||||||
*
|
|
||||||
* See an example implementation {@linkplain https://github.com/Tormak9970/Component-Testing-Plugin/blob/main/src/testing-window/ReorderableListTest.tsx here}.
|
|
||||||
*/
|
|
||||||
export function ReorderableList<T>(props: ReorderableListProps<T>) {
|
|
||||||
if (props.animate === undefined) props.animate = true;
|
|
||||||
const [entryList, setEntryList] = useState<ReorderableEntry<T>[]>(
|
|
||||||
props.entries.sort((a: ReorderableEntry<T>, b: ReorderableEntry<T>) => a.position - b.position),
|
|
||||||
);
|
|
||||||
const [reorderEnabled, setReorderEnabled] = useState<boolean>(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setEntryList(props.entries.sort((a: ReorderableEntry<T>, b: ReorderableEntry<T>) => a.position - b.position));
|
|
||||||
}, [props.entries]);
|
|
||||||
|
|
||||||
function toggleReorderEnabled(): void {
|
|
||||||
let newReorderValue = !reorderEnabled;
|
|
||||||
setReorderEnabled(newReorderValue);
|
|
||||||
|
|
||||||
if (!newReorderValue) {
|
|
||||||
props.onSave(entryList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveOnBackout(e: Event) {
|
|
||||||
const event = e as CustomEvent;
|
|
||||||
if (event.detail.button == GamepadButton.CANCEL && reorderEnabled) {
|
|
||||||
setReorderEnabled(!reorderEnabled);
|
|
||||||
props.onSave(entryList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Fragment>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: 'inherit',
|
|
||||||
height: 'inherit',
|
|
||||||
flex: '1 1 1px',
|
|
||||||
scrollPadding: '48px 0px',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
justifyContent: 'flex-start',
|
|
||||||
alignContent: 'stretch',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Focusable
|
|
||||||
onSecondaryButton={toggleReorderEnabled}
|
|
||||||
onSecondaryActionDescription={reorderEnabled ? 'Save Order' : 'Reorder'}
|
|
||||||
onClick={toggleReorderEnabled}
|
|
||||||
onButtonDown={saveOnBackout}
|
|
||||||
>
|
|
||||||
{entryList.map((entry: ReorderableEntry<T>) => (
|
|
||||||
<ReorderableItem
|
|
||||||
animate={props.animate!}
|
|
||||||
listData={entryList}
|
|
||||||
entryData={entry}
|
|
||||||
reorderEntryFunc={setEntryList}
|
|
||||||
reorderEnabled={reorderEnabled}
|
|
||||||
fieldProps={props.fieldProps}
|
|
||||||
>
|
|
||||||
{props.interactables ? <props.interactables entry={entry} /> : null}
|
|
||||||
</ReorderableItem>
|
|
||||||
))}
|
|
||||||
</Focusable>
|
|
||||||
</div>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Properties for a ReorderableItem component of type <T>
|
|
||||||
*/
|
|
||||||
export type ReorderableListEntryProps<T> = {
|
|
||||||
fieldProps?: FieldProps;
|
|
||||||
listData: ReorderableEntry<T>[];
|
|
||||||
entryData: ReorderableEntry<T>;
|
|
||||||
reorderEntryFunc: CallableFunction;
|
|
||||||
reorderEnabled: boolean;
|
|
||||||
animate: boolean;
|
|
||||||
children: ReactElement | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
function ReorderableItem<T>(props: ReorderableListEntryProps<T>) {
|
|
||||||
const [isSelected, _setIsSelected] = useState<boolean>(false);
|
|
||||||
const [isSelectedLastFrame, setIsSelectedLastFrame] = useState<boolean>(false);
|
|
||||||
const listEntries = props.listData;
|
|
||||||
|
|
||||||
function onReorder(e: Event): void {
|
|
||||||
if (!props.reorderEnabled) return;
|
|
||||||
|
|
||||||
const event = e as CustomEvent;
|
|
||||||
const currentIdx = listEntries.findIndex((entryData: ReorderableEntry<T>) => entryData === props.entryData);
|
|
||||||
const currentIdxValue = listEntries[currentIdx];
|
|
||||||
if (currentIdx < 0) return;
|
|
||||||
|
|
||||||
let targetPosition: number = -1;
|
|
||||||
if (event.detail.button == GamepadButton.DIR_DOWN) {
|
|
||||||
targetPosition = currentIdxValue.position + 1;
|
|
||||||
} else if (event.detail.button == GamepadButton.DIR_UP) {
|
|
||||||
targetPosition = currentIdxValue.position - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetPosition >= listEntries.length || targetPosition < 0) return;
|
|
||||||
|
|
||||||
let otherToUpdate = listEntries.find((entryData: ReorderableEntry<T>) => entryData.position === targetPosition);
|
|
||||||
if (!otherToUpdate) return;
|
|
||||||
|
|
||||||
let currentPosition = currentIdxValue.position;
|
|
||||||
|
|
||||||
currentIdxValue.position = otherToUpdate.position;
|
|
||||||
otherToUpdate.position = currentPosition;
|
|
||||||
|
|
||||||
props.reorderEntryFunc(
|
|
||||||
[...listEntries].sort((a: ReorderableEntry<T>, b: ReorderableEntry<T>) => a.position - b.position),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function setIsSelected(val: boolean) {
|
|
||||||
_setIsSelected(val);
|
|
||||||
// Wait 3 frames, then set. I have no idea why, but if you dont wait long enough it doesn't work.
|
|
||||||
for (let i = 0; i < 3; i++) await new Promise((res) => requestAnimationFrame(res));
|
|
||||||
setIsSelectedLastFrame(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
style={
|
|
||||||
props.animate
|
|
||||||
? {
|
|
||||||
transition:
|
|
||||||
isSelected || isSelectedLastFrame
|
|
||||||
? ''
|
|
||||||
: 'transform 0.3s cubic-bezier(0.25, 1, 0.5, 1), opacity 0.3s cubic-bezier(0.25, 1, 0.5, 1)', // easeOutQuart https://easings.net/#easeOutQuart
|
|
||||||
transform: !props.reorderEnabled || isSelected ? 'scale(1)' : 'scale(0.9)',
|
|
||||||
opacity: !props.reorderEnabled || isSelected ? 1 : 0.7,
|
|
||||||
}
|
|
||||||
: {}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Field
|
|
||||||
label={props.entryData.label}
|
|
||||||
{...props.fieldProps}
|
|
||||||
focusable={!props.children}
|
|
||||||
onButtonDown={onReorder}
|
|
||||||
onGamepadBlur={() => setIsSelected(false)}
|
|
||||||
onGamepadFocus={() => setIsSelected(true)}
|
|
||||||
>
|
|
||||||
<Focusable style={{ display: 'flex', width: '100%', position: 'relative' }}>{props.children}</Focusable>
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -13,8 +13,6 @@ export const SuspensefulImage: FC<SuspensefulImageProps> = (props) => {
|
|||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
|
||||||
setError(false);
|
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.src = props.src || '';
|
img.src = props.src || '';
|
||||||
img.addEventListener('load', () => {
|
img.addEventListener('load', () => {
|
||||||
@@ -23,7 +21,7 @@ export const SuspensefulImage: FC<SuspensefulImageProps> = (props) => {
|
|||||||
img.addEventListener('error', () => {
|
img.addEventListener('error', () => {
|
||||||
setError(true);
|
setError(true);
|
||||||
});
|
});
|
||||||
}, [props.src]);
|
}, []);
|
||||||
|
|
||||||
return loading ? (
|
return loading ? (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
export * from './SuspensefulImage';
|
export * from './SuspensefulImage';
|
||||||
export * from './ColorPickerModal';
|
export * from './ColorPickerModal';
|
||||||
export * from './ReorderableList';
|
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { getGamepadNavigationTrees } from '../utils';
|
|
||||||
|
declare global {
|
||||||
|
var FocusNavController: any;
|
||||||
|
}
|
||||||
|
|
||||||
function getQuickAccessWindow(): Window | null {
|
function getQuickAccessWindow(): Window | null {
|
||||||
const navTrees = getGamepadNavigationTrees();
|
try {
|
||||||
return navTrees.find((tree: any) => tree?.id === 'QuickAccess-NA')?.m_Root?.m_element?.ownerDocument.defaultView ?? null;
|
const context = FocusNavController?.m_ActiveContext || FocusNavController?.m_LastActiveContext;
|
||||||
|
const navTrees = context?.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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ export interface ButtonItemProps extends ItemProps {
|
|||||||
onClick?(e: MouseEvent): void;
|
onClick?(e: MouseEvent): void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
export const ButtonItem =
|
|
||||||
CommonUIModule.ButtonField ||
|
export const ButtonItem = Object.values(CommonUIModule).find(
|
||||||
(Object.values(CommonUIModule).find(
|
(mod: any) =>
|
||||||
(mod: any) =>
|
mod?.render?.toString()?.includes('"highlightOnFocus","childrenContainerWidth"') ||
|
||||||
mod?.render?.toString()?.includes('"highlightOnFocus","childrenContainerWidth"') ||
|
mod?.render?.toString()?.includes('childrenContainerWidth:"min"'),
|
||||||
mod?.render?.toString()?.includes('childrenContainerWidth:"min"'),
|
) as FC<ButtonItemProps>;
|
||||||
) as FC<ButtonItemProps>);
|
|
||||||
|
|||||||
@@ -8,5 +8,4 @@ export interface ItemProps {
|
|||||||
bottomSeparator?: 'standard' | 'thick' | 'none';
|
bottomSeparator?: 'standard' | 'thick' | 'none';
|
||||||
indentLevel?: number;
|
indentLevel?: number;
|
||||||
tooltip?: string;
|
tooltip?: string;
|
||||||
highlightOnFocus?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { CSSProperties, FC } from 'react';
|
import { CSSProperties, FC, ReactNode } from 'react';
|
||||||
|
|
||||||
import { findModuleChild } from '../webpack';
|
import { findModuleChild } from '../webpack';
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ export interface MarqueeProps {
|
|||||||
resetOnPause?: boolean;
|
resetOnPause?: boolean;
|
||||||
style?: CSSProperties;
|
style?: CSSProperties;
|
||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Marquee: FC<MarqueeProps> = findModuleChild((m) => {
|
export const Marquee: FC<MarqueeProps> = findModuleChild((m) => {
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ export const MenuGroup: FC<MenuGroupProps> = findModuleChild((m) => {
|
|||||||
|
|
||||||
for (let prop in m) {
|
for (let prop in m) {
|
||||||
if (
|
if (
|
||||||
(m[prop]?.toString()?.includes?.('bInGamepadUI:') &&
|
(m[prop]?.toString()?.includes('bInGamepadUI:') &&
|
||||||
fakeRenderComponent(() => m[prop]({overview: {appid: 7}}))?.type?.prototype?.RenderSubMenu) ||
|
fakeRenderComponent(() => m[prop]())?.type?.prototype?.RenderSubMenu) ||
|
||||||
(m[prop]?.prototype?.RenderSubMenu && m[prop]?.prototype?.ShowSubMenu)
|
(m[prop]?.prototype?.RenderSubMenu && m[prop]?.prototype?.ShowSubMenu)
|
||||||
) {
|
) {
|
||||||
return m[prop];
|
return m[prop];
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ export const ModalRoot = (Object.values(
|
|||||||
if (typeof m !== 'object') return false;
|
if (typeof m !== 'object') return false;
|
||||||
|
|
||||||
for (let prop in m) {
|
for (let prop in m) {
|
||||||
if (m[prop]?.m_mapModalManager && Object.values(m)?.find((x: any) => x?.type)) {
|
if (m[prop]?.m_mapModalManager) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { FC, ReactNode } from 'react';
|
import { FC } from 'react';
|
||||||
|
|
||||||
import { findModuleChild } from '../webpack';
|
import { findModuleChild } from '../webpack';
|
||||||
|
|
||||||
export interface PanelSectionProps {
|
export interface PanelSectionProps {
|
||||||
title?: string;
|
title?: string;
|
||||||
spinner?: boolean;
|
spinner?: boolean;
|
||||||
children?: ReactNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const [panelSection, mod] = findModuleChild((mod: any) => {
|
const [panelSection, mod] = findModuleChild((mod: any) => {
|
||||||
@@ -19,10 +18,6 @@ const [panelSection, mod] = findModuleChild((mod: any) => {
|
|||||||
|
|
||||||
export const PanelSection = panelSection as FC<PanelSectionProps>;
|
export const PanelSection = panelSection as FC<PanelSectionProps>;
|
||||||
|
|
||||||
export interface PanelSectionRowProps {
|
export const PanelSectionRow = Object.values(mod).filter(
|
||||||
children?: ReactNode;
|
(exp: any) => !exp?.toString()?.includes('.PanelSection'),
|
||||||
}
|
)[0] as FC;
|
||||||
// New as of Feb 22 2023 Beta || Old
|
|
||||||
export const PanelSectionRow =
|
|
||||||
mod.PanelSectionRow ||
|
|
||||||
(Object.values(mod).filter((exp: any) => !exp?.toString()?.includes('.PanelSection'))[0] as FC<PanelSectionRowProps>);
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { sleep } from '../utils';
|
|
||||||
import { Module, findModuleChild } from '../webpack';
|
import { Module, findModuleChild } from '../webpack';
|
||||||
|
|
||||||
export enum SideMenu {
|
export enum SideMenu {
|
||||||
@@ -15,8 +14,7 @@ export enum QuickAccessTab {
|
|||||||
Settings,
|
Settings,
|
||||||
Perf,
|
Perf,
|
||||||
Help,
|
Help,
|
||||||
Music,
|
Decky,
|
||||||
Decky = 999,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DisplayStatus {
|
export enum DisplayStatus {
|
||||||
@@ -78,6 +76,7 @@ export interface WindowRouter {
|
|||||||
NavigateToChat(): void;
|
NavigateToChat(): void;
|
||||||
NavigateToSteamWeb(url: string): void;
|
NavigateToSteamWeb(url: string): void;
|
||||||
NavigateBack(): void;
|
NavigateBack(): void;
|
||||||
|
NavigateToWebRoute(unknown?: any, unknown2?: any): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WindowStore {
|
export interface WindowStore {
|
||||||
@@ -118,6 +117,7 @@ export interface Navigation {
|
|||||||
NavigateToLibraryTab(): void;
|
NavigateToLibraryTab(): void;
|
||||||
NavigateToLayoutPreview(e: unknown): void;
|
NavigateToLayoutPreview(e: unknown): void;
|
||||||
NavigateToSteamWeb(url: string): void;
|
NavigateToSteamWeb(url: string): void;
|
||||||
|
NavigateToWebRoute(unknown?: any, unknown2?: any): void;
|
||||||
OpenSideMenu(sideMenu: SideMenu): void;
|
OpenSideMenu(sideMenu: SideMenu): void;
|
||||||
OpenQuickAccessMenu(quickAccessTab?: QuickAccessTab): void;
|
OpenQuickAccessMenu(quickAccessTab?: QuickAccessTab): void;
|
||||||
OpenMainMenu(): void;
|
OpenMainMenu(): void;
|
||||||
@@ -125,62 +125,32 @@ export interface Navigation {
|
|||||||
CloseSideMenus(): void;
|
CloseSideMenus(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export let Navigation = {} as Navigation;
|
export const Navigation = {
|
||||||
|
Navigate: Router.Navigate.bind(Router),
|
||||||
try {
|
NavigateBack: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateBack.bind(
|
||||||
(async () => {
|
Router.WindowStore.GamepadUIMainWindowInstance,
|
||||||
let InternalNavigators: any = {};
|
),
|
||||||
if (!Router.NavigateToAppProperties || (Router as unknown as any).deckyShim) {
|
NavigateToAppProperties: Router.NavigateToAppProperties.bind(Router),
|
||||||
function initInternalNavigators() {
|
NavigateToExternalWeb: Router.NavigateToExternalWeb.bind(Router),
|
||||||
try {
|
NavigateToInvites: Router.NavigateToInvites.bind(Router),
|
||||||
InternalNavigators = findModuleChild((m: any) => {
|
NavigateToChat: Router.NavigateToChat.bind(Router),
|
||||||
if (typeof m !== 'object') return undefined;
|
NavigateToLibraryTab: Router.NavigateToLibraryTab.bind(Router),
|
||||||
for (let prop in m) {
|
NavigateToLayoutPreview: Router.NavigateToLayoutPreview.bind(Router),
|
||||||
if (m[prop]?.GetNavigator) {
|
NavigateToSteamWeb: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateToSteamWeb.bind(
|
||||||
return m[prop];
|
Router.WindowStore.GamepadUIMainWindowInstance,
|
||||||
}
|
),
|
||||||
}
|
NavigateToWebRoute: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateToWebRoute.bind(
|
||||||
})?.GetNavigator();
|
Router.WindowStore.GamepadUIMainWindowInstance,
|
||||||
} catch (e) {
|
),
|
||||||
console.error('[DFL:Router]: Failed to init internal navigators, trying again');
|
OpenSideMenu: Router.WindowStore?.GamepadUIMainWindowInstance?.MenuStore.OpenSideMenu.bind(
|
||||||
}
|
Router.WindowStore.GamepadUIMainWindowInstance.MenuStore,
|
||||||
}
|
),
|
||||||
initInternalNavigators();
|
OpenQuickAccessMenu: Router.WindowStore?.GamepadUIMainWindowInstance?.MenuStore.OpenQuickAccessMenu.bind(
|
||||||
while (!InternalNavigators?.AppProperties) {
|
Router.WindowStore.GamepadUIMainWindowInstance.MenuStore,
|
||||||
console.log('[DFL:Router]: Trying to init internal navigators again');
|
),
|
||||||
await sleep(100);
|
OpenMainMenu: Router.WindowStore?.GamepadUIMainWindowInstance?.MenuStore.OpenMainMenu.bind(
|
||||||
initInternalNavigators();
|
Router.WindowStore.GamepadUIMainWindowInstance.MenuStore,
|
||||||
}
|
),
|
||||||
}
|
CloseSideMenus: Router.CloseSideMenus.bind(Router),
|
||||||
const newNavigation = {
|
OpenPowerMenu: Router.OpenPowerMenu.bind(Router),
|
||||||
Navigate: Router.Navigate?.bind(Router),
|
} as Navigation;
|
||||||
NavigateBack: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateBack?.bind(
|
|
||||||
Router.WindowStore.GamepadUIMainWindowInstance,
|
|
||||||
),
|
|
||||||
NavigateToAppProperties: InternalNavigators?.AppProperties || Router.NavigateToAppProperties?.bind(Router),
|
|
||||||
NavigateToExternalWeb: InternalNavigators?.ExternalWeb || Router.NavigateToExternalWeb?.bind(Router),
|
|
||||||
NavigateToInvites: InternalNavigators?.Invites || Router.NavigateToInvites?.bind(Router),
|
|
||||||
NavigateToChat: Router.NavigateToChat?.bind(Router),
|
|
||||||
NavigateToLibraryTab: InternalNavigators?.LibraryTab || Router.NavigateToLibraryTab?.bind(Router),
|
|
||||||
NavigateToLayoutPreview: Router.NavigateToLayoutPreview?.bind(Router),
|
|
||||||
NavigateToSteamWeb: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateToSteamWeb?.bind(
|
|
||||||
Router.WindowStore.GamepadUIMainWindowInstance,
|
|
||||||
),
|
|
||||||
OpenSideMenu: Router.WindowStore?.GamepadUIMainWindowInstance?.MenuStore.OpenSideMenu?.bind(
|
|
||||||
Router.WindowStore.GamepadUIMainWindowInstance.MenuStore,
|
|
||||||
),
|
|
||||||
OpenQuickAccessMenu: Router.WindowStore?.GamepadUIMainWindowInstance?.MenuStore.OpenQuickAccessMenu?.bind(
|
|
||||||
Router.WindowStore.GamepadUIMainWindowInstance.MenuStore,
|
|
||||||
),
|
|
||||||
OpenMainMenu: Router.WindowStore?.GamepadUIMainWindowInstance?.MenuStore.OpenMainMenu?.bind(
|
|
||||||
Router.WindowStore.GamepadUIMainWindowInstance.MenuStore,
|
|
||||||
),
|
|
||||||
CloseSideMenus: Router.CloseSideMenus?.bind(Router),
|
|
||||||
OpenPowerMenu: Router.OpenPowerMenu?.bind(Router),
|
|
||||||
} as Navigation;
|
|
||||||
|
|
||||||
Object.assign(Navigation, newNavigation);
|
|
||||||
})();
|
|
||||||
} catch (e) {
|
|
||||||
console.error('[DFL:Router]: Error initializing Navigation interface', e);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ReactNode, VFC } from 'react';
|
|||||||
import { Module, findModuleChild } from '../webpack';
|
import { Module, findModuleChild } from '../webpack';
|
||||||
|
|
||||||
export interface SidebarNavigationPage {
|
export interface SidebarNavigationPage {
|
||||||
title: ReactNode;
|
title: string;
|
||||||
content: ReactNode;
|
content: ReactNode;
|
||||||
icon?: ReactNode;
|
icon?: ReactNode;
|
||||||
visible?: boolean;
|
visible?: boolean;
|
||||||
@@ -16,7 +16,7 @@ export interface SidebarNavigationPage {
|
|||||||
|
|
||||||
export interface SidebarNavigationProps {
|
export interface SidebarNavigationProps {
|
||||||
title?: string;
|
title?: string;
|
||||||
pages: (SidebarNavigationPage | 'separator')[];
|
pages: SidebarNavigationPage[];
|
||||||
showTitle?: boolean;
|
showTitle?: boolean;
|
||||||
disableRouteReporting?: boolean;
|
disableRouteReporting?: boolean;
|
||||||
page?: string;
|
page?: string;
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ export interface SliderFieldProps extends ItemProps {
|
|||||||
valueSuffix?: string;
|
valueSuffix?: string;
|
||||||
minimumDpadGranularity?: number;
|
minimumDpadGranularity?: number;
|
||||||
onChange?(value: number): void;
|
onChange?(value: number): void;
|
||||||
className?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SliderField = Object.values(CommonUIModule).find((mod: any) =>
|
export const SliderField = Object.values(CommonUIModule).find((mod: any) =>
|
||||||
|
|||||||
@@ -217,14 +217,6 @@ export type AppLanguages = {
|
|||||||
strShortName: string;
|
strShortName: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LogoPinPositions = 'BottomLeft' | 'UpperLeft' | 'CenterCenter' | 'UpperCenter' | 'BottomCenter';
|
|
||||||
|
|
||||||
export interface LogoPosition {
|
|
||||||
pinnedPosition: LogoPinPositions;
|
|
||||||
nWidthPct: number;
|
|
||||||
nHeightPct: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface AppDetails {
|
export interface AppDetails {
|
||||||
achievements: AppAchievements;
|
achievements: AppAchievements;
|
||||||
bCanMoveInstallFolder: boolean;
|
bCanMoveInstallFolder: boolean;
|
||||||
@@ -300,18 +292,9 @@ export interface AppDetails {
|
|||||||
vecMusicAlbums: any[];
|
vecMusicAlbums: any[];
|
||||||
vecPlatforms: string[];
|
vecPlatforms: string[];
|
||||||
vecScreenShots: any[];
|
vecScreenShots: any[];
|
||||||
libraryAssets?: {
|
|
||||||
logoPosition?: LogoPosition;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SteamAppOverview {
|
export interface SteamAppOverview {
|
||||||
display_name: string;
|
display_name: string;
|
||||||
gameid: string;
|
gameid: string;
|
||||||
appid: number;
|
|
||||||
icon_hash: string;
|
|
||||||
third_party_mod?: boolean;
|
|
||||||
selected_clientid?: string;
|
|
||||||
BIsModOrShortcut: () => boolean;
|
|
||||||
BIsShortcut: () => boolean;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import { findModuleChild } from '../webpack';
|
|||||||
export const SteamSpinner = findModuleChild((m) => {
|
export const SteamSpinner = findModuleChild((m) => {
|
||||||
if (typeof m !== 'object') return undefined;
|
if (typeof m !== 'object') return undefined;
|
||||||
for (let prop in m) {
|
for (let prop in m) {
|
||||||
if (
|
if (m[prop]?.toString()?.includes('Steam Spinner') && m[prop].toString().includes('PreloadThrobber'))
|
||||||
m[prop]?.toString?.()?.includes('Steam Spinner') && m[prop]?.toString?.()?.includes('src')
|
|
||||||
)
|
|
||||||
return m[prop];
|
return m[prop];
|
||||||
}
|
}
|
||||||
}) as FC<SVGAttributes<SVGElement>>;
|
}) as FC<SVGAttributes<SVGElement>>;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { CommonUIModule } from '../webpack';
|
|||||||
import { ItemProps } from './Item';
|
import { ItemProps } from './Item';
|
||||||
|
|
||||||
export interface ToggleFieldProps extends ItemProps {
|
export interface ToggleFieldProps extends ItemProps {
|
||||||
highlightOnFocus?: boolean;
|
|
||||||
checked: boolean;
|
checked: boolean;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
onChange?(checked: boolean): void;
|
onChange?(checked: boolean): void;
|
||||||
|
|||||||
@@ -26,56 +26,8 @@ export * from './Toggle';
|
|||||||
export * from './ToggleField';
|
export * from './ToggleField';
|
||||||
export * from './SteamClient';
|
export * from './SteamClient';
|
||||||
|
|
||||||
import { AppDetails, LogoPosition, SteamAppOverview, SteamClient } from './SteamClient';
|
import {SteamClient} from './SteamClient'
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
var SteamClient: SteamClient;
|
var SteamClient: SteamClient;
|
||||||
|
|
||||||
interface Window {
|
|
||||||
LocalizationManager: {
|
|
||||||
m_mapTokens: Map<string, string>;
|
|
||||||
m_mapFallbackTokens: Map<string, string>;
|
|
||||||
m_rgLocalesToUse: string[];
|
|
||||||
};
|
|
||||||
App: {
|
|
||||||
m_CurrentUser: {
|
|
||||||
bIsLimited: boolean;
|
|
||||||
bIsOfflineMode: boolean;
|
|
||||||
bSupportAlertActive: boolean;
|
|
||||||
bCanInviteFriends: boolean;
|
|
||||||
NotificationCounts: {
|
|
||||||
comments: number;
|
|
||||||
inventory_items: number;
|
|
||||||
invites: number;
|
|
||||||
gifts: number;
|
|
||||||
offline_messages: number;
|
|
||||||
trade_offers: number;
|
|
||||||
async_game_updates: number;
|
|
||||||
moderator_messages: number;
|
|
||||||
help_request_replies: number;
|
|
||||||
};
|
|
||||||
strAccountBalance: string;
|
|
||||||
strAccountName: string;
|
|
||||||
strSteamID: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
appStore: {
|
|
||||||
GetAppOverviewByAppID: (appId: number) => SteamAppOverview | null;
|
|
||||||
GetCustomVerticalCapsuleURLs: (app: SteamAppOverview) => string[];
|
|
||||||
GetCustomLandcapeImageURLs: (app: SteamAppOverview) => string[];
|
|
||||||
GetCustomHeroImageURLs: (app: SteamAppOverview) => string[];
|
|
||||||
GetCustomLogoImageURLs: (app: SteamAppOverview) => string[];
|
|
||||||
GetLandscapeImageURLForApp: (app: SteamAppOverview) => string;
|
|
||||||
GetVerticalCapsuleURLForApp: (app: SteamAppOverview) => string;
|
|
||||||
GetCachedLandscapeImageURLForApp: (app: SteamAppOverview) => string;
|
|
||||||
GetCachedVerticalImageURLForApp: (app: SteamAppOverview) => string;
|
|
||||||
GetPregeneratedVerticalCapsuleForApp: (app: SteamAppOverview) => string;
|
|
||||||
GetIconURLForApp: (app: SteamAppOverview) => string;
|
|
||||||
};
|
|
||||||
appDetailsStore: {
|
|
||||||
GetAppDetails: (appId: number) => AppDetails | null;
|
|
||||||
GetCustomLogoPosition: (app: SteamAppOverview) => LogoPosition | null;
|
|
||||||
SaveCustomLogoPosition: (app: SteamAppOverview, logoPositions: LogoPosition) => any;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -441,69 +441,6 @@ type AppDetailsClasses = Record<
|
|||||||
string
|
string
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type GamepadUIClasses = Record<
|
|
||||||
| 'duration-app-launch'
|
|
||||||
| 'TransitionMenuDelay'
|
|
||||||
| 'PanelSection'
|
|
||||||
| 'PanelSectionTitle'
|
|
||||||
| 'Text'
|
|
||||||
| 'PanelSectionRow'
|
|
||||||
| 'Label'
|
|
||||||
| 'ComingSoon'
|
|
||||||
| 'LowBattery'
|
|
||||||
| 'ReallyLow'
|
|
||||||
| 'LowBatteryGauge'
|
|
||||||
| 'Remaining'
|
|
||||||
| 'EmptyNotifications'
|
|
||||||
| 'BatterySectionContainer'
|
|
||||||
| 'BatteryIcon'
|
|
||||||
| 'BatteryPercentageLabel'
|
|
||||||
| 'BatteryDetailsLabels'
|
|
||||||
| 'BatteryProjectedValue'
|
|
||||||
| 'BatteryProjectedLabel'
|
|
||||||
| 'ViewPlaceholder'
|
|
||||||
| 'FullHeight'
|
|
||||||
| 'Title'
|
|
||||||
| 'Container'
|
|
||||||
| 'Open'
|
|
||||||
| 'QuickAccessMenu'
|
|
||||||
| 'HeaderContainer'
|
|
||||||
| 'Menu'
|
|
||||||
| 'HeaderAndFooterVisible'
|
|
||||||
| 'TabContentColumn'
|
|
||||||
| 'Tabs'
|
|
||||||
| 'Tab'
|
|
||||||
| 'Selected'
|
|
||||||
| 'ItemFocusAnim-darkerGrey'
|
|
||||||
| 'ItemFocusAnim-darkerGrey-nocolor'
|
|
||||||
| 'VoiceTab'
|
|
||||||
| 'ItemFocusAnim-green'
|
|
||||||
| 'Blocked'
|
|
||||||
| 'TabPanelHidden'
|
|
||||||
| 'FriendsTitle'
|
|
||||||
| 'FriendsListTabPanel'
|
|
||||||
| 'PanelOuterNav'
|
|
||||||
| 'PanelExitAnchor'
|
|
||||||
| 'TabGroupPanel'
|
|
||||||
| 'FooterBoxShadow'
|
|
||||||
| 'AllTabContents'
|
|
||||||
| 'ContentTransition'
|
|
||||||
| 'ActiveTab'
|
|
||||||
| 'Up'
|
|
||||||
| 'Enter'
|
|
||||||
| 'EnterActive'
|
|
||||||
| 'Exit'
|
|
||||||
| 'ExitActive'
|
|
||||||
| 'Down'
|
|
||||||
| 'KeyboardButton'
|
|
||||||
| 'ItemFocusAnim-darkGrey'
|
|
||||||
| 'ItemFocusAnim-grey'
|
|
||||||
| 'ItemFocusAnimBorder-darkGrey'
|
|
||||||
| 'focusAnimation'
|
|
||||||
| 'hoverAnimation',
|
|
||||||
string
|
|
||||||
>;
|
|
||||||
|
|
||||||
export const quickAccessMenuClasses: QuickAccessMenuClasses = findModule(
|
export const quickAccessMenuClasses: QuickAccessMenuClasses = findModule(
|
||||||
(mod) => typeof mod === 'object' && mod?.Title?.includes('quickaccessmenu'),
|
(mod) => typeof mod === 'object' && mod?.Title?.includes('quickaccessmenu'),
|
||||||
);
|
);
|
||||||
@@ -522,7 +459,7 @@ export const gamepadDialogClasses: GamepadDialogClasses = findModule(
|
|||||||
(mod) => typeof mod === 'object' && mod?.GamepadDialogContent?.includes('gamepaddialog'),
|
(mod) => typeof mod === 'object' && mod?.GamepadDialogContent?.includes('gamepaddialog'),
|
||||||
);
|
);
|
||||||
export const quickAccessControlsClasses: QuickAccessControlsClasses = findModule(
|
export const quickAccessControlsClasses: QuickAccessControlsClasses = findModule(
|
||||||
(mod) => typeof mod === 'object' && typeof mod?.PanelSection === 'string' && mod?.PanelSection?.includes('quickaccesscontrols'),
|
(mod) => typeof mod === 'object' && mod?.PanelSection?.includes('quickaccesscontrols'),
|
||||||
);
|
);
|
||||||
export const updaterFieldClasses: UpdaterFieldClasses = findModule(
|
export const updaterFieldClasses: UpdaterFieldClasses = findModule(
|
||||||
(mod) => typeof mod === 'object' && mod?.OOBEUpdateStatusContainer?.includes('updaterfield'),
|
(mod) => typeof mod === 'object' && mod?.OOBEUpdateStatusContainer?.includes('updaterfield'),
|
||||||
@@ -539,6 +476,3 @@ export const appDetailsHeaderClasses: AppDetailsHeaderClasses = findModule(
|
|||||||
export const appDetailsClasses: AppDetailsClasses = findModule(
|
export const appDetailsClasses: AppDetailsClasses = findModule(
|
||||||
(mod) => typeof mod === 'object' && mod?.HeaderLoaded?.includes('appdetails_'),
|
(mod) => typeof mod === 'object' && mod?.HeaderLoaded?.includes('appdetails_'),
|
||||||
);
|
);
|
||||||
export const gamepadUIClasses: GamepadUIClasses = findModule(
|
|
||||||
(mod) => typeof mod === 'object' && mod?.BasicUiRoot?.includes('gamepadui_'),
|
|
||||||
);
|
|
||||||
@@ -21,6 +21,52 @@ interface ServerResponseError {
|
|||||||
|
|
||||||
export type ServerResponse<TRes> = ServerResponseSuccess<TRes> | ServerResponseError;
|
export type ServerResponse<TRes> = ServerResponseSuccess<TRes> | ServerResponseError;
|
||||||
|
|
||||||
|
export interface MainMenuItem {
|
||||||
|
/** Called when clicking this menu item, useful if you do not want to navigate to a route.
|
||||||
|
* For navigating to a route, use route instead. */
|
||||||
|
action?: () => void;
|
||||||
|
/** The route this menu item navigates to @example "/steamweb" */
|
||||||
|
route?: string;
|
||||||
|
/** Props for the route this item navigates to. Currently only used for /steamweb to determine what webpack to navigate to @example {url: 'https://store.steampowered.com/'} */
|
||||||
|
routeState?: any;
|
||||||
|
/** Label for this menu item, @example "Store" */
|
||||||
|
label: ReactNode;
|
||||||
|
/** Runs when this item is selected. Defaults to setting the focused app to null.
|
||||||
|
* If you override this you must also call the original to retain proper behaivour */
|
||||||
|
onFocus?: () => void;
|
||||||
|
/** Icon of this menu item, you probably want a react SVG node */
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CustomMainMenuItem extends MainMenuItem {
|
||||||
|
index: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MainMenuItemReactNode {
|
||||||
|
props: MainMenuItem;
|
||||||
|
type: ComponentType;
|
||||||
|
key: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OverlayReactNode {
|
||||||
|
props: MainMenuItem;
|
||||||
|
type: ComponentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ItemPatch = (item: MainMenuItemReactNode) => MainMenuItemReactNode;
|
||||||
|
export type OverlayPatch = (overlay: OverlayReactNode) => OverlayReactNode;
|
||||||
|
|
||||||
|
export interface MenuHook {
|
||||||
|
addItem(item: CustomMainMenuItem): CustomMainMenuItem;
|
||||||
|
addPatch(path: string, patch: ItemPatch): ItemPatch;
|
||||||
|
addOverlayPatch(patch: OverlayPatch): OverlayPatch;
|
||||||
|
addOverlayComponent(component: ReactNode): ReactNode;
|
||||||
|
removePatch(path: string, patch: ItemPatch): void;
|
||||||
|
removeOverlayPatch(patch: OverlayPatch): void;
|
||||||
|
removeOverlayComponent(component: ReactNode): void;
|
||||||
|
removeItem(item: CustomMainMenuItem): void;
|
||||||
|
}
|
||||||
|
|
||||||
export type RoutePatch = (route: RouteProps) => RouteProps;
|
export type RoutePatch = (route: RouteProps) => RouteProps;
|
||||||
|
|
||||||
export interface RouterHook {
|
export interface RouterHook {
|
||||||
@@ -57,26 +103,11 @@ export interface FilePickerRes {
|
|||||||
realpath: string;
|
realpath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum FileSelectionType {
|
|
||||||
FILE,
|
|
||||||
FOLDER,
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ServerAPI {
|
export interface ServerAPI {
|
||||||
routerHook: RouterHook;
|
routerHook: RouterHook;
|
||||||
|
menuHook: MenuHook;
|
||||||
toaster: Toaster;
|
toaster: Toaster;
|
||||||
openFilePicker(startPath: string, includeFiles?: boolean, regex?: RegExp): Promise<FilePickerRes>;
|
openFilePicker(startPath: string, includeFiles?: boolean, regex?: RegExp): Promise<FilePickerRes>;
|
||||||
openFilePickerV2(
|
|
||||||
startPath: string,
|
|
||||||
includeFiles?: boolean,
|
|
||||||
includeFolders?: boolean,
|
|
||||||
filter?: RegExp | ((file: File) => boolean),
|
|
||||||
extensions?: string[],
|
|
||||||
showHiddenFiles?: boolean,
|
|
||||||
allowAllFiles?: boolean,
|
|
||||||
max?: number,
|
|
||||||
select?: FileSelectionType,
|
|
||||||
): Promise<FilePickerRes>;
|
|
||||||
callPluginMethod<TArgs = {}, TRes = {}>(methodName: string, args: TArgs): Promise<ServerResponse<TRes>>;
|
callPluginMethod<TArgs = {}, TRes = {}>(methodName: string, args: TArgs): Promise<ServerResponse<TRes>>;
|
||||||
callServerMethod<TArgs = {}, TRes = {}>(methodName: string, args: TArgs): Promise<ServerResponse<TRes>>;
|
callServerMethod<TArgs = {}, TRes = {}>(methodName: string, args: TArgs): Promise<ServerResponse<TRes>>;
|
||||||
fetchNoCors<TRes = {}>(url: RequestInfo, request?: RequestInit): Promise<ServerResponse<TRes>>;
|
fetchNoCors<TRes = {}>(url: RequestInfo, request?: RequestInit): Promise<ServerResponse<TRes>>;
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
export * from './patcher';
|
export * from './patcher';
|
||||||
export * from './react';
|
export * from './react';
|
||||||
|
|
||||||
declare global {
|
|
||||||
var FocusNavController: any;
|
|
||||||
var GamepadNavTree: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function joinClassNames(...classes: string[]): string {
|
export function joinClassNames(...classes: string[]): string {
|
||||||
return classes.join(' ');
|
return classes.join(' ');
|
||||||
}
|
}
|
||||||
@@ -21,22 +16,7 @@ export function findSP(): Window {
|
|||||||
// old (SP as host)
|
// old (SP as host)
|
||||||
if (document.title == 'SP') return window;
|
if (document.title == 'SP') return window;
|
||||||
// new (SP as popup)
|
// new (SP as popup)
|
||||||
const navTrees = getGamepadNavigationTrees();
|
const context = FocusNavController.m_ActiveContext || FocusNavController.m_LastActiveContext;
|
||||||
return navTrees?.find((x: any) => x.m_ID == 'root_1_').Root.Element.ownerDocument.defaultView;
|
return context.m_rgGamepadNavigationTrees.find((x: any) => x.m_ID == 'root_1_').Root
|
||||||
}
|
.Element.ownerDocument.defaultView;
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the correct FocusNavController, as the Feb 22 2023 beta has two for some reason.
|
|
||||||
*/
|
|
||||||
export function getFocusNavController(): any {
|
|
||||||
return window.GamepadNavTree?.m_context?.m_controller || window.FocusNavController;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the gamepad navigation trees as Valve seems to be moving them.
|
|
||||||
*/
|
|
||||||
export function getGamepadNavigationTrees(): any {
|
|
||||||
const focusNav = getFocusNavController();
|
|
||||||
const context = focusNav.m_ActiveContext || focusNav.m_LastActiveContext;
|
|
||||||
return context?.m_rgGamepadNavigationTrees;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"githubPages": false,
|
||||||
"categorizeByGroup": false,
|
"categorizeByGroup": false,
|
||||||
"excludeExternals": true
|
"excludeExternals": true
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user