mirror of
https://github.com/SteamDeckHomebrew/decky-frontend-lib.git
synced 2026-05-19 17:40:08 +02:00
Compare commits
262 Commits
aa/menu-ho
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b151bdce8b | ||
|
|
e44664c970 | ||
|
|
ac8da8e9b6 | ||
|
|
b688bc3544 | ||
|
|
3126dd3e04 | ||
|
|
8596294667 | ||
|
|
772a85523b | ||
|
|
aabc522740 | ||
|
|
66e0afccae | ||
|
|
77e6acd828 | ||
|
|
261162c8bc | ||
|
|
f8fda380f1 | ||
|
|
7242c69758 | ||
|
|
fd651eb989 | ||
|
|
6e443c06d3 | ||
|
|
25b4b60e34 | ||
|
|
cf6572cd7b | ||
|
|
779b1ae0de | ||
|
|
366357d9a3 | ||
|
|
37dd88513e | ||
|
|
ed87f73602 | ||
|
|
3d5de65077 | ||
|
|
33d224bc3f | ||
|
|
aa0678c857 | ||
|
|
39fdde9481 | ||
|
|
a4627a70c5 | ||
|
|
1f6611a10f | ||
|
|
c149711265 | ||
|
|
7a4c2af6ec | ||
|
|
fc5cde95d6 | ||
|
|
c4579c8307 | ||
|
|
131ab4cc11 | ||
|
|
7e7a325cd9 | ||
|
|
41d0555d31 | ||
|
|
716f947710 | ||
|
|
ed7ba9bbb6 | ||
|
|
c03db3e0d5 | ||
|
|
aef063d2e2 | ||
|
|
33e5d8541d | ||
|
|
9c34100215 | ||
|
|
a1507ac55b | ||
|
|
484a882015 | ||
|
|
200125cb98 | ||
|
|
5ab8472ffe | ||
|
|
a43cd7f3c5 | ||
|
|
41401b1d01 | ||
|
|
8117693427 | ||
|
|
d80c047580 | ||
|
|
d6ecba605d | ||
|
|
bf58e08e4b | ||
|
|
e965816144 | ||
|
|
59ce9e450c | ||
|
|
980df687e7 | ||
|
|
bea9ac7774 | ||
|
|
063dedbbc1 | ||
|
|
723e2ff76e | ||
|
|
241b22cad7 | ||
|
|
93c59d8026 | ||
|
|
0f9fb5a3b8 | ||
|
|
8c6043b5a7 | ||
|
|
3aa07dc9ce | ||
|
|
3f335b3583 | ||
|
|
4c97097757 | ||
|
|
1ee43e86d6 | ||
|
|
db6ab9c448 | ||
|
|
4646f22b0c | ||
|
|
7eb484d55c | ||
|
|
5164f980b3 | ||
|
|
0457feec95 | ||
|
|
73b8d52c7f | ||
|
|
2b8d2ae4db | ||
|
|
48de8928e4 | ||
|
|
d60715b755 | ||
|
|
a370c1f7d3 | ||
|
|
d83bada4af | ||
|
|
1f7178f175 | ||
|
|
44fdf9ed3b | ||
|
|
1b5fd78bc2 | ||
|
|
d64c42ac31 | ||
|
|
0ec60edf4d | ||
|
|
2c3a9f81de | ||
|
|
00079a71cc | ||
|
|
c04f024b34 | ||
|
|
5dae77b003 | ||
|
|
6b8c28e69c | ||
|
|
3ef9648355 | ||
|
|
0da85355c2 | ||
|
|
dcdbb2d6c7 | ||
|
|
58e3d35e1e | ||
|
|
bd1dc85b92 | ||
|
|
aa78f4c0a2 | ||
|
|
b04044451a | ||
|
|
5d8f141114 | ||
|
|
2bfe62409f | ||
|
|
f5cefa9eea | ||
|
|
abfd2c0105 | ||
|
|
8cb7c273eb | ||
|
|
c440fa76b1 | ||
|
|
4e4859deb6 | ||
|
|
9579c41c6d | ||
|
|
4dd6afd91b | ||
|
|
b092d49bf8 | ||
|
|
7e0cb153b1 | ||
|
|
b1e503853f | ||
|
|
832ad697c7 | ||
|
|
62b454f712 | ||
|
|
ea19d62dab | ||
|
|
9f262097b9 | ||
|
|
e6e8c91ec7 | ||
|
|
688c7471cd | ||
|
|
6c1b12b95f | ||
|
|
0dfb2cedb6 | ||
|
|
2a78cc0116 | ||
|
|
1716782183 | ||
|
|
0cd498beac | ||
|
|
b728d90263 | ||
|
|
3384d2910d | ||
|
|
78c4cdb9e9 | ||
|
|
d20659e073 | ||
|
|
d91f49e728 | ||
|
|
735080fee3 | ||
|
|
86e6e4c0f5 | ||
|
|
46b1d6e8ea | ||
|
|
a7635b6305 | ||
|
|
bffd530bda | ||
|
|
9c79187d37 | ||
|
|
29e6439115 | ||
|
|
a8eeb917e2 | ||
|
|
17b99dfed8 | ||
|
|
9ef419cee1 | ||
|
|
5aad952936 | ||
|
|
c2b0fad298 | ||
|
|
4d4cfedfe0 | ||
|
|
bb12921863 | ||
|
|
223739af25 | ||
|
|
95d977df45 | ||
|
|
0f2692a3f2 | ||
|
|
ebf496bf61 | ||
|
|
0a5170e412 | ||
|
|
11dd82bbb1 | ||
|
|
153bb209d1 | ||
|
|
e27b638d26 | ||
|
|
7d287f10d6 | ||
|
|
9925bc8cfb | ||
|
|
179a93d5e1 | ||
|
|
5203ce348a | ||
|
|
3f47b5ccce | ||
|
|
d22d32677b | ||
|
|
30e319425b | ||
|
|
aebdfaa089 | ||
|
|
de914b1a35 | ||
|
|
4c4fda47e3 | ||
|
|
678084e4fd | ||
|
|
4f8f65d429 | ||
|
|
8a352d288d | ||
|
|
fd0d011cbf | ||
|
|
70219d90bc | ||
|
|
1ff9351f96 | ||
|
|
c256d341c8 | ||
|
|
c9b583945c | ||
|
|
c213204ff4 | ||
|
|
9128c1e7da | ||
|
|
a06650cf09 | ||
|
|
3170779c6b | ||
|
|
5ffa14bec8 | ||
|
|
ee51dc5fc0 | ||
|
|
b38ec17d8f | ||
|
|
8b54ee990e | ||
|
|
7e01781d40 | ||
|
|
2b31473614 | ||
|
|
8bfeae4b35 | ||
|
|
a7761321bc | ||
|
|
979a630f2b | ||
|
|
a4d1fcf086 | ||
|
|
e9e7f5c026 | ||
|
|
9a691cea09 | ||
|
|
44d9b90cdc | ||
|
|
585c3b8348 | ||
|
|
1287493b63 | ||
|
|
bf01a0184b | ||
|
|
fb5f043ba9 | ||
|
|
26f2c92dce | ||
|
|
01e53d4c13 | ||
|
|
18d341f82a | ||
|
|
3ca8c43a54 | ||
|
|
99353467ad | ||
|
|
b093ce93ba | ||
|
|
74a7cbaf94 | ||
|
|
8fb35e3c09 | ||
|
|
5d5cb31638 | ||
|
|
21f1e5f0af | ||
|
|
0fa43701a9 | ||
|
|
4d52eaea12 | ||
|
|
7e1182a83f | ||
|
|
167ded103a | ||
|
|
b8ddf3d927 | ||
|
|
62f4b354a8 | ||
|
|
79d229be50 | ||
|
|
f43157fde5 | ||
|
|
19819b7a5b | ||
|
|
8752f576a7 | ||
|
|
102a441124 | ||
|
|
62f40bd48f | ||
|
|
a7acc9ae45 | ||
|
|
be7f17a3c3 | ||
|
|
5d097b6108 | ||
|
|
ae98930eeb | ||
|
|
6ce0da996d | ||
|
|
b1591f86bb | ||
|
|
f7318f0210 | ||
|
|
1a34501868 | ||
|
|
7dacb23e8b | ||
|
|
7e5c7b5ac3 | ||
|
|
f71e4dedc8 | ||
|
|
419835204e | ||
|
|
86f33de2c0 | ||
|
|
0b6dc24c0d | ||
|
|
18ce1ad790 | ||
|
|
5a074b5bb6 | ||
|
|
26fae13c8e | ||
|
|
53faf55df1 | ||
|
|
b480d397c4 | ||
|
|
dfcb3bec19 | ||
|
|
cf7dc26a0c | ||
|
|
d3b87b26c5 | ||
|
|
b64dd9f723 | ||
|
|
82214fef4c | ||
|
|
e559a43af9 | ||
|
|
c53d7f8448 | ||
|
|
68a46263a4 | ||
|
|
56e7b2c492 | ||
|
|
1282636b0b | ||
|
|
2343274a5b | ||
|
|
f965c05c27 | ||
|
|
f8c8ae7c29 | ||
|
|
3085efd439 | ||
|
|
db8d91a7ff | ||
|
|
2091daaeac | ||
|
|
b1b2f4fa2d | ||
|
|
b146eab8d7 | ||
|
|
667933bd7c | ||
|
|
dbd01b11ca | ||
|
|
47a6fddc89 | ||
|
|
c57e0eed34 | ||
|
|
5adc5e14ed | ||
|
|
cea315a52c | ||
|
|
5b166d6db8 | ||
|
|
edcc43a6ee | ||
|
|
9723854ddc | ||
|
|
7501817b76 | ||
|
|
4affd4aaec | ||
|
|
6b3db72a14 | ||
|
|
58b69f0d6c | ||
|
|
c62102e993 | ||
|
|
2e66e5a555 | ||
|
|
ce525318d8 | ||
|
|
aac2d520a6 | ||
|
|
e761ee02ba | ||
|
|
c53f87b4a9 | ||
|
|
a656f4e57f | ||
|
|
0b50f2cf0b | ||
|
|
3c171cfb8f |
15
.github/workflows/docs.yaml
vendored
15
.github/workflows/docs.yaml
vendored
@@ -1,9 +1,10 @@
|
||||
name: Generate docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
# push:
|
||||
# branches:
|
||||
# - main
|
||||
|
||||
jobs:
|
||||
release:
|
||||
@@ -11,19 +12,19 @@ jobs:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Setup | Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: lib
|
||||
- name: Setup | Checkout wiki
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: SteamDeckHomebrew/wiki
|
||||
path: wiki
|
||||
ssh-key: ${{ secrets.SSH_DEPLOY_KEY }}
|
||||
persist-credentials: true
|
||||
- name: Setup | Node.js
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Setup | Dependencies
|
||||
@@ -51,4 +52,4 @@ jobs:
|
||||
ssh: true
|
||||
directory: ./wiki
|
||||
repository: SteamDeckHomebrew/wiki
|
||||
branch: main
|
||||
branch: main
|
||||
|
||||
11
.github/workflows/release.yaml
vendored
11
.github/workflows/release.yaml
vendored
@@ -6,19 +6,23 @@ on:
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Setup | Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup | Node.js
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 24
|
||||
- name: Setup | Dependencies
|
||||
run: npm i -g pnpm && pnpm i --frozen-lockfile
|
||||
- name: Build
|
||||
@@ -29,5 +33,4 @@ jobs:
|
||||
if: github.event_name != 'pull_request'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
run: pnpm exec semantic-release
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx --no -- commitlint --edit "${1}"
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
{
|
||||
"branches": ["main", "dev"],
|
||||
"branches": ["main", "v4-dev"],
|
||||
"plugins": [
|
||||
[
|
||||
"@semantic-release/commit-analyzer",
|
||||
{
|
||||
"preset": "angular",
|
||||
"releaseRules": [
|
||||
{"type": "chore", "scope": "classes", "release": "patch"},
|
||||
{"type": "*", "scope": "docs", "release": false}
|
||||
{ "type": "chore", "scope": "classes", "release": "patch" },
|
||||
{ "type": "docs", "scope": "steamclient", "release": "patch" },
|
||||
{ "type": "*", "scope": "docs", "release": false }
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
26
.vscode/tasks.json
vendored
26
.vscode/tasks.json
vendored
@@ -1,15 +1,13 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "dev",
|
||||
"problemMatcher": [
|
||||
"$tsc-watch"
|
||||
],
|
||||
"label": "npm: dev",
|
||||
"detail": "tsc -b -w",
|
||||
"isBackground": true
|
||||
}
|
||||
]
|
||||
}
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "dev",
|
||||
"problemMatcher": ["$tsc-watch"],
|
||||
"label": "npm: dev",
|
||||
"detail": "tsc -b -w",
|
||||
"isBackground": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
605
CHANGELOG.md
605
CHANGELOG.md
@@ -1,3 +1,608 @@
|
||||
## [4.11.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.11.3...v4.11.4) (2026-05-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **dropdown:** hack to fix styling in dropdownitem ([e44664c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e44664c9704b3b284284619bc26cf6a910890136))
|
||||
* **Field:** fix filter for field on beta ([ac8da8e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/ac8da8e9b650cfcabcd3e5752e1475e91e7edf7a))
|
||||
|
||||
## [4.11.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.11.2...v4.11.3) (2026-03-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Tabs:** update for latest beta ([#129](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/129)) ([3126dd3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/3126dd3e040eaef00eb0362b69efb143d7e01030))
|
||||
|
||||
## [4.11.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.11.1...v4.11.2) (2026-03-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ci:** microsoft ([aabc522](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/aabc5227400f1660ddcb7917fa8f305ad2fce3d7))
|
||||
* **ci:** microsoft stinks ([66e0afc](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/66e0afccae6803ee57d817621340d09a12ba75d8))
|
||||
* **ci:** update semantic release ([772a855](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/772a85523b8c4bbf80ccd4827a89801e3a51cfd6))
|
||||
* **ci:** use new npm publishing auth ([77e6acd](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/77e6acd828b1d0f0978356292b1c46bfc3b8e422))
|
||||
* **components:** update for latest beta ([261162c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/261162c8bceecc50afad07d57a78b85b98936fe1))
|
||||
|
||||
## [4.11.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.11.0...v4.11.1) (2025-11-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **webpack:** ignore window module (lol), ignore filter errors ([7242c69](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/7242c697580f3a6a6d373eaacc4fb83ccff9bd2a))
|
||||
|
||||
# [4.11.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.10.6...v4.11.0) (2025-10-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* react 19 support update ([6e443c0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/6e443c06d3b7f2790da8b44a5c907517fcf12152))
|
||||
|
||||
## [4.10.6](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.10.5...v4.10.6) (2025-09-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ci:** update to resolve deprecation in sem. rel. due to octokit ([779b1ae](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/779b1ae0defac84dd0d93517858d5aa5e51a2328))
|
||||
|
||||
## [4.10.5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.10.4...v4.10.5) (2025-08-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **DialogHeader:** valve rewrote component on beta, update filter to search for both versions ([37dd885](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/37dd88513ed7360d3bcdc99630d6cb0c8d31db3e))
|
||||
|
||||
## [4.10.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.10.3...v4.10.4) (2025-07-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modals:** fix ModalRoot on beta ([3d5de65](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/3d5de65077098ff3fb5192cb55fb1534336411f5))
|
||||
|
||||
## [4.10.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.10.2...v4.10.3) (2025-07-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modals:** fix `<ConfirmModal />` for new Steam beta ([#123](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/123)) ([aa0678c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/aa0678c857e07f58de58e5d20565bf2718fff6dc))
|
||||
|
||||
## [4.10.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.10.1...v4.10.2) (2025-06-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SteamClient:** export shared types for enums ([a4627a7](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/a4627a70c5a60a42cd39690b3b03f2c1d79ee3b4))
|
||||
|
||||
## [4.10.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.10.0...v4.10.1) (2025-06-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix <Menu /> for new Steam Client Beta ([fc5cde9](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/fc5cde95d6475c82856769c86ab648dfb22a4b10))
|
||||
|
||||
# [4.10.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.9.2...v4.10.0) (2025-04-23)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **globals:** Steam client reference ([#92](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/92)) ([131ab4c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/131ab4cc1190e2bd0cf561fe6dd70049a7921fc5))
|
||||
|
||||
## [4.9.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.9.1...v4.9.2) (2025-03-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SidebarNavigation:** change title to ReactNode type ([#117](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/117)) ([41d0555](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/41d0555d314f9f68d3cdcc45f454f13b952b4581))
|
||||
|
||||
## [4.9.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.9.0...v4.9.1) (2025-01-29)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Menu:** add missing arg to showContextMenu and document it ([c03db3e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/c03db3e0d55f2ba14a8d82ba1380e9838769efe1))
|
||||
|
||||
# [4.9.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.8.3...v4.9.0) (2025-01-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add MenuSeparator component ([484a882](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/484a882015ceb51c2c80e08151e79056e751ac15))
|
||||
|
||||
## [4.8.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.8.2...v4.8.3) (2024-12-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **utils:** add new nav root name ([a43cd7f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/a43cd7f3c56a2e30e332417e5b4abde8f4492be1))
|
||||
|
||||
## [4.8.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.8.1...v4.8.2) (2024-11-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Footer:** add missing focus/nav properties ([#113](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/113)) ([8117693](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/8117693427e4dba2f3b5bd24f36704d8d5e65ae2))
|
||||
|
||||
## [4.8.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.8.0...v4.8.1) (2024-10-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **DialogCheckbox:** prevent some potential issues in dialogcheckbox ([bf58e08](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/bf58e08e4b5b183737c9ad43a858b642ce593f93))
|
||||
* prevent issues where toString may not be a function (what) ([e965816](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e96581614471524cbf91bf962742df867ba3c3e9))
|
||||
|
||||
# [4.8.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.7.4...v4.8.0) (2024-10-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **components/Modal:** dont break in desktop ui ([bea9ac7](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/bea9ac777452b883c2f3f3ebf8510c22c4577cd0))
|
||||
* **components/Router:** dont break in desktop ui ([980df68](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/980df687e7b7bf389f478e831f992fb9475eeb15))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **utils/react:** add some window-related utils ([063dedb](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/063dedbbc1573a825571c675bf6bfa8a1bc1c6cd))
|
||||
|
||||
## [4.7.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.7.3...v4.7.4) (2024-10-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **DialogCheckbox:** don't access getters to prevent their side effects from breaking the component ([241b22c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/241b22cad711621a1695dfd11da857f13c3fffdf))
|
||||
|
||||
## [4.7.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.7.2...v4.7.3) (2024-10-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **components:** fix missing components on oct 2 2024 beta ([0f9fb5a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0f9fb5a3b8ef4f9978025a28323ab080fb0e7a4c))
|
||||
|
||||
## [4.7.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.7.1...v4.7.2) (2024-09-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **utils:** fix potential race condition in findSP ([3aa07dc](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/3aa07dc9ce798ff8d1148424ee9e8a8bf2ba78c6))
|
||||
|
||||
## [4.7.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.7.0...v4.7.1) (2024-08-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **utils/react:** fix potential race condition in injectFCTrampoline ([4c97097](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/4c97097757919580a380b70785e6c161de6b03cc))
|
||||
|
||||
# [4.7.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.6.0...v4.7.0) (2024-07-28)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **router:** support desktop bpm overlay ([7eb484d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/7eb484d55c6be6e7844878eb47eda55591a6cf51))
|
||||
|
||||
# [4.6.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.5.0...v4.6.0) (2024-07-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **classMapper:** add findClassByName back ([2b8d2ae](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/2b8d2ae4dbd9a0c4a59a43be0101a0a8fe1c518f))
|
||||
|
||||
# [4.5.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.4.0...v4.5.0) (2024-07-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **classMapper:** add classModuleMap, make findClass require ID ([a370c1f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/a370c1f7d3dca0db56a346c98c28ed9681a415e0))
|
||||
* **webpack:** refactor to prepare for classMapper changes ([d83bada](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/d83bada4af2d16c750955de9a52f94a0080a2c14))
|
||||
|
||||
# [4.4.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.3.1...v4.4.0) (2024-07-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **utils/react:** add injectFCTrampoline ([44fdf9e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/44fdf9ed3b9a676a88b0ddc6a1c2c89d46ff7651))
|
||||
|
||||
## [4.3.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.3.0...v4.3.1) (2024-07-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Menu/MenuGroup:** rewrite filter to work on beta and prevent future errors ([d64c42a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/d64c42ac310d3c3266c4ff610d9ec5ab6c7707b6))
|
||||
|
||||
# [4.3.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.2.2...v4.3.0) (2024-07-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **utils:** react tree patching api ([2c3a9f8](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/2c3a9f81de0b63364bb31f4a4dd8e559784ece16))
|
||||
|
||||
## [4.2.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.2.1...v4.2.2) (2024-07-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **SteamSpinner:** add background option ([c04f024](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/c04f024b34b1148c965850965127f9fd44204157))
|
||||
|
||||
## [4.2.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.2.0...v4.2.1) (2024-06-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **errorboundary:** work around broken react types ([3ef9648](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/3ef96483550020cecf656b94a73d2bb9313bda07))
|
||||
|
||||
# [4.2.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.1.1...v4.2.0) (2024-06-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **components:** add ErrorBoundary ([dcdbb2d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/dcdbb2d6c7c0b72197f04153d7c3e73e9e71ea5c))
|
||||
|
||||
## [4.1.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.1.0...v4.1.1) (2024-06-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ReorderableList:** avoid mutating props ([#109](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/109)) ([bd1dc85](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/bd1dc85b9202c8ec6ca994177417574fdd71cbd7))
|
||||
|
||||
# [4.1.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.0.1...v4.1.0) (2024-06-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **release:** release v4.1.0 ([b040444](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/b04044451a9dc3633fe624e47dd58c7ea206d0a3))
|
||||
|
||||
## [4.0.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v4.0.0...v4.0.1) (2024-06-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **release:** empty commit to bump to v4.0.1 ([2bfe624](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/2bfe62409f775a69124e0f2e853ae0b1668a9c36))
|
||||
|
||||
# [4.0.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.25.0...v4.0.0) (2024-06-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ci:** empty commit so semantic-release shuts up ([8cb7c27](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/8cb7c273eb61c1f949844291b2864c11bf746058))
|
||||
* **ci:** temp remove npm publisher ([abfd2c0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/abfd2c010508ddf6e18149374dc52b50402ffb4c))
|
||||
* **components:** fix missing children prop ([688c747](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/688c7471cde96bf9e9a71c47d19bd63cff7a66b3))
|
||||
* **components:** forgot one ([e6e8c91](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e6e8c91ec7ea711f6c147f28e300f745dcbd24f4))
|
||||
* **Field:** add children prop ([2a78cc0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/2a78cc011671ab123fb6356f54102e531a7953a8))
|
||||
* fixes for jun 26 beta ([7e0cb15](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/7e0cb153b197267f49b5e1f513b54a880bf3710f))
|
||||
* **Menu:** work around ConfigContext error ([9f26209](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/9f262097b9808a0366bb52cd24844371bbe65316))
|
||||
* **package:** fix ts memes ([ea19d62](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/ea19d62dabfbecad97c1ab9384c676f8a018f96b))
|
||||
* **package:** pin react properly ([62b454f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/62b454f71255d5e1898677909a63612615e09083))
|
||||
* **package:** unbreak react ([b1e5038](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/b1e503853ff6d39f1e86a6180f355e73b9fd6925))
|
||||
* **plugin:** shim definePlugin for now [ci skip] ([0cd498b](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0cd498beacbd23efa3b771880ff0a4df3f636836))
|
||||
* **utils/react:** shut it ts ([d91f49e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/d91f49e728b613e24b40d7e81d47fd1f3bd92372))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add v4 webpack api and port everything to it ([bffd530](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/bffd530bda9a49aae603c323c0a2b4328eee968d))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **ci:** v4 release
|
||||
* **ci:** v4 release
|
||||
|
||||
## [3.26.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.26.0...v3.26.1) (2024-05-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Field:** add children prop ([2a78cc0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/2a78cc011671ab123fb6356f54102e531a7953a8))
|
||||
* **plugin:** shim definePlugin for now [ci skip] ([0cd498b](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0cd498beacbd23efa3b771880ff0a4df3f636836))
|
||||
|
||||
# [3.26.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.25.0...v3.26.0) (2024-05-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **utils/react:** shut it ts ([d91f49e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/d91f49e728b613e24b40d7e81d47fd1f3bd92372))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add v4 webpack api and port everything to it ([bffd530](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/bffd530bda9a49aae603c323c0a2b4328eee968d))
|
||||
|
||||
# [3.25.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.24.5...v3.25.0) (2024-03-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **staticclasses:** unbreak on latest beta ([17b99df](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/17b99dfed8e4e146d0f4f5e78a950db5b10ae2b4))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **classMapper:** add class mapper ([a8eeb91](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/a8eeb917e22ef72905d448e159d70375ebf77ba6))
|
||||
|
||||
## [3.24.5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.24.4...v3.24.5) (2024-02-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **finds:** make modal and scroll components work on latest betaa ([c2b0fad](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/c2b0fad298512aa8778c677275bd497bd8f7b00e))
|
||||
|
||||
## [3.24.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.24.3...v3.24.4) (2024-01-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **types:** fix incorrect `as` on many components leading to any types ([bb12921](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/bb129218634b77ddb1d73b0fe38a91898073707c))
|
||||
|
||||
## [3.24.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.24.2...v3.24.3) (2024-01-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **router:** wait 2s if internal navigators init fails ([95d977d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/95d977df452d3b73b007c98854deab1842fa6fbf))
|
||||
|
||||
## [3.24.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.24.1...v3.24.2) (2024-01-20)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **navigation:** Fix on chromium 109 ([#100](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/100)) ([ebf496b](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/ebf496bf61cffa1a5205b4a094fd2279011bffa9))
|
||||
|
||||
## [3.24.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.24.0...v3.24.1) (2023-12-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **utils/react:** support react 18, add getReactRoot ([11dd82b](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/11dd82bbb1814ac4d2fa9d381372e325daba2558))
|
||||
|
||||
# [3.24.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.23.1...v3.24.0) (2023-12-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **static-classes:** add BasicAppDetailsSectionStylerClasses ([#99](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/99)) ([e27b638](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e27b638d26e41332b1554dbd55ca0c55a1821138))
|
||||
|
||||
## [3.23.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.23.0...v3.23.1) (2023-11-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **webpack:** don't break if a module fails to load ([5203ce3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/5203ce348afd727da0c8c52f6d8f8a16712f88d2))
|
||||
|
||||
# [3.23.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.22.1...v3.23.0) (2023-10-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **static-classes:** add more css classes ([#94](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/94)) ([30e3194](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/30e319425bd4b0ee481dd7bd3245dacd90806afb))
|
||||
|
||||
## [3.22.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.22.0...v3.22.1) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **useQuickAccessVisible:** use the "Page Visibility API" instead of focus/blur ([4c4fda4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/4c4fda47e3d9fd936b493c5965634a0ff443014f))
|
||||
|
||||
# [3.22.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.21.8...v3.22.0) (2023-08-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add patch indicator to prevent crashes ([3170779](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/3170779c6b3d02ea17f7b6c1fbd57e00498ffe4f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add components found while working on tabmaster ([4f8f65d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/4f8f65d42979149cc80b4a86545d3d0d9bf14bf3))
|
||||
* add components found while working on tabmaster ([fd0d011](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/fd0d011cbf05790c5a1078970b5be72f9267402c))
|
||||
|
||||
## [3.21.8](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.21.7...v3.21.8) (2023-06-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* the typescript compiler was eating the enum ([c9b5839](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/c9b583945c1cb5267b41a821743590a841572abe))
|
||||
|
||||
## [3.21.7](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.21.6...v3.21.7) (2023-06-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add patch indicator to prevent crashes ([#88](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/88)) ([9128c1e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/9128c1e7dadb98a8926d3dba9907a01cc78d90cf))
|
||||
|
||||
## [3.21.6](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.21.5...v3.21.6) (2023-06-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* reposition parameter for file picker V2 ([ee51dc5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/ee51dc5fc0dd5bdc2b0b9e10aa27607fbe51f491))
|
||||
|
||||
## [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)
|
||||
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
Library used to develop plugins used for use with [decky-loader](https://github.com/SteamDeckHomebrew/decky-loader).
|
||||
|
||||
## Decky Loader Discord [](https://discord.gg/ZU74G2NJzk)
|
||||
## Decky Loader Discord [](https://deckbrew.xyz/discord)
|
||||
|
||||
Please contact the developers here for questions and support that cannot be addressed via a Github issue.
|
||||
Please [contact the developers here](https://deckbrew.xyz/discord) for questions and support that cannot be addressed via a Github issue.
|
||||
|
||||
## Developers and Contributors
|
||||
|
||||
@@ -20,8 +20,11 @@ This library can also theoretically be used to extend existing UI elements of th
|
||||
|
||||
### Getting Started (Developers)
|
||||
|
||||
If you would like a feature added to decky-frontend-lib, please request it via a Github issue.
|
||||
If you would like a feature added to decky-frontend-lib, please request it via a Github issue.
|
||||
|
||||
If you want to start making a plugin with decky-frontend-lib, please direct your attention to the [decky-plugin-template](https://github.com/SteamDeckHomebrew/decky-plugin-template) repository.
|
||||
|
||||
This library can be found on [npm](https://www.npmjs.com/package/decky-frontend-lib) and as such you can pull it without a local copy for your project as needed.
|
||||
|
||||
Tips for fixing failing module finds after Steam updates:
|
||||
- `Object.entries(DFL)` can point out any undefined exports
|
||||
@@ -1,3 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript',],
|
||||
presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'],
|
||||
};
|
||||
|
||||
10
global.d.ts
vendored
Normal file
10
global.d.ts
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
import type * as React from 'react';
|
||||
import type * as ReactDOM from 'react-dom';
|
||||
import type * as JSXRuntime from 'react/jsx-runtime';
|
||||
declare global {
|
||||
interface Window {
|
||||
SP_REACT: typeof React;
|
||||
SP_REACTDOM: typeof ReactDOM;
|
||||
SP_JSX: typeof JSXRuntime;
|
||||
}
|
||||
}
|
||||
5
globals.d.ts
vendored
5
globals.d.ts
vendored
@@ -1,5 +0,0 @@
|
||||
declare global {
|
||||
interface Window {
|
||||
SP_REACT: typeof React;
|
||||
}
|
||||
}
|
||||
59
package.json
59
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "decky-frontend-lib",
|
||||
"version": "3.18.4",
|
||||
"description": "A library for building decky plugins",
|
||||
"name": "@decky/ui",
|
||||
"version": "4.11.4",
|
||||
"description": "A library for interacting with the Steam frontend in Decky plugins and elsewhere.",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"module": "dist/index.js",
|
||||
@@ -9,7 +9,7 @@
|
||||
"scripts": {
|
||||
"build": "shx rm -rf dist && tsc -b",
|
||||
"dev": "tsc -b -w",
|
||||
"docs": "typedoc --tsconfig ./tsconfig.json src/**/*",
|
||||
"docs": "typedoc --theme wiki-js --tsconfig ./tsconfig.json src/**/*",
|
||||
"test": "echo 'No tests for now!'",
|
||||
"prepare": "husky install",
|
||||
"commit": "git-cz"
|
||||
@@ -29,7 +29,7 @@
|
||||
"steam",
|
||||
"components"
|
||||
],
|
||||
"author": "Jonas Dellinger <jonas@dellinger.dev>",
|
||||
"author": "SteamDeckHomebrew Team",
|
||||
"license": "LGPL-2.1",
|
||||
"bugs": {
|
||||
"url": "https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues"
|
||||
@@ -41,29 +41,30 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.0.2",
|
||||
"@commitlint/config-conventional": "^17.0.2",
|
||||
"@commitlint/cz-commitlint": "^17.0.0",
|
||||
"@semantic-release/changelog": "^6.0.1",
|
||||
"@commitlint/cli": "^19.8.1",
|
||||
"@commitlint/config-conventional": "^19.8.1",
|
||||
"@commitlint/cz-commitlint": "^19.8.1",
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/react": "16.14.0",
|
||||
"@types/react-router": "5.1.18",
|
||||
"commitizen": "^4.2.4",
|
||||
"husky": "^8.0.1",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/react": "19.1.1",
|
||||
"@types/react-dom": "19.1.1",
|
||||
"@types/react-router": "5.1.20",
|
||||
"commitizen": "^4.3.1",
|
||||
"husky": "^9.1.7",
|
||||
"import-sort-style-module": "^6.0.0",
|
||||
"jest": "^27.5.1",
|
||||
"minimist": "^1.2.6",
|
||||
"prettier": "^2.7.1",
|
||||
"jest": "^29.7.0",
|
||||
"minimist": "^1.2.8",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-import-sort": "^0.0.7",
|
||||
"semantic-release": "^19.0.3",
|
||||
"semantic-release": "^25.0.3",
|
||||
"shx": "^0.3.4",
|
||||
"ts-jest": "^27.1.4",
|
||||
"typedoc": "^0.23.15",
|
||||
"typedoc-plugin-markdown": "^3.13.6",
|
||||
"typedoc-plugin-mdn-links": "^2.0.0",
|
||||
"typedoc-plugin-missing-exports": "^1.0.0",
|
||||
"typescript": "^4.6.3"
|
||||
"ts-jest": "^29.4.1",
|
||||
"typedoc": "^0.25.13",
|
||||
"typedoc-plugin-mdn-links": "^3.3.8",
|
||||
"typedoc-plugin-missing-exports": "^2.3.0",
|
||||
"typedoc-wikijs-theme": "^1.0.5",
|
||||
"typescript": "^5.9.2"
|
||||
},
|
||||
"pnpm": {
|
||||
"peerDependencyRules": {
|
||||
@@ -71,6 +72,12 @@
|
||||
"react",
|
||||
"react-dom"
|
||||
]
|
||||
},
|
||||
"updateConfig": {
|
||||
"ignoreDependencies": [
|
||||
"react",
|
||||
"react-dom"
|
||||
]
|
||||
}
|
||||
},
|
||||
"importSort": {
|
||||
@@ -78,5 +85,9 @@
|
||||
"style": "module",
|
||||
"parser": "typescript"
|
||||
}
|
||||
},
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/",
|
||||
"tag": "latest"
|
||||
}
|
||||
}
|
||||
|
||||
9071
pnpm-lock.yaml
generated
Executable file → Normal file
9071
pnpm-lock.yaml
generated
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
40
src/class-mapper.ts
Normal file
40
src/class-mapper.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Module, ModuleID, createModuleMapping } from './webpack';
|
||||
|
||||
export interface ClassModule {
|
||||
[name: string]: string;
|
||||
}
|
||||
|
||||
export const classModuleMap: Map<ModuleID, ClassModule> = createModuleMapping((m: Module) => {
|
||||
if (typeof m == 'object' && !m.__esModule) {
|
||||
const keys = Object.keys(m);
|
||||
// special case some libraries
|
||||
if (keys.length == 1 && m.version) return false;
|
||||
// special case localization
|
||||
if (keys.length > 1000 && m.AboutSettings) return false;
|
||||
|
||||
return keys.length > 0 && keys.every((k) => !Object.getOwnPropertyDescriptor(m, k)?.get && typeof m[k] == 'string');
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
export const classMap = [...classModuleMap.values()];
|
||||
|
||||
export function findClass(id: string, name: string): string | void {
|
||||
return classModuleMap.get(id)?.[name];
|
||||
}
|
||||
|
||||
export function findClassByName(name: string): string | void {
|
||||
return classMap.find((m) => m[name])?.[name];
|
||||
}
|
||||
|
||||
export function findClassModule(filter: (module: any) => boolean): ClassModule | void {
|
||||
return classMap.find((m) => filter(m));
|
||||
}
|
||||
|
||||
export function unminifyClass(minifiedClass: string): string | void {
|
||||
for (let m of classModuleMap.values()) {
|
||||
for (let className of Object.keys(m)) {
|
||||
if (m[className] == minifiedClass) return className;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,15 @@ import { FC } from 'react';
|
||||
|
||||
import { CommonUIModule } from '../webpack';
|
||||
import { ItemProps } from './Item';
|
||||
import { createPropListRegex } from '../utils';
|
||||
|
||||
export interface ButtonItemProps extends ItemProps {
|
||||
onClick?(e: MouseEvent): void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const buttonItemRegex = createPropListRegex(["highlightOnFocus", "childrenContainerWidth"], false);
|
||||
export const ButtonItem = Object.values(CommonUIModule).find(
|
||||
(mod: any) =>
|
||||
mod?.render?.toString()?.includes('"highlightOnFocus","childrenContainerWidth"') ||
|
||||
mod?.render?.toString()?.includes('childrenContainerWidth:"min"'),
|
||||
(mod?.render?.toString && buttonItemRegex.test(mod.render.toString())) ||
|
||||
mod?.render?.toString?.().includes('childrenContainerWidth:"min"'),
|
||||
) as FC<ButtonItemProps>;
|
||||
@@ -1,6 +1,6 @@
|
||||
import { HTMLAttributes, ReactNode, RefAttributes, VFC } from 'react';
|
||||
import { HTMLAttributes, ReactNode, RefAttributes, FC } from 'react';
|
||||
|
||||
import { findModuleChild } from '../webpack';
|
||||
import { Export, findModuleExport } from '../webpack';
|
||||
|
||||
export interface CarouselProps extends HTMLAttributes<HTMLDivElement> {
|
||||
autoFocus?: boolean;
|
||||
@@ -20,9 +20,6 @@ export interface CarouselProps extends HTMLAttributes<HTMLDivElement> {
|
||||
scrollToAlignment?: 'center';
|
||||
}
|
||||
|
||||
export const Carousel = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.render?.toString().includes('setFocusedColumn:')) return m[prop];
|
||||
}
|
||||
}) as VFC<CarouselProps & RefAttributes<HTMLDivElement>>;
|
||||
export const Carousel = findModuleExport((e: Export) => e.render?.toString().includes('setFocusedColumn:')) as FC<
|
||||
CarouselProps & RefAttributes<HTMLDivElement>
|
||||
>;
|
||||
14
src/components/ControlsList.ts
Normal file
14
src/components/ControlsList.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { FC, ReactNode } from 'react';
|
||||
|
||||
import { Export, findModuleExport } from '../webpack';
|
||||
|
||||
export interface ControlsListProps {
|
||||
alignItems?: 'left' | 'right' | 'center';
|
||||
spacing?: 'standard' | 'extra';
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export const ControlsList: FC<ControlsListProps> = findModuleExport(
|
||||
(e: Export) =>
|
||||
e?.toString && e.toString().includes('().ControlsListChild') && e.toString().includes('().ControlsListOuterPanel'),
|
||||
);
|
||||
@@ -1,17 +1,18 @@
|
||||
import { CSSProperties, FC, RefAttributes } from 'react';
|
||||
import { CSSProperties, FC, ReactNode, RefAttributes } from 'react';
|
||||
|
||||
import { CommonUIModule } from '../webpack';
|
||||
import { CommonUIModule, Module } from '../webpack';
|
||||
import { FooterLegendProps } from './FooterLegend';
|
||||
|
||||
export interface DialogCommonProps extends RefAttributes<HTMLDivElement> {
|
||||
style?: CSSProperties;
|
||||
className?: string;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
@@ -19,25 +20,25 @@ export interface DialogButtonProps extends DialogCommonProps, FooterLegendProps
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* 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;
|
||||
@@ -51,17 +52,37 @@ export interface DialogButtonProps extends DialogCommonProps, FooterLegendProps
|
||||
}
|
||||
|
||||
const CommonDialogDivs = Object.values(CommonUIModule).filter(
|
||||
(m: any) => typeof m === 'object' && m?.render?.toString().includes('"div",Object.assign({},'),
|
||||
(m: any) => typeof m === 'object' &&
|
||||
// New
|
||||
(
|
||||
m?.render?.toString().includes('jsx)("div",{...') ||
|
||||
m?.render?.toString().includes('jsx)("div",Object.assign({},')
|
||||
) ||
|
||||
// Old
|
||||
(
|
||||
m?.render?.toString().includes('createElement("div",{...') ||
|
||||
m?.render?.toString().includes('createElement("div",Object.assign({},')
|
||||
)
|
||||
);
|
||||
const MappedDialogDivs = new Map(
|
||||
Object.values(CommonDialogDivs).map((m: any) => {
|
||||
const renderedDiv = m.render({});
|
||||
// Take only the first class name segment as it identifies the element we want
|
||||
return [renderedDiv.props.className.split(' ')[0], m];
|
||||
try {
|
||||
const renderedDiv = m.render({});
|
||||
// Take only the first class name segment as it identifies the element we want
|
||||
return [renderedDiv.props.className.split(' ')[0], m];
|
||||
} catch (e) {
|
||||
console.error("[DFL:Dialog]: failed to render common dialog component", e);
|
||||
return [null, null];
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
export const DialogHeader = MappedDialogDivs.get('DialogHeader') as FC<DialogCommonProps>;
|
||||
// Old | New
|
||||
export const DialogHeader = (MappedDialogDivs.get('DialogHeader') || Object.values(CommonUIModule).find((component: Module) => {
|
||||
const str = component?.render?.toString?.();
|
||||
return str?.includes("role:\"heading\"") && str.includes(")(\"DialogHeader\",");
|
||||
})) as FC<DialogCommonProps>;
|
||||
|
||||
export const DialogSubHeader = MappedDialogDivs.get('DialogSubHeader') as FC<DialogCommonProps>;
|
||||
export const DialogFooter = MappedDialogDivs.get('DialogFooter') as FC<DialogCommonProps>;
|
||||
export const DialogLabel = MappedDialogDivs.get('DialogLabel') as FC<DialogCommonProps>;
|
||||
@@ -71,14 +92,11 @@ export const DialogControlsSection = MappedDialogDivs.get('DialogControlsSection
|
||||
export const DialogControlsSectionHeader = MappedDialogDivs.get('DialogControlsSectionHeader') as FC<DialogCommonProps>;
|
||||
|
||||
export const DialogButtonPrimary = Object.values(CommonUIModule).find(
|
||||
(mod: any) => mod?.render?.toString()?.includes('DialogButton') && mod?.render?.toString()?.includes('Primary'),
|
||||
(mod: any) => mod?.render?.toString?.()?.includes('"DialogButton","_DialogLayout","Primary"'),
|
||||
) as FC<DialogButtonProps>;
|
||||
|
||||
export const DialogButtonSecondary = Object.values(CommonUIModule).find(
|
||||
(mod: any) =>
|
||||
mod?.render?.toString()?.includes('Object.assign({type:"button"') &&
|
||||
mod?.render?.toString()?.includes('DialogButton') &&
|
||||
mod?.render?.toString()?.includes('Secondary'),
|
||||
(mod: any) => mod?.render?.toString?.()?.includes('"DialogButton","_DialogLayout","Secondary"')
|
||||
) as FC<DialogButtonProps>;
|
||||
|
||||
// This is the "main" button. The Primary can act as a submit button,
|
||||
33
src/components/DialogCheckbox.ts
Normal file
33
src/components/DialogCheckbox.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { FC, ReactNode } from 'react';
|
||||
|
||||
import { findModuleExport } from '../webpack';
|
||||
import { DialogCommonProps } from './Dialog';
|
||||
import { FooterLegendProps } from './FooterLegend';
|
||||
|
||||
export interface DialogCheckboxProps extends DialogCommonProps, FooterLegendProps {
|
||||
onChange?(checked: boolean): void;
|
||||
label?: ReactNode;
|
||||
description?: ReactNode;
|
||||
disabled?: boolean;
|
||||
tooltip?: string;
|
||||
color?: string;
|
||||
highlightColor?: string;
|
||||
bottomSeparator?: 'standard' | 'thick' | 'none';
|
||||
controlled?: boolean;
|
||||
checked?: boolean;
|
||||
onClick?(evt: Event): void;
|
||||
}
|
||||
|
||||
// Do not access KeyDown, SetChecked, Toggle here as they are getters and accessing them outside of a render breaks them globally
|
||||
export const DialogCheckbox = findModuleExport(e =>
|
||||
e?.prototype &&
|
||||
typeof e?.prototype == "object" &&
|
||||
"GetPanelElementProps" in e?.prototype &&
|
||||
"SetChecked" in e?.prototype &&
|
||||
"Toggle" in e?.prototype &&
|
||||
// beta || stable as of oct 2 2024
|
||||
(e?.prototype?.render?.toString?.().includes('="DialogCheckbox"') || (
|
||||
e.contextType &&
|
||||
e.prototype?.render?.toString?.().includes('fallback:')
|
||||
))
|
||||
) as FC<DialogCheckboxProps>;
|
||||
@@ -1,7 +1,9 @@
|
||||
import { ReactNode, VFC } from 'react';
|
||||
import { ReactNode, FC } from 'react';
|
||||
|
||||
import { CommonUIModule } from '../webpack';
|
||||
import { ItemProps } from './Item';
|
||||
import { createPropListRegex } from '../utils';
|
||||
import type { ContextMenuPositionOptions } from './Menu';
|
||||
|
||||
export interface SingleDropdownOption {
|
||||
data: any;
|
||||
@@ -26,7 +28,7 @@ export interface DropdownProps {
|
||||
onMenuWillOpen?(showMenu: () => void): void;
|
||||
onMenuOpened?(): void;
|
||||
onChange?(data: SingleDropdownOption): void;
|
||||
contextMenuPositionOptions?: any;
|
||||
contextMenuPositionOptions?: ContextMenuPositionOptions;
|
||||
menuLabel?: string;
|
||||
strDefaultLabel?: string;
|
||||
renderButtonValue?(element: ReactNode): ReactNode;
|
||||
@@ -35,10 +37,13 @@ export interface DropdownProps {
|
||||
|
||||
export const Dropdown = Object.values(CommonUIModule).find(
|
||||
(mod: any) => mod?.prototype?.SetSelectedOption && mod?.prototype?.BuildMenu,
|
||||
) as VFC<DropdownProps>;
|
||||
) as FC<DropdownProps>;
|
||||
|
||||
export interface DropdownItemProps extends DropdownProps, ItemProps {}
|
||||
|
||||
export const DropdownItem = Object.values(CommonUIModule).find((mod: any) =>
|
||||
mod?.toString()?.includes('"dropDownControlRef","description"'),
|
||||
) as VFC<DropdownItemProps>;
|
||||
const dropdownItemRegex = createPropListRegex(["dropDownControlRef", "description"], false);
|
||||
export const DropdownItemInternal = Object.values(CommonUIModule).find((mod: any) =>
|
||||
mod?.toString && dropdownItemRegex.test(mod.toString()),
|
||||
) as FC<DropdownItemProps>;
|
||||
|
||||
export const DropdownItem = ((args: DropdownItemProps) => <DropdownItemInternal childrenContainerWidth="min" {...args}/>) as FC<DropdownItemProps>;
|
||||
6
src/components/ErrorBoundary.ts
Normal file
6
src/components/ErrorBoundary.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { FC, PropsWithChildren } from "react";
|
||||
import { findModuleExport } from "../webpack";
|
||||
|
||||
export const ErrorBoundary = findModuleExport(
|
||||
(e) => e.InstallErrorReportingStore && e?.prototype?.Reset && e?.prototype?.componentDidCatch,
|
||||
) as FC<PropsWithChildren>; // Actually a class but @types/react is broken lol
|
||||
@@ -1,9 +1,10 @@
|
||||
import { FC, ReactNode, RefAttributes } from 'react';
|
||||
|
||||
import { findModuleChild } from '../webpack';
|
||||
import { Export, findModuleExport } from '../webpack';
|
||||
import { FooterLegendProps } from './FooterLegend';
|
||||
|
||||
export interface FieldProps extends FooterLegendProps {
|
||||
children?: ReactNode;
|
||||
label?: ReactNode;
|
||||
bottomSeparator?: 'standard' | 'thick' | 'none';
|
||||
description?: ReactNode;
|
||||
@@ -23,9 +24,7 @@ export interface FieldProps extends FooterLegendProps {
|
||||
onClick?: (e: CustomEvent | MouseEvent) => void;
|
||||
}
|
||||
|
||||
export const Field = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.render?.toString().includes('"shift-children-below"')) return m[prop];
|
||||
}
|
||||
}) as FC<FieldProps & RefAttributes<HTMLDivElement>>;
|
||||
// new || old
|
||||
export const Field = findModuleExport((e: Export) => (e?.toString()?.includes('().Field') && e?.toString()?.includes('"shift-children-below"')) || e?.render?.toString()?.includes('"shift-children-below"')) as FC<
|
||||
FieldProps & RefAttributes<HTMLDivElement>
|
||||
>;
|
||||
15
src/components/FocusRing.ts
Normal file
15
src/components/FocusRing.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ElementType, FC, ReactNode } from 'react';
|
||||
|
||||
import { Export, findModuleExport } from '../webpack';
|
||||
|
||||
export interface FocusRingProps {
|
||||
className?: string;
|
||||
rootClassName?: string;
|
||||
render?: ElementType;
|
||||
children?: ReactNode;
|
||||
NavigationManager?: any;
|
||||
}
|
||||
|
||||
export const FocusRing = findModuleExport((e: Export) =>
|
||||
e?.toString?.()?.includes('.GetShowDebugFocusRing())'),
|
||||
) as FC<FocusRingProps>;
|
||||
21
src/components/Focusable.ts
Normal file
21
src/components/Focusable.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { HTMLAttributes, ReactNode, RefAttributes, FC } from 'react';
|
||||
|
||||
import { Export, findModuleExport } from '../webpack';
|
||||
import { FooterLegendProps } from './FooterLegend';
|
||||
import { createPropListRegex } from '../utils';
|
||||
|
||||
export interface FocusableProps extends HTMLAttributes<HTMLDivElement>, FooterLegendProps {
|
||||
children: ReactNode;
|
||||
'flow-children'?: string;
|
||||
focusClassName?: string;
|
||||
focusWithinClassName?: string;
|
||||
noFocusRing?: boolean;
|
||||
onActivate?: (e: CustomEvent) => void;
|
||||
onCancel?: (e: CustomEvent) => void;
|
||||
}
|
||||
|
||||
const focusableRegex = createPropListRegex(["flow-children", "onActivate", "onCancel", "focusClassName", "focusWithinClassName"]);
|
||||
|
||||
export const Focusable = findModuleExport((e: Export) =>
|
||||
(typeof e == 'function' && e?.toString && focusableRegex.test(e.toString())) || (e?.render?.toString && focusableRegex.test(e.render.toString()))
|
||||
) as FC<FocusableProps & RefAttributes<HTMLDivElement>>;
|
||||
117
src/components/FooterLegend.ts
Normal file
117
src/components/FooterLegend.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export enum GamepadButton {
|
||||
INVALID,
|
||||
OK,
|
||||
CANCEL,
|
||||
SECONDARY,
|
||||
OPTIONS,
|
||||
BUMPER_LEFT,
|
||||
BUMPER_RIGHT,
|
||||
TRIGGER_LEFT,
|
||||
TRIGGER_RIGHT,
|
||||
DIR_UP,
|
||||
DIR_DOWN,
|
||||
DIR_LEFT,
|
||||
DIR_RIGHT,
|
||||
SELECT,
|
||||
START,
|
||||
LSTICK_CLICK,
|
||||
RSTICK_CLICK,
|
||||
LSTICK_TOUCH,
|
||||
RSTICK_TOUCH,
|
||||
LPAD_TOUCH,
|
||||
LPAD_CLICK,
|
||||
RPAD_TOUCH,
|
||||
RPAD_CLICK,
|
||||
REAR_LEFT_UPPER,
|
||||
REAR_LEFT_LOWER,
|
||||
REAR_RIGHT_UPPER,
|
||||
REAR_RIGHT_LOWER,
|
||||
STEAM_GUIDE,
|
||||
STEAM_QUICK_MENU,
|
||||
}
|
||||
export enum NavEntryPositionPreferences {
|
||||
/**
|
||||
* Always give focus to the first child element.
|
||||
*/
|
||||
FIRST,
|
||||
|
||||
/**
|
||||
* Always give focus to the last child element.
|
||||
*/
|
||||
LAST,
|
||||
|
||||
/**
|
||||
* Give focus to the child element that would maintain the flow in the X axis.
|
||||
*
|
||||
* Imagine you have a calculator window with 9 standard buttons.
|
||||
* You have 3 rows of buttons, with 3 buttons per row.
|
||||
* If you select button with number 8 and navigate down, the buttons
|
||||
* will be navigated in the following order 8->5->3.
|
||||
* The flow is maintained for the X axis while you're navigating the Y axis.
|
||||
*/
|
||||
MAINTAIN_X,
|
||||
|
||||
/**
|
||||
* Give focus to the child element that would maintain the flow in the Y axis.
|
||||
*
|
||||
* Imagine you have a calculator window with 9 standard buttons.
|
||||
* You have 3 columns of buttons, with 3 buttons per column.
|
||||
* If you select button with number 4 and navigate right, the buttons
|
||||
* will be navigated in the following order 4->5->6.
|
||||
* The flow is maintained for the Y axis while you're navigating the X axis.
|
||||
*/
|
||||
MAINTAIN_Y,
|
||||
|
||||
/**
|
||||
* Give focus to the first child element with `preferredFocus == true` prop.
|
||||
*/
|
||||
PREFERRED_CHILD,
|
||||
}
|
||||
export interface GamepadEventDetail {
|
||||
button: number;
|
||||
is_repeat?: boolean;
|
||||
source: number;
|
||||
}
|
||||
export declare type ActionDescriptionMap = {
|
||||
[key in GamepadButton]?: ReactNode;
|
||||
};
|
||||
export declare type GamepadEvent = CustomEvent<GamepadEventDetail>;
|
||||
export interface FooterLegendProps {
|
||||
/**
|
||||
* Navigation entry strategy to be used when gaining focus during navigation.
|
||||
*
|
||||
* This is meant to be used on a parent container that has children. Once the
|
||||
* container (e.g. Focusable) is navigated to and has children in it, the children
|
||||
* is then navigated to (focused) using the provided strategy.
|
||||
*
|
||||
* If no strategy is provided, it seems that the `NavEntryPositionPreferences.FIRST`
|
||||
* is used initialy, but for the next time the parent remembers previously focused
|
||||
* child and focused back on it instead.
|
||||
*/
|
||||
navEntryPreferPosition?: NavEntryPositionPreferences;
|
||||
|
||||
/**
|
||||
* Mark the element as the preferred child (to be focused) whenever the parent uses the
|
||||
* `NavEntryPositionPreferences.PREFERRED_CHILD` navigation strategy.
|
||||
*/
|
||||
preferredFocus?: boolean;
|
||||
|
||||
actionDescriptionMap?: ActionDescriptionMap;
|
||||
onOKActionDescription?: ReactNode;
|
||||
onCancelActionDescription?: ReactNode;
|
||||
onSecondaryActionDescription?: ReactNode;
|
||||
onOptionsActionDescription?: ReactNode;
|
||||
onMenuActionDescription?: ReactNode;
|
||||
onButtonDown?: (evt: GamepadEvent) => void;
|
||||
onButtonUp?: (evt: GamepadEvent) => void;
|
||||
onOKButton?: (evt: GamepadEvent) => void;
|
||||
onCancelButton?: (evt: GamepadEvent) => void;
|
||||
onSecondaryButton?: (evt: GamepadEvent) => void;
|
||||
onOptionsButton?: (evt: GamepadEvent) => void;
|
||||
onGamepadDirection?: (evt: GamepadEvent) => void;
|
||||
onGamepadFocus?: (evt: GamepadEvent) => void;
|
||||
onGamepadBlur?: (evt: GamepadEvent) => void;
|
||||
onMenuButton?: (evt: GamepadEvent) => void;
|
||||
}
|
||||
@@ -3,9 +3,12 @@ import { ReactNode } from 'react';
|
||||
export interface ItemProps {
|
||||
label?: ReactNode;
|
||||
description?: ReactNode;
|
||||
children?: ReactNode;
|
||||
layout?: 'below' | 'inline';
|
||||
icon?: ReactNode;
|
||||
bottomSeparator?: 'standard' | 'thick' | 'none';
|
||||
childrenContainerWidth?: 'min' | 'max' | 'fixed'; // Does not work with layout==='below'
|
||||
indentLevel?: number;
|
||||
tooltip?: string;
|
||||
highlightOnFocus?: boolean;
|
||||
}
|
||||
20
src/components/Marquee.ts
Normal file
20
src/components/Marquee.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { CSSProperties, FC } from 'react';
|
||||
|
||||
import { Export, findModuleExport } from '../webpack';
|
||||
|
||||
export interface MarqueeProps {
|
||||
play?: boolean;
|
||||
direction?: 'left' | 'right';
|
||||
speed?: number;
|
||||
delay?: number;
|
||||
fadeLength?: number;
|
||||
center?: boolean;
|
||||
resetOnPause?: boolean;
|
||||
style?: CSSProperties;
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Marquee: FC<MarqueeProps> = findModuleExport(
|
||||
(e: Export) => e?.toString && e.toString().includes('.Marquee') && e.toString().includes('--fade-length'),
|
||||
);
|
||||
175
src/components/Menu.ts
Executable file
175
src/components/Menu.ts
Executable file
@@ -0,0 +1,175 @@
|
||||
import { FC, ReactNode } from 'react';
|
||||
|
||||
import { Export, findModuleByExport, findModuleDetailsByExport, findModuleExport } from '../webpack';
|
||||
import { FooterLegendProps } from './FooterLegend';
|
||||
|
||||
interface PopupCreationOptions {
|
||||
/**
|
||||
* Initially hidden, make it appear with {@link ContextMenuInstance.Show}.
|
||||
*/
|
||||
bCreateHidden?: boolean;
|
||||
|
||||
bModal?: boolean;
|
||||
|
||||
/**
|
||||
* Document title.
|
||||
*/
|
||||
title?: string;
|
||||
}
|
||||
|
||||
// Separate interface, since one of webpack module exports uses this exact object,
|
||||
// so maybe it could be reused elsewhere.
|
||||
interface MonitorOptions {
|
||||
targetMonitor: {
|
||||
flMonitorScale: number;
|
||||
nScreenLeft: number;
|
||||
nScreenTop: number;
|
||||
nScreenWidth: number;
|
||||
nScreenHeight: number;
|
||||
};
|
||||
flGamepadScale: number;
|
||||
}
|
||||
|
||||
export interface ContextMenuPositionOptions extends PopupCreationOptions, Partial<MonitorOptions> {
|
||||
/**
|
||||
* When {@link bForcePopup} is true, makes the window appear above everything else.
|
||||
*/
|
||||
bAlwaysOnTop?: boolean;
|
||||
|
||||
/**
|
||||
* Disables the mouse overlay, granting the ability to click anywhere while
|
||||
* the menu's active.
|
||||
*/
|
||||
bDisableMouseOverlay?: boolean;
|
||||
|
||||
/**
|
||||
* Disables the {@link bPreferPopTop} behavior.
|
||||
*/
|
||||
bDisablePopTop?: boolean;
|
||||
|
||||
bFitToWindow?: boolean;
|
||||
|
||||
/**
|
||||
* Forces the menu to open in a separate window instead of inside the parent.
|
||||
*/
|
||||
bForcePopup?: boolean;
|
||||
|
||||
/**
|
||||
* Like {@link bMatchWidth}, but don't shrink below the menu's minimum width.
|
||||
*/
|
||||
bGrowToElementWidth?: boolean;
|
||||
|
||||
/**
|
||||
* Match the parent's exact height.
|
||||
*/
|
||||
bMatchHeight?: boolean;
|
||||
|
||||
/**
|
||||
* Match the parent's exact width.
|
||||
*/
|
||||
bMatchWidth?: boolean;
|
||||
|
||||
bNoFocusWhenShown?: boolean;
|
||||
|
||||
/**
|
||||
* Makes the menu **invisible**, instead of getting removed from the DOM.
|
||||
*/
|
||||
bRetainOnHide?: boolean;
|
||||
|
||||
bScreenCoordinates?: boolean;
|
||||
|
||||
/**
|
||||
* Set to `true` to not account for the parent's width.
|
||||
*/
|
||||
bOverlapHorizontal?: boolean;
|
||||
|
||||
/**
|
||||
* Set to `true` to not account for the parent's height.
|
||||
*/
|
||||
bOverlapVertical?: boolean;
|
||||
|
||||
/**
|
||||
* Set to `true` to make the entire menu try to appear on the left side from
|
||||
* the parent.
|
||||
*/
|
||||
bPreferPopLeft?: boolean;
|
||||
|
||||
/**
|
||||
* Set to `true` to make the entire menu try to appear above the parent.
|
||||
*/
|
||||
bPreferPopTop?: boolean;
|
||||
|
||||
bShiftToFitWindow?: boolean;
|
||||
|
||||
// different window creation flags (StandaloneContextMenu vs PopupContextMenu)
|
||||
bStandalone?: boolean;
|
||||
|
||||
/**
|
||||
* Class name **replacement** for the container element, i.e. it replaces the
|
||||
* default class.
|
||||
*/
|
||||
strClassName?: string;
|
||||
}
|
||||
|
||||
interface ContextMenuInstance {
|
||||
Hide(): void;
|
||||
Show(): void;
|
||||
}
|
||||
|
||||
export const showContextMenu: (
|
||||
children: ReactNode,
|
||||
parent?: EventTarget,
|
||||
options?: ContextMenuPositionOptions,
|
||||
) => ContextMenuInstance = findModuleExport(
|
||||
(e: Export) =>
|
||||
typeof e === 'function' &&
|
||||
e.toString().includes('GetContextMenuManagerFromWindow(') &&
|
||||
e.toString().includes('.CreateContextMenuInstance('),
|
||||
);
|
||||
|
||||
export interface MenuProps extends FooterLegendProps {
|
||||
label: string;
|
||||
onCancel?(): void;
|
||||
cancelText?: string;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
const MenuModule = findModuleDetailsByExport((e: Export) => e?.render?.toString()?.includes('bPlayAudio:') || (e?.prototype?.OnOKButton && e?.prototype?.OnMouseEnter));
|
||||
|
||||
export const Menu: FC<MenuProps> =
|
||||
findModuleExport((e: Export) => e?.prototype?.HideIfSubmenu && e?.prototype?.HideMenu) || // Legacy Menu
|
||||
(Object.values(MenuModule?.[0] ?? {}).find((e) => e?.toString()?.includes?.(`useId`) && e?.toString()?.includes?.(`labelId`)) as FC<MenuProps>); // New Menu 6/15/2025
|
||||
|
||||
export interface MenuGroupProps {
|
||||
label: string;
|
||||
disabled?: boolean;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
const MenuGoupModule = findModuleByExport(e => e?.prototype?.Focus && e?.prototype?.OnOKButton && e?.prototype?.render?.toString().includes?.(`"emphasis"==this.props.tone`));
|
||||
export const MenuGroup: FC<MenuGroupProps> = MenuGoupModule && Object.values(MenuGoupModule).find((e: Export) => typeof e == "function" && e?.toString?.()?.includes("bInGamepadUI:"));
|
||||
export interface MenuItemProps extends FooterLegendProps {
|
||||
bInteractableItem?: boolean;
|
||||
onClick?(evt: Event): void;
|
||||
onSelected?(evt: Event): void;
|
||||
onMouseEnter?(evt: MouseEvent): void;
|
||||
onMoveRight?(): void;
|
||||
selected?: boolean;
|
||||
disabled?: boolean;
|
||||
bPlayAudio?: boolean;
|
||||
tone?: 'positive' | 'emphasis' | 'destructive';
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export const MenuItem: FC<MenuItemProps> = MenuModule?.[1];
|
||||
|
||||
export const MenuSeparator: FC = findModuleExport(
|
||||
(e: Export) => typeof e === 'function' && /className:.+?\.ContextMenuSeparator/.test(e.toString()),
|
||||
);
|
||||
|
||||
/*
|
||||
all().map(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]}
|
||||
}).find(x => x)
|
||||
*/
|
||||
@@ -1,11 +1,11 @@
|
||||
import { FC, ReactNode } from 'react';
|
||||
|
||||
import { findSP } from '../utils';
|
||||
import { findModule, findModuleChild } from '../webpack';
|
||||
import { Export, findModule, findModuleDetailsByExport, findModuleExport } from '../webpack';
|
||||
|
||||
// All of the popout options + strTitle are related. Proper usage is not yet known...
|
||||
export interface ShowModalProps {
|
||||
browserContext?: unknown; // This is another Deck Object that is yet to be found
|
||||
browserContext?: unknown;
|
||||
bForcePopOut?: boolean;
|
||||
bHideActionIcons?: boolean;
|
||||
bHideMainWindowForPopouts?: boolean;
|
||||
@@ -29,38 +29,18 @@ export interface ShowModalResult {
|
||||
Update: (modal: ReactNode) => void;
|
||||
}
|
||||
|
||||
const showModalRaw:
|
||||
| ((
|
||||
modal: ReactNode,
|
||||
parent?: EventTarget,
|
||||
title?: string,
|
||||
props?: ShowModalProps,
|
||||
unknown1?: unknown,
|
||||
hideActions?: { bHideActions?: boolean },
|
||||
modalManager?: unknown,
|
||||
) => 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];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const oldShowModalRaw: ((modal: ReactNode, parent?: EventTarget, props?: ShowModalProps) => 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];
|
||||
}
|
||||
}
|
||||
});
|
||||
const showModalRaw: (
|
||||
modal: ReactNode,
|
||||
parent?: EventTarget,
|
||||
title?: string,
|
||||
props?: ShowModalProps,
|
||||
unknown1?: unknown,
|
||||
hideActions?: { bHideActions?: boolean },
|
||||
modalManager?: unknown,
|
||||
) => ShowModalResult = findModuleExport(
|
||||
(e: Export) =>
|
||||
typeof e === 'function' && e.toString().includes('props.bDisableBackgroundDismiss') && !e?.prototype?.Cancel,
|
||||
);
|
||||
|
||||
export const showModal = (
|
||||
modal: ReactNode,
|
||||
@@ -70,15 +50,9 @@ export const showModal = (
|
||||
bHideMainWindowForPopouts: false,
|
||||
},
|
||||
): 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');
|
||||
}
|
||||
return showModalRaw(modal, parent || findSP() || window, props.strTitle, props, undefined, {
|
||||
bHideActions: props.bHideActionIcons,
|
||||
});
|
||||
};
|
||||
|
||||
export interface ModalRootProps {
|
||||
@@ -108,49 +82,40 @@ export interface ConfirmModalProps extends ModalRootProps {
|
||||
bMiddleDisabled?: boolean;
|
||||
}
|
||||
|
||||
export const ConfirmModal = 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<ConfirmModalProps>;
|
||||
export const ConfirmModal = findModuleExport(
|
||||
(e: Export) => e?.toString()?.includes('bUpdateDisabled') && e?.toString()?.includes('closeModal') && e?.toString()?.includes('onGamepadCancel'),
|
||||
) as FC<ConfirmModalProps>;
|
||||
|
||||
// new as of december 2022 on beta
|
||||
export const ModalRoot = (Object.values(
|
||||
findModule((m: any) => {
|
||||
if (typeof m !== 'object') return false;
|
||||
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.m_mapModalManager) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}) || {},
|
||||
)?.find((x: any) => x?.type?.toString()?.includes('((function(){')) ||
|
||||
// before december 2022 beta
|
||||
export const ModalRoot =
|
||||
// new
|
||||
findModuleExport((e: Export) => typeof e === 'function' && e.toString().includes('Either closeModal or onCancel should be passed to GenericDialog. Classes: ')) ||
|
||||
// old
|
||||
Object.values(
|
||||
findModule((m: any) => {
|
||||
if (typeof m !== 'object') return false;
|
||||
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.toString()?.includes('"ModalManager","DialogWrapper"')) {
|
||||
if (m[prop]?.m_mapModalManager && Object.values(m)?.find((x: any) => x?.type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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>;
|
||||
)?.find((x: any) => x?.type?.toString?.()?.includes('((function(){')) as FC<ModalRootProps>;
|
||||
|
||||
interface SimpleModalProps {
|
||||
active?: boolean;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
const [ModalModule, _ModalPosition] = findModuleDetailsByExport((e: Export) => e?.toString().includes('.ModalPosition'), 5)
|
||||
|
||||
const ModalModuleProps = ModalModule ? Object.values(ModalModule) : [];
|
||||
|
||||
export const SimpleModal = ModalModuleProps.find((prop) => {
|
||||
const string = prop?.toString();
|
||||
return string?.includes('.ShowPortalModal()') && string?.includes('.OnElementReadyCallbacks.Register(');
|
||||
}) as FC<SimpleModalProps>;
|
||||
|
||||
export const ModalPosition = _ModalPosition as FC<SimpleModalProps>;
|
||||
26
src/components/Panel.ts
Normal file
26
src/components/Panel.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { FC, ReactNode } from 'react';
|
||||
|
||||
import { Export, findModuleDetailsByExport } from '../webpack';
|
||||
|
||||
// TODO where did this go?
|
||||
// export const Panel: FC<{ children?: ReactNode; }> = findModuleExport((e: Export) => {
|
||||
// if (typeof mod !== 'object' || !mod.__esModule) return undefined;
|
||||
// return mod.Panel;
|
||||
// });
|
||||
|
||||
export interface PanelSectionProps {
|
||||
title?: string;
|
||||
spinner?: boolean;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
const [mod, panelSection] = findModuleDetailsByExport((e: Export) => e.toString()?.includes('.PanelSection'));
|
||||
|
||||
export const PanelSection = panelSection as FC<PanelSectionProps>;
|
||||
|
||||
export interface PanelSectionRowProps {
|
||||
children?: ReactNode;
|
||||
}
|
||||
export const PanelSectionRow = Object.values(mod).filter(
|
||||
(exp: any) => !exp?.toString?.()?.includes('.PanelSection'),
|
||||
)[0] as FC<PanelSectionRowProps>;
|
||||
38
src/components/ProgressBar.ts
Normal file
38
src/components/ProgressBar.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { ReactNode, FC } from 'react';
|
||||
|
||||
import { Export, findModuleExport } from '../webpack';
|
||||
import { ItemProps } from './Item';
|
||||
import { createPropListRegex } from '../utils';
|
||||
|
||||
export interface ProgressBarItemProps extends ItemProps {
|
||||
indeterminate?: boolean;
|
||||
nTransitionSec?: number;
|
||||
nProgress?: number;
|
||||
focusable?: boolean;
|
||||
}
|
||||
|
||||
export interface ProgressBarProps {
|
||||
indeterminate?: boolean;
|
||||
nTransitionSec?: number;
|
||||
nProgress?: number;
|
||||
focusable?: boolean;
|
||||
}
|
||||
|
||||
export interface ProgressBarWithInfoProps extends ProgressBarItemProps {
|
||||
sTimeRemaining?: ReactNode;
|
||||
sOperationText?: ReactNode;
|
||||
}
|
||||
|
||||
export const ProgressBar = findModuleExport((e: Export) =>
|
||||
e?.toString?.()?.includes('.ProgressBar,"standard"=='),
|
||||
) as FC<ProgressBarProps>;
|
||||
|
||||
export const ProgressBarWithInfo = findModuleExport((e: Export) =>
|
||||
// new || old
|
||||
e?.toString?.()?.includes('.ProgressBarFieldStatus,children') || e?.toString?.()?.includes('.ProgressBarFieldStatus},'),
|
||||
) as FC<ProgressBarWithInfoProps>;
|
||||
|
||||
const progressBarItemRegex = createPropListRegex(["indeterminate", "nTransitionSec", "nProgress"]);
|
||||
export const ProgressBarItem = findModuleExport((e: Export) =>
|
||||
e?.toString && progressBarItemRegex.test(e.toString()),
|
||||
) as FC<ProgressBarItemProps>;
|
||||
16
src/components/Scroll.ts
Normal file
16
src/components/Scroll.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { FC, ReactNode } from 'react';
|
||||
|
||||
import { Export, findModuleByExport, findModuleExport } from '../webpack';
|
||||
|
||||
const ScrollingModule = findModuleByExport((e: Export) => e?.render?.toString?.().includes('{case"x":'));
|
||||
|
||||
const ScrollingModuleProps = ScrollingModule ? Object.values(ScrollingModule) : [];
|
||||
|
||||
export const ScrollPanel = ScrollingModuleProps.find((prop: any) =>
|
||||
prop?.render?.toString?.().includes('{case"x":'),
|
||||
) as FC<{ children?: ReactNode }>;
|
||||
|
||||
export const ScrollPanelGroup: FC<{ children?: ReactNode }> = findModuleExport((e: Export) =>
|
||||
// new || old
|
||||
e?.render?.toString().includes('.FocusVisibleChild(),[])') || e?.render?.toString().includes('.FocusVisibleChild()),[])'),
|
||||
);
|
||||
30
src/components/SidebarNavigation.ts
Normal file
30
src/components/SidebarNavigation.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { ReactNode, FC } from 'react';
|
||||
|
||||
import { Export, findModuleExport } from '../webpack';
|
||||
import { createPropListRegex } from '../utils';
|
||||
|
||||
export interface SidebarNavigationPage {
|
||||
title: ReactNode;
|
||||
content: ReactNode;
|
||||
icon?: ReactNode;
|
||||
visible?: boolean;
|
||||
hideTitle?: boolean;
|
||||
identifier?: string;
|
||||
route?: string;
|
||||
link?: string;
|
||||
padding?: 'none' | 'compact';
|
||||
}
|
||||
|
||||
export interface SidebarNavigationProps {
|
||||
title?: ReactNode;
|
||||
pages: (SidebarNavigationPage | 'separator')[];
|
||||
showTitle?: boolean;
|
||||
disableRouteReporting?: boolean;
|
||||
page?: string;
|
||||
onPageRequested?: (page: string) => void;
|
||||
}
|
||||
|
||||
const sidebarNavigationRegex = createPropListRegex(["pages", "fnSetNavigateToPage", "disableRouteReporting"]);
|
||||
export const SidebarNavigation = findModuleExport((e: Export) =>
|
||||
e?.toString && sidebarNavigationRegex.test(e.toString()),
|
||||
) as FC<SidebarNavigationProps>;
|
||||
@@ -25,8 +25,10 @@ export interface SliderFieldProps extends ItemProps {
|
||||
valueSuffix?: string;
|
||||
minimumDpadGranularity?: number;
|
||||
onChange?(value: number): void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const SliderField = Object.values(CommonUIModule).find((mod: any) =>
|
||||
mod?.toString()?.includes('SliderField,fallback'),
|
||||
// stable || beta as of oct 2 2024
|
||||
mod?.toString?.()?.includes('SliderField,fallback') || mod?.toString?.()?.includes("SliderField\",")
|
||||
) as FC<SliderFieldProps>;
|
||||
8
src/components/Spinner.ts
Executable file
8
src/components/Spinner.ts
Executable file
@@ -0,0 +1,8 @@
|
||||
import { FC, SVGAttributes } from 'react';
|
||||
|
||||
import { IconsModule } from '../webpack';
|
||||
|
||||
// TODO type this and other icons?
|
||||
export const Spinner = IconsModule && Object.values(IconsModule)?.find(
|
||||
(mod: any) => mod?.toString && /Spinner\),children:\[\(0,\w+\.jsx\)\("path",\{d:"M18 /.test(mod.toString()) || /Spinner\)}\)?,.\.createElement\(\"path\",{d:\"M18 /.test(mod.toString()),
|
||||
) as FC<SVGAttributes<SVGElement>>;
|
||||
12
src/components/SteamSpinner.ts
Executable file
12
src/components/SteamSpinner.ts
Executable file
@@ -0,0 +1,12 @@
|
||||
import { FC, ReactNode, SVGAttributes } from 'react';
|
||||
|
||||
import { Export, findModuleExport } from '../webpack';
|
||||
|
||||
interface SteamSpinnerProps {
|
||||
children?: ReactNode;
|
||||
background?: "transparent"; // defaults to black seemingly, but only "transparent" is checked against
|
||||
}
|
||||
|
||||
export const SteamSpinner = findModuleExport(
|
||||
(e: Export) => e?.toString?.()?.includes('Steam Spinner') && e?.toString?.()?.includes('src'),
|
||||
) as FC<SVGAttributes<SVGElement> & SteamSpinnerProps>;
|
||||
70
src/components/Tabs.ts
Normal file
70
src/components/Tabs.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { FC, ReactNode } from 'react';
|
||||
import { findModuleByExport } from '../webpack';
|
||||
import { FooterLegendProps } from './FooterLegend';
|
||||
|
||||
/**
|
||||
* Individual tab objects for the Tabs component
|
||||
*
|
||||
* `id` ID of this tab, can be used with activeTab to auto-focus a given tab
|
||||
* `title` Title shown in the header bar
|
||||
* `renderTabAddon` Return a {@link ReactNode} to render it next to the tab title, i.e. the counts for each tab on the Media page
|
||||
* `content` Content of the tab
|
||||
* `footer` Sets up button handlers and labels
|
||||
*/
|
||||
export interface Tab {
|
||||
id: string;
|
||||
title: string;
|
||||
renderTabAddon?: () => ReactNode;
|
||||
content: ReactNode;
|
||||
footer?: FooterLegendProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Props for the {@link Tabs}
|
||||
*
|
||||
* `tabs` array of {@link Tab}
|
||||
* `activeTab` tab currently active, needs to be one of the tabs {@link Tab.id}, must be set using a `useState` in the `onShowTab` handler
|
||||
* `onShowTab` Called when the active tab should change, needs to set `activeTab`. See example.
|
||||
* `autoFocusContents` Whether to automatically focus the tab contents or not.
|
||||
* `footer` Sets up button handlers and labels
|
||||
*
|
||||
* @example
|
||||
* const Component: FC = () => {
|
||||
* const [currentTab, setCurrentTab] = useState<string>("Tab1");
|
||||
*
|
||||
* return (
|
||||
* <Tabs
|
||||
* title="Theme Manager"
|
||||
* activeTab={currentTabRoute}
|
||||
* onShowTab={(tabID: string) => {
|
||||
* setCurrentTabRoute(tabID);
|
||||
* }}
|
||||
* tabs={[
|
||||
* {
|
||||
* title: "Tab 1",
|
||||
* content: <Tab1Component />,
|
||||
* id: "Tab1",
|
||||
* },
|
||||
* {
|
||||
* title: "Tab 2",
|
||||
* content: <Tab2Component />,
|
||||
* id: "Tab2",
|
||||
* },
|
||||
* ]}
|
||||
* />
|
||||
* );
|
||||
* };
|
||||
*/
|
||||
export interface TabsProps {
|
||||
tabs: Tab[];
|
||||
activeTab: string;
|
||||
onShowTab: (tab: string) => void;
|
||||
autoFocusContents?: boolean;
|
||||
}
|
||||
|
||||
const tabsModule = findModuleByExport(e => e?.toString?.()?.includes(".TabRowTabs") && e?.toString?.()?.includes("activeTab:"));
|
||||
|
||||
/**
|
||||
* Tabs component as used in the library and media tabs. See {@link TabsProps}.
|
||||
*/
|
||||
export const Tabs = tabsModule && Object.values(tabsModule).find((e: any) => e?.type?.toString?.()?.includes("(function()")) as FC<TabsProps>;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChangeEventHandler, HTMLAttributes, ReactNode, VFC } from 'react';
|
||||
import { ChangeEventHandler, HTMLAttributes, ReactNode, FC } from 'react';
|
||||
|
||||
import { CommonUIModule, Module } from '../webpack';
|
||||
|
||||
@@ -25,4 +25,4 @@ export interface TextFieldProps extends HTMLAttributes<HTMLInputElement> {
|
||||
|
||||
export const TextField = Object.values(CommonUIModule).find(
|
||||
(mod: Module) => mod?.validateUrl && mod?.validateEmail,
|
||||
) as VFC<TextFieldProps>;
|
||||
) as FC<TextFieldProps>;
|
||||
@@ -10,5 +10,5 @@ export interface ToggleProps {
|
||||
}
|
||||
|
||||
export const Toggle = Object.values(CommonUIModule).find((mod: any) =>
|
||||
mod?.render?.toString()?.includes('.ToggleOff)'),
|
||||
mod?.render?.toString?.()?.includes('.ToggleOff)'),
|
||||
) as FC<ToggleProps>;
|
||||
@@ -4,11 +4,13 @@ import { CommonUIModule } from '../webpack';
|
||||
import { ItemProps } from './Item';
|
||||
|
||||
export interface ToggleFieldProps extends ItemProps {
|
||||
highlightOnFocus?: boolean;
|
||||
checked: boolean;
|
||||
disabled?: boolean;
|
||||
onChange?(checked: boolean): void;
|
||||
}
|
||||
|
||||
export const ToggleField = Object.values(CommonUIModule).find((mod: any) =>
|
||||
mod?.render?.toString()?.includes('ToggleField,fallback'),
|
||||
// stable || beta as of oct 2 2024
|
||||
mod?.render?.toString?.()?.includes('ToggleField,fallback') || mod?.render?.toString?.()?.includes("ToggleField\",")
|
||||
) as FC<ToggleFieldProps>;
|
||||
@@ -5,6 +5,7 @@ export * from './ControlsList';
|
||||
export * from './Dialog';
|
||||
export * from './DialogCheckbox';
|
||||
export * from './Dropdown';
|
||||
export * from './ErrorBoundary';
|
||||
export * from './Field';
|
||||
export * from './Focusable';
|
||||
export * from './FocusRing';
|
||||
@@ -14,20 +15,12 @@ export * from './Menu';
|
||||
export * from './Modal';
|
||||
export * from './Panel';
|
||||
export * from './ProgressBar';
|
||||
export * from './Router';
|
||||
export * from './SidebarNavigation';
|
||||
export * from './SliderField';
|
||||
export * from './Spinner';
|
||||
export * from './static-classes';
|
||||
export * from './SteamSpinner';
|
||||
export * from './Tabs';
|
||||
export * from './TextField';
|
||||
export * from './Toggle';
|
||||
export * from './ToggleField';
|
||||
export * from './SteamClient';
|
||||
|
||||
import {SteamClient} from './SteamClient'
|
||||
|
||||
declare global {
|
||||
var SteamClient: SteamClient;
|
||||
}
|
||||
export * from './Scroll';
|
||||
@@ -1,6 +1,7 @@
|
||||
import { CSSProperties, FC, useState } from 'react';
|
||||
|
||||
import { ConfirmModal, SliderField, gamepadSliderClasses } from '../deck-components';
|
||||
import { ConfirmModal, SliderField } from '../components';
|
||||
import { gamepadSliderClasses } from '../utils/static-classes';
|
||||
|
||||
interface ColorPickerModalProps {
|
||||
closeModal: () => void;
|
||||
|
||||
183
src/custom-components/ReorderableList.tsx
Normal file
183
src/custom-components/ReorderableList.tsx
Normal file
@@ -0,0 +1,183 @@
|
||||
import { Fragment, JSXElementConstructor, ReactElement, ReactNode, useEffect, useState } from 'react';
|
||||
|
||||
import { Field, FieldProps, Focusable, GamepadButton } from '../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<any> | 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>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
import { FC, ImgHTMLAttributes, useState } from 'react';
|
||||
|
||||
import { Spinner } from '../deck-components';
|
||||
import { Spinner } from '../components';
|
||||
|
||||
interface SuspensefulImageProps extends ImgHTMLAttributes<HTMLImageElement> {
|
||||
suspenseWidth?: string | number;
|
||||
@@ -13,6 +13,8 @@ export const SuspensefulImage: FC<SuspensefulImageProps> = (props) => {
|
||||
const [error, setError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
setError(false);
|
||||
const img = new Image();
|
||||
img.src = props.src || '';
|
||||
img.addEventListener('load', () => {
|
||||
@@ -21,7 +23,7 @@ export const SuspensefulImage: FC<SuspensefulImageProps> = (props) => {
|
||||
img.addEventListener('error', () => {
|
||||
setError(true);
|
||||
});
|
||||
}, []);
|
||||
}, [props.src]);
|
||||
|
||||
return loading ? (
|
||||
<div
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './SuspensefulImage';
|
||||
export * from './ColorPickerModal';
|
||||
export * from './ReorderableList';
|
||||
|
||||
65
src/custom-hooks/useQuickAccessVisible.ts
Normal file
65
src/custom-hooks/useQuickAccessVisible.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { getGamepadNavigationTrees } from '../utils';
|
||||
|
||||
function getQuickAccessWindow(): Window | null {
|
||||
const navTrees = getGamepadNavigationTrees();
|
||||
return (
|
||||
navTrees.find((tree: any) => tree?.id === 'QuickAccess-NA')?.m_Root?.m_element?.ownerDocument.defaultView ?? null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns state indicating the visibility of quick access menu.
|
||||
*
|
||||
* @deprecated moved to @decky/api
|
||||
*
|
||||
* @returns `true` if quick access menu is visible and `false` otherwise.
|
||||
*
|
||||
* @example
|
||||
* import { FC, useEffect } from "react";
|
||||
* import { useQuickAccessVisible } from "@decky/ui";
|
||||
*
|
||||
* export const PluginPanelView: FC<{}> = ({ }) => {
|
||||
* const isVisible = useQuickAccessVisible();
|
||||
*
|
||||
* useEffect(() => {
|
||||
* if (!isVisible) {
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* const interval = setInterval(() => console.log("Hello world!"), 1000);
|
||||
* return () => {
|
||||
* clearInterval(interval);
|
||||
* }
|
||||
* }, [isVisible])
|
||||
*
|
||||
* return (
|
||||
* <div>
|
||||
* {isVisible ? "VISIBLE" : "INVISIBLE"}
|
||||
* </div>
|
||||
* );
|
||||
* };
|
||||
*/
|
||||
export function useQuickAccessVisible(): boolean {
|
||||
// By default we say that document is not hidden, unless we know otherwise.
|
||||
// This would cover the cases when Valve breaks something and the quick access window
|
||||
// cannot be accessed anymore - the plugins that use this would continue working somewhat.
|
||||
const [isHidden, setIsHidden] = useState(getQuickAccessWindow()?.document.hidden ?? false);
|
||||
|
||||
useEffect(() => {
|
||||
const quickAccessWindow = getQuickAccessWindow();
|
||||
if (quickAccessWindow === null) {
|
||||
console.error('Could not get window of QuickAccess menu!');
|
||||
return;
|
||||
}
|
||||
|
||||
const onVisibilityChange = () => setIsHidden(quickAccessWindow.document.hidden);
|
||||
quickAccessWindow.addEventListener('visibilitychange', onVisibilityChange);
|
||||
return () => {
|
||||
quickAccessWindow.removeEventListener('visibilitychange', onVisibilityChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return !isHidden;
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
declare global {
|
||||
var FocusNavController: any;
|
||||
}
|
||||
|
||||
function getQuickAccessWindow(): Window | null {
|
||||
try {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns state indicating the visibility of quick access menu.
|
||||
*
|
||||
* @remarks
|
||||
* During development it is possible to open the quick access menu without giving it
|
||||
* focus in some cases. In such cases, the quick access menu state is invisible.
|
||||
*
|
||||
* This seems to be impossible to replicate when running the deck normally. Even in
|
||||
* the edge cases it always seems to have a focus.
|
||||
*
|
||||
* @returns `true` if quick access menu is visible (focused) and `false` otherwise.
|
||||
*
|
||||
* @example
|
||||
* import { VFC, useEffect } from "react";
|
||||
* import { useQuickAccessVisible } from "decky-frontend-lib";
|
||||
*
|
||||
* export const PluginPanelView: VFC<{}> = ({ }) => {
|
||||
* const isVisible = useQuickAccessVisible();
|
||||
*
|
||||
* useEffect(() => {
|
||||
* if (!isVisible) {
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* const interval = setInterval(() => console.log("Hello world!"), 1000);
|
||||
* return () => {
|
||||
* clearInterval(interval);
|
||||
* }
|
||||
* }, [isVisible])
|
||||
*
|
||||
* return (
|
||||
* <div>
|
||||
* {isVisible ? "VISIBLE" : "INVISIBLE"}
|
||||
* </div>
|
||||
* );
|
||||
* };
|
||||
*/
|
||||
export function useQuickAccessVisible(): boolean {
|
||||
const [isVisible, setIsVisible] = useState(getQuickAccessWindow()?.document.hasFocus() ?? true);
|
||||
|
||||
useEffect(() => {
|
||||
const quickAccessWindow = getQuickAccessWindow();
|
||||
if (quickAccessWindow === null) {
|
||||
console.error('Could not get window of QuickAccess menu!');
|
||||
return;
|
||||
}
|
||||
|
||||
const onBlur = () => setIsVisible(false);
|
||||
const onFocus = () => setIsVisible(true);
|
||||
|
||||
quickAccessWindow.addEventListener('blur', onBlur);
|
||||
quickAccessWindow.addEventListener('focus', onFocus);
|
||||
return () => {
|
||||
quickAccessWindow.removeEventListener('blur', onBlur);
|
||||
quickAccessWindow.removeEventListener('focus', onFocus);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return isVisible;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { findModuleChild } from '../webpack';
|
||||
import { FC } from 'react';
|
||||
|
||||
export interface ControlsListProps {
|
||||
alignItems?: 'left' | 'right' | 'center';
|
||||
spacing?: 'standard' | 'extra';
|
||||
}
|
||||
|
||||
export const ControlsList: FC<ControlsListProps> = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return;
|
||||
for (const prop in m) {
|
||||
if (m[prop]?.toString && m[prop].toString().includes('().ControlsListChild') && m[prop].toString().includes('().ControlsListOuterPanel')) {
|
||||
return m[prop];
|
||||
}
|
||||
}
|
||||
return;
|
||||
});
|
||||
@@ -1,33 +0,0 @@
|
||||
import { FC, ReactNode } from 'react';
|
||||
|
||||
import { findModule } from '../webpack';
|
||||
import { DialogCommonProps } from './Dialog';
|
||||
import { FooterLegendProps } from './FooterLegend';
|
||||
|
||||
export interface DialogCheckboxProps extends DialogCommonProps, FooterLegendProps {
|
||||
onChange?(checked: boolean): void;
|
||||
label?: ReactNode;
|
||||
description?: ReactNode;
|
||||
disabled?: boolean;
|
||||
tooltip?: string;
|
||||
color?: string;
|
||||
highlightColor?: string;
|
||||
bottomSeparator?: 'standard' | 'thick' | 'none';
|
||||
controlled?: boolean;
|
||||
checked?: boolean;
|
||||
onClick?(evt: Event): void;
|
||||
}
|
||||
|
||||
export const DialogCheckbox = Object.values(findModule((m: any) => {
|
||||
if (typeof m !== 'object') return false;
|
||||
for (const prop in m) {
|
||||
if (m[prop]?.prototype?.GetPanelElementProps) return true;
|
||||
}
|
||||
return false;
|
||||
})).find((m: any) =>
|
||||
m.contextType &&
|
||||
m.prototype?.render.toString().includes('fallback:') &&
|
||||
m?.prototype?.SetChecked &&
|
||||
m?.prototype?.Toggle &&
|
||||
m?.prototype?.GetPanelElementProps
|
||||
) as FC<DialogCheckboxProps>;
|
||||
@@ -1,19 +0,0 @@
|
||||
import { ElementType, FC, ReactNode } from 'react';
|
||||
|
||||
import { findModuleChild } from '../webpack';
|
||||
|
||||
export interface FocusRingProps {
|
||||
className?: string;
|
||||
rootClassName?: string;
|
||||
render?: ElementType;
|
||||
children?: ReactNode;
|
||||
NavigationManager?: any;
|
||||
}
|
||||
|
||||
export const FocusRing = findModuleChild((m: any) => {
|
||||
if (typeof m !== 'object') return false;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.toString()?.includes('.GetShowDebugFocusRing())')) return m[prop];
|
||||
}
|
||||
return false;
|
||||
}) as FC<FocusRingProps>;
|
||||
@@ -1,22 +0,0 @@
|
||||
import { HTMLAttributes, ReactNode, RefAttributes, VFC } from 'react';
|
||||
|
||||
import { findModuleChild } from '../webpack';
|
||||
import { FooterLegendProps } from './FooterLegend';
|
||||
|
||||
export interface FocusableProps extends HTMLAttributes<HTMLDivElement>, FooterLegendProps {
|
||||
children: ReactNode;
|
||||
'flow-children'?: string;
|
||||
focusClassName?: string;
|
||||
focusWithinClassName?: string;
|
||||
noFocusRing?: boolean;
|
||||
onActivate?: (e: CustomEvent) => void;
|
||||
onCancel?: (e: CustomEvent) => void;
|
||||
}
|
||||
|
||||
export const Focusable = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.render?.toString()?.includes('["flow-children","onActivate","onCancel","focusClassName",'))
|
||||
return m[prop];
|
||||
}
|
||||
}) as VFC<FocusableProps & RefAttributes<HTMLDivElement>>;
|
||||
@@ -1,67 +0,0 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export enum GamepadButton {
|
||||
INVALID,
|
||||
OK,
|
||||
CANCEL,
|
||||
SECONDARY,
|
||||
OPTIONS,
|
||||
BUMPER_LEFT,
|
||||
BUMPER_RIGHT,
|
||||
TRIGGER_LEFT,
|
||||
TRIGGER_RIGHT,
|
||||
DIR_UP,
|
||||
DIR_DOWN,
|
||||
DIR_LEFT,
|
||||
DIR_RIGHT,
|
||||
SELECT,
|
||||
START,
|
||||
LSTICK_CLICK,
|
||||
RSTICK_CLICK,
|
||||
LSTICK_TOUCH,
|
||||
RSTICK_TOUCH,
|
||||
LPAD_TOUCH,
|
||||
LPAD_CLICK,
|
||||
RPAD_TOUCH,
|
||||
RPAD_CLICK,
|
||||
REAR_LEFT_UPPER,
|
||||
REAR_LEFT_LOWER,
|
||||
REAR_RIGHT_UPPER,
|
||||
REAR_RIGHT_LOWER,
|
||||
STEAM_GUIDE,
|
||||
STEAM_QUICK_MENU,
|
||||
}
|
||||
export declare enum NavEntryPositionPreferences {
|
||||
FIRST,
|
||||
LAST,
|
||||
MAINTAIN_X,
|
||||
MAINTAIN_Y,
|
||||
PREFERRED_CHILD
|
||||
}
|
||||
export interface GamepadEventDetail {
|
||||
button: number;
|
||||
is_repeat?: boolean;
|
||||
source: number;
|
||||
}
|
||||
export declare type ActionDescriptionMap = {
|
||||
[key in GamepadButton]?: ReactNode
|
||||
}
|
||||
export declare type GamepadEvent = CustomEvent<GamepadEventDetail>;
|
||||
export interface FooterLegendProps {
|
||||
actionDescriptionMap?: ActionDescriptionMap;
|
||||
onOKActionDescription?: ReactNode;
|
||||
onCancelActionDescription?: ReactNode;
|
||||
onSecondaryActionDescription?: ReactNode;
|
||||
onOptionsActionDescription?: ReactNode;
|
||||
onMenuActionDescription?: ReactNode;
|
||||
onButtonDown?: (evt: GamepadEvent) => void;
|
||||
onButtonUp?: (evt: GamepadEvent) => void;
|
||||
onOKButton?: (evt: GamepadEvent) => void;
|
||||
onCancelButton?: (evt: GamepadEvent) => void;
|
||||
onSecondaryButton?: (evt: GamepadEvent) => void;
|
||||
onOptionsButton?: (evt: GamepadEvent) => void;
|
||||
onGamepadDirection?: (evt: GamepadEvent) => void;
|
||||
onGamepadFocus?: (evt: GamepadEvent) => void;
|
||||
onGamepadBlur?: (evt: GamepadEvent) => void;
|
||||
onMenuButton?: (evt: GamepadEvent) => void;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { CSSProperties, FC } from 'react';
|
||||
|
||||
import { findModuleChild } from '../webpack';
|
||||
|
||||
export interface MarqueeProps {
|
||||
play?: boolean;
|
||||
direction?: 'left' | 'right';
|
||||
speed?: number;
|
||||
delay?: number;
|
||||
fadeLength?: number;
|
||||
center?: boolean;
|
||||
resetOnPause?: boolean;
|
||||
style?: CSSProperties;
|
||||
className?: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Marquee: FC<MarqueeProps> = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return;
|
||||
for (const prop in m) {
|
||||
if (m[prop]?.toString && m[prop].toString().includes('.Marquee') && m[prop].toString().includes('--fade-length')) {
|
||||
return m[prop];
|
||||
}
|
||||
}
|
||||
return;
|
||||
});
|
||||
@@ -1,84 +0,0 @@
|
||||
import { FC, ReactNode } from 'react';
|
||||
|
||||
import { fakeRenderComponent } from '../utils';
|
||||
import { findModuleChild } from '../webpack';
|
||||
import { FooterLegendProps } from './FooterLegend';
|
||||
|
||||
export const showContextMenu: (children: ReactNode, parent?: EventTarget) => void = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
for (let prop in m) {
|
||||
if (typeof m[prop] === 'function' && m[prop].toString().includes('stopPropagation))')) {
|
||||
return m[prop];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export interface MenuProps extends FooterLegendProps {
|
||||
label: string;
|
||||
onCancel?(): void;
|
||||
cancelText?: string;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export const Menu: FC<MenuProps> = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.prototype?.HideIfSubmenu && m[prop]?.prototype?.HideMenu) {
|
||||
return m[prop];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export interface MenuGroupProps {
|
||||
label: string;
|
||||
disabled?: boolean;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export const MenuGroup: FC<MenuGroupProps> = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
|
||||
for (let prop in m) {
|
||||
if (
|
||||
(m[prop]?.toString()?.includes('bInGamepadUI:') &&
|
||||
fakeRenderComponent(() => m[prop]())?.type?.prototype?.RenderSubMenu) ||
|
||||
(m[prop]?.prototype?.RenderSubMenu && m[prop]?.prototype?.ShowSubMenu)
|
||||
) {
|
||||
return m[prop];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export interface MenuItemProps extends FooterLegendProps {
|
||||
bInteractableItem?: boolean;
|
||||
onClick?(evt: Event): void;
|
||||
onSelected?(evt: Event): void;
|
||||
onMouseEnter?(evt: MouseEvent): void;
|
||||
onMoveRight?(): void;
|
||||
selected?: boolean;
|
||||
disabled?: boolean;
|
||||
bPlayAudio?: boolean;
|
||||
tone?: 'positive' | 'emphasis' | 'destructive';
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
export const MenuItem: FC<MenuItemProps> = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
|
||||
for (let prop in m) {
|
||||
if (
|
||||
m[prop]?.render?.toString()?.includes('bPlayAudio:') ||
|
||||
(m[prop]?.prototype?.OnOKButton && m[prop]?.prototype?.OnMouseEnter)
|
||||
) {
|
||||
return m[prop];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
all().map(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]}
|
||||
}).find(x => x)
|
||||
*/
|
||||
@@ -1,23 +0,0 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { findModuleChild } from '../webpack';
|
||||
|
||||
export interface PanelSectionProps {
|
||||
title?: string;
|
||||
spinner?: boolean;
|
||||
}
|
||||
|
||||
const [panelSection, mod] = findModuleChild((mod: any) => {
|
||||
for (let prop in mod) {
|
||||
if (mod[prop]?.toString()?.includes('.PanelSection')) {
|
||||
return [mod[prop], mod];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
export const PanelSection = panelSection as FC<PanelSectionProps>;
|
||||
|
||||
export const PanelSectionRow = Object.values(mod).filter(
|
||||
(exp: any) => !exp?.toString()?.includes('.PanelSection'),
|
||||
)[0] as FC;
|
||||
@@ -1,44 +0,0 @@
|
||||
import { ReactNode, VFC } from 'react';
|
||||
|
||||
import { findModuleChild } from '../webpack';
|
||||
import { ItemProps } from './Item';
|
||||
|
||||
export interface ProgressBarItemProps extends ItemProps {
|
||||
indeterminate?: boolean;
|
||||
nTransitionSec?: number;
|
||||
nProgress?: number;
|
||||
focusable?: boolean;
|
||||
}
|
||||
|
||||
export interface ProgressBarProps {
|
||||
indeterminate?: boolean;
|
||||
nTransitionSec?: number;
|
||||
nProgress?: number;
|
||||
focusable?: boolean;
|
||||
}
|
||||
|
||||
export interface ProgressBarWithInfoProps extends ProgressBarItemProps {
|
||||
sTimeRemaining?: ReactNode;
|
||||
sOperationText?: ReactNode;
|
||||
}
|
||||
|
||||
export const ProgressBar = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.toString()?.includes('.ProgressBar,"standard"==')) return m[prop];
|
||||
}
|
||||
}) as VFC<ProgressBarProps>;
|
||||
|
||||
export const ProgressBarWithInfo = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.toString()?.includes('.ProgressBarFieldStatus},')) return m[prop];
|
||||
}
|
||||
}) as VFC<ProgressBarWithInfoProps>;
|
||||
|
||||
export const ProgressBarItem = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.toString()?.includes('"indeterminate","nTransitionSec"')) return m[prop];
|
||||
}
|
||||
}) as VFC<ProgressBarItemProps>;
|
||||
@@ -1,156 +0,0 @@
|
||||
import { Module, findModuleChild } from '../webpack';
|
||||
|
||||
export enum SideMenu {
|
||||
None,
|
||||
Main,
|
||||
QuickAccess,
|
||||
}
|
||||
|
||||
export enum QuickAccessTab {
|
||||
Notifications,
|
||||
RemotePlayTogetherControls,
|
||||
VoiceChat,
|
||||
Friends,
|
||||
Settings,
|
||||
Perf,
|
||||
Help,
|
||||
Decky,
|
||||
}
|
||||
|
||||
export enum DisplayStatus {
|
||||
Invalid = 0,
|
||||
Launching = 1,
|
||||
Uninstalling = 2,
|
||||
Installing = 3,
|
||||
Running = 4,
|
||||
Validating = 5,
|
||||
Updating = 6,
|
||||
Downloading = 7,
|
||||
Synchronizing = 8,
|
||||
ReadyToInstall = 9,
|
||||
ReadyToPreload = 10,
|
||||
ReadyToLaunch = 11,
|
||||
RegionRestricted = 12,
|
||||
PresaleOnly = 13,
|
||||
InvalidPlatform = 14,
|
||||
PreloadComplete = 16,
|
||||
BorrowerLocked = 17,
|
||||
UpdatePaused = 18,
|
||||
UpdateQueued = 19,
|
||||
UpdateRequired = 20,
|
||||
UpdateDisabled = 21,
|
||||
DownloadPaused = 22,
|
||||
DownloadQueued = 23,
|
||||
DownloadRequired = 24,
|
||||
DownloadDisabled = 25,
|
||||
LicensePending = 26,
|
||||
LicenseExpired = 27,
|
||||
AvailForFree = 28,
|
||||
AvailToBorrow = 29,
|
||||
AvailGuestPass = 30,
|
||||
Purchase = 31,
|
||||
Unavailable = 32,
|
||||
NotLaunchable = 33,
|
||||
CloudError = 34,
|
||||
CloudOutOfDate = 35,
|
||||
Terminating = 36,
|
||||
}
|
||||
|
||||
export type AppOverview = {
|
||||
appid: string;
|
||||
display_name: string;
|
||||
display_status: DisplayStatus;
|
||||
sort_as: string;
|
||||
};
|
||||
|
||||
export interface MenuStore {
|
||||
OpenSideMenu(sideMenu: SideMenu): void;
|
||||
OpenQuickAccessMenu(quickAccessTab?: QuickAccessTab): void;
|
||||
OpenMainMenu(): void;
|
||||
}
|
||||
|
||||
export interface WindowRouter {
|
||||
BrowserWindow: Window;
|
||||
MenuStore: MenuStore;
|
||||
Navigate(path: string): void;
|
||||
NavigateToChat(): void;
|
||||
NavigateToSteamWeb(url: string): void;
|
||||
NavigateBack(): void;
|
||||
NavigateToWebRoute(unknown?: any, unknown2?: any): void;
|
||||
}
|
||||
|
||||
export interface WindowStore {
|
||||
GamepadUIMainWindowInstance?: WindowRouter; // Current
|
||||
SteamUIWindows: WindowRouter[];
|
||||
OverlayWindows: WindowRouter[]; // Used by desktop GamepadUI
|
||||
}
|
||||
|
||||
export interface Router {
|
||||
WindowStore?: WindowStore;
|
||||
CloseSideMenus(): void;
|
||||
Navigate(path: string): void;
|
||||
NavigateToAppProperties(): void;
|
||||
NavigateToExternalWeb(url: string): void;
|
||||
NavigateToInvites(): void;
|
||||
NavigateToChat(): void;
|
||||
NavigateToLibraryTab(): void;
|
||||
NavigateToLayoutPreview(e: unknown): void;
|
||||
OpenPowerMenu(unknown?: any): void;
|
||||
get RunningApps(): AppOverview[];
|
||||
get MainRunningApp(): AppOverview | undefined;
|
||||
}
|
||||
|
||||
export const Router = findModuleChild((m: Module) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.Navigate && m[prop]?.NavigationManager) return m[prop];
|
||||
}
|
||||
}) as Router;
|
||||
|
||||
export interface Navigation {
|
||||
Navigate(path: string): void;
|
||||
NavigateBack(): void;
|
||||
NavigateToAppProperties(): void;
|
||||
NavigateToExternalWeb(url: string): void;
|
||||
NavigateToInvites(): void;
|
||||
NavigateToChat(): void;
|
||||
NavigateToLibraryTab(): void;
|
||||
NavigateToLayoutPreview(e: unknown): void;
|
||||
NavigateToSteamWeb(url: string): void;
|
||||
NavigateToWebRoute(unknown?: any, unknown2?: any): void;
|
||||
OpenSideMenu(sideMenu: SideMenu): void;
|
||||
OpenQuickAccessMenu(quickAccessTab?: QuickAccessTab): void;
|
||||
OpenMainMenu(): void;
|
||||
OpenPowerMenu(unknown?: any): void;
|
||||
CloseSideMenus(): void;
|
||||
}
|
||||
|
||||
export const Navigation = {
|
||||
Navigate: Router.Navigate.bind(Router),
|
||||
NavigateBack: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateBack.bind(
|
||||
Router.WindowStore.GamepadUIMainWindowInstance,
|
||||
),
|
||||
NavigateToAppProperties: Router.NavigateToAppProperties.bind(Router),
|
||||
NavigateToExternalWeb: Router.NavigateToExternalWeb.bind(Router),
|
||||
NavigateToInvites: Router.NavigateToInvites.bind(Router),
|
||||
NavigateToChat: Router.NavigateToChat.bind(Router),
|
||||
NavigateToLibraryTab: Router.NavigateToLibraryTab.bind(Router),
|
||||
NavigateToLayoutPreview: Router.NavigateToLayoutPreview.bind(Router),
|
||||
NavigateToSteamWeb: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateToSteamWeb.bind(
|
||||
Router.WindowStore.GamepadUIMainWindowInstance,
|
||||
),
|
||||
NavigateToWebRoute: Router.WindowStore?.GamepadUIMainWindowInstance?.NavigateToWebRoute.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;
|
||||
@@ -1,33 +0,0 @@
|
||||
import { ReactNode, VFC } from 'react';
|
||||
|
||||
import { Module, findModuleChild } from '../webpack';
|
||||
|
||||
export interface SidebarNavigationPage {
|
||||
title: string;
|
||||
content: ReactNode;
|
||||
icon?: ReactNode;
|
||||
visible?: boolean;
|
||||
hideTitle?: boolean;
|
||||
identifier?: string;
|
||||
route?: string;
|
||||
link?: string;
|
||||
padding?: 'none' | 'compact';
|
||||
}
|
||||
|
||||
export interface SidebarNavigationProps {
|
||||
title?: string;
|
||||
pages: SidebarNavigationPage[];
|
||||
showTitle?: boolean;
|
||||
disableRouteReporting?: boolean;
|
||||
page?: string;
|
||||
onPageRequested?: (page: string) => void;
|
||||
}
|
||||
|
||||
export const SidebarNavigation = findModuleChild((mod: Module) => {
|
||||
for (let prop in mod) {
|
||||
if (mod[prop]?.toString()?.includes('"disableRouteReporting"')) {
|
||||
return mod[prop];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}) as VFC<SidebarNavigationProps>;
|
||||
@@ -1,8 +0,0 @@
|
||||
import { FC, SVGAttributes } from 'react';
|
||||
|
||||
import { IconsModule } from '../webpack';
|
||||
|
||||
// TODO type this and other icons?
|
||||
export const Spinner = Object.values(IconsModule).find(
|
||||
(mod: any) => mod?.toString && /Spinner\)}\),.\.createElement\(\"path\",{d:\"M18 /.test(mod.toString()),
|
||||
) as FC<SVGAttributes<SVGElement>>;
|
||||
@@ -1,300 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { FC, SVGAttributes } from 'react';
|
||||
|
||||
import { findModuleChild } from '../webpack';
|
||||
|
||||
export const SteamSpinner = findModuleChild((m) => {
|
||||
if (typeof m !== 'object') return undefined;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.toString()?.includes('Steam Spinner') && m[prop].toString().includes('PreloadThrobber'))
|
||||
return m[prop];
|
||||
}
|
||||
}) as FC<SVGAttributes<SVGElement>>;
|
||||
@@ -1,134 +0,0 @@
|
||||
import { FC, ReactNode, createElement, useEffect, useState } from 'react';
|
||||
|
||||
import { fakeRenderComponent, findInReactTree, sleep } from '../utils';
|
||||
import { findModule } from '../webpack';
|
||||
import { FooterLegendProps } from './FooterLegend';
|
||||
import { SteamSpinner } from './SteamSpinner';
|
||||
|
||||
/**
|
||||
* Individual tab objects for the Tabs component
|
||||
*
|
||||
* `id` ID of this tab, can be used with activeTab to auto-focus a given tab
|
||||
* `title` Title shown in the header bar
|
||||
* `renderTabAddon` Return a {@link ReactNode} to render it next to the tab title, i.e. the counts for each tab on the Media page
|
||||
* `content` Content of the tab
|
||||
* `footer` Sets up button handlers and labels
|
||||
*/
|
||||
export interface Tab {
|
||||
id: string;
|
||||
title: string;
|
||||
renderTabAddon?: () => ReactNode;
|
||||
content: ReactNode;
|
||||
footer?: FooterLegendProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Props for the {@link Tabs}
|
||||
*
|
||||
* `tabs` array of {@link Tab}
|
||||
* `activeTab` tab currently active, needs to be one of the tabs {@link Tab.id}, must be set using a `useState` in the `onShowTab` handler
|
||||
* `onShowTab` Called when the active tab should change, needs to set `activeTab`. See example.
|
||||
* `autoFocusContents` Whether to automatically focus the tab contents or not.
|
||||
* `footer` Sets up button handlers and labels
|
||||
*
|
||||
* @example
|
||||
* const Component: FC = () => {
|
||||
* const [currentTab, setCurrentTab] = useState<string>("Tab1");
|
||||
*
|
||||
* return (
|
||||
* <Tabs
|
||||
* title="Theme Manager"
|
||||
* activeTab={currentTabRoute}
|
||||
* onShowTab={(tabID: string) => {
|
||||
* setCurrentTabRoute(tabID);
|
||||
* }}
|
||||
* tabs={[
|
||||
* {
|
||||
* title: "Tab 1",
|
||||
* content: <Tab1Component />,
|
||||
* id: "Tab1",
|
||||
* },
|
||||
* {
|
||||
* title: "Tab 2",
|
||||
* content: <Tab2Component />,
|
||||
* id: "Tab2",
|
||||
* },
|
||||
* ]}
|
||||
* />
|
||||
* );
|
||||
* };
|
||||
*/
|
||||
export interface TabsProps {
|
||||
tabs: Tab[];
|
||||
activeTab: string;
|
||||
onShowTab: (tab: string) => void;
|
||||
autoFocusContents?: boolean;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return (tabsComponent = fakeRenderComponent(
|
||||
() => {
|
||||
return findInReactTree(
|
||||
findInReactTree(
|
||||
// @ts-ignore
|
||||
window.DeckyPluginLoader.routerHook.routes
|
||||
.find((x: any) => x.props.path == '/library/app/:appid/achievements')
|
||||
.props.children.type(),
|
||||
(x) => x?.props?.scrollTabsTop,
|
||||
).type({ appid: 1 }),
|
||||
(x) => x?.props?.tabs,
|
||||
).type;
|
||||
},
|
||||
{
|
||||
useRef: () => ({ current: { reaction: { track: () => {} } } }),
|
||||
useContext: () => ({ match: { params: { appid: 1 } } }),
|
||||
useMemo: () => ({ data: {} }),
|
||||
},
|
||||
));
|
||||
};
|
||||
|
||||
let oldTabs: any;
|
||||
|
||||
try {
|
||||
const oldTabsModule = findModule((m: any) => {
|
||||
if (typeof m !== 'object') return false;
|
||||
for (let prop in m) {
|
||||
if (m[prop]?.Unbleed) return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (oldTabsModule)
|
||||
oldTabs = Object.values(oldTabsModule).find((x: any) => x?.type?.toString()?.includes('((function(){'));
|
||||
} catch (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>);
|
||||
@@ -1,478 +0,0 @@
|
||||
import { findModule } from '../webpack';
|
||||
|
||||
type QuickAccessMenuClasses = Record<
|
||||
| 'ActiveTab'
|
||||
| 'AllTabContents'
|
||||
| 'BatteryDetailsLabels'
|
||||
| 'BatteryIcon'
|
||||
| 'BatteryPercentageLabel'
|
||||
| 'BatteryProjectedLabel'
|
||||
| 'BatteryProjectedValue'
|
||||
| 'BatterySectionContainer'
|
||||
| 'Blocked'
|
||||
| 'ComingSoon'
|
||||
| 'Container'
|
||||
| 'ContentTransition'
|
||||
| 'Down'
|
||||
| 'EmptyNotifications'
|
||||
| 'Enter'
|
||||
| 'EnterActive'
|
||||
| 'Exit'
|
||||
| 'ExitActive'
|
||||
| 'FooterBoxShadow'
|
||||
| 'FriendsListTabPanel'
|
||||
| 'FriendsTitle'
|
||||
| 'FullHeight'
|
||||
| 'HeaderAndFooterVisible'
|
||||
| 'HeaderContainer'
|
||||
| 'ItemFocusAnim-darkGrey'
|
||||
| 'ItemFocusAnim-darkerGrey'
|
||||
| 'ItemFocusAnim-darkerGrey-nocolor'
|
||||
| 'ItemFocusAnim-green'
|
||||
| 'ItemFocusAnim-grey'
|
||||
| 'ItemFocusAnimBorder-darkGrey'
|
||||
| 'KeyboardButton'
|
||||
| 'Label'
|
||||
| 'LowBattery'
|
||||
| 'LowBatteryGauge'
|
||||
| 'Menu'
|
||||
| 'Open'
|
||||
| 'PanelExitAnchor'
|
||||
| 'PanelOuterNav'
|
||||
| 'PanelSection'
|
||||
| 'PanelSectionRow'
|
||||
| 'PanelSectionTitle'
|
||||
| 'QuickAccessMenu'
|
||||
| 'ReallyLow'
|
||||
| 'Remaining'
|
||||
| 'Selected'
|
||||
| 'Tab'
|
||||
| 'TabContentColumn'
|
||||
| 'TabGroupPanel'
|
||||
| 'TabPanelHidden'
|
||||
| 'Tabs'
|
||||
| 'Text'
|
||||
| 'Title'
|
||||
| 'TransitionMenuDelay'
|
||||
| 'Up'
|
||||
| 'ViewPlaceholder'
|
||||
| 'VoiceTab'
|
||||
| 'duration-app-launch'
|
||||
| 'focusAnimation'
|
||||
| 'hoverAnimation',
|
||||
string
|
||||
>;
|
||||
|
||||
type ScrollPanelClasses = Record<'ScrollBoth' | 'ScrollPanel' | 'ScrollX' | 'ScrollY', string>;
|
||||
|
||||
type GamepadDialogClasses = Record<
|
||||
| 'duration-app-launch'
|
||||
| 'GamepadDialogContent'
|
||||
| 'GamepadDialogContent_InnerWidth'
|
||||
| 'Field'
|
||||
| 'Button'
|
||||
| 'NoMinWidth'
|
||||
| 'ActiveAndUnfocused'
|
||||
| 'StandaloneFieldSeparator'
|
||||
| 'StandardPadding'
|
||||
| 'CompactPadding'
|
||||
| 'WithDescription'
|
||||
| 'WithBottomSeparatorStandard'
|
||||
| 'WithBottomSeparatorThick'
|
||||
| 'HighlightOnFocus'
|
||||
| 'ItemFocusAnim-darkerGrey'
|
||||
| 'ItemFocusAnim-darkGrey'
|
||||
| 'WithBottomSeparator'
|
||||
| 'Disabled'
|
||||
| 'Clickable'
|
||||
| 'FieldClickTarget'
|
||||
| 'FieldChildren'
|
||||
| 'FieldLeadIcon'
|
||||
| 'FieldLabelRow'
|
||||
| 'VerticalAlignCenter'
|
||||
| 'InlineWrapShiftsChildrenBelow'
|
||||
| 'ExtraPaddingOnChildrenBelow'
|
||||
| 'ChildrenWidthFixed'
|
||||
| 'ChildrenWidthGrow'
|
||||
| 'WithFirstRow'
|
||||
| 'WithChildrenBelow'
|
||||
| 'FieldLabel'
|
||||
| 'FieldLabelValue'
|
||||
| 'FieldDescription'
|
||||
| 'ModalPosition'
|
||||
| 'WithStandardPadding'
|
||||
| 'slideInAnimation'
|
||||
| 'BasicTextInput'
|
||||
| 'Toggle'
|
||||
| 'ToggleRail'
|
||||
| 'On'
|
||||
| 'ToggleSwitch'
|
||||
| 'LabelFieldValue'
|
||||
| 'DropDownControlButtonContents'
|
||||
| 'Spacer'
|
||||
| 'ControlsListOuterPanel'
|
||||
| 'StandardSpacing'
|
||||
| 'ExtraSpacing'
|
||||
| 'AlignRight'
|
||||
| 'AlignLeft'
|
||||
| 'AlignCenter'
|
||||
| 'ControlsListChild'
|
||||
| 'QuickAccess-Menu'
|
||||
| 'BigButtons'
|
||||
| 'BottomButtons'
|
||||
| 'ItemFocusAnim-darkerGrey-nocolor'
|
||||
| 'ItemFocusAnim-grey'
|
||||
| 'ItemFocusAnimBorder-darkGrey'
|
||||
| 'ItemFocusAnim-green'
|
||||
| 'focusAnimation'
|
||||
| 'hoverAnimation',
|
||||
string
|
||||
>;
|
||||
|
||||
type QuickAccessControlsClasses = Record<
|
||||
| 'duration-app-launch'
|
||||
| 'PanelSection'
|
||||
| 'PanelSectionTitle'
|
||||
| 'Text'
|
||||
| 'PanelSectionRow'
|
||||
| 'Label'
|
||||
| 'ComingSoon'
|
||||
| 'LowBattery'
|
||||
| 'ReallyLow'
|
||||
| 'LowBatteryGauge'
|
||||
| 'Remaining'
|
||||
| 'EmptyNotifications'
|
||||
| 'BatterySectionContainer'
|
||||
| 'BatteryIcon'
|
||||
| 'BatteryPercentageLabel'
|
||||
| 'BatteryDetailsLabels'
|
||||
| 'BatteryProjectedValue'
|
||||
| 'BatteryProjectedLabel'
|
||||
| 'ItemFocusAnim-darkerGrey-nocolor'
|
||||
| 'ItemFocusAnim-darkerGrey'
|
||||
| 'ItemFocusAnim-darkGrey'
|
||||
| 'ItemFocusAnim-grey'
|
||||
| 'ItemFocusAnimBorder-darkGrey'
|
||||
| 'ItemFocusAnim-green'
|
||||
| 'focusAnimation'
|
||||
| 'hoverAnimation',
|
||||
string
|
||||
>;
|
||||
|
||||
type UpdaterFieldClasses = Record<
|
||||
| 'duration-app-launch'
|
||||
| 'OOBEUpdateStatusContainer'
|
||||
| 'UpdateScreen'
|
||||
| 'UpdatePanel'
|
||||
| 'CurrentStatus'
|
||||
| 'TotalUpdateSize'
|
||||
| 'ProgressInfoContainer'
|
||||
| 'TimeRemaining'
|
||||
| 'BatteryLowWarning'
|
||||
| 'fadeInAnimation'
|
||||
| 'ProgressStatus'
|
||||
| 'UpdateStatusContainer'
|
||||
| 'UpdaterFieldStatusSuccess'
|
||||
| 'UpdaterFieldStatusApplying'
|
||||
| 'TextContainer'
|
||||
| 'ApplyingText'
|
||||
| 'UpdateBytesRemaining'
|
||||
| 'Label'
|
||||
| 'Numerator'
|
||||
| 'Separator'
|
||||
| 'Denominator'
|
||||
| 'PatchNotes'
|
||||
| 'PostedTime'
|
||||
| 'EventDetailTitle'
|
||||
| 'EventDetailsSubTitle'
|
||||
| 'EventDetailsBody'
|
||||
| 'InsufficientBatteryText'
|
||||
| 'UnsupportedHardwareWarning'
|
||||
| 'Title'
|
||||
| 'Text'
|
||||
| 'Body'
|
||||
| 'ItemFocusAnim-darkerGrey-nocolor'
|
||||
| 'ItemFocusAnim-darkerGrey'
|
||||
| 'ItemFocusAnim-darkGrey'
|
||||
| 'ItemFocusAnim-grey'
|
||||
| 'ItemFocusAnimBorder-darkGrey'
|
||||
| 'ItemFocusAnim-green'
|
||||
| 'focusAnimation'
|
||||
| 'hoverAnimation',
|
||||
string
|
||||
>;
|
||||
|
||||
type PlaySectionClasses = Record<
|
||||
| 'AchievementCountLabel'
|
||||
| 'AchievementProgressRow'
|
||||
| 'ActionSection'
|
||||
| 'AppButtonsContainer'
|
||||
| 'Arrow'
|
||||
| 'AvatarAndPersona'
|
||||
| 'BreakNarrow'
|
||||
| 'BreakShort'
|
||||
| 'BreakTall'
|
||||
| 'BreakUltraWide'
|
||||
| 'BreakWide'
|
||||
| 'ClickablePlayBarItem'
|
||||
| 'CloudStatusIcon'
|
||||
| 'CloudStatusLabel'
|
||||
| 'CloudStatusRow'
|
||||
| 'CloudSyncProblem'
|
||||
| 'CloudSynching'
|
||||
| 'ComingSoon'
|
||||
| 'Container'
|
||||
| 'DetailsProgressBar'
|
||||
| 'DetailsProgressContainer'
|
||||
| 'DetailsSection'
|
||||
| 'DetailsSectionExtra'
|
||||
| 'DetailsSectionStatus'
|
||||
| 'DotDotDot'
|
||||
| 'DownloadPaused'
|
||||
| 'DownloadProgressBar'
|
||||
| 'Downloading'
|
||||
| 'FavoriteButton'
|
||||
| 'Favorited'
|
||||
| 'GameInfoButton'
|
||||
| 'GameStat'
|
||||
| 'GameStatIcon'
|
||||
| 'GameStatIconForced'
|
||||
| 'GameStatRight'
|
||||
| 'GameStatsSection'
|
||||
| 'GamepadUIBreakNarrow'
|
||||
| 'GamepadUIBreakShort'
|
||||
| 'GamepadUIBreakWide'
|
||||
| 'Glassy'
|
||||
| 'HideWhenNarrow'
|
||||
| 'Icon'
|
||||
| 'Icons'
|
||||
| 'InPage'
|
||||
| 'InnerContainer'
|
||||
| 'InvalidPlatform'
|
||||
| 'ItemFocusAnim-darkGrey'
|
||||
| 'ItemFocusAnim-darkerGrey'
|
||||
| 'ItemFocusAnim-darkerGrey-nocolor'
|
||||
| 'ItemFocusAnim-green'
|
||||
| 'ItemFocusAnim-grey'
|
||||
| 'ItemFocusAnimBorder-darkGrey'
|
||||
| 'Label'
|
||||
| 'LastPlayed'
|
||||
| 'LastPlayedInfo'
|
||||
| 'MenuActive'
|
||||
| 'MenuButton'
|
||||
| 'MiniAchievements'
|
||||
| 'OfflineMode'
|
||||
| 'OnlyDownloadBar'
|
||||
| 'PermanentlyUnavailable'
|
||||
| 'PlayBar'
|
||||
| 'PlayBarCloudStatusContainer'
|
||||
| 'PlayBarDetailLabel'
|
||||
| 'PlayBarGameIcon'
|
||||
| 'PlayBarGameName'
|
||||
| 'PlayBarIconAndGame'
|
||||
| 'PlayBarLabel'
|
||||
| 'Playtime'
|
||||
| 'PlaytimeIcon'
|
||||
| 'PlaytimeIconForced'
|
||||
| 'PortraitBar'
|
||||
| 'Presale'
|
||||
| 'RecentlyUpdated'
|
||||
| 'RecentlyUpdatedIcon'
|
||||
| 'RecentlyUpdatedLink'
|
||||
| 'RecentlyUpdatedText'
|
||||
| 'RightBreakNarrow'
|
||||
| 'RightBreakUltraNarrow'
|
||||
| 'RightBreakUltraWide'
|
||||
| 'RightBreakWide'
|
||||
| 'RightControls'
|
||||
| 'Row'
|
||||
| 'SharedLibrary'
|
||||
| 'StatusAndStats'
|
||||
| 'StatusNameContainer'
|
||||
| 'StickyHeader'
|
||||
| 'StickyHeaderShadow'
|
||||
| 'SuperimposedGridItems'
|
||||
| 'SyncAnim'
|
||||
| 'Visible'
|
||||
| 'duration-app-launch'
|
||||
| 'favorited'
|
||||
| 'focusAnimation'
|
||||
| 'hoverAnimation',
|
||||
string
|
||||
>;
|
||||
|
||||
type GamepadSliderClasses = Record<
|
||||
| 'error-shake-duration'
|
||||
| 'SliderControlPanelGroup'
|
||||
| 'SliderControlAndNotches'
|
||||
| 'WithDefaultValue'
|
||||
| 'SliderControl'
|
||||
| 'Disabled'
|
||||
| 'SliderTrack'
|
||||
| 'SliderHasNotches'
|
||||
| 'SliderTrackDark'
|
||||
| 'SliderHandleContainer'
|
||||
| 'VerticalLineSliderHandleContainer'
|
||||
| 'ParenSliderHandleContainer'
|
||||
| 'SliderHandle'
|
||||
| 'SliderHandleFocusPop'
|
||||
| 'VerticalLineSliderHandle'
|
||||
| 'ParenSliderHandle'
|
||||
| 'Left'
|
||||
| 'SliderControlWithIcon'
|
||||
| 'Icon'
|
||||
| 'SliderNotchContainer'
|
||||
| 'SliderNotch'
|
||||
| 'AlignToEnds'
|
||||
| 'SliderNotchLabel'
|
||||
| 'AlignToLeft'
|
||||
| 'AlignToRight'
|
||||
| 'SliderNotchTick'
|
||||
| 'TickActive'
|
||||
| 'LabelText'
|
||||
| 'DescriptionValue'
|
||||
| 'EditableValue'
|
||||
| 'FakeEditableValue'
|
||||
| 'RedBorder'
|
||||
| 'EditableValueSuffix'
|
||||
| 'ErrorShake'
|
||||
| 'error-shake'
|
||||
| 'CompoundSlider'
|
||||
| 'CompoundSliderSubSlider'
|
||||
| 'Right'
|
||||
| 'CompoundSliderSubSliderLabelContainer'
|
||||
| 'CompoundSliderSubSliderLabelPositioner'
|
||||
| 'CompoundSliderSubSliderLabel'
|
||||
| 'CompoundSliderSubSliderLabelInternal'
|
||||
| 'DefaultValueTickContainer'
|
||||
| 'DefaultValueTick',
|
||||
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'),
|
||||
);
|
||||
/**
|
||||
* @depreciated please use quickAccessMenuClasses instead
|
||||
*/
|
||||
export const staticClasses = quickAccessMenuClasses;
|
||||
export const scrollPanelClasses: ScrollPanelClasses = findModule(
|
||||
(mod) => typeof mod === 'object' && mod?.ScrollPanel?.includes('scrollpanel'),
|
||||
);
|
||||
/**
|
||||
* @depreciated please use scrollPanelClasses instead
|
||||
*/
|
||||
export const scrollClasses = scrollPanelClasses;
|
||||
export const gamepadDialogClasses: GamepadDialogClasses = findModule(
|
||||
(mod) => typeof mod === 'object' && mod?.GamepadDialogContent?.includes('gamepaddialog'),
|
||||
);
|
||||
export const quickAccessControlsClasses: QuickAccessControlsClasses = findModule(
|
||||
(mod) => typeof mod === 'object' && mod?.PanelSection?.includes('quickaccesscontrols'),
|
||||
);
|
||||
export const updaterFieldClasses: UpdaterFieldClasses = findModule(
|
||||
(mod) => typeof mod === 'object' && mod?.OOBEUpdateStatusContainer?.includes('updaterfield'),
|
||||
);
|
||||
export const playSectionClasses: PlaySectionClasses = findModule(
|
||||
(mod) => typeof mod === 'object' && mod?.Container?.includes('appdetailsplaysection'),
|
||||
);
|
||||
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_'),
|
||||
);
|
||||
6
src/globals/SteamClient.ts
Normal file
6
src/globals/SteamClient.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import {SteamClient} from "./steam-client";
|
||||
export * from "./steam-client/shared";
|
||||
|
||||
declare global {
|
||||
var SteamClient: SteamClient;
|
||||
}
|
||||
2
src/globals/index.ts
Normal file
2
src/globals/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './SteamClient';
|
||||
export * from './stores';
|
||||
1749
src/globals/steam-client/App.ts
Normal file
1749
src/globals/steam-client/App.ts
Normal file
File diff suppressed because it is too large
Load Diff
105
src/globals/steam-client/Auth.ts
Normal file
105
src/globals/steam-client/Auth.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { EResult, JsPbMessage, OperationResponse } from "./shared";
|
||||
import {EOSType} from "./system";
|
||||
|
||||
export interface Auth {
|
||||
/**
|
||||
* @returns a boolean indicating if the operation succeeded.
|
||||
*/
|
||||
ClearCachedSignInPin(): Promise<boolean>;
|
||||
|
||||
CurrentUserHasCachedSignInPin(): Promise<boolean>;
|
||||
|
||||
GetLocalHostname(): Promise<string>;
|
||||
|
||||
/**
|
||||
* @returns a ProtoBuf message. If deserialized, returns {@link CAuthentication_DeviceDetails}.
|
||||
*/
|
||||
GetMachineID(): Promise<ArrayBuffer>;
|
||||
|
||||
GetRefreshInfo(): Promise<AuthRefreshInfo>;
|
||||
|
||||
GetSteamGuardData(param0: string): Promise<SteamGuardData>;
|
||||
|
||||
/**
|
||||
* "Secured" refers to unshared.
|
||||
*/
|
||||
IsSecureComputer(): Promise<boolean>;
|
||||
|
||||
SetCachedSignInPin(pin: string): Promise<boolean>;
|
||||
|
||||
SetLoginToken(refreshToken: string, accountName: string): Promise<OperationResponse>;
|
||||
|
||||
SetSteamGuardData(accountName: string, newGuardData: string): void;
|
||||
|
||||
StartSignInFromCache(accountName: string, offlineMode: boolean): Promise<OperationResponse | void>;
|
||||
|
||||
UserHasCachedSignInPin(accountName: string): Promise<boolean>;
|
||||
|
||||
ValidateCachedSignInPin(accountName: string, pin: string): Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface AuthRefreshInfo {
|
||||
reason: number;
|
||||
account_name: string;
|
||||
login_id_token: string;
|
||||
}
|
||||
|
||||
export interface SteamGuardData {
|
||||
data: string;
|
||||
eresult: EResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* `deserializeBinary` argument:
|
||||
* ```
|
||||
* [
|
||||
* await SteamClient.System.GetOSType(),
|
||||
* await SteamClient.Auth.GetLocalHostname(),
|
||||
* await SteamClient.Auth.GetMachineID(),
|
||||
* ];
|
||||
* ```
|
||||
*/
|
||||
export interface CAuthentication_DeviceDetails extends JsPbMessage {
|
||||
client_count(): number | undefined;
|
||||
|
||||
device_friendly_name(): string | undefined;
|
||||
|
||||
gaming_device_type(): EGamingDeviceType | undefined;
|
||||
|
||||
machine_id(): Uint8Array | string;
|
||||
|
||||
os_type(): EOSType | undefined;
|
||||
|
||||
platform_type(): EAuthTokenPlatformType | undefined;
|
||||
|
||||
set_client_count(): any;
|
||||
|
||||
set_device_friendly_name(): any;
|
||||
|
||||
set_gaming_device_type(): any;
|
||||
|
||||
set_machine_id(): any;
|
||||
|
||||
set_os_type(): any;
|
||||
|
||||
set_platform_type(): any;
|
||||
}
|
||||
|
||||
export enum EAuthTokenPlatformType {
|
||||
Unknown,
|
||||
SteamClient,
|
||||
WebBrowser,
|
||||
MobileApp,
|
||||
}
|
||||
|
||||
export enum EGamingDeviceType {
|
||||
Unknown,
|
||||
StandardPC,
|
||||
Console = 256,
|
||||
PS3 = 272,
|
||||
Steambox = 288,
|
||||
Tesla = 320,
|
||||
Handheld = 512,
|
||||
Phone = 528,
|
||||
SteamDeck = 544,
|
||||
}
|
||||
56
src/globals/steam-client/Broadcast.ts
Normal file
56
src/globals/steam-client/Broadcast.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { EResult, Unregisterable } from "./shared";
|
||||
|
||||
export interface Broadcast {
|
||||
/**
|
||||
* Approves a viewer request for the broadcast.
|
||||
* @param steamId64 The SteamID64 of the user whose request is to be approved.
|
||||
*/
|
||||
ApproveViewerRequest(steamId64: string, param1: number): void;
|
||||
|
||||
/**
|
||||
* Invites a user identified by their SteamID64 to watch the broadcast.
|
||||
* @param steamId64 The SteamID64 of the user to invite.
|
||||
*/
|
||||
InviteToWatch(steamId64: string): Promise<EResult>;
|
||||
|
||||
/**
|
||||
* Registers a callback to be called when the broadcast status changes.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForBroadcastStatus(callback: (status: BroadcastStatus) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback to be called when viewer requests are received.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForViewerRequests(
|
||||
callback: (viewerFriendCode: number, param1: number, param2: number) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Rejects a viewer request for the broadcast.
|
||||
* @param steamId64 The SteamID64 of the user whose request is to be rejected.
|
||||
*/
|
||||
RejectViewerRequest(steamId64: string, param1: number): void;
|
||||
|
||||
/**
|
||||
* Stops the broadcast.
|
||||
*/
|
||||
StopBroadcasting(): void;
|
||||
}
|
||||
|
||||
export interface BroadcastStatus {
|
||||
broadcastid: string;
|
||||
nViewers: number;
|
||||
nRequests: number;
|
||||
bIsBroadcasting: boolean;
|
||||
bIsRecordingDesktop: boolean;
|
||||
eBroadcastReady: EResult;
|
||||
bBroadcastCapable: boolean;
|
||||
bMicrophoneEnabled: boolean;
|
||||
bMicrophoneActive: boolean;
|
||||
nCurrentFPS: number;
|
||||
nUploadKbps: number;
|
||||
}
|
||||
91
src/globals/steam-client/Browser.ts
Normal file
91
src/globals/steam-client/Browser.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
|
||||
export interface Browser {
|
||||
AddWordToDictionary(word: string): void;
|
||||
|
||||
ClearAllBrowsingData(): void;
|
||||
|
||||
ClearHistory(): void;
|
||||
|
||||
CloseDevTools(): void;
|
||||
|
||||
GetBrowserID(): Promise<number>;
|
||||
|
||||
GetSpellingSuggestions(word: string): string[];
|
||||
|
||||
GetSteamBrowserID(): Promise<number>; // 16-bit unsigned integer?
|
||||
|
||||
/**
|
||||
* Hides the mouse cursor until input.
|
||||
*/
|
||||
HideCursorUntilMouseEvent(): void;
|
||||
|
||||
/**
|
||||
* yup that's right, clientY and clientX are reversed
|
||||
*/
|
||||
InspectElement(clientY: number, clientX: number): void;
|
||||
|
||||
NotifyUserActivation(): void;
|
||||
|
||||
OpenDevTools(): void;
|
||||
|
||||
/**
|
||||
* Pastes the clipboard contents.
|
||||
*/
|
||||
Paste(): void;
|
||||
|
||||
/**
|
||||
* @note Not available on a created BrowserView.
|
||||
* @todo unconfirmed
|
||||
*/
|
||||
RegisterForGestureEvents(callback: (gesture: TouchGesture) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* @note Not available on a created BrowserView.
|
||||
*/
|
||||
RegisterForOpenNewTab: Unregisterable;
|
||||
|
||||
ReplaceMisspelling(param0: string): void;
|
||||
|
||||
/**
|
||||
* Restarts the Steam JS context.
|
||||
*/
|
||||
RestartJSContext(): void;
|
||||
|
||||
SetBackgroundThrottlingDisabled(value: boolean): void;
|
||||
|
||||
SetPendingFilePath(path: string): Promise<boolean>;
|
||||
|
||||
SetShouldExitSteamOnBrowserClosed(value: boolean): Promise<void>;
|
||||
|
||||
SetTouchGesturesToCancel(gestures: ETouchGesture[]): void;
|
||||
|
||||
/**
|
||||
* Prompts and downloads a file.
|
||||
* @param url The URL of the file to download.
|
||||
*/
|
||||
StartDownload(url: string): void;
|
||||
}
|
||||
|
||||
export interface TouchGesture {
|
||||
eTouchGesture: ETouchGesture;
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export enum ETouchGesture {
|
||||
None,
|
||||
Touch,
|
||||
Tap,
|
||||
DoubleTap,
|
||||
ShortPress,
|
||||
LongPress,
|
||||
LongTap,
|
||||
TwoFingerTap,
|
||||
TapCancelled,
|
||||
PinchBegin,
|
||||
PinchUpdate,
|
||||
PinchEnd,
|
||||
FlingStart,
|
||||
FlingCancelled,
|
||||
}
|
||||
39
src/globals/steam-client/ClientNotifications.ts
Normal file
39
src/globals/steam-client/ClientNotifications.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { BrowserContext } from "./shared";
|
||||
|
||||
export interface ClientNotifications {
|
||||
/**
|
||||
* Displays a Steam notification.
|
||||
* @param notification Notification type.
|
||||
* @param options Stringified object of {@link SteamNotificationOptions}.
|
||||
* @param callback
|
||||
*/
|
||||
DisplayClientNotification(
|
||||
notification: EClientUINotificationType,
|
||||
options: string,
|
||||
callback: (context: BrowserContext) => void,
|
||||
): void;
|
||||
|
||||
/**
|
||||
* @param notificationId The ID of the notification to handle.
|
||||
* @param handleAction `true` to execute the callback function associated with the notification.
|
||||
*/
|
||||
OnRespondToClientNotification(notificationId: number, handleAction: boolean): void;
|
||||
}
|
||||
|
||||
export interface SteamNotificationOptions {
|
||||
body: string;
|
||||
chatroomgroupid?: number;
|
||||
chatroomid?: number;
|
||||
icon?: string;
|
||||
state: string;
|
||||
/** A Steam64 ID. */
|
||||
steamid: string;
|
||||
tag?: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export enum EClientUINotificationType {
|
||||
GroupChatMessage = 1,
|
||||
FriendChatMessage,
|
||||
FriendPersonaState,
|
||||
}
|
||||
14
src/globals/steam-client/Cloud.ts
Normal file
14
src/globals/steam-client/Cloud.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface Cloud {
|
||||
/**
|
||||
* Resolves a synchronization conflict for an app in the cloud.
|
||||
* @param appId The ID of the app with the sync conflict.
|
||||
* @param keepLocal Whether to keep the local version during conflict resolution.
|
||||
*/
|
||||
ResolveAppSyncConflict(appId: number, keepLocal: boolean): void;
|
||||
|
||||
/**
|
||||
* Retries syncing an app with the cloud.
|
||||
* @param appId The ID of the app to retry syncing.
|
||||
*/
|
||||
RetryAppSync(appId: number): void;
|
||||
}
|
||||
24
src/globals/steam-client/CommunityItems.ts
Normal file
24
src/globals/steam-client/CommunityItems.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
export interface CommunityItems {
|
||||
/*
|
||||
DownloadMovie(e) {
|
||||
return (0, o.mG)(this, void 0, void 0, (function* () {
|
||||
if (0 != e.movie_webm_local_path.length) return !0;
|
||||
let t = yield SteamClient.CommunityItems.DownloadItemAsset(e.communityitemid, w, e.movie_webm),
|
||||
n = 1 == t.result;
|
||||
if (n) {
|
||||
e.movie_webm_local_path = t.path;
|
||||
let n = [];
|
||||
this.m_startupMovies.forEach((t => {
|
||||
t.movie_webm == e.movie_webm ? n.push(e) : n.push(t)
|
||||
})), this.m_startupMovies = n
|
||||
}
|
||||
return n
|
||||
}))
|
||||
}
|
||||
*/
|
||||
DownloadItemAsset(communityItemId: string, param1: any, param2: string): any;
|
||||
|
||||
GetItemAssetPath(communityItemId: string, param1: any, param2: string): any;
|
||||
|
||||
RemoveDownloadedItemAsset(communityItemId: string, param1: any, param2: string): any;
|
||||
}
|
||||
43
src/globals/steam-client/Console.ts
Normal file
43
src/globals/steam-client/Console.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
|
||||
/**
|
||||
* Represents the console functionality for executing commands and handling spew output.
|
||||
*/
|
||||
export interface Console {
|
||||
/**
|
||||
* Executes a console command.
|
||||
* @param command The command to execute in the console.
|
||||
*/
|
||||
ExecCommand(command: string): void;
|
||||
|
||||
/**
|
||||
* Retrieves autocomplete suggestions for a given console command.
|
||||
* @param command The console command to provide autocomplete suggestions for.
|
||||
* @returns an array of autocomplete suggestions.
|
||||
*/
|
||||
GetAutocompleteSuggestions(command: string): Promise<string[]>;
|
||||
|
||||
/**
|
||||
* Registers a callback function to receive spew output.
|
||||
* @param callback The callback function that will receive spew output.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForSpewOutput(callback: (output: SpewOutput) => void): Unregisterable;
|
||||
}
|
||||
|
||||
export type SpewType_t = "assert" | "error" | "warning" | "info" | "input";
|
||||
|
||||
/**
|
||||
* Represents spew output information.
|
||||
*/
|
||||
export interface SpewOutput {
|
||||
/**
|
||||
* The content of the spew output.
|
||||
*/
|
||||
spew: string;
|
||||
|
||||
/**
|
||||
* The type or category of the spew output.
|
||||
*/
|
||||
spew_type: SpewType_t;
|
||||
}
|
||||
12
src/globals/steam-client/Customization.ts
Normal file
12
src/globals/steam-client/Customization.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface Customization {
|
||||
GenerateLocalStartupMoviesThumbnails(param0: number): Promise<number>;
|
||||
|
||||
//param0: "startupmovies"
|
||||
GetDownloadedStartupMovies(param0: string): Promise<StartupMovie[]>;
|
||||
|
||||
GetLocalStartupMovies(): Promise<StartupMovie[]>;
|
||||
}
|
||||
|
||||
export interface StartupMovie {
|
||||
strMovieURL: string;
|
||||
}
|
||||
175
src/globals/steam-client/Downloads.ts
Normal file
175
src/globals/steam-client/Downloads.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
import {EAppUpdateError} from "./App";
|
||||
|
||||
/**
|
||||
* Represents functions related to managing downloads in Steam.
|
||||
*/
|
||||
export interface Downloads {
|
||||
/**
|
||||
* Enables or disables all downloads in Steam.
|
||||
* @param enable True to enable downloads, false to disable.
|
||||
*/
|
||||
EnableAllDownloads(enable: boolean): void;
|
||||
|
||||
/**
|
||||
* Moves the update for a specific app down the download queue.
|
||||
* @param appId The ID of the application to move.
|
||||
*/
|
||||
MoveAppUpdateDown(appId: number): void;
|
||||
|
||||
/**
|
||||
* Moves the update for a specific app up the download queue.
|
||||
* @param appId The ID of the application to move.
|
||||
*/
|
||||
MoveAppUpdateUp(appId: number): void;
|
||||
|
||||
PauseAppUpdate(appId: number): void; // Broken? It seems to be removing it from download list like RemoveFromDownloadList
|
||||
|
||||
/**
|
||||
* Adds the update for a specific app to the download queue.
|
||||
* @param appId The ID of the application to queue.
|
||||
*/
|
||||
QueueAppUpdate(appId: number): void;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when download items change.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForDownloadItems(
|
||||
callback: (isDownloading: boolean, downloadItems: DownloadItem[]) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when download overview changes.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForDownloadOverview(callback: (overview: DownloadOverview) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Removes the update for a specific app from the download list and places it in the unscheduled list.
|
||||
* @param appId The ID of the application to remove.
|
||||
*/
|
||||
RemoveFromDownloadList(appId: number): void;
|
||||
|
||||
/**
|
||||
* Resumes the update for a specific app in the queue.
|
||||
* @param appId The ID of the application to resume.
|
||||
*/
|
||||
ResumeAppUpdate(appId: number): void;
|
||||
|
||||
/**
|
||||
* Sets an app to launch when its download is complete.
|
||||
* @param appId The ID of the application to set.
|
||||
*/
|
||||
SetLaunchOnUpdateComplete(appId: number): void;
|
||||
|
||||
/**
|
||||
* Sets the queue index for an app in the download queue.
|
||||
* @param appId The ID of the application to set the index for.
|
||||
* @param index The index to set.
|
||||
* @remarks Index of 0 is the current download in progress.
|
||||
*/
|
||||
SetQueueIndex(appId: number, index: number): void;
|
||||
|
||||
/**
|
||||
* Suspends or resumes download throttling.
|
||||
* @param suspend Whether to suspend or resume download throttling.
|
||||
*/
|
||||
SuspendDownloadThrottling(suspend: boolean): void;
|
||||
|
||||
/**
|
||||
* Suspends or resumes local transfers.
|
||||
* @param suspend Whether to suspend or resume local transfers.
|
||||
*/
|
||||
SuspendLanPeerContent(suspend: boolean): void;
|
||||
}
|
||||
|
||||
export interface DownloadItem {
|
||||
/** True if this app is currently downloading */
|
||||
active: boolean;
|
||||
/** Appid of app */
|
||||
appid: number;
|
||||
/** Current build ID for the installed app, zero if the app isn't installed yet */
|
||||
buildid: number;
|
||||
/** True if this update has been completed */
|
||||
completed: boolean;
|
||||
/** For completed downloads, time of completion, 0 if not completed */
|
||||
completed_time: number;
|
||||
deferred_time: number;
|
||||
/** Bytes already downloaded, sum across all content types */
|
||||
downloaded_bytes: number;
|
||||
/** If true, game will launch when its download completes successfully */
|
||||
launch_on_completion: boolean;
|
||||
/** True if this app has been paused by the user or the system */
|
||||
paused: boolean;
|
||||
/** Queue index, -1 if the item is unqueued */
|
||||
queue_index: number;
|
||||
/** Build ID that this download is moving towards. This can be the same as buildid.*/
|
||||
target_buildid: number;
|
||||
/** Total bytes to download, sum across all content types */
|
||||
total_bytes: number;
|
||||
/**
|
||||
* Update error description, when paused and there has been an error.
|
||||
* Unlocalized and shouldn't be displayed to the user.
|
||||
*/
|
||||
update_error: string;
|
||||
update_result: EAppUpdateError;
|
||||
update_type_info: UpdateTypeInfo[];
|
||||
}
|
||||
|
||||
export interface DownloadOverview {
|
||||
/** Set if we are downloading from LAN peer content server */
|
||||
lan_peer_hostname: string;
|
||||
/** True if all downloads are paused */
|
||||
paused: boolean;
|
||||
/** True if download throttling has been temporarily suspended for the current download */
|
||||
throttling_suspended: boolean;
|
||||
/** Appid of currently updating app */
|
||||
update_appid: number;
|
||||
/** Bytes already downloaded */
|
||||
update_bytes_downloaded: number;
|
||||
/** Bytes already processed in current phase - resets to zero when update stage changes */
|
||||
update_bytes_processed: number;
|
||||
/** Bytes already staged */
|
||||
update_bytes_staged: number;
|
||||
/** Total bytes to download */
|
||||
update_bytes_to_download: number;
|
||||
/** Total bytes to process in current phase - resets to zero when update stage changes */
|
||||
update_bytes_to_process: number;
|
||||
/** Total bytes to be staged */
|
||||
update_bytes_to_stage: number;
|
||||
/** Current disk throughput estimate */
|
||||
update_disc_bytes_per_second: number;
|
||||
/** True if the current update is an initial install */
|
||||
update_is_install: boolean;
|
||||
/** True if download and staging sizes are prefetch estimates */
|
||||
update_is_prefetch_estimate: boolean;
|
||||
/** True if the current update is for shader update */
|
||||
update_is_shader: boolean;
|
||||
/** True if the client is running in peer content server mode serving other peers */
|
||||
update_is_upload: boolean;
|
||||
/** True if the current update is for workshop content */
|
||||
update_is_workshop: boolean;
|
||||
/** Current bandwidth estimate for download */
|
||||
update_network_bytes_per_second: number;
|
||||
/** Peak bandwidth estimate for download */
|
||||
update_peak_network_bytes_per_second: number;
|
||||
/** Estimate of remaining time (in seconds) until download completes (not including staging) */
|
||||
update_seconds_remaining: number;
|
||||
/** Time current update started */
|
||||
update_start_time: number;
|
||||
update_state: 'None' | 'Starting' | 'Updating' | 'Stopping';
|
||||
}
|
||||
|
||||
export interface UpdateTypeInfo {
|
||||
/** True if this content type had an update and it has completed */
|
||||
completed_update: boolean;
|
||||
/** Bytes already downloaded for this content type */
|
||||
downloaded_bytes: number;
|
||||
/** True if this content type has or had an update */
|
||||
has_update: boolean;
|
||||
/** Total bytes to download for this content type */
|
||||
total_bytes: number;
|
||||
}
|
||||
30
src/globals/steam-client/FamilySharing.ts
Normal file
30
src/globals/steam-client/FamilySharing.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { EResult, Unregisterable } from "./shared";
|
||||
|
||||
/**
|
||||
* Represents functions related to Steam Family Sharing.
|
||||
*/
|
||||
export interface FamilySharing {
|
||||
GetAvailableLenders(appId: number): Promise<Lender[]>;
|
||||
|
||||
RegisterForKickedBorrower: Unregisterable;
|
||||
|
||||
SetPreferredLender(appId: number, param1: number): Promise<EResult>;
|
||||
}
|
||||
|
||||
interface LenderDLC {
|
||||
rtStoreAssetModifyTime: number;
|
||||
strHeaderFilename: string;
|
||||
strName: string;
|
||||
unAppID: number;
|
||||
}
|
||||
|
||||
export interface Lender {
|
||||
/**
|
||||
* A Steam64 ID.
|
||||
*/
|
||||
steamid: string;
|
||||
appid: number;
|
||||
numDlc: number;
|
||||
bPreferred: boolean;
|
||||
vecDLC: LenderDLC[];
|
||||
}
|
||||
80
src/globals/steam-client/FriendSettings.ts
Normal file
80
src/globals/steam-client/FriendSettings.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { VDFBoolean_t } from "./shared";
|
||||
|
||||
/**
|
||||
* Represents friend settings and configuration.
|
||||
*/
|
||||
export interface FriendSettings {
|
||||
/**
|
||||
* Retrieves a list of enabled friend settings features.
|
||||
* @returns an array of enabled friend settings features.
|
||||
*/
|
||||
GetEnabledFeatures(): Promise<FriendSettingsFeatureObject[]>;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be notified of friend settings changes.
|
||||
* @param callback The callback function to be called when friend settings change.
|
||||
* @remarks The callback receives a JSON object string which may be parsed into {@link FriendSettingsChange}.
|
||||
*/
|
||||
RegisterForSettingsChanges(callback: (settings: string) => void): void;
|
||||
|
||||
/**
|
||||
* @param details Stringified {@link FriendSettingsChange}.
|
||||
*/
|
||||
SetFriendSettings(details: string): void;
|
||||
}
|
||||
|
||||
export enum EChatFlashMode {
|
||||
Always,
|
||||
Minimized,
|
||||
Never,
|
||||
}
|
||||
|
||||
export interface FriendSettingsFeatureObject {
|
||||
feature: FriendSettingsFeature_t;
|
||||
bEnabled: boolean;
|
||||
}
|
||||
|
||||
export type FriendSettingsFeature_t =
|
||||
| "DoNotDisturb"
|
||||
| "FriendsFilter"
|
||||
| "LoaderWindowSynchronization"
|
||||
| "NewVoiceHotKeyState"
|
||||
| "NonFriendMessageHandling"
|
||||
| "PersonaNotifications"
|
||||
| "ServerVirtualizedMemberLists"
|
||||
| "SteamworksChatAPI";
|
||||
|
||||
export type FriendSettingsEnabledFeatures<T> = {
|
||||
[feature in FriendSettingsFeature_t]: T;
|
||||
};
|
||||
|
||||
export interface FriendSettingsChange {
|
||||
bNotifications_ShowIngame: VDFBoolean_t;
|
||||
bNotifications_ShowOnline: VDFBoolean_t;
|
||||
bNotifications_ShowMessage: VDFBoolean_t;
|
||||
bNotifications_EventsAndAnnouncements: VDFBoolean_t;
|
||||
bSounds_PlayIngame: VDFBoolean_t;
|
||||
bSounds_PlayOnline: VDFBoolean_t;
|
||||
bSounds_PlayMessage: VDFBoolean_t;
|
||||
bSounds_EventsAndAnnouncements: VDFBoolean_t;
|
||||
bAlwaysNewChatWindow: VDFBoolean_t;
|
||||
bForceAlphabeticFriendSorting: VDFBoolean_t;
|
||||
nChatFlashMode: EChatFlashMode;
|
||||
bRememberOpenChats: VDFBoolean_t;
|
||||
bCompactQuickAccess: VDFBoolean_t;
|
||||
bCompactFriendsList: VDFBoolean_t;
|
||||
bNotifications_ShowChatRoomNotification: VDFBoolean_t;
|
||||
bSounds_PlayChatRoomNotification: VDFBoolean_t;
|
||||
bHideOfflineFriendsInTagGroups: VDFBoolean_t;
|
||||
bHideCategorizedFriends: VDFBoolean_t;
|
||||
bCategorizeInGameFriendsByGame: VDFBoolean_t;
|
||||
nChatFontSize: number;
|
||||
b24HourClock: VDFBoolean_t;
|
||||
bDoNotDisturbMode: VDFBoolean_t;
|
||||
bDisableEmbedInlining: VDFBoolean_t;
|
||||
bSignIntoFriends: VDFBoolean_t;
|
||||
bDisableSpellcheck: VDFBoolean_t;
|
||||
bDisableRoomEffects: VDFBoolean_t;
|
||||
bAnimatedAvatars: VDFBoolean_t;
|
||||
featuresEnabled: FriendSettingsEnabledFeatures<VDFBoolean_t>;
|
||||
}
|
||||
70
src/globals/steam-client/Friends.ts
Normal file
70
src/globals/steam-client/Friends.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
|
||||
/**
|
||||
* Represents functions related to managing friends in Steam.
|
||||
*/
|
||||
export interface Friends {
|
||||
/**
|
||||
* Adds a user to the friend list.
|
||||
* @param steamId The Steam ID of the user to add as a friend.
|
||||
* @returns `true` if the friend was added successfully.
|
||||
*/
|
||||
AddFriend(steamId: string): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* @returns a list of players you recently played with.
|
||||
*/
|
||||
GetCoplayData(): Promise<CoplayData>;
|
||||
|
||||
InviteUserToCurrentGame(steam64Id: string, steamIdTarget: string): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Invites a user to a specific game.
|
||||
* @param steamId The Steam ID of the user to invite.
|
||||
* @param appId The ID of the game to invite the user to.
|
||||
* @param connectString Additional parameters for the invitation.
|
||||
* @returns `true` if the user was invited successfully.
|
||||
*/
|
||||
InviteUserToGame(steamId: string, appId: number, connectString: string): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Invites a user to a specific lobby.
|
||||
* @returns `true` if the user was invited successfully.
|
||||
*/
|
||||
InviteUserToLobby(steam64Id: string, steamIdTarget: string): Promise<boolean>;
|
||||
|
||||
InviteUserToRemotePlayTogetherCurrentGame(steam64Id: string): Promise<boolean>;
|
||||
|
||||
RegisterForMultiplayerSessionShareURLChanged(
|
||||
appId: number,
|
||||
callback: (param0: string, param1: string) => void,
|
||||
): Unregisterable;
|
||||
|
||||
RegisterForVoiceChatStatus(callback: (status: VoiceChatStatus) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Removes a user from the friend list.
|
||||
* @param steamId The Steam ID of the user to remove from the friend list.
|
||||
* @returns `true` if the friend was removed successfully.
|
||||
*/
|
||||
RemoveFriend(steamId: string): Promise<boolean>;
|
||||
|
||||
ShowRemotePlayTogetherUI(): void;
|
||||
}
|
||||
|
||||
export interface CoplayData {
|
||||
currentUsers: CoplayUser[];
|
||||
recentUsers: CoplayUser[];
|
||||
}
|
||||
|
||||
export interface CoplayUser {
|
||||
accountid: number;
|
||||
rtTimePlayed: number;
|
||||
appid: number;
|
||||
}
|
||||
|
||||
export interface VoiceChatStatus {
|
||||
bVoiceChatActive: boolean;
|
||||
bMicMuted: boolean;
|
||||
bOutputMuted: boolean;
|
||||
}
|
||||
73
src/globals/steam-client/GameNotes.ts
Normal file
73
src/globals/steam-client/GameNotes.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { EResult, OperationResponse } from "./shared";
|
||||
|
||||
export interface GameNotes {
|
||||
/**
|
||||
* @returns a boolean indicating whether the operation was successful.
|
||||
*/
|
||||
DeleteImage(param0: string): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* @returns a boolean indicating whether the operation was successful.
|
||||
*/
|
||||
DeleteNotes(param0: string): Promise<boolean>;
|
||||
|
||||
GetNotes(filenameForNotes: string, directoryForNoteImages: string): Promise<Notes>;
|
||||
|
||||
GetNotesMetadata(note: string): Promise<NoteMetadata>;
|
||||
GetNumNotes(): Promise<number>;
|
||||
GetQuota: Promise<NotesQuota>;
|
||||
|
||||
IterateNotes(appId: number, length: number): Promise<NoteMetadata[]>;
|
||||
ResolveSyncConflicts(param0: boolean): Promise<EResult>;
|
||||
|
||||
/**
|
||||
* @param notes Escaped JSON array of {@link Note}.
|
||||
*/
|
||||
SaveNotes(filenameForNotes: string, notes: string): Promise<EResult>;
|
||||
SyncToClient(): Promise<EResult>;
|
||||
|
||||
SyncToServer(): Promise<EResult>;
|
||||
|
||||
/**
|
||||
* @param mimeType Image MIME type.
|
||||
* @param base64 Image contents in base64.
|
||||
* @returns an image file name with its extension that's meant to be used as a part of some URL. (todo)
|
||||
* @throws OperationResponse if invalid MIME type or unable to parse base64 BUT NOT if it failed.
|
||||
*/
|
||||
UploadImage(imageFileNamePrefix: string, mimeType: string, base64: string): Promise<EResult | OperationResponse>;
|
||||
}
|
||||
|
||||
export interface Note {
|
||||
appid: number;
|
||||
id: string;
|
||||
/**
|
||||
* Note contents in BB code.
|
||||
*/
|
||||
content: string;
|
||||
ordinal: number;
|
||||
time_created: number;
|
||||
time_modified: number;
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface Notes {
|
||||
result: EResult;
|
||||
/**
|
||||
* Escaped JSON array of {@link Note}. Not present if {@link result} is {@link EResult.FileNotFound}.
|
||||
*/
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
interface NoteMetadata {
|
||||
filename: string;
|
||||
filesize: number;
|
||||
result: EResult;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
interface NotesQuota {
|
||||
bytes: number;
|
||||
bytesAvailable: number;
|
||||
numFiles: number;
|
||||
numFilesAvailable: number;
|
||||
}
|
||||
29
src/globals/steam-client/GameRecording.ts
Normal file
29
src/globals/steam-client/GameRecording.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { JsPbMessage, Unregisterable } from "./shared";
|
||||
|
||||
export interface GameRecording {
|
||||
/**
|
||||
* If `data` is deserialized, returns {@link CGameRecording_AudioSessionsChanged_Notification}.
|
||||
*/
|
||||
RegisterForAudioSessionsChanged(callback: (data: ArrayBuffer) => void): Unregisterable;
|
||||
SetAudioSessionCaptureState(id: string, name: string, state: boolean): void;
|
||||
}
|
||||
|
||||
export interface AudioSession {
|
||||
id(): string | undefined;
|
||||
name(): string | undefined;
|
||||
is_system(): boolean | undefined;
|
||||
is_muted(): boolean | undefined;
|
||||
is_active(): boolean | undefined;
|
||||
is_captured(): boolean | undefined;
|
||||
recent_peak(): number | undefined;
|
||||
is_game(): boolean | undefined;
|
||||
is_steam(): boolean | undefined;
|
||||
is_saved(): boolean | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @note Taken from https://github.com/SteamDatabase/SteamTracking/blob/master/Protobufs/steammessages_gamerecording_objects.proto
|
||||
*/
|
||||
export interface CGameRecording_AudioSessionsChanged_Notification extends JsPbMessage {
|
||||
sessions(): AudioSession[];
|
||||
}
|
||||
59
src/globals/steam-client/GameSessions.ts
Normal file
59
src/globals/steam-client/GameSessions.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
import {AppAchievements} from "./App";
|
||||
import { Screenshot } from "./Screenshots";
|
||||
|
||||
/**
|
||||
* Represents functions related to Steam Game Sessions.
|
||||
*/
|
||||
export interface GameSessions {
|
||||
/**
|
||||
* Registers a callback function to be called when an achievement notification is received.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForAchievementNotification(
|
||||
callback: (notification: AchievementNotification) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when an app lifetime notification is received.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForAppLifetimeNotifications(
|
||||
callback: (notification: AppLifetimeNotification) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when a screenshot notification is received.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForScreenshotNotification(
|
||||
callback: (notification: ScreenshotNotification) => void,
|
||||
): Unregisterable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @prop unAppID is not properly set by Steam for non-steam game shortcuts, so it defaults to 0 for them
|
||||
*/
|
||||
interface GameSessionNotificationBase {
|
||||
unAppID: number;
|
||||
}
|
||||
|
||||
export interface AchievementNotification extends GameSessionNotificationBase {
|
||||
achievement: AppAchievements;
|
||||
nCurrentProgress: number;
|
||||
nMaxProgress: number;
|
||||
}
|
||||
|
||||
export interface AppLifetimeNotification extends GameSessionNotificationBase {
|
||||
nInstanceID: number;
|
||||
bRunning: boolean;
|
||||
}
|
||||
|
||||
export interface ScreenshotNotification extends GameSessionNotificationBase {
|
||||
details: Screenshot;
|
||||
hScreenshot: number;
|
||||
strOperation: "deleted" | "written";
|
||||
}
|
||||
810
src/globals/steam-client/Input.ts
Normal file
810
src/globals/steam-client/Input.ts
Normal file
@@ -0,0 +1,810 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
|
||||
/**
|
||||
* Represents functions related to input and controllers in Steam.
|
||||
*/
|
||||
export interface Input {
|
||||
CalibrateControllerIMU(controllerIndex: any): any;
|
||||
|
||||
CalibrateControllerJoystick(controllerIndex: any): any;
|
||||
|
||||
CalibrateControllerTrackpads(controllerIndex: any): any;
|
||||
|
||||
CancelGyroSWCalibration(): any;
|
||||
|
||||
ClearSelectedConfigForApp(appId: number, controllerIndex: number): any;
|
||||
|
||||
CloseDesktopConfigurator: any;
|
||||
|
||||
/**
|
||||
* Writes text.
|
||||
* @param textToWrite The text to write.
|
||||
*/
|
||||
ControllerKeyboardSendText(textToWrite: string): void;
|
||||
|
||||
/**
|
||||
* Sets a specified key's pressed state.
|
||||
* @param key The key index to set the state for.
|
||||
* @param state `true` for pressed, `false` otherwise.
|
||||
* @example
|
||||
* Send paste command:
|
||||
* ```
|
||||
* SteamClient.Input.ControllerKeyboardSetKeyState(EHIDKeyboardKey.LControl, true);
|
||||
* SteamClient.Input.ControllerKeyboardSetKeyState(EHIDKeyboardKey.V, true);
|
||||
* SteamClient.Input.ControllerKeyboardSetKeyState(EHIDKeyboardKey.V, false);
|
||||
* SteamClient.Input.ControllerKeyboardSetKeyState(EHIDKeyboardKey.LControl, false);
|
||||
* ```
|
||||
*/
|
||||
ControllerKeyboardSetKeyState(key: EHIDKeyboardKey, state: boolean): void;
|
||||
|
||||
DecrementCloudedControllerConfigsCounter(): any;
|
||||
|
||||
DeletePersonalControllerConfiguration(param0: any): any;
|
||||
|
||||
//f.Debug("sending to client"), this.SetEditingConfigurationValue(e, t, c.QU, (e => SteamClient.Input.DuplicateControllerConfigurationSourceMode(this.m_unControllerIndex, e))), this.SaveEditingConfiguration(e), this
|
||||
DuplicateControllerConfigurationSourceMode(controllerIndex: number, param1: any): any;
|
||||
|
||||
EndControllerDeviceSupportFlow(): any;
|
||||
|
||||
ExportCurrentControllerConfiguration(controllerIndex: number, appId: number, param2: number, title: string, description: string, param5: string): Promise<any>;
|
||||
|
||||
ForceConfiguratorFocus(param0: boolean): any;
|
||||
|
||||
ForceSimpleHapticEvent(param0: number, param1: number, param2: number, param3: number, param4: number): any;
|
||||
|
||||
FreeControllerConfig(m_ChordSummaryConfiguration: any): any;
|
||||
|
||||
GetConfigForAppAndController(appId: number, unControllerIndex: number): any;
|
||||
|
||||
/**
|
||||
* Retrieves the controller mapping string for the specified controller index.
|
||||
* @param unControllerIndex The controller index.
|
||||
* @returns the controller mapping string.
|
||||
*/
|
||||
GetControllerMappingString(unControllerIndex: number): Promise<string>;
|
||||
|
||||
GetControllerPreviouslySeen(): Promise<number[]>;
|
||||
|
||||
GetSteamControllerDongleState(): Promise<boolean>;
|
||||
|
||||
GetTouchMenuIconsForApp(appId: number): Promise<any>;
|
||||
|
||||
GetXboxDriverInstallState(): Promise<any>; // "{"nResult":0}"
|
||||
IdentifyController(controllerIndex: number): any;
|
||||
|
||||
InitControllerSounds(): any;
|
||||
|
||||
InitializeControllerPersonalizationSettings(controllerIndex: number): any;
|
||||
|
||||
ModalKeyboardDismissed(): void;
|
||||
|
||||
OpenDesktopConfigurator: any;
|
||||
|
||||
PreviewConfigForAppAndController(appId: number, controllerIndex: number, workshopUri: string): any;
|
||||
|
||||
PreviewControllerLEDColor(flHue: number, flSaturation: number, flBrightness: number): any;
|
||||
|
||||
QueryControllerConfigsForApp(appId: number, controllerIndex: number, param2: boolean): any;
|
||||
|
||||
RegisterForActiveControllerChanges: Unregisterable; // {"nActiveController":0}
|
||||
//param0 - e possibly appid?
|
||||
//param1 - some index?
|
||||
RegisterForConfigSelectionChanges(callback: (param0: number, param1: number) => void): Unregisterable;
|
||||
|
||||
RegisterForControllerAccountChanges: Unregisterable;
|
||||
|
||||
RegisterForControllerAnalogInputMessages(
|
||||
callback: (msgs: ControllerAnalogInputMessage[]) => void,
|
||||
): Unregisterable;
|
||||
|
||||
RegisterForControllerBatteryChanges(callback: any): Unregisterable;
|
||||
|
||||
RegisterForControllerCommandMessages(
|
||||
callback: (msg: ControllerCommandMessage) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback for changes in controller configuration cloud state.
|
||||
* @param callback The callback function for config cloud state changes.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForControllerConfigCloudStateChanges(
|
||||
callback: (state: ControllerConfigCloudState) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback for receiving controller configuration info messages (controller layouts query, personal controller layout query).
|
||||
* @param callback The callback function for controller config info messages.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
* @remarks Do Not Use, this will break the controller layout selection unless you know what you are doing.
|
||||
*/
|
||||
RegisterForControllerConfigInfoMessages(
|
||||
callback: (
|
||||
msgs: ControllerConfigInfoMessageList[] | ControllerConfigInfoMessageQuery[],
|
||||
) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be invoked when controller input messages are received.
|
||||
* @param callback The callback function to be invoked when controller input messages are received.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForControllerInputMessages(
|
||||
callback: (controllerIndex: number, gamepadButton: ControllerInputGamepadButton, isButtonPressed: boolean) => void,
|
||||
): Unregisterable;
|
||||
|
||||
RegisterForControllerListChanges(callback: (controllerListChanges: ControllerInfo[]) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback for changes in the controller state (buttons presses, triggers presses, joystick changes etc...).
|
||||
* @param callback The callback function for controller state changes.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForControllerStateChanges(
|
||||
callback: (changes: ControllerStateChange[]) => void,
|
||||
): Unregisterable;
|
||||
|
||||
RegisterForDualSenseUpdateNotification(callback: (m_strDualSenseUpdateProduct: string) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback for receiving game keyboard messages (text field popup for inputting text for games when in character creation or etc...).
|
||||
* @param callback The callback function for game keyboard messages.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForGameKeyboardMessages(callback: (msg: GameKeyboardMessage) => void): Unregisterable;
|
||||
|
||||
RegisterForRemotePlayConfigChanges(callback: () => void): Unregisterable;
|
||||
|
||||
//data.appId, data.ulConfigId
|
||||
RegisterForShowControllerLayoutPreviewMessages(callback: (data: any) => void): Unregisterable;
|
||||
|
||||
/*
|
||||
onTouchMenuInput(e) {
|
||||
for (let t = 0; t < e.length; t++) {
|
||||
const n = this.TouchMenuGetKey(e[t]), o = this.m_mapActiveTouchMenus.get(n);
|
||||
void 0 !== o && o.updateTouchMenuState(e[t])
|
||||
}
|
||||
}
|
||||
*/
|
||||
RegisterForTouchMenuInputMessages(callback: (inputs: number[]) => void): Unregisterable;
|
||||
|
||||
RegisterForTouchMenuMessages(callback: (msg: TouchMenuMessage) => void): Unregisterable;
|
||||
|
||||
//param0 - index?
|
||||
RegisterForUIVisualization(param0: any, param1: any, param2: any): Unregisterable;
|
||||
|
||||
RegisterForUnboundControllerListChanges(callback: (m_unboundControllerList: any) => void): Unregisterable; // param0 is an array
|
||||
|
||||
/*
|
||||
OnDismissKeyboardMessage(e) {
|
||||
this.m_WindowStore.SteamUIWindows.forEach((e => e.VirtualKeyboardManager.SetVirtualKeyboardHidden(e.BrowserWindow)))
|
||||
}
|
||||
*/
|
||||
RegisterForUserDismissKeyboardMessages(callback: (param0: any) => void): Unregisterable;
|
||||
|
||||
RegisterForUserKeyboardMessages: Unregisterable;
|
||||
|
||||
RequestGyroActive(controllerIndex: number, param1: boolean): any;
|
||||
|
||||
RequestRemotePlayControllerConfigs(param0: any): any;
|
||||
|
||||
ResetControllerBindings(param0: any): any;
|
||||
|
||||
ResolveCloudedControllerConfigConflict(param0: any): any;
|
||||
|
||||
RestoreControllerPersonalizationSettings(controllerIndex: number): any;
|
||||
|
||||
SaveControllerCalibration(controllerIndex: number): any;
|
||||
|
||||
SaveControllerPersonalizationSettings(param0: any): any;
|
||||
|
||||
SaveControllerSounds: any;
|
||||
|
||||
SaveEditingControllerConfiguration(controllerIndex: number, sharedConfig: boolean): any;
|
||||
|
||||
//this.SetEditingConfigurationValue(e, t, c.sL, (e => SteamClient.Input.SetControllerConfigurationModeShiftBinding(this.m_unControllerIndex, e)))
|
||||
SetControllerConfigurationModeShiftBinding(controllerIndex: number, param1: any): any;
|
||||
|
||||
SetControllerHapticSetting(controllerIndex: number, eHapticSetting: any): any;
|
||||
|
||||
SetControllerMappingString(mapping: string): void;
|
||||
|
||||
SetControllerName(controllerIndex: number, controllerName: string): any;
|
||||
|
||||
SetControllerNintendoLayoutSetting: any;
|
||||
SetControllerPersonalizationName: any;
|
||||
|
||||
//param0 - nLStickDeadzone, bSWAntiDrift, nRHapticStrength, flRPadPressureCurve
|
||||
/*
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("nLStickDeadzone", e.nLStickDeadzone),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("nRStickDeadzone", e.nRStickDeadzone),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("bSWAntiDrift", e.bSWAntiDrift ? 1 : 0),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("nLHapticStrength", e.nLHapticStrength),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("nRHapticStrength", e.nRHapticStrength),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("flLPadPressureCurve", 100 * e.flLPadPressureCurve),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("flRPadPressureCurve", 100 * e.flRPadPressureCurve),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("ePlayerSlotLEDSetting", e),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nGyroSampleAngleOffsetX", e.nGyroSampleAngleOffsetX),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.bMomentumEnabled", e.bMomentumEnabled ? 1 : 0),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nMomentumFrictionX", e.nMomentumFrictionX),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nMomentumFrictionY", e.nMomentumFrictionY),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nAccerationLevel", e.nAccerationLevel),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.bInvertX", e.bInvertX ? 1 : 0),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.bInvertY", e.bInvertY ? 1 : 0),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nRotationAngle", e.nRotationAngle),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nTriggerClamping", e.nTriggerClamping),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nTriggerClampingAmount", e.nTriggerClampingAmount),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nGyroEnableButton", e.nGyroEnableButton),
|
||||
SteamClient.Input.SetControllerPersonalizationSetting("GyroPreferenceData.nGyroEnableButtonBehavior", e.nGyroEnableButtonBehavior),
|
||||
*/
|
||||
SetControllerPersonalizationSetting(param0: string, param1: number): any;
|
||||
|
||||
//param0 - flGyroStationaryTolerance, flAccelerometerStationaryTolerance,
|
||||
/*
|
||||
SteamClient.Input.SetControllerPersonalizationSettingFloat("GyroPreferenceData.flGyroNaturalSensitivity", e.flGyroNaturalSensitivity),
|
||||
SteamClient.Input.SetControllerPersonalizationSettingFloat("GyroPreferenceData.flGyroXYRatio", e.flGyroXYRatio),
|
||||
SteamClient.Input.SetControllerPersonalizationSettingFloat("GyroPreferenceData.flGyroSpeedDeadzone", e.flGyroSpeedDeadzone),
|
||||
SteamClient.Input.SetControllerPersonalizationSettingFloat("GyroPreferenceData.flGyroPrecisionSpeed", e.flGyroPrecisionSpeed),
|
||||
SteamClient.Input.SetControllerPersonalizationSettingFloat("flGyroStationaryTolerance", e.flGyroStationaryTolerance),
|
||||
SteamClient.Input.SetControllerPersonalizationSettingFloat("flAccelerometerStationaryTolerance", e.flAccelerometerStationaryTolerance),
|
||||
*/
|
||||
SetControllerPersonalizationSettingFloat(param0: string, param1: number): any;
|
||||
|
||||
SetControllerRumbleSetting(controllerIndex: number, rumblePreference: EControllerRumbleSetting): any;
|
||||
|
||||
SetControllerUseUniversalFaceButtonGlyphs(controllerIndex: number, value: boolean): void;
|
||||
|
||||
SetCursorActionset(param0: boolean): any;
|
||||
|
||||
SetDualSenseUpdateNotification(param0: boolean): any
|
||||
|
||||
/*
|
||||
SetEditingConfigurationValue(e, t, n, o) {
|
||||
const a = new r.BinaryWriter;
|
||||
n.serializeBinaryToWriter(n.fromObject(t), a);
|
||||
const s = a.getResultBase64String();
|
||||
f.Debug("SetEditingConfigurationValue serializeBinaryToWriter", (0, i.ZN)(t), s), this.EditingConfigurationWillUpdate(), this.m_updatingEditingConfigurationPromise = o(s).then((t => {
|
||||
if (null == t) return f.Debug("SetEditingConfigurationValue returned nothing."), void (0, i.z)((() => this.UpdateEditingConfiguration(e, this.m_unControllerIndex, this.EditingConfiguration)));
|
||||
const n = c.bE.deserializeBinary(t).toObject();
|
||||
f.Debug("SetEditingConfigurationValue returned controller configuration.", n), this.UpdateEditingConfiguration(e, this.m_unControllerIndex, n), this.m_nEditNumber++, -1 == n.url.indexOf("autosave://") && this.SaveEditingConfiguration(e)
|
||||
})).catch((e => {
|
||||
f.Error("SetEditingConfigurationValue fail:", o, l.jt(e.result), e.message), this.m_bIsUpdatingActiveConfiguration = !1
|
||||
}))
|
||||
}
|
||||
|
||||
SetControllerActionSet(e, t) {
|
||||
this.SetEditingConfigurationValue(e, t, c.X3, (e => SteamClient.Input.SetEditingControllerConfigurationActionSet(this.m_unControllerIndex, e)))
|
||||
}
|
||||
*/
|
||||
SetEditingControllerConfigurationActionSet(controllerIndex: number, param1: any): any;
|
||||
|
||||
//this.SetEditingConfigurationValue(e, t, c.io, (e => SteamClient.Input.SetEditingControllerConfigurationInputActivator(this.m_unControllerIndex, e)))
|
||||
SetEditingControllerConfigurationInputActivator(controllerIndex: number, param1: any): any;
|
||||
|
||||
//this.SetEditingConfigurationValue(e, t, c.tH, (e => SteamClient.Input.SetEditingControllerConfigurationInputActivatorEnabled(this.m_unControllerIndex, e)))
|
||||
SetEditingControllerConfigurationInputActivatorEnabled(controllerIndex: number, param1: any): any;
|
||||
|
||||
//this.SetEditingConfigurationValue(e, t, c.J2, (e => SteamClient.Input.SetEditingControllerConfigurationInputBinding(this.m_unControllerIndex, e)))
|
||||
SetEditingControllerConfigurationInputBinding(controllerIndex: number, param1: any): any;
|
||||
|
||||
//this.SetEditingConfigurationValue(e, t, c.Sz, (e => SteamClient.Input.SetEditingControllerConfigurationMiscSetting(this.m_unControllerIndex, e)))
|
||||
SetEditingControllerConfigurationMiscSetting(controllerIndex: number, param1: any): any;
|
||||
|
||||
//f.Debug("sending to client"), this.SetEditingConfigurationValue(e, t, c.QU, (e => SteamClient.Input.SetEditingControllerConfigurationSourceMode(this.m_unControllerIndex, e)))
|
||||
SetEditingControllerConfigurationSourceMode(controllerIndex: number, param1: any): any;
|
||||
|
||||
SetGamepadKeyboardText(param0: boolean, param1: string): any;
|
||||
|
||||
SetKeyboardActionset(param0: boolean, param1: boolean): any;
|
||||
|
||||
/**
|
||||
* Sets the mouse position.
|
||||
* @param pid 0
|
||||
* @param x Mouse X position.
|
||||
* @param y Mouse Y position.
|
||||
*/
|
||||
SetMousePosition(pid: number, x: number, y: number): void;
|
||||
|
||||
SetSelectedConfigForApp(appId: number, controllerIndex: number, url: string, param3: boolean): any;
|
||||
|
||||
SetSteamControllerDonglePairingMode(bEnable: boolean, bSilent: boolean): any;
|
||||
|
||||
SetVirtualMenuKeySelected(unControllerIndex: number, unMenuIndex: number, m_controllerMenuActiveMenuItem: number): any; //
|
||||
SetWebBrowserActionset(param0: boolean): any;
|
||||
|
||||
SetXboxDriverInstallState(param0: any): any; // state
|
||||
|
||||
/**
|
||||
* Opens the Steam Input controller settings.
|
||||
* This function displays the Steam Input controller settings for configuration.
|
||||
*/
|
||||
ShowControllerSettings(): void;
|
||||
|
||||
StandaloneKeyboardDismissed(): any;
|
||||
|
||||
StartControllerDeviceSupportFlow(param0: any, param1: any, callback: (param2: any) => void): any;
|
||||
|
||||
/*
|
||||
this.m_updatingEditingConfigurationPromise = SteamClient.Input.StartEditingControllerConfigurationForAppIDAndControllerIndex(e, t).then((n=>{
|
||||
const o = c.bE.deserializeBinary(n).toObject();
|
||||
f.Debug("Loaded controller config for appid", e, n, o),
|
||||
(0,
|
||||
i.z)((()=>this.UpdateEditingConfiguration(e, t, o)))
|
||||
}
|
||||
)).catch((n=>{
|
||||
f.Debug("Loading controller config for appid rejected", e, n),
|
||||
(0,
|
||||
i.z)((()=>this.UpdateEditingConfiguration(e, t, null)))
|
||||
}
|
||||
))
|
||||
*/
|
||||
StartEditingControllerConfigurationForAppIDAndControllerIndex(m_appId: number, m_unControllerIndex: number): Promise<any>;
|
||||
|
||||
StartGyroSWCalibration(callback: () => void): any;
|
||||
|
||||
StopEditingControllerConfiguration(controllerIndex: number): any;
|
||||
|
||||
SwapControllerConfigurationSourceModes: any;
|
||||
|
||||
//this.SetEditingConfigurationValue(e, t, c.Qb, (e => SteamClient.Input.SwapControllerModeInputBindings(this.m_unControllerIndex, e)))
|
||||
SwapControllerModeInputBindings(controllerIndex: number, param1: any): any;
|
||||
|
||||
SwapControllerOrder(controllerIndex1: number, controllerIndex2: number): any;
|
||||
|
||||
SyncCloudedControllerConfigs(): any;
|
||||
|
||||
// type - enum
|
||||
/*
|
||||
Off - 0, Tick, Click
|
||||
*/
|
||||
TriggerHapticPulse(controllerIndex: number, eHapticType: number, param2: number): any;
|
||||
|
||||
TriggerSimpleHapticEvent(
|
||||
controllerIndex: number,
|
||||
eHapticType: number,
|
||||
unIntensity: number,
|
||||
ndBGain: number,
|
||||
param4: number,
|
||||
): any;
|
||||
|
||||
UnregisterForControllerStateChanges(): void;
|
||||
|
||||
UnregisterForUIVisualization(controllerIndex: number): any;
|
||||
|
||||
UploadChangesForCloudedControllerConfigs(): any;
|
||||
}
|
||||
|
||||
export enum EHIDKeyboardKey {
|
||||
Invalid,
|
||||
BeforeFirst = 3,
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
Key_1,
|
||||
Key_2,
|
||||
Key_3,
|
||||
Key_4,
|
||||
Key_5,
|
||||
Key_6,
|
||||
Key_7,
|
||||
Key_8,
|
||||
Key_9,
|
||||
Key_0,
|
||||
Return,
|
||||
Escape,
|
||||
Backspace,
|
||||
Tab,
|
||||
Space,
|
||||
Dash,
|
||||
Equals,
|
||||
LeftBracket,
|
||||
RightBracket,
|
||||
Backslash,
|
||||
Unused1,
|
||||
Semicolon,
|
||||
SingleQuote,
|
||||
Backtick,
|
||||
Comma,
|
||||
Period,
|
||||
ForwardSlash,
|
||||
CapsLock,
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
PrintScreen,
|
||||
ScrollLock,
|
||||
Break,
|
||||
Insert,
|
||||
Home,
|
||||
PageUp,
|
||||
Delete,
|
||||
End,
|
||||
PageDown,
|
||||
RightArrow,
|
||||
LeftArrow,
|
||||
DownArrow,
|
||||
UpArrow,
|
||||
NumLock,
|
||||
KeypadForwardSlash,
|
||||
KeypadAsterisk,
|
||||
KeypadDash,
|
||||
KeypadPlus,
|
||||
KeypadEnter,
|
||||
Keypad_1,
|
||||
Keypad_2,
|
||||
Keypad_3,
|
||||
Keypad_4,
|
||||
Keypad_5,
|
||||
Keypad_6,
|
||||
Keypad_7,
|
||||
Keypad_8,
|
||||
Keypad_9,
|
||||
Keypad_0,
|
||||
KeypadPeriod,
|
||||
LAlt,
|
||||
LShift,
|
||||
LWin,
|
||||
LControl,
|
||||
RAlt,
|
||||
RShift,
|
||||
RWin,
|
||||
RControl,
|
||||
VolUp,
|
||||
VolDown,
|
||||
Mute,
|
||||
Play,
|
||||
Stop,
|
||||
Next,
|
||||
Prev,
|
||||
AfterLast,
|
||||
}
|
||||
|
||||
export interface ControllerAnalogInputMessage {
|
||||
nA: number;
|
||||
x: number;
|
||||
y: number;
|
||||
nC: number;
|
||||
}
|
||||
|
||||
export interface ControllerCommandMessage {
|
||||
/**
|
||||
* @todo enum
|
||||
*/
|
||||
eAction: number;
|
||||
nControllerIndex: number;
|
||||
}
|
||||
|
||||
export interface ControllerConfigCloudState {
|
||||
bSyncDone: boolean;
|
||||
bSyncConflict: boolean;
|
||||
bSyncError: boolean;
|
||||
}
|
||||
|
||||
export interface ControllerConfigInfoMessage {
|
||||
appID: number;
|
||||
}
|
||||
|
||||
export interface ControllerConfigInfoMessageQuery extends ControllerConfigInfoMessage {
|
||||
bPersonalQueryDone: boolean;
|
||||
}
|
||||
|
||||
export interface ControllerConfigInfoMessageList extends ControllerConfigInfoMessage {
|
||||
nControllerType: number;
|
||||
publishedFileID: string;
|
||||
accountID: number;
|
||||
Title: string;
|
||||
Description: string;
|
||||
URL: string;
|
||||
timeUpdated: string;
|
||||
bOfficial: boolean;
|
||||
bProgenitorOfficial: boolean;
|
||||
bRecommended: boolean;
|
||||
bProgenitorRecommended: boolean;
|
||||
bUsesSIAPI: boolean;
|
||||
bUsesMouse: boolean;
|
||||
bUsesKeyboard: boolean;
|
||||
bUsesGamepad: boolean;
|
||||
/**
|
||||
* @todo unconfirmed
|
||||
*/
|
||||
eExportType: EControllerConfigExportType;
|
||||
playtime: string;
|
||||
bSelected: boolean;
|
||||
}
|
||||
|
||||
export enum EControllerConfigExportType {
|
||||
Unknown,
|
||||
PersonalLocal,
|
||||
PersonalCloud,
|
||||
Community,
|
||||
Template,
|
||||
Official,
|
||||
OfficialDefault,
|
||||
}
|
||||
|
||||
export enum EControllerRumbleSetting {
|
||||
ControllerPreference,
|
||||
Off,
|
||||
On,
|
||||
}
|
||||
|
||||
export enum ControllerInputGamepadButton {
|
||||
GAMEPAD_BUTTON_A = 0,
|
||||
GAMEPAD_BUTTON_B = 1,
|
||||
GAMEPAD_BUTTON_X = 2,
|
||||
GAMEPAD_BUTTON_Y = 3,
|
||||
GAMEPAD_BUTTON_DPAD_UP = 4,
|
||||
GAMEPAD_BUTTON_DPAD_RIGHT = 5,
|
||||
GAMEPAD_BUTTON_DPAD_DOWN = 6,
|
||||
GAMEPAD_BUTTON_DPAD_LEFT = 7,
|
||||
GAMEPAD_BUTTON_MENU = 8,
|
||||
GAMEPAD_BUTTON_VIEW = 9,
|
||||
GAMEPAD_LEFTPAD_UP = 10,
|
||||
GAMEPAD_LEFTPAD_DOWN = 11,
|
||||
GAMEPAD_LEFTPAD_LEFT = 12,
|
||||
GAMEPAD_LEFTPAD_RIGHT = 13,
|
||||
GAMEPAD_LEFTPAD_ANALOG = 14,
|
||||
GAMEPAD_RIGHTPAD_UP = 15,
|
||||
GAMEPAD_RIGHTPAD_DOWN = 16,
|
||||
GAMEPAD_RIGHTPAD_LEFT = 17,
|
||||
GAMEPAD_RIGHTPAD_RIGHT = 18,
|
||||
GAMEPAD_RIGHTPAD_ANALOG = 19,
|
||||
GAMEPAD_LEFTSTICK_UP = 20,
|
||||
GAMEPAD_LEFTSTICK_DOWN = 21,
|
||||
GAMEPAD_LEFTSTICK_LEFT = 22,
|
||||
GAMEPAD_LEFTSTICK_RIGHT = 23,
|
||||
GAMEPAD_LEFTSTICK_ANALOG = 24,
|
||||
GAMEPAD_LEFTSTICK_CLICK = 25,
|
||||
GAMEPAD_LTRIGGER_ANALOG = 26,
|
||||
GAMEPAD_RTRIGGER_ANALOG = 27,
|
||||
GAMEPAD_BUTTON_LTRIGGER = 28,
|
||||
GAMEPAD_BUTTON_RTRIGGER = 29,
|
||||
GAMEPAD_BUTTON_LSHOULDER = 30,
|
||||
GAMEPAD_BUTTON_RSHOULDER = 31,
|
||||
GAMEPAD_BUTTON_LBACK = 32,
|
||||
GAMEPAD_BUTTON_RBACK = 33,
|
||||
GAMEPAD_BUTTON_GUIDE = 34,
|
||||
GAMEPAD_BUTTON_SELECT = 35,
|
||||
GAMEPAD_BUTTON_START = 36,
|
||||
GAMEPAD_BUTTON_LPAD_CLICKED = 37,
|
||||
GAMEPAD_BUTTON_LPAD_TOUCH = 38,
|
||||
GAMEPAD_BUTTON_RPAD_CLICKED = 39,
|
||||
GAMEPAD_BUTTON_RPAD_TOUCH = 40,
|
||||
GAMEPAD_RIGHTSTICK_CLICK = 41,
|
||||
GAMEPAD_RIGHTSTICK_TOUCH = 42,
|
||||
GAMEPAD_LEFTSTICK_TOUCH = 43,
|
||||
GAMEPAD_BUTTON_LBACK_UPPER = 44,
|
||||
GAMEPAD_BUTTON_RBACK_UPPER = 45,
|
||||
GAMEPAD_BUTTON_LAST = 46,
|
||||
GAMEPAD_ANALOG_SCROLL = 47,
|
||||
GAMEPAD_ANALOG_LEFT_KEYBOARD_CURSOR = 48,
|
||||
GAMEPAD_ANALOG_RIGHT_KEYBOARD_CURSOR = 49,
|
||||
GAMEPAD_ANALOG_LAST = 50
|
||||
}
|
||||
|
||||
// TODO: Not the actual name, but the enum is only represented in a dropdown
|
||||
// options vector, ty valve
|
||||
export enum EThirdPartyControllerConfiguration {
|
||||
Off,
|
||||
DefaultSetting,
|
||||
On,
|
||||
}
|
||||
|
||||
export interface ActiveAccount {
|
||||
strActiveAccountID: string;
|
||||
strName: string;
|
||||
strAvatarHash: string;
|
||||
}
|
||||
|
||||
export interface ControllerInfo {
|
||||
strName: string;
|
||||
eControllerType: EControllerType;
|
||||
nXInputIndex: number;
|
||||
nControllerIndex: number;
|
||||
eRumblePreference: EControllerRumbleSetting;
|
||||
bWireless: boolean;
|
||||
unUniqueID: number;
|
||||
unVendorID: number;
|
||||
unProductID: number;
|
||||
/** Bitmask */
|
||||
unCapabilities: number;
|
||||
strFirmwareBuildTime: string;
|
||||
strSerialNumber: string;
|
||||
strChipID: string;
|
||||
nLEDColorR: number;
|
||||
nLEDColorG: number;
|
||||
nLEDColorB: number;
|
||||
flLEDBrightness: number;
|
||||
flLEDSaturation: number;
|
||||
nTurnOnSound: number;
|
||||
nTurnOffSound: number;
|
||||
nLStickDeadzone: number;
|
||||
nRStickDeadzone: number;
|
||||
nLHapticStrength: number;
|
||||
nRHapticStrength: number;
|
||||
flLPadPressureCurve: number;
|
||||
flRPadPressureCurve: number;
|
||||
bHaptics: boolean;
|
||||
bSWAntiDrift: boolean;
|
||||
flGyroStationaryTolerance: number;
|
||||
flAccelerometerStationaryTolerance: number;
|
||||
bRemoteDevice: boolean;
|
||||
bNintendoLayout: boolean;
|
||||
bUseReversedLayout: boolean;
|
||||
ActiveAccount: ActiveAccount | undefined;
|
||||
vecAltAccounts: any[]; // The type for this property might need to be more specific based on the actual data structure
|
||||
}
|
||||
|
||||
export enum EControllerType {
|
||||
None = -1,
|
||||
Unknown,
|
||||
UnknownSteamController,
|
||||
SteamController, // Codename Gordon
|
||||
SteamControllerV2, // Codename Headcrab
|
||||
SteamControllerNeptune, // Steam Deck
|
||||
FrontPanelBoard = 20,
|
||||
Generic = 30,
|
||||
XBox360Controller,
|
||||
XBoxOneController,
|
||||
PS3Controller,
|
||||
PS4Controller,
|
||||
WiiController,
|
||||
AppleController,
|
||||
AndroidController,
|
||||
SwitchProController,
|
||||
SwitchJoyConLeft,
|
||||
SwitchJoyConRight,
|
||||
SwitchJoyConPair,
|
||||
SwitchProGenericInputOnlyController,
|
||||
MobileTouch,
|
||||
SwitchProXInputSwitchController,
|
||||
PS5Controller,
|
||||
XboxEliteController,
|
||||
LastController, // Unverified
|
||||
PS5EdgeController,
|
||||
GenericKeyboard = 400,
|
||||
GenericMouse = 800,
|
||||
}
|
||||
|
||||
export interface ControllerStateChange {
|
||||
unControllerIndex: number;
|
||||
unPacketNum: number;
|
||||
/**
|
||||
* Bitmask representing pressed upper buttons.
|
||||
* - Bit 0-8: Unknown (@todo Please provide more details if known)
|
||||
* - Bit 9: L4
|
||||
* - Bit 10: R4
|
||||
* - Bit 11-13: Unknown (@todo Please provide more details if known)
|
||||
* - Bit 14: Left Joystick Touch
|
||||
* - Bit 15: Right Joystick Touch
|
||||
* - Bit 16-17: Unknown (@todo Please provide more details if known)
|
||||
* - Bit 18: Quick Access Menu
|
||||
*/
|
||||
ulUpperButtons: number;
|
||||
/**
|
||||
* Bitmask representing pressed buttons.
|
||||
* - Bit 0: R2
|
||||
* - Bit 1: L2
|
||||
* - Bit 2: R1
|
||||
* - Bit 3: L1
|
||||
* - Bit 4: Y
|
||||
* - Bit 5: B
|
||||
* - Bit 6: X
|
||||
* - Bit 7: A
|
||||
* - Bit 8: D-Pad Up
|
||||
* - Bit 9: D-Pad Right
|
||||
* - Bit 10: D-Pad Left
|
||||
* - Bit 11: D-Pad Down
|
||||
* - Bit 12: Select
|
||||
* - Bit 13: Steam/Home
|
||||
* - Bit 14: Start
|
||||
* - Bit 15: L5
|
||||
* - Bit 16: R5
|
||||
* - Bit 17: Left Touchpad Click
|
||||
* - Bit 18: Right Touchpad Click
|
||||
* - Bit 19: Left Touchpad Touch
|
||||
* - Bit 20: Right Touchpad Touch
|
||||
* - Bit 21: Unknown (@todo Please provide more details if known)
|
||||
* - Bit 22: L3
|
||||
* - Bit 23-25: Unknown (@todo Please provide more details if known)
|
||||
* - Bit 26: R3
|
||||
* - Bit 27-28: Unknown (@todo Please provide more details if known)
|
||||
* - Bit 29: Mute (Dualsense)
|
||||
* - Bit 30-31: Unknown (@todo Please provide more details if known)
|
||||
*/
|
||||
ulButtons: number;
|
||||
sLeftPadX: number;
|
||||
sLeftPadY: number;
|
||||
sRightPadX: number;
|
||||
sRightPadY: number;
|
||||
sCenterPadX: number;
|
||||
sCenterPadY: number;
|
||||
sLeftStickX: number;
|
||||
sLeftStickY: number;
|
||||
sRightStickX: number;
|
||||
sRightStickY: number;
|
||||
sTriggerL: number;
|
||||
sTriggerR: number;
|
||||
flTrustedGravityVectorX: number;
|
||||
flTrustedGravityVectorY: number;
|
||||
flTrustedGravityVectorZ: number;
|
||||
flSoftwareQuatW: number;
|
||||
flSoftwareQuatX: number;
|
||||
flSoftwareQuatY: number;
|
||||
flSoftwareQuatZ: number;
|
||||
flSoftwareGyroDegreesPerSecondPitch: number;
|
||||
flSoftwareGyroDegreesPerSecondYaw: number;
|
||||
flSoftwareGyroDegreesPerSecondRoll: number;
|
||||
flHardwareQuatW: number;
|
||||
flHardwareQuatX: number;
|
||||
flHardwareQuatY: number;
|
||||
flHardwareQuatZ: number;
|
||||
flHardwareGyroDegreesPerSecondPitch: number;
|
||||
flHardwareGyroDegreesPerSecondYaw: number;
|
||||
flHardwareGyroDegreesPerSecondRoll: number;
|
||||
flGyroNoiseLength: number;
|
||||
flGyroCalibrationProgress: number;
|
||||
flGravityVectorX: number;
|
||||
flGravityVectorY: number;
|
||||
flGravityVectorZ: number;
|
||||
flAccelerometerNoiseLength: number;
|
||||
sBatteryLevel: number;
|
||||
sPressurePadLeft: number;
|
||||
sPressurePadRight: number;
|
||||
sPressureBumperLeft: number;
|
||||
sPressureBumperRight: number;
|
||||
unHardwareUpdateInMicrosec: number;
|
||||
}
|
||||
|
||||
export interface GameKeyboardMessage {
|
||||
m_bOpen: boolean;
|
||||
nAppID: number;
|
||||
m_dwPID: number;
|
||||
m_dwOverlayPID: number;
|
||||
m_hPipe: number;
|
||||
/** @todo enum */
|
||||
m_eInputMode: number;
|
||||
/** @todo enum */
|
||||
m_eLineInputMode: number;
|
||||
m_pchDescription: string;
|
||||
m_unCharMax: number;
|
||||
m_pchExistingText: string;
|
||||
}
|
||||
|
||||
export interface TouchMenuMessage {
|
||||
bHasVirtualMenus: boolean;
|
||||
unControllerIndex: number;
|
||||
appID: number;
|
||||
}
|
||||
167
src/globals/steam-client/InstallFolder.ts
Normal file
167
src/globals/steam-client/InstallFolder.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
import {EAppUpdateError} from "./App";
|
||||
|
||||
/**
|
||||
* Represents functions related to Steam Install Folders.
|
||||
*/
|
||||
export interface InstallFolder {
|
||||
/**
|
||||
* Adds a Steam Library folder to the Steam client.
|
||||
* @param path The path of the Steam Library folder to be added.
|
||||
* @returns the index of the added folder.
|
||||
*/
|
||||
AddInstallFolder(path: string): Promise<number>;
|
||||
|
||||
/**
|
||||
* Opens the file explorer to browse files in a specific Steam Library folder.
|
||||
* @param folderIndex The index of the folder to be opened.
|
||||
*/
|
||||
BrowseFilesInFolder(folderIndex: number): void;
|
||||
|
||||
/**
|
||||
* Cancels the current move operation for moving game content.
|
||||
*/
|
||||
CancelMove(): void;
|
||||
|
||||
/**
|
||||
* Retrieves a list of installed Steam Library folders.
|
||||
* @returns an array of SteamInstallFolder objects.
|
||||
*/
|
||||
GetInstallFolders(): Promise<SteamInstallFolder[]>;
|
||||
|
||||
/**
|
||||
* Retrieves a list of potential Steam Library folders that can be added.
|
||||
* @returns an array of PotentialInstallFolder objects.
|
||||
*/
|
||||
GetPotentialFolders(): Promise<PotentialInstallFolder[]>;
|
||||
|
||||
/**
|
||||
* Moves the installation folder for a specific app to another Steam Library folder.
|
||||
* @param appId The ID of the application to be moved.
|
||||
* @param folderIndex The index of the target Steam Library folder.
|
||||
*/
|
||||
MoveInstallFolderForApp(appId: number, folderIndex: number): void;
|
||||
|
||||
/**
|
||||
* Refreshes the list of installed Steam Library folders.
|
||||
*/
|
||||
RefreshFolders(): void;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when changes occur in Steam Install Folders.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForInstallFolderChanges(callback: (change: FolderChange) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when moving game content progresses.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForMoveContentProgress(callback: (progress: MoveContentProgress) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when repairing an install folder is finished.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForRepairFolderFinished(callback: (change: FolderChange) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Removes a Steam Library folder from the Steam client.
|
||||
* @param folderIndex The index of the folder to be removed.
|
||||
*/
|
||||
RemoveInstallFolder(folderIndex: number): void;
|
||||
|
||||
/**
|
||||
* Repairs an installed Steam Library folder.
|
||||
* @param folderIndex The index of the folder to be repaired.
|
||||
*/
|
||||
RepairInstallFolder(folderIndex: number): void;
|
||||
|
||||
/**
|
||||
* Sets a specific Steam Library folder as the default install folder.
|
||||
* @param folderIndex The index of the folder to be set as default.
|
||||
*/
|
||||
SetDefaultInstallFolder(folderIndex: number): void;
|
||||
|
||||
/**
|
||||
* Sets a user-defined label for a specific Steam Library folder.
|
||||
* @param folderIndex The index of the folder to be labeled.
|
||||
* @param label The label to be assigned to the folder.
|
||||
*/
|
||||
SetFolderLabel(folderIndex: number, label: string): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents information about an installation folder.
|
||||
*/
|
||||
export interface SteamInstallFolder extends PotentialInstallFolder {
|
||||
/** Index of the folder. */
|
||||
nFolderIndex: number;
|
||||
/** Used space in the folder. */
|
||||
strUsedSize: string;
|
||||
/** Size of DLC storage used in the folder. */
|
||||
strDLCSize: string;
|
||||
/** Size of workshop storage used in the folder. */
|
||||
strWorkshopSize: string;
|
||||
/** Size of staged storage used in the folder. */
|
||||
strStagedSize: string;
|
||||
/** Indicates if the folder is set as the default installation folder. */
|
||||
bIsDefaultFolder: boolean;
|
||||
/** Indicates if the folder is currently mounted. */
|
||||
bIsMounted: boolean;
|
||||
/** List of applications installed in the folder. */
|
||||
vecApps: AppInfo[];
|
||||
}
|
||||
|
||||
export interface PotentialInstallFolder {
|
||||
/** Path of the folder. */
|
||||
strFolderPath: string;
|
||||
/** User label for the folder. */
|
||||
strUserLabel: string;
|
||||
/** Name of the drive where the folder is located. */
|
||||
strDriveName: string;
|
||||
/** Total capacity of the folder. */
|
||||
strCapacity: string;
|
||||
/** Available free space in the folder. */
|
||||
strFreeSpace: string;
|
||||
/** Indicates if the folder is on a fixed drive. */
|
||||
bIsFixed: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents information about an installed application.
|
||||
*/
|
||||
export interface AppInfo {
|
||||
/** ID of the application. */
|
||||
nAppID: number;
|
||||
/** Name of the application. */
|
||||
strAppName: string;
|
||||
/** Sorting information for the application. */
|
||||
strSortAs: string;
|
||||
/** Last played time in Unix Epoch time format. */
|
||||
rtLastPlayed: number;
|
||||
/** Size of used storage by the application. */
|
||||
strUsedSize: string;
|
||||
/** Size of DLC storage used by the application. */
|
||||
strDLCSize: string;
|
||||
/** Size of workshop storage used by the application. */
|
||||
strWorkshopSize: string;
|
||||
/** Size of staged storage used by the application. */
|
||||
strStagedSize: string;
|
||||
}
|
||||
|
||||
export interface FolderChange {
|
||||
folderIndex: number;
|
||||
}
|
||||
|
||||
export interface MoveContentProgress {
|
||||
appid: number;
|
||||
eError: EAppUpdateError;
|
||||
flProgress: number;
|
||||
strBytesMoved: string;
|
||||
strTotalBytesToMove: string;
|
||||
nFilesMoved: number;
|
||||
}
|
||||
131
src/globals/steam-client/Installs.ts
Normal file
131
src/globals/steam-client/Installs.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
import {EAppUpdateError} from "./App";
|
||||
|
||||
/**
|
||||
* Represents functions related to managing installs and installation wizards in Steam.
|
||||
*/
|
||||
export interface Installs {
|
||||
/**
|
||||
* Cancels the installation wizard if it is open.
|
||||
*/
|
||||
CancelInstall(): void;
|
||||
|
||||
/**
|
||||
* Continues and starts the installation if the wizard is still open.
|
||||
*/
|
||||
ContinueInstall(): void;
|
||||
|
||||
/**
|
||||
* Retrieves information from the last opened or currently opened installation wizard.
|
||||
*/
|
||||
GetInstallManagerInfo(): Promise<InstallMgrInfo>;
|
||||
|
||||
/**
|
||||
* Opens the restore from backup installer wizard for a specific app.
|
||||
* @param appBackupPath The backup path of the app.
|
||||
*/
|
||||
OpenInstallBackup(appBackupPath: string): void;
|
||||
|
||||
/**
|
||||
* Opens the installation wizard for specified app IDs.
|
||||
* @param appIds An array of app IDs to install.
|
||||
*/
|
||||
OpenInstallWizard(appIds: number[]): void;
|
||||
|
||||
/**
|
||||
* Opens the uninstall wizard for specified app IDs.
|
||||
* @param appIds An array of app IDs to uninstall.
|
||||
* @param dontPrompt Whether to *not* prompt the user to uninstall.
|
||||
*/
|
||||
OpenUninstallWizard(appIds: number[], dontPrompt: boolean): void;
|
||||
|
||||
RegisterForShowConfirmUninstall: Unregisterable; // Broken? doesn't seem to work
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when the "Failed Uninstall" dialog is shown.
|
||||
* @param callback The callback function to be called when the dialog is shown.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForShowFailedUninstall(callback: (appId: number, reason: EAppUpdateError) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when the installation wizard is shown.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForShowInstallWizard(callback: (data: InstallMgrInfo) => void): Unregisterable;
|
||||
|
||||
RegisterForShowRegisterCDKey: any;
|
||||
|
||||
/**
|
||||
* Sets a list of app identifiers for downloads in the installation wizard.
|
||||
* @param appIds An array of app IDs to set.
|
||||
* @remarks The wizard will not reflect this change immediately, but changing another option will.
|
||||
*/
|
||||
SetAppList(appIds: number[]): void;
|
||||
|
||||
/**
|
||||
* Sets the options for creating shortcuts in the installation wizard.
|
||||
* @param bDesktopShortcut Whether to create a desktop shortcut.
|
||||
* @param bSystemMenuShortcut Whether to create a system menu shortcut.
|
||||
* @remarks The wizard will not reflect this change immediately, but changing another option will.
|
||||
*/
|
||||
SetCreateShortcuts(bDesktopShortcut: boolean, bSystemMenuShortcut: boolean): void;
|
||||
|
||||
/**
|
||||
* Sets the install folder for the installation wizard using an install folder index.
|
||||
* @param folderIndex The index of the install folder.
|
||||
* @remarks The wizard will not reflect this change immediately, but changing another option will.
|
||||
*/
|
||||
SetInstallFolder(folderIndex: number): void;
|
||||
}
|
||||
|
||||
export interface InstallMgrInfo {
|
||||
rgAppIDs: InstallInfoApps[];
|
||||
eInstallState: EInstallMgrState;
|
||||
nDiskSpaceRequired: number;
|
||||
nDiskSpaceAvailable: number;
|
||||
nCurrentDisk: number;
|
||||
nTotalDisks: number;
|
||||
bCanChangeInstallFolder: boolean;
|
||||
/**
|
||||
* Index of the install folder. -1 if not installed.
|
||||
*/
|
||||
iInstallFolder: number;
|
||||
iUnmountedFolder: number;
|
||||
currentAppID: number;
|
||||
eAppError: EAppUpdateError;
|
||||
errorDetail: string;
|
||||
bSystemMenuShortcut: boolean;
|
||||
bDesktopShortcut: boolean;
|
||||
bIsBackupInstall: boolean;
|
||||
// device/hostname
|
||||
strPeerContentServer: string;
|
||||
bPeerContentServerOnline: boolean;
|
||||
bPeerContentServerAvailable: boolean;
|
||||
}
|
||||
|
||||
export interface InstallInfoApps {
|
||||
nAppID: number;
|
||||
lDiskSpaceRequiredBytes: number;
|
||||
}
|
||||
|
||||
export enum EInstallMgrState {
|
||||
None,
|
||||
Setup,
|
||||
WaitLicense,
|
||||
FreeLicense,
|
||||
ShowCDKey,
|
||||
WaitAppInfo,
|
||||
ShowPassword,
|
||||
ShowConfig,
|
||||
ShowEULAs,
|
||||
CreateApps,
|
||||
ReadFromMedia,
|
||||
ShowChangeMedia,
|
||||
WaitLegacyCDKeys,
|
||||
ShowSignup,
|
||||
Complete,
|
||||
Failed,
|
||||
Canceled,
|
||||
}
|
||||
20
src/globals/steam-client/Messaging.ts
Normal file
20
src/globals/steam-client/Messaging.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
|
||||
export interface Messaging {
|
||||
// section - "ContentManagement", "JumpList", "PostToLibrary"
|
||||
// seems multipurpose
|
||||
RegisterForMessages<T extends string>(
|
||||
message: T,
|
||||
callback: (message: T, section: string, args: string) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/*
|
||||
function m(e) {
|
||||
SteamClient.Messaging.PostMessage("LibraryCommands", "ShowFriendChatDialog", JSON.stringify({
|
||||
steamid: e.persona.m_steamid.ConvertTo64BitString()
|
||||
}))
|
||||
}
|
||||
SteamClient.Messaging.PostMessage("FriendsUI", "AcceptedRemotePlayInvite", JSON.stringify({id: this.appID})) : SteamClient.Messaging.PostMessage("FriendsUI", "AcceptedGameInvite", JSON.stringify({id: this.appID}))
|
||||
*/
|
||||
PostMessage(message: string, section: string, args: string): void;
|
||||
}
|
||||
99
src/globals/steam-client/Music.ts
Normal file
99
src/globals/steam-client/Music.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
|
||||
/**
|
||||
* Represents functions related to controlling music playback in the Steam client.
|
||||
*/
|
||||
export interface Music {
|
||||
/**
|
||||
* Decreases the music volume by 10%.
|
||||
*/
|
||||
DecreaseVolume(): void;
|
||||
|
||||
/**
|
||||
* Increases the music volume by 10%.
|
||||
*/
|
||||
IncreaseVolume(): void;
|
||||
|
||||
/**
|
||||
* Plays the next track in the music playlist.
|
||||
*/
|
||||
PlayNext(): void;
|
||||
|
||||
/**
|
||||
* Plays the previous track in the music playlist.
|
||||
*/
|
||||
PlayPrevious(): void;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when music playback changes.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForMusicPlaybackChanges(callback: (param0: boolean | MusicTrack) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when the music playback position changes.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForMusicPlaybackPosition(callback: (position: number) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Sets the playback position of the music track.
|
||||
* @param position The position to set in seconds.
|
||||
*/
|
||||
SetPlaybackPosition(position: number): void;
|
||||
|
||||
/**
|
||||
* Sets the repeat status for music playback.
|
||||
* @param status The repeat status.
|
||||
*/
|
||||
SetPlayingRepeatStatus(status: EMusicPlayingRepeatStatus): void;
|
||||
|
||||
/**
|
||||
* Sets the shuffle status for music playback.
|
||||
* @param value True to enable shuffle, false to disable shuffle.
|
||||
*/
|
||||
SetPlayingShuffled(value: boolean): void;
|
||||
|
||||
/**
|
||||
* Sets the volume for music playback.
|
||||
* @param volume The volume level to set.
|
||||
* @remarks Ranges from 0 to 100.
|
||||
*/
|
||||
SetVolume(volume: number): void;
|
||||
|
||||
/**
|
||||
* Toggles the mute state of the music volume.
|
||||
*/
|
||||
ToggleMuteVolume(): void;
|
||||
|
||||
/**
|
||||
* Toggles between play and pause for music playback.
|
||||
*/
|
||||
TogglePlayPause(): void;
|
||||
}
|
||||
|
||||
export interface MusicTrack {
|
||||
uSoundtrackAppId: number;
|
||||
ePlaybackStatus: EAudioPlayback;
|
||||
eRepeatStatus: EMusicPlayingRepeatStatus;
|
||||
bShuffle: boolean;
|
||||
nVolume: number;
|
||||
nActiveTrack: number;
|
||||
nLengthInMsec: number;
|
||||
}
|
||||
|
||||
export enum EAudioPlayback {
|
||||
Undefined,
|
||||
Playing,
|
||||
Paused,
|
||||
Idle,
|
||||
}
|
||||
|
||||
export enum EMusicPlayingRepeatStatus {
|
||||
None,
|
||||
All,
|
||||
Once,
|
||||
Max,
|
||||
}
|
||||
333
src/globals/steam-client/Notifications.ts
Normal file
333
src/globals/steam-client/Notifications.ts
Normal file
@@ -0,0 +1,333 @@
|
||||
import { JsPbMessage, Unregisterable } from "./shared";
|
||||
|
||||
/**
|
||||
* Everything is taken from here:
|
||||
* https://github.com/SteamDatabase/SteamTracking/blob/master/Protobufs/steammessages_clientnotificationtypes.proto
|
||||
*/
|
||||
export interface Notifications {
|
||||
/**
|
||||
* If `data` is deserialized, returns one of the following here: {@link Notifications}
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForNotifications(
|
||||
callback: (notificationIndex: number, type: EClientNotificationType, data: ArrayBuffer) => void,
|
||||
): Unregisterable;
|
||||
}
|
||||
|
||||
export enum EClientNotificationType {
|
||||
Invalid,
|
||||
DownloadComplete,
|
||||
FriendInvite,
|
||||
FriendInGame,
|
||||
FriendOnline,
|
||||
Achievement,
|
||||
LowBattery,
|
||||
SystemUpdate,
|
||||
FriendMessage,
|
||||
GroupChatMessage,
|
||||
FriendInviteRollup,
|
||||
FamilySharingDeviceAuthorizationChanged,
|
||||
FamilySharingStopPlaying,
|
||||
FamilySharingLibraryAvailable,
|
||||
Screenshot,
|
||||
CloudSyncFailure,
|
||||
CloudSyncConflict,
|
||||
IncomingVoiceChat,
|
||||
ClaimSteamDeckRewards,
|
||||
GiftReceived,
|
||||
ItemAnnouncement,
|
||||
HardwareSurvey,
|
||||
LowDiskSpace,
|
||||
BatteryTemperature,
|
||||
DockUnsupportedFirmware,
|
||||
PeerContentUpload,
|
||||
CannotReadControllerGuideButton,
|
||||
Comment,
|
||||
Wishlist,
|
||||
TradeOffer,
|
||||
AsyncGame,
|
||||
General,
|
||||
HelpRequest,
|
||||
OverlaySplashScreen,
|
||||
BroadcastAvailableToWatch,
|
||||
TimedTrialRemaining,
|
||||
LoginRefresh,
|
||||
MajorSale,
|
||||
TimerExpired,
|
||||
ModeratorMsg,
|
||||
SteamInputActionSetChanged,
|
||||
RemoteClientConnection,
|
||||
RemoteClientStartStream,
|
||||
StreamingClientConnection,
|
||||
FamilyInvite,
|
||||
PlaytimeWarning,
|
||||
FamilyPurchaseRequest,
|
||||
FamilyPurchaseRequestResponse,
|
||||
ParentalFeatureRequest,
|
||||
ParentalPlaytimeRequest,
|
||||
GameRecordingError,
|
||||
ParentalFeatureResponse,
|
||||
ParentalPlaytimeResponse,
|
||||
RequestedGameAdded,
|
||||
ClipDownloaded,
|
||||
GameRecordingStart,
|
||||
GameRecordingStop,
|
||||
GameRecordingUserMarkerAdded,
|
||||
GameRecordingInstantClip,
|
||||
}
|
||||
|
||||
export enum ESystemUpdateNotificationType {
|
||||
Invalid,
|
||||
Available,
|
||||
NeedsRestart,
|
||||
}
|
||||
|
||||
export enum EGameRecordingErrorType {
|
||||
General = 1,
|
||||
LowDiskSpace,
|
||||
}
|
||||
|
||||
export interface ClientNotificationGroupChatMessage extends JsPbMessage {
|
||||
tag(): string;
|
||||
|
||||
/** A Steam64 ID. */
|
||||
steamid_sender(): string;
|
||||
|
||||
chat_group_id(): string;
|
||||
|
||||
chat_id(): string;
|
||||
|
||||
title(): string;
|
||||
|
||||
body(): string;
|
||||
|
||||
rawbody(): string;
|
||||
|
||||
icon(): string;
|
||||
|
||||
notificationid(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationFriendMessage extends JsPbMessage {
|
||||
body(): string;
|
||||
|
||||
icon(): string;
|
||||
|
||||
notificationid(): number;
|
||||
|
||||
response_steamurl(): string;
|
||||
|
||||
/** A Steam64 ID. */
|
||||
steamid(): string;
|
||||
|
||||
tag(): string;
|
||||
|
||||
title(): string;
|
||||
}
|
||||
|
||||
export interface ClientNotificationCloudSyncFailure extends JsPbMessage {
|
||||
appid(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationCloudSyncConflict extends JsPbMessage {
|
||||
appid(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationScreenshot extends JsPbMessage {
|
||||
screenshot_handle(): string;
|
||||
description(): string;
|
||||
local_url(): string;
|
||||
}
|
||||
|
||||
export interface ClientNotificationDownloadCompleted extends JsPbMessage {
|
||||
appid(): number;
|
||||
dlc_appid(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationFriendInvite extends JsPbMessage {
|
||||
steamid(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationFriendInviteRollup extends JsPbMessage {
|
||||
new_invite_count(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationFriendInGame extends JsPbMessage {
|
||||
steamid(): number;
|
||||
game_name(): string;
|
||||
}
|
||||
|
||||
export interface ClientNotificationFriendOnline extends JsPbMessage {
|
||||
steamid(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationAchievement extends JsPbMessage {
|
||||
achievement_id(): string;
|
||||
appid(): number;
|
||||
name(): string;
|
||||
description(): string;
|
||||
image_url(): string;
|
||||
achieved(): boolean;
|
||||
rtime_unlocked(): number;
|
||||
min_progress(): number;
|
||||
current_progress(): number;
|
||||
max_progress(): number;
|
||||
global_achieved_pct(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationLowBattery extends JsPbMessage {
|
||||
pct_remaining(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationSystemUpdate extends JsPbMessage {
|
||||
type(): ESystemUpdateNotificationType;
|
||||
}
|
||||
|
||||
export interface ClientNotificationFriendMessage extends JsPbMessage {
|
||||
tag(): string;
|
||||
steamid(): string;
|
||||
title(): string;
|
||||
body(): string;
|
||||
icon(): string;
|
||||
notificationid(): number;
|
||||
response_steamurl(): string;
|
||||
}
|
||||
|
||||
export interface ClientNotificationGroupChatMessage extends JsPbMessage {
|
||||
tag(): string;
|
||||
steamid_sender(): string;
|
||||
chat_group_id(): string;
|
||||
chat_id(): string;
|
||||
title(): string;
|
||||
body(): string;
|
||||
rawbody(): string;
|
||||
icon(): string;
|
||||
notificationid(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationFamilySharingDeviceAuthorizationChanged extends JsPbMessage {
|
||||
accountid_owner(): number;
|
||||
authorized(): boolean;
|
||||
}
|
||||
|
||||
export interface ClientNotificationFamilySharingStopPlaying extends JsPbMessage {
|
||||
accountid_owner(): number;
|
||||
seconds_remaining(): number;
|
||||
appid(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationFamilySharingLibraryAvailable extends JsPbMessage {
|
||||
accountid_owner(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationIncomingVoiceChat extends JsPbMessage {
|
||||
steamid(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationClaimSteamDeckRewards extends JsPbMessage {
|
||||
}
|
||||
|
||||
export interface ClientNotificationGiftReceived extends JsPbMessage {
|
||||
sender_name(): string;
|
||||
}
|
||||
|
||||
export interface ClientNotificationItemAnnouncement extends JsPbMessage {
|
||||
new_item_count(): number;
|
||||
new_backpack_items(): boolean;
|
||||
}
|
||||
|
||||
export interface ClientNotificationHardwareSurveyPending extends JsPbMessage {
|
||||
}
|
||||
|
||||
export interface ClientNotificationLowDiskSpace extends JsPbMessage {
|
||||
folder_index(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationBatteryTemperature extends JsPbMessage {
|
||||
temperature(): number;
|
||||
notification_type(): string;
|
||||
}
|
||||
|
||||
export interface ClientNotificationDockUnsupportedFirmware extends JsPbMessage {
|
||||
}
|
||||
|
||||
export interface ClientNotificationPeerContentUpload extends JsPbMessage {
|
||||
appid(): number;
|
||||
peer_name(): string;
|
||||
}
|
||||
|
||||
export interface ClientNotificationCannotReadControllerGuideButton extends JsPbMessage {
|
||||
controller_index(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationOverlaySplashScreen extends JsPbMessage {
|
||||
}
|
||||
|
||||
export interface ClientNotificationBroadcastAvailableToWatch extends JsPbMessage {
|
||||
broadcast_permission(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationTimedTrialRemaining extends JsPbMessage {
|
||||
appid(): number;
|
||||
icon(): string;
|
||||
offline(): boolean;
|
||||
allowed_seconds(): number;
|
||||
played_seconds(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationLoginRefresh extends JsPbMessage {
|
||||
}
|
||||
|
||||
export interface ClientNotificationTimerExpired extends JsPbMessage {
|
||||
}
|
||||
|
||||
export interface ClientNotificationSteamInputActionSetChanged extends JsPbMessage {
|
||||
controller_index(): number;
|
||||
action_set_name(): string;
|
||||
}
|
||||
|
||||
export interface ClientNotificationRemoteClientConnection extends JsPbMessage {
|
||||
machine(): string;
|
||||
connected(): boolean;
|
||||
}
|
||||
|
||||
export interface ClientNotificationRemoteClientStartStream extends JsPbMessage {
|
||||
machine(): string;
|
||||
game_name(): string;
|
||||
}
|
||||
|
||||
export interface ClientNotificationStreamingClientConnection extends JsPbMessage {
|
||||
hostname(): string;
|
||||
machine(): string;
|
||||
connected(): boolean;
|
||||
}
|
||||
|
||||
export interface ClientNotificationPlaytimeWarning extends JsPbMessage {
|
||||
type(): string;
|
||||
playtime_remaining(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationGameRecordingError extends JsPbMessage {
|
||||
game_id(): number;
|
||||
error_type(): EGameRecordingErrorType;
|
||||
}
|
||||
|
||||
export interface ClientNotificationGameRecordingStart extends JsPbMessage {
|
||||
game_id(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationGameRecordingStop extends JsPbMessage {
|
||||
game_id(): number;
|
||||
clip_id(): string;
|
||||
duration_secs(): number;
|
||||
}
|
||||
|
||||
export interface ClientNotificationGameRecordingUserMarkerAdded extends JsPbMessage {
|
||||
game_id(): number;
|
||||
}
|
||||
|
||||
export interface CClientNotificationGameRecordingInstantClip extends JsPbMessage {
|
||||
game_id(): number;
|
||||
clip_id(): string;
|
||||
duration_secs(): number;
|
||||
}
|
||||
122
src/globals/steam-client/OpenVR.ts
Normal file
122
src/globals/steam-client/OpenVR.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import { Unregisterable } from "./shared";
|
||||
|
||||
|
||||
export interface OpenVR {
|
||||
Device: VRDevice;
|
||||
DeviceProperties: DeviceProperties;
|
||||
|
||||
/**
|
||||
* @throws OperationResponse if mutual capabilities haven't been loaded.
|
||||
*/
|
||||
GetMutualCapabilities(): Promise<any>;
|
||||
|
||||
GetWebSecret(): Promise<string>;
|
||||
|
||||
InstallVR(): any;
|
||||
|
||||
Keyboard: Keyboard;
|
||||
PathProperties: PathProperties;
|
||||
|
||||
QuitAllVR(): any;
|
||||
|
||||
RegisterForButtonPress: Unregisterable;
|
||||
|
||||
RegisterForHMDActivityLevelChanged(callback: (m_eHMDActivityLevel: EHMDActivityLevel) => void): Unregisterable;
|
||||
|
||||
RegisterForInstallDialog: Unregisterable;
|
||||
|
||||
RegisterForStartupErrors(callback: (clientError: any, initError: any, initErrorString: string) => void): Unregisterable;
|
||||
|
||||
RegisterForVRHardwareDetected(callback: (m_bHMDPresent: any, m_bHMDHardwareDetected: any, m_strHMDName: any) => void): Unregisterable;
|
||||
|
||||
RegisterForVRModeChange(callback: (m_bIsVRRunning: boolean) => void): Unregisterable;
|
||||
|
||||
RegisterForVRSceneAppChange(callback: (param0: number) => void): Unregisterable;
|
||||
|
||||
SetOverlayInteractionAffordance: any;
|
||||
|
||||
StartVR: any;
|
||||
TriggerOverlayHapticEffect: any;
|
||||
VRNotifications: VRNotifications;
|
||||
VROverlay: VROverlay;
|
||||
}
|
||||
|
||||
export interface VRDevice {
|
||||
BIsConnected: any;
|
||||
RegisterForDeviceConnectivityChange: Unregisterable;
|
||||
|
||||
RegisterForVRDeviceSeenRecently(callback: (m_bVRDeviceSeenRecently: any) => void): Unregisterable;
|
||||
}
|
||||
|
||||
export interface DeviceProperties {
|
||||
GetBoolDeviceProperty: any;
|
||||
GetDoubleDeviceProperty: any;
|
||||
GetFloatDeviceProperty: any;
|
||||
GetInt32DeviceProperty: any;
|
||||
GetStringDeviceProperty: any;
|
||||
RegisterForDevicePropertyChange: Unregisterable;
|
||||
}
|
||||
|
||||
export interface Keyboard {
|
||||
Hide(): any;
|
||||
|
||||
/**
|
||||
* {@link EKeyboardFlags} could be useful here
|
||||
*/
|
||||
RegisterForStatus(callback: (m_bIsKeyboardOpen: boolean, m_eKeyboardFlags: number, m_sInitialKeyboardText: string) => void): Unregisterable;
|
||||
|
||||
SendDone(): any;
|
||||
|
||||
SendText(key: string): any; //???
|
||||
Show(): any;
|
||||
}
|
||||
|
||||
export interface PathProperties {
|
||||
GetBoolPathProperty: any;
|
||||
GetDoublePathProperty: any;
|
||||
GetFloatPathProperty: any;
|
||||
GetInt32PathProperty: any;
|
||||
GetStringPathProperty: any;
|
||||
RegisterForPathPropertyChange: any;
|
||||
SetBoolPathProperty: any;
|
||||
SetDoublePathProperty: any;
|
||||
SetFloatPathProperty: any;
|
||||
SetInt32PathProperty: any;
|
||||
SetStringPathProperty: any;
|
||||
}
|
||||
|
||||
export interface VRNotifications {
|
||||
HideCustomNotification: any;
|
||||
RegisterForNotificationEvent: Unregisterable;
|
||||
ShowCustomNotification: any;
|
||||
}
|
||||
|
||||
export interface VROverlay {
|
||||
HideDashboard: any;
|
||||
|
||||
IsDashboardVisible(): Promise<boolean>;
|
||||
|
||||
RegisterForButtonPress: Unregisterable;
|
||||
RegisterForCursorMovement: Unregisterable;
|
||||
RegisterForThumbnailChanged: Unregisterable;
|
||||
RegisterForVisibilityChanged: Unregisterable;
|
||||
ShowDashboard: any;
|
||||
|
||||
SwitchToDashboardOverlay(param0: string): void;
|
||||
}
|
||||
|
||||
export enum EHMDActivityLevel {
|
||||
Unknown = -1,
|
||||
Idle,
|
||||
UserInteraction,
|
||||
UserInteraction_Timeout,
|
||||
Standby,
|
||||
Idle_Timeout,
|
||||
}
|
||||
|
||||
export enum EKeyboardFlags {
|
||||
Minimal = 1 << 0,
|
||||
Modal = 1 << 1,
|
||||
ShowArrowKeys = 1 << 2,
|
||||
HideDoneKey = 1 << 3,
|
||||
}
|
||||
172
src/globals/steam-client/Overlay.ts
Normal file
172
src/globals/steam-client/Overlay.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import type { EBrowserType, ESteamRealm, EUIComposition, EUIMode, Unregisterable } from "./shared";
|
||||
|
||||
export interface Overlay {
|
||||
/**
|
||||
* Destroys the gamepad UI desktop configurator window if open.
|
||||
*/
|
||||
DestroyGamePadUIDesktopConfiguratorWindow(): void;
|
||||
|
||||
GetOverlayBrowserInfo(): Promise<OverlayBrowserInfo[]>;
|
||||
|
||||
// steam://gamewebcallback
|
||||
HandleGameWebCallback(url: string): void;
|
||||
|
||||
/**
|
||||
* @param protocol Something like {@link OverlayBrowserProtocols.strScheme}
|
||||
*/
|
||||
HandleProtocolForOverlayBrowser(appId: number, protocol: string): void;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when an overlay is activated from an app.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForActivateOverlayRequests(callback: (request: ActivateOverlayRequest) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when a microtransaction authorization is requested.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForMicroTxnAuth(
|
||||
callback: (appId: number, microTxnId: string, realm: ESteamRealm, microTxnUrl: string) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when a microtransaction authorization is dismissed by the user in Steam's authorization page.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForMicroTxnAuthDismiss(callback: (appId: number, microTxnId: string) => void): Unregisterable;
|
||||
|
||||
RegisterForNotificationPositionChanged(
|
||||
callback: (appId: number, position: ENotificationPosition, horizontalInset: number, verticalInset: number) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when an overlay is activated or closed.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForOverlayActivated(
|
||||
callback: (overlayProcessPid: number, appId: number, active: boolean, param3: boolean) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when the overlay browser protocols change.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForOverlayBrowserProtocols(
|
||||
callback: (browseProtocols: OverlayBrowserProtocols) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers **the** callback function to be called when the overlay browser information changes.
|
||||
* @param callback The callback function to be called when the overlay browser information changes.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
* @remarks Do Not Use, this will break the overlay unless you know what you are doing.
|
||||
*/
|
||||
RegisterOverlayBrowserInfoChanged(callback: () => void): Unregisterable;
|
||||
|
||||
SetOverlayState(appId: string, state: EUIComposition): void;
|
||||
}
|
||||
|
||||
type OverlayRequestDialog_t =
|
||||
| 'achievements'
|
||||
| 'asyncnotificationsrequested'
|
||||
| 'chat'
|
||||
| 'community'
|
||||
| 'friendadd'
|
||||
| 'friendremove'
|
||||
| 'friendrequestaccept'
|
||||
| 'friendrequestignore'
|
||||
| 'friendremove'
|
||||
| 'jointrade'
|
||||
| 'leaderboards'
|
||||
| 'lobbyinvite'
|
||||
| 'lobbyinviteconnectstring'
|
||||
| 'officialgamegroup'
|
||||
| 'requestplaytime'
|
||||
| 'remoteplaytogether'
|
||||
| 'remoteplaytogetherinvite'
|
||||
| 'settings'
|
||||
| 'stats'
|
||||
| 'steamid'
|
||||
| 'store';
|
||||
|
||||
// EPosition
|
||||
export enum ENotificationPosition {
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight,
|
||||
}
|
||||
|
||||
export interface ActivateOverlayRequest {
|
||||
/**
|
||||
* The app ID that just had an overlay request.
|
||||
*/
|
||||
appid: number;
|
||||
|
||||
/**
|
||||
* `true` if webpage, and so {@link strDialog} will start with `https://`.
|
||||
*/
|
||||
bWebPage: boolean;
|
||||
|
||||
eFlag: EOverlayToStoreFlag;
|
||||
|
||||
eWebPageMode: EActivateGameOverlayToWebPageMode;
|
||||
|
||||
/**
|
||||
* Steam64 ID.
|
||||
*/
|
||||
steamidTarget: string;
|
||||
|
||||
/**
|
||||
* Game invites string for `Friends.InviteUserToGame`.
|
||||
*/
|
||||
strConnectString: string;
|
||||
|
||||
/**
|
||||
* Web page URL if starts with `https://`, so cast the type to `string` if it is.
|
||||
*/
|
||||
strDialog: OverlayRequestDialog_t;
|
||||
|
||||
/**
|
||||
* App ID of the requesting game.
|
||||
*/
|
||||
unRequestingAppID: number;
|
||||
}
|
||||
|
||||
export interface OverlayBrowserInfo {
|
||||
appID: number;
|
||||
eBrowserType: EBrowserType;
|
||||
eUIMode: EUIMode;
|
||||
flDisplayScale?: number;
|
||||
gameID: string;
|
||||
nBrowserID: number;
|
||||
nScreenHeight: number;
|
||||
nScreenWidth: number;
|
||||
/**
|
||||
* The PID of the overlay process.
|
||||
*/
|
||||
unPID: number;
|
||||
}
|
||||
|
||||
export interface OverlayBrowserProtocols {
|
||||
unAppID: number;
|
||||
strScheme: string;
|
||||
bAdded: boolean;
|
||||
}
|
||||
|
||||
export enum EActivateGameOverlayToWebPageMode {
|
||||
Default,
|
||||
Modal,
|
||||
}
|
||||
|
||||
export enum EOverlayToStoreFlag {
|
||||
None,
|
||||
AddToCart,
|
||||
AddToCartAndShow,
|
||||
}
|
||||
129
src/globals/steam-client/Parental.ts
Normal file
129
src/globals/steam-client/Parental.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
import { EResult, Unregisterable } from "./shared";
|
||||
|
||||
/**
|
||||
* Interface for managing parental control settings.
|
||||
*/
|
||||
export interface Parental {
|
||||
/**
|
||||
* Locks the parental control settings.
|
||||
*/
|
||||
LockParentalLock(): void;
|
||||
|
||||
RegisterForParentalPlaytimeWarnings(callback: (time: number) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be invoked when parental settings change.
|
||||
* @param callback The callback function to be invoked when parental settings change.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForParentalSettingsChanges(callback: (settings: ParentalSettings) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Unlocks the parental lock with the provided PIN.
|
||||
* @param pin The 4-digit PIN to unlock the parental lock.
|
||||
* @returns a number representing the result of the unlock operation.
|
||||
*/
|
||||
UnlockParentalLock(pin: string, param1: boolean): Promise<EResult>;
|
||||
}
|
||||
|
||||
export interface ParentalSettings {
|
||||
ever_enabled: boolean;
|
||||
locked: boolean;
|
||||
/**
|
||||
* If deserialized, returns {@link ParentalSettingsProtoMsg}.
|
||||
*/
|
||||
settings: ArrayBuffer;
|
||||
strPlaintextPassword: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the parental settings and restrictions.
|
||||
* @todo This whole thing is unconfirmed as I do not have access to parental
|
||||
* stuff and things
|
||||
*/
|
||||
export interface ParentalSettingsProtoMsg {
|
||||
steamid?: number;
|
||||
applist_base_id?: number;
|
||||
applist_base_description?: string;
|
||||
/**
|
||||
* Base list.
|
||||
*/
|
||||
applist_base: ParentalApp[];
|
||||
/**
|
||||
* Custom list of allowed applications.
|
||||
*/
|
||||
applist_custom: ParentalApp[];
|
||||
/**
|
||||
* @todo enum ?
|
||||
*/
|
||||
passwordhashtype?: number;
|
||||
salt?: number;
|
||||
passwordhash?: number;
|
||||
/**
|
||||
* Indicates whether parental settings are enabled.
|
||||
*/
|
||||
is_enabled?: boolean;
|
||||
/**
|
||||
* Bitmask representing enabled features.
|
||||
* - Bit 0: Unknown (@todo Please provide more details if known)
|
||||
* - Bit 1: Online content & features - Steam Store
|
||||
* - Bit 2: Online content & features - Community-generated content
|
||||
* - Bit 3: Online content & features - My online profile, screenshots, and achievements
|
||||
* - Bit 4: Online content & features - Friends, chat, and groups
|
||||
* - Bit 5-11: Unknown (@todo Please provide more details if known)
|
||||
* - Bit 12: Library content - 0: Only games I choose, 1: All games
|
||||
* @todo {@link EParentalFeature} ?
|
||||
*/
|
||||
enabled_features?: number;
|
||||
/**
|
||||
* Email for recovery (if applicable).
|
||||
*/
|
||||
recovery_email?: string;
|
||||
is_site_license_lock?: boolean;
|
||||
temporary_enabled_features?: number;
|
||||
rtime_temporary_feature_expiration?: number;
|
||||
playtime_restrictions?: ParentalPlaytimeRestrictions;
|
||||
temporary_playtime_restrictions?: ParentalTemporaryPlaytimeRestrictions;
|
||||
excluded_store_content_descriptors: number[];
|
||||
excluded_community_content_descriptors: number[];
|
||||
utility_appids: number[];
|
||||
}
|
||||
|
||||
interface ParentalApp {
|
||||
appid: number;
|
||||
is_allowed: boolean;
|
||||
}
|
||||
|
||||
interface ParentalPlaytimeDay {
|
||||
allowed_time_windows?: number;
|
||||
allowed_daily_minutes?: number;
|
||||
}
|
||||
|
||||
interface ParentalPlaytimeRestrictions {
|
||||
apply_playtime_restrictions?: boolean;
|
||||
playtime_days: ParentalPlaytimeDay[];
|
||||
}
|
||||
|
||||
interface ParentalTemporaryPlaytimeRestrictions {
|
||||
restrictions?: ParentalPlaytimeDay;
|
||||
rtime_expires?: number;
|
||||
}
|
||||
|
||||
export enum EParentalFeature {
|
||||
Invalid,
|
||||
Store,
|
||||
Community,
|
||||
Profile,
|
||||
Friends,
|
||||
News,
|
||||
Trading,
|
||||
Settings,
|
||||
Console,
|
||||
Browser,
|
||||
ParentalSetup,
|
||||
Library,
|
||||
Test,
|
||||
SiteLicense,
|
||||
KioskMode,
|
||||
Max,
|
||||
}
|
||||
342
src/globals/steam-client/RemotePlay.ts
Normal file
342
src/globals/steam-client/RemotePlay.ts
Normal file
@@ -0,0 +1,342 @@
|
||||
import {EControllerType} from "./Input";
|
||||
import { EParentalFeature } from "./Parental";
|
||||
import { EResult, Unregisterable } from "./shared";
|
||||
|
||||
export interface RemotePlay {
|
||||
/**
|
||||
* @param param1 TODO: Something about restrictions countries ? maybe it's games
|
||||
*/
|
||||
BCanAcceptInviteForGame(gameId: string, param1: string): Promise<boolean>;
|
||||
BCanCreateInviteForGame(gameId: string, param1: boolean): Promise<boolean>;
|
||||
|
||||
BRemotePlayTogetherGuestOnPhoneOrTablet(steam64Id: string, guestId: number): Promise<boolean>;
|
||||
|
||||
BRemotePlayTogetherGuestSupported(): Promise<boolean>;
|
||||
|
||||
// TODO: both calls have 1 arg, but it requires 2
|
||||
CancelInviteAndSession(steam64Id: string, param1: number): Promise<EResult>;
|
||||
|
||||
CancelInviteAndSessionWithGuestID(steam64Id: string, guestId: number): Promise<EResult>;
|
||||
|
||||
CancelRemoteClientPairing(): void;
|
||||
|
||||
CloseGroup(): Promise<number>;
|
||||
|
||||
CreateGroup(param0: string): Promise<EResult>;
|
||||
|
||||
CreateInviteAndSession(steam64Id: string, param1: string): Promise<EResult>;
|
||||
|
||||
CreateInviteAndSessionWithGuestID(steam64Id: string, guestId: number, param2: string): Promise<EResult>;
|
||||
|
||||
GetClientID(): Promise<string>;
|
||||
|
||||
// TODO: -1 no preference? no idea where the settings are anyway lol
|
||||
GetClientStreamingBitrate(): Promise<number>;
|
||||
GetClientStreamingQuality(): Promise<number>;
|
||||
GetControllerType(controllerIndex: number): Promise<EControllerType>;
|
||||
|
||||
/**
|
||||
* @returns an integer from 0 to 100.
|
||||
*/
|
||||
GetGameSystemVolume(): Promise<number>;
|
||||
|
||||
GetPerUserInputSettings(steam64Id: string): Promise<RemotePlayInputSettings>;
|
||||
|
||||
GetPerUserInputSettingsWithGuestID(steam64Id: string, guestId: number): Promise<RemotePlayInputSettings>;
|
||||
|
||||
IdentifyController(nControllerIndex: number): void;
|
||||
|
||||
InstallAudioDriver(): void;
|
||||
InstallInputDriver(): void;
|
||||
MoveControllerToSlot(controllerIndex: number, slot: number): void;
|
||||
RegisterForAdditionalParentalBlocks(callback: (blocks: EParentalFeature[]) => void): Unregisterable;
|
||||
RegisterForAudioDriverPrompt(callback: () => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* @todo no mentions of it in Steam code
|
||||
*/
|
||||
RegisterForBitrateOverride: Unregisterable;
|
||||
RegisterForClearControllers(callback: () => void): Unregisterable;
|
||||
RegisterForControllerIndexSet(
|
||||
callback: (steamid: string, slot: number, guestid: number) => void
|
||||
): Unregisterable;
|
||||
|
||||
RegisterForDevicesChanges(callback: (devices: RemotePlayDevice[]) => void): Unregisterable;
|
||||
|
||||
RegisterForGroupCreated(callback: (steamId: string, appId: string) => void): Unregisterable;
|
||||
RegisterForGroupDisbanded(callback: () => void): Unregisterable;
|
||||
RegisterForInputDriverPrompt(callback: () => void): Unregisterable;
|
||||
RegisterForInputDriverRestartNotice(callback: () => void): Unregisterable;
|
||||
|
||||
RegisterForInputUsed(
|
||||
callback: (steam64Id: string, type: EClientUsedInputType, guestId: number) => void,
|
||||
): Unregisterable; // only fires on host
|
||||
|
||||
RegisterForInviteResult(
|
||||
callback: (
|
||||
steamId: string,
|
||||
param1: any,
|
||||
result: ERemoteClientLaunch,
|
||||
) => void
|
||||
): Unregisterable;
|
||||
|
||||
RegisterForNetworkUtilizationUpdate(
|
||||
callback: (steam64Id: string, guestId: number, networkUtilization: number, networkDuration: number) => void,
|
||||
): Unregisterable; // only fires on host
|
||||
|
||||
RegisterForPlaceholderStateChanged(callback: (isShowingPlaceholder: boolean) => void): Unregisterable;
|
||||
|
||||
RegisterForPlayerInputSettingsChanged(
|
||||
callback: (steamId: string, settings: RemotePlayInputSettings, guestId: number) => void
|
||||
): Unregisterable;
|
||||
|
||||
RegisterForQualityOverride(callback: (hostStreamingQualityOverride: number) => void): Unregisterable;
|
||||
|
||||
RegisterForRemoteClientLaunchFailed(callback: (state: ERemoteClientLaunch) => void): Unregisterable;
|
||||
|
||||
RegisterForRemoteClientStarted(callback: (steam64Id: string, appId: string) => void): Unregisterable; // only fires on client
|
||||
|
||||
RegisterForRemoteClientStopped(callback: (steam64Id: string, appId: string) => void): Unregisterable; // only fires on client
|
||||
|
||||
RegisterForRemoteDeviceAuthorizationCancelled(callback: () => void): Unregisterable;
|
||||
|
||||
RegisterForRemoteDeviceAuthorizationRequested(callback: (device: string) => void): Unregisterable;
|
||||
|
||||
RegisterForRemoteDevicePairingPINChanged(callback: (device: string, pin: string) => void): Unregisterable;
|
||||
|
||||
RegisterForRestrictedSessionChanges(callback: (restrictedSession: boolean) => void): Unregisterable;
|
||||
|
||||
RegisterForSessionStopped(callback: (steam64Id: string, guestId: number, avatarHash: string) => void): Unregisterable;
|
||||
|
||||
RegisterForSessionStarted(callback: (steam64Id: string, gameId: string, guestId: number) => void): Unregisterable;
|
||||
|
||||
RegisterForSessionStopped(callback: (steam64Id: string, guestId: number) => void): Unregisterable;
|
||||
|
||||
RegisterForSettingsChanges(callback: (remotePlaySettings: RemotePlaySettings) => void): Unregisterable;
|
||||
|
||||
SetClientStreamingBitrate(bitrate: number): void;
|
||||
|
||||
SetClientStreamingQuality(quality: number): void;
|
||||
|
||||
SetGameSystemVolume(volume: number): void;
|
||||
|
||||
SetPerUserControllerInputEnabled(steam64Id: string, enabled: boolean): void;
|
||||
|
||||
SetPerUserControllerInputEnabledWithGuestID(steam64Id: string, guestId: number, enabled: boolean): void;
|
||||
|
||||
SetPerUserKeyboardInputEnabled(steam64Id: string, enabled: boolean): void;
|
||||
|
||||
SetPerUserKeyboardInputEnabledWithGuestID(steam64Id: string, guestId: number, enabled: boolean): void;
|
||||
|
||||
SetPerUserMouseInputEnabled(steam64Id: string, enabled: boolean): void;
|
||||
|
||||
SetPerUserMouseInputEnabledWithGuestID(steam64Id: string, guestId: number, enabled: boolean): void;
|
||||
|
||||
SetRemoteDeviceAuthorized(param0: boolean, param1: string): void;
|
||||
|
||||
SetRemoteDevicePIN(pin: string): void;
|
||||
|
||||
SetRemotePlayEnabled(enabled: boolean): void;
|
||||
|
||||
/**
|
||||
* @param base64 Serialized base64 message from {@link StreamingClientConfig}.
|
||||
*/
|
||||
SetStreamingClientConfig(base64: string, sessionId: number): void;
|
||||
|
||||
/**
|
||||
* Enables advanced client options.
|
||||
*/
|
||||
SetStreamingClientConfigEnabled(value: boolean): void;
|
||||
|
||||
SetStreamingDesktopToRemotePlayTogetherEnabled(enabled: boolean): void;
|
||||
|
||||
SetStreamingP2PScope(scope: EStreamP2PScope): void;
|
||||
|
||||
/**
|
||||
* @param base64 Serialized base64 message from {@link StreamingServerConfig}.
|
||||
*/
|
||||
SetStreamingServerConfig(base64: string, sessionId: number): void;
|
||||
|
||||
/**
|
||||
* Enables advanced host options.
|
||||
*/
|
||||
SetStreamingServerConfigEnabled(value: boolean): void;
|
||||
|
||||
StopStreamingClient(): void;
|
||||
|
||||
StopStreamingSession(id: number): void;
|
||||
StopStreamingSessionAndSuspendDevice(id: number): void;
|
||||
|
||||
UnlockH264(): void;
|
||||
|
||||
/**
|
||||
* Unpairs all devices.
|
||||
*/
|
||||
UnpairRemoteDevices(): void;
|
||||
}
|
||||
|
||||
export enum EClientUsedInputType {
|
||||
Keyboard,
|
||||
Mouse,
|
||||
Controller,
|
||||
Max,
|
||||
}
|
||||
|
||||
export interface RemotePlayDevice {
|
||||
clientId: string;
|
||||
clientName: string;
|
||||
status: string; // "Connected", "Paired",
|
||||
formFactor: number;
|
||||
unStreamingSessionID: number;
|
||||
bCanSteamVR: boolean;
|
||||
bCanSuspend: boolean;
|
||||
}
|
||||
|
||||
interface RemotePlayInputSettings {
|
||||
bKeyboardEnabled: true;
|
||||
bMouseEnabled: true;
|
||||
bControllerEnabled: true;
|
||||
}
|
||||
|
||||
export interface RemotePlaySettings {
|
||||
bAV1DecodeAvailable: boolean;
|
||||
bHEVCDecodeAvailable: boolean;
|
||||
bRemotePlayDisabledBySystemPolicy: boolean;
|
||||
bRemotePlaySupported: boolean;
|
||||
bRemotePlayEnabled: boolean;
|
||||
eRemotePlayP2PScope: EStreamP2PScope;
|
||||
bRemotePlayServerConfigAvailable: boolean;
|
||||
bRemotePlayServerConfigEnabled: boolean;
|
||||
bRemotePlayClientConfigEnabled: boolean;
|
||||
unStreamingSessionID: number;
|
||||
strStreamingClientName: string;
|
||||
/**
|
||||
* If deserialized, returns {@link StreamingClientConfig}.
|
||||
*/
|
||||
RemotePlayClientConfig: StreamingClientConfig;
|
||||
/**
|
||||
* If deserialized, returns {@link StreamingServerConfig}.
|
||||
*/
|
||||
RemotePlayServerConfig: ArrayBuffer;
|
||||
nDefaultAudioChannels: number;
|
||||
nAutomaticResolutionX: number;
|
||||
nAutomaticResolutionY: number;
|
||||
}
|
||||
|
||||
export interface StreamingClientConfig {
|
||||
quality?: EStreamQualityPreference;
|
||||
desired_resolution_x?: number;
|
||||
desired_resolution_y?: number;
|
||||
desired_framerate_numerator?: number;
|
||||
desired_framerate_denominator?: number;
|
||||
desired_bitrate_kbps?: number;
|
||||
enable_hardware_decoding?: boolean;
|
||||
enable_performance_overlay?: boolean;
|
||||
enable_video_streaming?: boolean;
|
||||
enable_audio_streaming?: boolean;
|
||||
enable_input_streaming?: boolean;
|
||||
audio_channels?: number;
|
||||
enable_video_hevc?: boolean;
|
||||
enable_performance_icons?: boolean;
|
||||
enable_microphone_streaming?: boolean;
|
||||
controller_overlay_hotkey?: string;
|
||||
enable_touch_controller_OBSOLETE?: boolean;
|
||||
p2p_scope?: EStreamP2PScope;
|
||||
enable_audio_uncompressed?: boolean;
|
||||
display_limit?: StreamVideoLimit;
|
||||
quality_limit?: StreamVideoLimit;
|
||||
runtime_limit?: StreamVideoLimit;
|
||||
decoder_limit: StreamVideoLimit[];
|
||||
}
|
||||
|
||||
export interface StreamingServerConfig {
|
||||
change_desktop_resolution?: boolean;
|
||||
dynamically_adjust_resolution_OBSOLETE?: boolean;
|
||||
enable_capture_nvfbc?: boolean;
|
||||
enable_hardware_encoding_nvidia_OBSOLETE?: boolean;
|
||||
enable_hardware_encoding_amd_OBSOLETE?: boolean;
|
||||
enable_hardware_encoding_intel_OBSOLETE?: boolean;
|
||||
software_encoding_threads?: number;
|
||||
enable_traffic_priority?: boolean;
|
||||
host_play_audio?: EStreamHostPlayAudioPreference;
|
||||
enable_hardware_encoding?: boolean;
|
||||
}
|
||||
|
||||
export interface StreamVideoLimit {
|
||||
codec?: EStreamVideoCodec;
|
||||
mode?: StreamVideoMode;
|
||||
bitrate_kbps?: number;
|
||||
burst_bitrate_kbps?: number;
|
||||
}
|
||||
|
||||
export interface StreamVideoMode {
|
||||
width?: number;
|
||||
height?: number;
|
||||
refresh_rate?: number;
|
||||
refresh_rate_numerator?: number;
|
||||
refresh_rate_denominator?: number;
|
||||
}
|
||||
|
||||
export enum ERemoteClientLaunch {
|
||||
OK = 1,
|
||||
Fail,
|
||||
RequiresUI,
|
||||
RequiresLaunchOption,
|
||||
RequiresEULA,
|
||||
Timeout,
|
||||
StreamTimeout,
|
||||
StreamClientFail,
|
||||
OtherGameRunning,
|
||||
DownloadStarted,
|
||||
DownloadNoSpace,
|
||||
DownloadFiltered,
|
||||
DownloadRequiresUI,
|
||||
AccessDenied,
|
||||
NetworkError,
|
||||
Progress,
|
||||
ParentalUnlockFailed,
|
||||
ScreenLocked,
|
||||
Unsupported,
|
||||
DisabledLocal,
|
||||
DisabledRemote,
|
||||
Broadcasting,
|
||||
Busy,
|
||||
DriversNotInstalled,
|
||||
TransportUnavailable,
|
||||
Canceled,
|
||||
Invisible,
|
||||
RestrictedCountry,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
export enum EStreamVideoCodec {
|
||||
None,
|
||||
Raw,
|
||||
VP8,
|
||||
VP9,
|
||||
H264,
|
||||
HEVC,
|
||||
ORBX1,
|
||||
ORBX2,
|
||||
AV1,
|
||||
}
|
||||
|
||||
export enum EStreamHostPlayAudioPreference {
|
||||
Default,
|
||||
Always,
|
||||
}
|
||||
|
||||
export enum EStreamQualityPreference {
|
||||
Automatic = -1,
|
||||
Fast = 1,
|
||||
Balanced,
|
||||
Beautiful,
|
||||
}
|
||||
|
||||
export enum EStreamP2PScope {
|
||||
Automatic,
|
||||
Disabled,
|
||||
OnlyMe,
|
||||
Friends,
|
||||
Everyone,
|
||||
}
|
||||
149
src/globals/steam-client/Screenshots.ts
Normal file
149
src/globals/steam-client/Screenshots.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Interface for managing screenshots.
|
||||
*/
|
||||
export interface Screenshots {
|
||||
/**
|
||||
* Deletes a local screenshot.
|
||||
* @param appId The ID of the application.
|
||||
* @param screenshotIndex The index of the local screenshot.
|
||||
* @returns a boolean value indicating whether the deletion was successful.
|
||||
*/
|
||||
DeleteLocalScreenshot(appId: string, screenshotIndex: number): Promise<boolean>;
|
||||
|
||||
DeleteLocalScreenshots(screenshots: ScreenshotToDelete[]): Promise<ScreenshotDeletionResponse>;
|
||||
|
||||
/**
|
||||
* Retrieves all local screenshots for all applications.
|
||||
* @returns an array of Screenshot objects.
|
||||
*/
|
||||
GetAllAppsLocalScreenshots(): Promise<Screenshot[]>;
|
||||
|
||||
/**
|
||||
* Retrieves the count of all local screenshots for all applications.
|
||||
* @returns the count of local screenshots.
|
||||
*/
|
||||
GetAllAppsLocalScreenshotsCount(): Promise<number>;
|
||||
|
||||
/**
|
||||
* Retrieves a range of local screenshots for all applications.
|
||||
* @param start The starting index of the screenshot range.
|
||||
* @param end The ending index of the screenshot range.
|
||||
* @returns an array of Screenshot objects within the specified range.
|
||||
*/
|
||||
GetAllAppsLocalScreenshotsRange(start: number, end: number): Promise<Screenshot[]>;
|
||||
|
||||
/**
|
||||
* Retrieves all local screenshots.
|
||||
* @returns an array of Screenshot objects.
|
||||
*/
|
||||
GetAllLocalScreenshots(): Promise<Screenshot[]>;
|
||||
|
||||
/**
|
||||
* Retrieves the game associated with a specific local screenshot index.
|
||||
* @param screenshotIndex The index of the local screenshot.
|
||||
* @returns the ID of the game associated with the screenshot.
|
||||
*/
|
||||
GetGameWithLocalScreenshots(screenshotIndex: number): Promise<number>;
|
||||
|
||||
/**
|
||||
* Retrieves the last taken local screenshot.
|
||||
* @returns the last taken local screenshot.
|
||||
*/
|
||||
GetLastScreenshotTaken(): Promise<Screenshot>;
|
||||
|
||||
/**
|
||||
* Retrieves a specific local screenshot for an application.
|
||||
* @param appId The ID of the application.
|
||||
* @param screenshotIndex The index of the local screenshot.
|
||||
* @returns the requested local screenshot.
|
||||
*/
|
||||
GetLocalScreenshotByHandle(appId: string, screenshotIndex: number): Promise<Screenshot>;
|
||||
|
||||
/**
|
||||
* Retrieves the count of local screenshots for a specific application.
|
||||
* @param appId The ID of the application.
|
||||
* @returns the count of local screenshots for the application.
|
||||
*/
|
||||
GetLocalScreenshotCount(appId: number): Promise<number>;
|
||||
|
||||
/**
|
||||
* Retrieves the path of a screenshot.
|
||||
* @param appId The ID of the application.
|
||||
* @param hHandle The handle of the screenshot.
|
||||
* @returns the screenshot path or the screenshot directory if no such handle.
|
||||
*/
|
||||
GetLocalScreenshotPath(appId: number, hHandle: number): Promise<string>;
|
||||
|
||||
/**
|
||||
* Retrieves the number of games with local screenshots.
|
||||
* @returns the number of games with local screenshots.
|
||||
*/
|
||||
GetNumGamesWithLocalScreenshots(): Promise<number>;
|
||||
|
||||
/**
|
||||
* Gets total screenshot usage in the specified library folder.
|
||||
* @param path Library folder path.
|
||||
* @returns the number of taken space in bytes.
|
||||
*/
|
||||
GetTotalDiskSpaceUsage(path: string): Promise<number>;
|
||||
|
||||
/**
|
||||
* Opens a local screenshot in the system image viewer.
|
||||
* If the screenshot index is invalid, this function opens the screenshots directory for the specified application ID.
|
||||
* @param appId The ID of the application.
|
||||
* @param screenshotIndex The index of the local screenshot.
|
||||
*/
|
||||
ShowScreenshotInSystemViewer(appId: string, screenshotIndex: number): void;
|
||||
|
||||
/**
|
||||
* Opens the folder containing local screenshots for a specific application.
|
||||
* @param appId The ID of the application.
|
||||
*/
|
||||
ShowScreenshotsOnDisk(appId: string): void;
|
||||
|
||||
/**
|
||||
* Uploads a local screenshot.
|
||||
* @param appId The ID of the application.
|
||||
* @param localScreenshot_hHandle The handle of the local screenshot.
|
||||
* @param filePrivacyState The privacy state of the screenshot file.
|
||||
* @returns a boolean value indicating whether the upload was successful.
|
||||
*/
|
||||
UploadLocalScreenshot(
|
||||
appId: string,
|
||||
localScreenshot_hHandle: number,
|
||||
filePrivacyState: EUCMFilePrivacyState,
|
||||
): Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface Screenshot {
|
||||
nAppID: number;
|
||||
strGameID: string;
|
||||
hHandle: number;
|
||||
nWidth: number;
|
||||
nHeight: number;
|
||||
nCreated: number; // timestamp
|
||||
ePrivacy: EUCMFilePrivacyState;
|
||||
strCaption: string;
|
||||
bSpoilers: boolean;
|
||||
strUrl: string;
|
||||
bUploaded: boolean;
|
||||
ugcHandle: string;
|
||||
}
|
||||
|
||||
export interface ScreenshotToDelete {
|
||||
gameID: string;
|
||||
rgHandles: number[];
|
||||
}
|
||||
|
||||
export interface ScreenshotDeletionResponse {
|
||||
bSuccess: boolean;
|
||||
rgFailedRequestIndices: number[];
|
||||
}
|
||||
|
||||
export enum EUCMFilePrivacyState {
|
||||
Invalid = -1,
|
||||
Private = 1 << 1,
|
||||
FriendsOnly = 1 << 2,
|
||||
Public = 1 << 3,
|
||||
Unlisted = 1 << 4,
|
||||
}
|
||||
372
src/globals/steam-client/ServerBrowser.ts
Normal file
372
src/globals/steam-client/ServerBrowser.ts
Normal file
@@ -0,0 +1,372 @@
|
||||
import { OperationResponse, Unregisterable } from "./shared";
|
||||
|
||||
/**
|
||||
* Represents functionality for the server browser.
|
||||
*/
|
||||
export interface ServerBrowser {
|
||||
/**
|
||||
* Adds a favorite server.
|
||||
* @param server The server to add.
|
||||
* @returns an empty string if successful, `Invalid/missing IPv4?` if failed.
|
||||
*/
|
||||
AddFavoriteServer(server: GameServer): Promise<string>;
|
||||
|
||||
/**
|
||||
* Adds a favorite server by IP.
|
||||
* @param ip The IP to add to favorite servers.
|
||||
* @returns an empty string if successful, localization string if failed.
|
||||
*/
|
||||
AddFavoriteServersByIP(ip: string): Promise<string>;
|
||||
|
||||
CancelServerQuery(dialogId: number, queryServer: number): void;
|
||||
|
||||
/**
|
||||
* Connects to a server from a given dialog.
|
||||
* @param dialogId The dialog ID to use.
|
||||
* @param password Server password, empty if none.
|
||||
* @returns a connection status.
|
||||
*/
|
||||
ConnectToServer(dialogId: number, password: string): Promise<EJoinServerError>;
|
||||
|
||||
/**
|
||||
* Creates a server info dialog for the server your friend is currently playing on.
|
||||
* @param pid 0
|
||||
* @param steamId A Steam64 ID of a friend.
|
||||
*/
|
||||
CreateFriendGameInfoDialog(pid: number, steamId: string): void;
|
||||
|
||||
/**
|
||||
* Creates a server info dialog.
|
||||
* @param ip The server IP.
|
||||
* @param port The server port.
|
||||
* @param queryPort
|
||||
* @returns the created dialog ID.
|
||||
*/
|
||||
CreateServerGameInfoDialog(ip: string, port: number, queryPort: number): Promise<number>;
|
||||
|
||||
/**
|
||||
* Retrieves the server list.
|
||||
* @param appId The game ID, 0 for every game.
|
||||
* @param queryType The tab to use.
|
||||
* @param filters Server filters.
|
||||
* @param serverCallback What to do with the found server?
|
||||
* @param requestCompletedCallback The callback function to be called when the request is completed.
|
||||
* @returns the current server list request ID.
|
||||
* @throws Throws if the query type is unknown.
|
||||
* @throws Throws if the filter list isn't key/value pairs, i.e. of an even length.
|
||||
* @remarks Stops at 10000 if there are more servers to be found.
|
||||
* @example
|
||||
* Filter examples, may be combined:
|
||||
* ```
|
||||
* [ 'gamedir', 'cstrike' ] // Doesn't work?
|
||||
* [ 'hasplayers', '1' ] // Only works with "1"?
|
||||
* [ 'notfull', '1' ] // Doesn't work?
|
||||
* [ 'map', 'cs_office' ] // Has to be an exact match!
|
||||
* ```
|
||||
*/
|
||||
|
||||
/*
|
||||
The enum in question:
|
||||
|
||||
(t =
|
||||
'lan' == this.id
|
||||
? this.all_servers.length > 0
|
||||
? '#ServerBrowser_NoServersMatch'
|
||||
: '#ServerBrowser_NoLanServers'
|
||||
: 'internet' == this.id
|
||||
? this.all_servers.length > 0
|
||||
? '#ServerBrowser_NoInternetGamesMatch'
|
||||
: e == l.zS.k_EServerFailedToRespond
|
||||
? '#ServerBrowser_MasterServerNotResponsive'
|
||||
: e == l.zS.k_ENoServersListedOnMasterServer
|
||||
? '#ServerBrowser_MasterServerHasNoServersListed'
|
||||
: '#ServerBrowser_NoInternetGamesResponded'
|
||||
: 'favorites' == this.id
|
||||
? this.all_servers.length > 0
|
||||
? '#ServerBrowser_NoServersMatch'
|
||||
: '#ServerBrowser_NoFavoriteServers'
|
||||
: 'history' == this.id
|
||||
? this.all_servers.length > 0
|
||||
? '#ServerBrowser_NoHistoryServersMatch'
|
||||
: '#ServerBrowser_NoServersPlayed'
|
||||
: 'friends' == this.id
|
||||
? this.all_servers.length > 0
|
||||
? '#ServerBrowser_NoServersMatch'
|
||||
: '#ServerBrowser_NoFriendsServers'
|
||||
: 'BUGBUG'),
|
||||
*/
|
||||
CreateServerListRequest(
|
||||
appId: number,
|
||||
queryType: ServerBrowserTab_t,
|
||||
filters: string[],
|
||||
serverCallback: (server: GameServer) => void,
|
||||
requestCompletedCallback: (response: number) => void,
|
||||
): Promise<number | OperationResponse>;
|
||||
|
||||
/**
|
||||
* Destroys the game info dialog functions (but not the window).
|
||||
* @param dialogId The dialog ID to use.
|
||||
* @remarks ServerBrowser.CancelServerQuery may throw if it tries to ping the server.
|
||||
*/
|
||||
DestroyGameInfoDialog(dialogId: number): void;
|
||||
|
||||
/**
|
||||
* Stops retrieving the server list.
|
||||
* @param activeServerListRequestId The active server request ID to use.
|
||||
*/
|
||||
DestroyServerListRequest(activeServerListRequestId: number): void;
|
||||
|
||||
/**
|
||||
* Gets a list of games that support the server browser feature.
|
||||
* @returns a list of games.
|
||||
*/
|
||||
GetMultiplayerGames(): Promise<ServerBrowserGame[]>;
|
||||
|
||||
/**
|
||||
* Gets the server browser preferences.
|
||||
* @returns server browser preferences.
|
||||
*/
|
||||
GetServerListPreferences(): Promise<ServerBrowserPreferences>;
|
||||
|
||||
/**
|
||||
* Pings the server of a specified dialog ID.
|
||||
* @param dialogId The dialog ID to use.
|
||||
*/
|
||||
PingServer(dialogId: number): Promise<number | OperationResponse>;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when a server gets added to favorite servers.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForFavorites(callback: (list: ServerBrowserFavoritesAndHistory) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when idk
|
||||
* @param dialogId The dialog ID to use.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForFriendGamePlayed(
|
||||
dialogId: number,
|
||||
callback: (server: ServerBrowserFriendServer) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when a server info dialog opens.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForGameInfoDialogs(callback: (dialogs: ServerBrowserDialog[]) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when player details get requested.
|
||||
* @param dialogId The dialog ID to use.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForPlayerDetails(
|
||||
dialogId: number,
|
||||
callback: (player: PlayerDetails) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when a server gets pinged.
|
||||
* @param dialogId The dialog ID to use.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForServerInfo(dialogId: number, callback: (server: GameServer) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Removes a server from favorite servers.
|
||||
* @param server The server to remove.
|
||||
*/
|
||||
RemoveFavoriteServer(server: GameServer): void;
|
||||
|
||||
/**
|
||||
* Removes a server from history of played servers.
|
||||
* @param server The server to remove.
|
||||
*/
|
||||
RemoveHistoryServer(server: GameServer): void;
|
||||
|
||||
/**
|
||||
* Requests player details for a specific dialog.
|
||||
* @param dialogId The dialog ID to use.
|
||||
*/
|
||||
RequestPlayerDetails(dialogId: number): Promise<number | OperationResponse>;
|
||||
|
||||
/**
|
||||
* Sets the server browser preferences.
|
||||
* @param prefs Server list preferences.
|
||||
*/
|
||||
SetServerListPreferences(prefs: ServerBrowserPreferences): void;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export type ServerBrowserTab_t = 'internet' | 'favorites' | 'history' | 'lan' | 'friends';
|
||||
|
||||
export interface ServerBrowserGame {
|
||||
/** The ID of the game. */
|
||||
appid: number;
|
||||
/** The ID of the game. */
|
||||
gameid: string;
|
||||
/** The game folder. */
|
||||
gamedir: string;
|
||||
/** The game's name. */
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ServerBrowserPreferences {
|
||||
GameList: string;
|
||||
filters: ServerBrowserTabFilters;
|
||||
}
|
||||
|
||||
export type ServerBrowserTabFilters = {
|
||||
[tab in ServerBrowserTab_t]: ServerBrowserGameFilter;
|
||||
};
|
||||
|
||||
export interface ServerBrowserGameFilter {
|
||||
/** Has users playing */
|
||||
NoEmpty: boolean;
|
||||
/** Server not full */
|
||||
NoFull: boolean;
|
||||
/** Is not password protected */
|
||||
NoPassword: boolean;
|
||||
/** Anti-cheat */
|
||||
Secure: EServerBrowserGameFilterAntiCheat;
|
||||
/** The ID of the game */
|
||||
appid: number;
|
||||
/** The game folder */
|
||||
game: string;
|
||||
/** Map filter */
|
||||
map: string;
|
||||
/** Latency */
|
||||
ping: EServerBrowserGameFilterPing;
|
||||
}
|
||||
|
||||
export enum EServerBrowserGameFilterAntiCheat {
|
||||
All,
|
||||
Secure,
|
||||
NotSecure,
|
||||
}
|
||||
|
||||
export enum EServerBrowserGameFilterPing {
|
||||
All,
|
||||
LessThan50 = 50,
|
||||
LessThan100 = 100,
|
||||
LessThan150 = 150,
|
||||
LessThan250 = 250,
|
||||
}
|
||||
|
||||
export interface ServerBrowserFavoritesAndHistory {
|
||||
favorites: GameServer[];
|
||||
history: GameServer[];
|
||||
}
|
||||
|
||||
export interface ServerBrowserFriendServer {
|
||||
/** The ID of the game. */
|
||||
appid: number;
|
||||
/** Non-Steam server? */
|
||||
bNonSteamServer: boolean;
|
||||
gameText: string;
|
||||
/** The ID of the game. */
|
||||
gameid: string;
|
||||
steamIDLobby: string;
|
||||
}
|
||||
|
||||
export interface ServerBrowserDialog {
|
||||
dialogID: number;
|
||||
ip: number;
|
||||
port: number;
|
||||
queryPort: number;
|
||||
}
|
||||
|
||||
export interface GameServer {
|
||||
/** The ID of the game. */
|
||||
appid: number;
|
||||
/** Do not refresh if had unsuccessful response? */
|
||||
bDoNotRefresh?: boolean;
|
||||
/** Found the server? */
|
||||
bHadSuccessfulResponse: boolean;
|
||||
/** Has password? */
|
||||
bPassword: boolean;
|
||||
/** Is VAC secured? */
|
||||
bSecure: boolean;
|
||||
/** How many bot players there currently are. */
|
||||
botPlayers: number;
|
||||
/** The server's game name/description. */
|
||||
gameDesc: string;
|
||||
/** The game folder. */
|
||||
gameDir: string;
|
||||
/** Server tags, separated by a comma. */
|
||||
gameTags: string;
|
||||
/** The server IP. */
|
||||
ip: string;
|
||||
/** Last time played as a UNIX timestamp. */
|
||||
lastPlayed: number;
|
||||
/** Current server map. */
|
||||
map: string;
|
||||
/** Max players on the server. */
|
||||
maxPlayers: number;
|
||||
/** The server name. */
|
||||
name: string;
|
||||
/** The latency to the server. */
|
||||
ping: number;
|
||||
/** How many players there currently are. */
|
||||
players: number;
|
||||
/** The server port. */
|
||||
port: number;
|
||||
queryPort: number;
|
||||
/** The server's game version it is running on. */
|
||||
serverVersion: number;
|
||||
/** Game server account ID. */
|
||||
steamID: string;
|
||||
}
|
||||
|
||||
export enum EJoinServerError {
|
||||
PingFailed = -3,
|
||||
Connecting,
|
||||
Pinging,
|
||||
None,
|
||||
VACBanned,
|
||||
ServerFull,
|
||||
ModNotInstalled,
|
||||
AppNotFound,
|
||||
NotInitialized,
|
||||
}
|
||||
|
||||
export interface PlayerDetails {
|
||||
/**
|
||||
* `true` is the server refresh is successful.
|
||||
*/
|
||||
bSuccess: boolean;
|
||||
|
||||
/**
|
||||
* `true` when the server refresh is done.
|
||||
*/
|
||||
bRefreshComplete: boolean;
|
||||
|
||||
/**
|
||||
* Player name.
|
||||
*
|
||||
* @note Defined when {@link bRefreshComplete} is `true`.
|
||||
*/
|
||||
playerName?: string;
|
||||
|
||||
/**
|
||||
* Player score.
|
||||
*
|
||||
* @note Defined when {@link bRefreshComplete} is `true`.
|
||||
*/
|
||||
score?: number;
|
||||
|
||||
/**
|
||||
* Time played on the server in seconds
|
||||
*
|
||||
* @note Defined when {@link bRefreshComplete} is `true`.
|
||||
*/
|
||||
timePlayed?: number;
|
||||
}
|
||||
|
||||
663
src/globals/steam-client/Settings.ts
Normal file
663
src/globals/steam-client/Settings.ts
Normal file
@@ -0,0 +1,663 @@
|
||||
import {CompatibilityTool as CompatibilityTool} from "./App";
|
||||
import { JsPbMessage, OperationResponse, Unregisterable } from "./shared";
|
||||
|
||||
export interface Settings {
|
||||
AddClientBeta(name: string, password: string): void;
|
||||
|
||||
/**
|
||||
* Clears HTTP cache located in `<STEAMPATH>/appcache/httpcache`.
|
||||
*/
|
||||
ClearAllHTTPCaches(): void;
|
||||
|
||||
/**
|
||||
* Clears download cache and logs you out.
|
||||
*/
|
||||
ClearDownloadCache(): void;
|
||||
|
||||
GetAccountSettings(): Promise<AccountSettings>;
|
||||
|
||||
GetAppUsesP2PVoice(appId: number): Promise<boolean>;
|
||||
|
||||
GetAvailableLanguages(): Promise<Language[]>;
|
||||
|
||||
GetAvailableTimeZones(): Promise<TimeZone[]>;
|
||||
|
||||
// Returns the current language "english"
|
||||
GetCurrentLanguage(): Promise<string>;
|
||||
|
||||
GetGlobalCompatTools(): Promise<CompatibilityTool[]>;
|
||||
|
||||
/**
|
||||
* @returns a ProtoBuf message. If deserialized, returns {@link MsgMonitorInfo}.
|
||||
*/
|
||||
GetMonitorInfo(): Promise<ArrayBuffer>;
|
||||
|
||||
GetOOBETestMode(): Promise<boolean>;
|
||||
|
||||
GetRegisteredSteamDeck(): Promise<RegisteredSteamDeck>;
|
||||
|
||||
// Returns the current timezone
|
||||
GetTimeZone(): Promise<string>;
|
||||
|
||||
GetWindowed(): Promise<boolean>;
|
||||
|
||||
IgnoreSteamDeckRewards(): void;
|
||||
|
||||
/**
|
||||
* Opens the Windows microphones dialog.
|
||||
*/
|
||||
OpenWindowsMicSettings(): void;
|
||||
|
||||
RegisterForMicVolumeUpdates: Unregisterable;
|
||||
|
||||
/**
|
||||
* If `data` is deserialized, returns {@link MsgClientSettings}.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForSettingsArrayChanges(callback: (data: ArrayBuffer) => void): Unregisterable;
|
||||
|
||||
RegisterForSettingsChanges(callback: (settings: SteamSettings) => void): Unregisterable;
|
||||
|
||||
RegisterForTimeZoneChange(callback: (timezoneId: string) => void): Unregisterable; // When timezone is changed from settings, callback will return new timezoneId
|
||||
ReinitMicSettings(): void;
|
||||
|
||||
RenderHotkey(event: KeyCaptureEvent): Promise<string>;
|
||||
|
||||
RequestDeviceAuthInfo(): void;
|
||||
|
||||
SelectClientBeta(nBetaID: number): void;
|
||||
|
||||
// Get from available languages
|
||||
SetCurrentLanguage(strShortName: string): void;
|
||||
|
||||
SetEnableSoftProcessKill(value: boolean): void; // Default value is false, this is Valve internal menu
|
||||
|
||||
SetHostname(hostname: string): void;
|
||||
|
||||
SetMicTestMode(value: boolean): void;
|
||||
|
||||
SetOOBETestMode(value: boolean): void;
|
||||
|
||||
SetPreferredMonitor(monitor: string): void;
|
||||
|
||||
SetRegisteredSteamDeck(steam64Id: string, serialNumber: string): void;
|
||||
|
||||
/**
|
||||
* Sets the "Don't save account credentials on this computer" option.
|
||||
* @param value Whether to save account credentials.
|
||||
*/
|
||||
SetSaveAccountCredentials(value: boolean): void;
|
||||
|
||||
/**
|
||||
* @param base64 Serialized base64 message from `CMsgClientSettings`.
|
||||
* @returns a boolean indicating whether the operation was successful.
|
||||
*/
|
||||
SetSetting(base64: string): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* You can get valid timezoneIds from {@link GetAvailableTimeZones}.
|
||||
*/
|
||||
SetTimeZone(timezoneId: string): void;
|
||||
|
||||
SetUseNintendoButtonLayout(controllerIndex: number, value: boolean): void;
|
||||
|
||||
SetUseUniversalFaceButtonGlyphs(nControllerIndex: number, value: boolean): void;
|
||||
|
||||
SetWindowed(value: boolean): void;
|
||||
|
||||
SpecifyGlobalCompatTool(strToolName: string): void;
|
||||
|
||||
ToggleSteamInstall(): Promise<OperationResponse>;
|
||||
}
|
||||
|
||||
export interface AccountSettings {
|
||||
strEmail: string;
|
||||
bEmailValidated: boolean;
|
||||
bHasAnyVACBans: boolean;
|
||||
bHasTwoFactor: boolean;
|
||||
eSteamGuardState: ESteamGuardState;
|
||||
rtSteamGuardEnableTime: number;
|
||||
bSaveAccountCredentials: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo unconfirmed, taken from localization strings
|
||||
*/
|
||||
export enum ESteamGuardState {
|
||||
EmailUnverified,
|
||||
Protected,
|
||||
Disabled,
|
||||
Offline,
|
||||
NotEnabled,
|
||||
}
|
||||
|
||||
export interface KeyCaptureEvent {
|
||||
alt_key: boolean;
|
||||
ctrl_key: boolean;
|
||||
display_name: string;
|
||||
meta_key: boolean;
|
||||
shift_key: boolean;
|
||||
}
|
||||
|
||||
export interface Language {
|
||||
language: ELanguage;
|
||||
strShortName: string;
|
||||
}
|
||||
|
||||
export enum ELanguage {
|
||||
None = -1,
|
||||
English,
|
||||
German,
|
||||
French,
|
||||
Italian,
|
||||
Korean,
|
||||
Spanish,
|
||||
SimplifiedChinese,
|
||||
TraditionalChinese,
|
||||
Russian,
|
||||
Thai,
|
||||
Japanese,
|
||||
Portuguese,
|
||||
Polish,
|
||||
Danish,
|
||||
Dutch,
|
||||
Finnish,
|
||||
Norwegian,
|
||||
Swedish,
|
||||
Hungarian,
|
||||
Czech,
|
||||
Romanian,
|
||||
Turkish,
|
||||
Brazilian,
|
||||
Bulgarian,
|
||||
Greek,
|
||||
Arabic,
|
||||
Ukrainian,
|
||||
LatamSpanish,
|
||||
Vietnamese,
|
||||
SteamChina_SChinese,
|
||||
Max,
|
||||
}
|
||||
export interface RegisteredSteamDeck {
|
||||
bRegistered: boolean;
|
||||
bIgnoreRegistrationPrompt: boolean;
|
||||
strSteamID: string;
|
||||
strSerialNumber: string;
|
||||
}
|
||||
|
||||
export interface TimeZone {
|
||||
utcOffset: number;
|
||||
timezoneID: string;
|
||||
timezoneLocalizationToken: string;
|
||||
regionsLocalizationToken: string;
|
||||
}
|
||||
|
||||
interface Region {
|
||||
nRegionID: number;
|
||||
strRegionName: string;
|
||||
}
|
||||
|
||||
interface Hour {
|
||||
nHour: number;
|
||||
strDisplay: string;
|
||||
}
|
||||
|
||||
interface AvailableClientBeta {
|
||||
nBetaID: number;
|
||||
strName: string;
|
||||
}
|
||||
|
||||
interface SteamSettings {
|
||||
bIsInClientBeta: boolean;
|
||||
bIsSteamSideload: boolean;
|
||||
eClientBetaState: EClientBetaState;
|
||||
strSelectedBetaName: string;
|
||||
nAvailableBetas: number;
|
||||
bChangeBetaEnabled: boolean;
|
||||
nSelectedBetaID: number;
|
||||
vecAvailableClientBetas: AvailableClientBeta[];
|
||||
bIsValveEmail: boolean;
|
||||
bIsInDesktopUIBeta: boolean;
|
||||
bEnableSoftProcessKill: boolean;
|
||||
vecValidDownloadRegions: Region[];
|
||||
vecValidAutoUpdateRestrictHours: Hour[];
|
||||
bCompatEnabled: boolean;
|
||||
bCompatEnabledForOtherTitles: boolean;
|
||||
strCompatTool: string;
|
||||
strDisplayName: string;
|
||||
bDisplayIsExternal: boolean;
|
||||
flAutoDisplayScaleFactor: number;
|
||||
flCurrentDisplayScaleFactor: number;
|
||||
bDisplayIsUsingAutoScale: boolean;
|
||||
flMinDisplayScaleFactor: number;
|
||||
flMaxDisplayScaleFactor: number;
|
||||
flCurrentUnderscanLevel: number;
|
||||
bUnderscanEnabled: boolean;
|
||||
vecNightModeScheduledHours: Hour[];
|
||||
}
|
||||
|
||||
export enum EClientBetaState {
|
||||
None,
|
||||
NoneChosen,
|
||||
NoneChosenNonAdmin,
|
||||
InBeta,
|
||||
InBetaNonAdmin,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* CMsgMonitorInfo
|
||||
*/
|
||||
export interface MsgMonitorInfo extends JsPbMessage {
|
||||
monitors(): Monitor[];
|
||||
|
||||
selected_display_name(): string;
|
||||
|
||||
add_monitors(param0: any, param1: any): any;
|
||||
|
||||
set_monitors(param0: any): any;
|
||||
|
||||
set_selected_display_name(param0: any): any;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Doesn't work on Linux ?
|
||||
*/
|
||||
export interface Monitor {
|
||||
monitor_device_name: string;
|
||||
monitor_display_name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* CMsgClientSettings
|
||||
*/
|
||||
export interface MsgClientSettings extends JsPbMessage {
|
||||
always_show_user_chooser(): boolean;
|
||||
|
||||
always_use_gamepadui_overlay(): boolean;
|
||||
|
||||
auto_scale_factor(): number;
|
||||
|
||||
bigpicture_windowed(): boolean;
|
||||
|
||||
broadcast_bitrate(): number;
|
||||
|
||||
broadcast_chat_corner(): number;
|
||||
|
||||
broadcast_encoding_option(): EBroadcastEncoderSetting;
|
||||
|
||||
broadcast_output_height(): number;
|
||||
|
||||
broadcast_output_width(): number;
|
||||
|
||||
broadcast_permissions(): EBroadcastPermission;
|
||||
|
||||
broadcast_record_all_audio(): boolean;
|
||||
|
||||
broadcast_record_all_video(): boolean;
|
||||
|
||||
broadcast_record_microphone(): boolean;
|
||||
|
||||
broadcast_show_live_reminder(): boolean;
|
||||
|
||||
broadcast_show_upload_stats(): boolean;
|
||||
|
||||
cef_remote_debugging_enabled(): boolean;
|
||||
|
||||
cloud_enabled(): boolean;
|
||||
|
||||
controller_combine_nintendo_joycons(): boolean;
|
||||
controller_enable_chord(): boolean;
|
||||
|
||||
controller_generic_support(): boolean;
|
||||
|
||||
controller_guide_button_focus_steam(): boolean;
|
||||
|
||||
controller_poll_rate(): boolean;
|
||||
controller_power_off_timeout(): number;
|
||||
|
||||
controller_ps_support(): number;
|
||||
|
||||
controller_switch_support(): boolean;
|
||||
|
||||
controller_xbox_driver(): boolean;
|
||||
|
||||
controller_xbox_support(): boolean;
|
||||
|
||||
default_ping_rate(): number;
|
||||
|
||||
disable_all_toasts(): boolean;
|
||||
|
||||
disable_toasts_in_game(): boolean;
|
||||
|
||||
display_name(): string;
|
||||
|
||||
download_peer_content(): number;
|
||||
|
||||
download_rate_bits_per_s(): boolean;
|
||||
|
||||
download_region(): number;
|
||||
|
||||
download_throttle_rate(): number;
|
||||
|
||||
download_throttle_while_streaming(): boolean;
|
||||
|
||||
download_while_app_running(): boolean;
|
||||
|
||||
enable_avif_screenshots(): boolean;
|
||||
|
||||
enable_dpi_scaling(): boolean;
|
||||
|
||||
enable_gpu_accelerated_webviews(): boolean;
|
||||
|
||||
enable_hardware_video_decoding(): boolean;
|
||||
|
||||
enable_marketing_messages(): boolean;
|
||||
|
||||
enable_overlay(): boolean;
|
||||
|
||||
enable_screenshot_notification(): boolean;
|
||||
|
||||
enable_screenshot_sound(): boolean;
|
||||
|
||||
enable_shader_background_processing(): boolean;
|
||||
|
||||
enable_shader_precache(): boolean;
|
||||
|
||||
enable_ui_sounds(): boolean;
|
||||
|
||||
force_deck_perf_tab(): boolean;
|
||||
|
||||
force_fake_mandatory_update(): boolean;
|
||||
|
||||
force_oobe(): boolean;
|
||||
|
||||
g_background_audio(): EGRAudio;
|
||||
|
||||
g_background_a_m(): number;
|
||||
|
||||
g_background_a_s(): boolean;
|
||||
|
||||
g_background_path(): string;
|
||||
|
||||
g_background_max_keep(): string;
|
||||
|
||||
g_background_mode(): EGRMode;
|
||||
|
||||
g_background_time_resolution(): number;
|
||||
|
||||
g_background_mk(): CMsgHotkey;
|
||||
|
||||
g_background_tg(): CMsgHotkey;
|
||||
|
||||
g_max_fps(): number;
|
||||
|
||||
gamerecording_automatic_gain_control(): boolean;
|
||||
gamerecording_export_codec(): EExportCodec;
|
||||
gamerecording_export_directory(): number;
|
||||
gamerecording_export_limit_bitrate(): number;
|
||||
gamerecording_export_limit_frame_rate(): number;
|
||||
gamerecording_export_limit_height(): number;
|
||||
gamerecording_export_limit_size_mb(): number;
|
||||
gamerecording_export_limit_width(): number;
|
||||
gamerecording_export_limit_type(): EGRExportLimitType;
|
||||
gamerecording_force_mic_mono(): boolean;
|
||||
gamerecording_hotkey_ic(): CMsgHotkey;
|
||||
gamerecording_ic_seconds(): number;
|
||||
gamerecording_video_bitrate(): string;
|
||||
gamerecording_video_maxheight(): number;
|
||||
|
||||
game_notes_enable_spellcheck(): boolean;
|
||||
|
||||
gamescope_allow_tearing(): boolean;
|
||||
|
||||
gamescope_app_target_framerate(): number;
|
||||
|
||||
gamescope_composite_debug(): boolean;
|
||||
|
||||
gamescope_disable_framelimit(): boolean;
|
||||
|
||||
gamescope_disable_mura_correction(): boolean;
|
||||
|
||||
gamescope_display_refresh_rate(): number;
|
||||
|
||||
gamescope_enable_app_target_framerate(): boolean;
|
||||
|
||||
gamescope_force_composite(): boolean;
|
||||
|
||||
gamescope_hdr_visualization(): EHDRVisualization;
|
||||
|
||||
gamescope_include_steamui_in_screenshots(): boolean;
|
||||
|
||||
gamescope_use_game_refresh_rate_in_steam(): boolean;
|
||||
|
||||
gamestream_enable_video_h265(): boolean;
|
||||
gamestream_hardware_video_encode(): boolean;
|
||||
|
||||
hdr_compat_testing(): boolean;
|
||||
|
||||
in_client_beta(): boolean;
|
||||
|
||||
is_external_display(): boolean;
|
||||
|
||||
is_steam_sideloaded(): boolean;
|
||||
|
||||
jumplist_flags(): number;
|
||||
|
||||
library_disable_community_content(): boolean;
|
||||
|
||||
library_display_icon_in_game_list(): boolean;
|
||||
|
||||
library_display_size(): number;
|
||||
|
||||
library_low_bandwidth_mode(): boolean;
|
||||
|
||||
library_low_perf_mode(): boolean;
|
||||
|
||||
library_whats_new_show_only_product_updates(): boolean;
|
||||
|
||||
max_scale_factor(): number;
|
||||
|
||||
min_scale_factor(): number;
|
||||
|
||||
music_download_high_quality(): boolean;
|
||||
|
||||
music_pause_on_app_start(): boolean;
|
||||
|
||||
music_pause_on_voice_chat(): boolean;
|
||||
|
||||
music_playlist_notification(): boolean;
|
||||
|
||||
music_volume(): number;
|
||||
|
||||
needs_steam_service_repair(): boolean;
|
||||
|
||||
no_save_personal_info(): boolean;
|
||||
|
||||
oobe_test_mode_enabled(): boolean;
|
||||
|
||||
os_version_unsupported(): boolean;
|
||||
|
||||
overlay_fps_counter_corner(): number;
|
||||
|
||||
overlay_fps_counter_high_contrast(): boolean;
|
||||
|
||||
overlay_key(): CMsgHotkey;
|
||||
|
||||
overlay_restore_browser_tabs(): boolean;
|
||||
|
||||
overlay_scale_interface(): boolean;
|
||||
|
||||
overlay_tabs(): string;
|
||||
|
||||
overlay_toolbar_list_view(): boolean;
|
||||
|
||||
override_browser_composer_mode(): number;
|
||||
|
||||
play_sound_on_toast(): boolean;
|
||||
|
||||
preferred_monitor(): string;
|
||||
|
||||
ready_to_play_includes_streaming(): boolean;
|
||||
|
||||
restrict_auto_updates(): boolean;
|
||||
|
||||
restrict_auto_updates_end(): number;
|
||||
|
||||
restrict_auto_updates_start(): number;
|
||||
|
||||
run_at_startup(): boolean;
|
||||
|
||||
save_uncompressed_screenshots(): boolean;
|
||||
|
||||
screenshot_items_per_row(): number;
|
||||
|
||||
screenshot_key(): CMsgHotkey;
|
||||
|
||||
screenshots_path(): string;
|
||||
|
||||
server_ping_rate(): number;
|
||||
|
||||
setting_validation_bool(): boolean;
|
||||
|
||||
setting_validation_enum(): EHDRVisualization;
|
||||
|
||||
setting_validation_int32(): number;
|
||||
|
||||
setting_validation_uint32(): number;
|
||||
|
||||
setting_validation_uint64(): number;
|
||||
|
||||
setting_validation_float(): number;
|
||||
|
||||
setting_validation_string(): string;
|
||||
|
||||
shader_precached_size(): string;
|
||||
|
||||
show_copy_count_in_library(): boolean;
|
||||
|
||||
show_family_sharing_notifications(): boolean;
|
||||
|
||||
show_screenshot_manager(): boolean;
|
||||
|
||||
show_steam_deck_info(): boolean;
|
||||
|
||||
show_store_content_on_home(): boolean;
|
||||
|
||||
show_timestamps_in_console(): boolean;
|
||||
|
||||
skip_steamvr_install_dialog(): boolean;
|
||||
|
||||
small_mode(): boolean;
|
||||
|
||||
smooth_scroll_webviews(): boolean;
|
||||
|
||||
start_in_big_picture_mode(): boolean;
|
||||
|
||||
start_page(): string;
|
||||
|
||||
startup_movie_id(): string;
|
||||
|
||||
startup_movie_local_path(): string;
|
||||
|
||||
startup_movie_shuffle(): boolean;
|
||||
|
||||
startup_movie_used_for_resume(): boolean;
|
||||
|
||||
steam_cef_gpu_blocklist_disabled(): boolean;
|
||||
|
||||
steam_input_configurator_error_msg_enable(): boolean;
|
||||
|
||||
steam_networking_share_ip(): number;
|
||||
|
||||
steam_os_underscan_enabled(): boolean;
|
||||
|
||||
steam_os_underscan_level(): number;
|
||||
|
||||
steamos_cec_enabled(): boolean;
|
||||
|
||||
steamos_cec_wake_on_resume(): boolean;
|
||||
|
||||
steamos_magnifier_scale(): number;
|
||||
|
||||
steamos_status_led_brightness(): number;
|
||||
|
||||
steamos_tdp_limit(): number;
|
||||
|
||||
steamos_tdp_limit_enabled(): boolean;
|
||||
|
||||
steamos_wifi_debug(): boolean;
|
||||
|
||||
steamos_wifi_force_wpa_supplicant(): boolean;
|
||||
|
||||
system_bluetooth_enabled(): boolean;
|
||||
|
||||
turn_off_controller_on_exit(): boolean;
|
||||
|
||||
voice_mic_device_name(): string;
|
||||
|
||||
voice_mic_input_gain(): number;
|
||||
|
||||
voice_push_to_talk_key(): CMsgHotkey;
|
||||
|
||||
voice_push_to_talk_setting(): number;
|
||||
|
||||
voice_speaker_output_gain(): number;
|
||||
|
||||
web_browser_home(): string;
|
||||
}
|
||||
|
||||
export interface CMsgHotkey extends JsPbMessage {
|
||||
key_code(): number;
|
||||
alt_key(): boolean;
|
||||
shift_key(): boolean;
|
||||
ctrl_key(): boolean;
|
||||
meta_key(): boolean;
|
||||
display_name(): string;
|
||||
}
|
||||
|
||||
export enum EBroadcastEncoderSetting {
|
||||
BestQuality,
|
||||
BestPerformance,
|
||||
}
|
||||
|
||||
export enum EBroadcastPermission {
|
||||
Disabled,
|
||||
FriendsApprove,
|
||||
FriendsAllowed,
|
||||
Public,
|
||||
Subscribers,
|
||||
}
|
||||
|
||||
export enum EExportCodec {
|
||||
Default,
|
||||
H264,
|
||||
H265,
|
||||
}
|
||||
|
||||
export enum EGRAudio {
|
||||
Game,
|
||||
System,
|
||||
Select,
|
||||
}
|
||||
|
||||
export enum EGRExportLimitType {
|
||||
Native,
|
||||
FileSize,
|
||||
Advanced,
|
||||
}
|
||||
|
||||
export enum EGRMode {
|
||||
Never,
|
||||
Always,
|
||||
Manual,
|
||||
}
|
||||
|
||||
export enum EHDRVisualization {
|
||||
None,
|
||||
Heatmap,
|
||||
Analysis,
|
||||
HeatmapExtended,
|
||||
HeatmapClassic,
|
||||
}
|
||||
43
src/globals/steam-client/SharedConnection.ts
Normal file
43
src/globals/steam-client/SharedConnection.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { ESteamRealm, Unregisterable } from "./shared";
|
||||
|
||||
/**
|
||||
* `hSharedConnection` is the number from {@link AllocateSharedConnection}.
|
||||
*/
|
||||
export interface SharedConnection {
|
||||
AllocateSharedConnection(): Promise<number>;
|
||||
|
||||
// if no such number, sends this warning:
|
||||
// src\clientdll\clientsharedconnection.cpp (154) : m_mapSharedConnections.HasElement( hSharedConnection )
|
||||
Close(hSharedConnection: number): void;
|
||||
|
||||
RegisterOnBinaryMessageReceived(hSharedConnection: number, callback: (data: ArrayBuffer) => void): Unregisterable;
|
||||
|
||||
RegisterOnLogonInfoChanged(hSharedConnection: number, callback: (info: LogonInfo) => void): Unregisterable;
|
||||
|
||||
RegisterOnMessageReceived(hSharedConnection: number, callback: (param0: any) => void): Unregisterable;
|
||||
|
||||
SendMsg: any;
|
||||
SendMsgAndAwaitBinaryResponse: any;
|
||||
|
||||
SendMsgAndAwaitResponse(hSharedConnection: number, msg: string): Promise<any>;
|
||||
|
||||
SubscribeToClientServiceMethod(hSharedConnection: number, param1: any): any;
|
||||
|
||||
SubscribeToEMsg(hSharedConnection: number, param1: any): any;
|
||||
}
|
||||
|
||||
export interface LogonInfo {
|
||||
/** `true` if logged on. */
|
||||
bLoggedOn: boolean;
|
||||
eUniverse: ESteamRealm;
|
||||
/** Account username. Empty if not logged on. */
|
||||
strAccountName: string;
|
||||
/** URL for community content. */
|
||||
strCommunityImagesURL: string;
|
||||
/** Account nickname. Empty if not logged on. */
|
||||
strPersonaName: string;
|
||||
/** Steam64 ID. */
|
||||
strSteamid: string;
|
||||
/** Country code. */
|
||||
strUserCountry: string;
|
||||
}
|
||||
10
src/globals/steam-client/Stats.ts
Normal file
10
src/globals/steam-client/Stats.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export interface Stats {
|
||||
// param0 - AppDetailsReviewSection, Showcases, LibraryReviewSpotlight
|
||||
// param1 -
|
||||
// AppDetailsReviewSection: PositiveClicked, NegativeClicked, NeutralClicked, PositiveReviewPosted, NegativeReviewPosted, EditClicked, ReviewCanceled
|
||||
// LibraryReviewSpotlight: ReviseClicked, PositiveClicked, ReviseCloseClicked, NegativeClicked, PositiveRevisePosted, NegativeRevisePosted, ReviseCanceled, ReviewCanceled, CloseClicked
|
||||
// Showcases: Delete, Save-Modify, Save-New
|
||||
RecordActivationEvent(param0: string, param1: string): void;
|
||||
|
||||
RecordDisplayEvent(param0: boolean, param1: string, param2: string): void;
|
||||
}
|
||||
3
src/globals/steam-client/SteamChina.ts
Normal file
3
src/globals/steam-client/SteamChina.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface SteamChina {
|
||||
GetCustomLauncherAppID(): Promise<number>;
|
||||
}
|
||||
24
src/globals/steam-client/Storage.ts
Normal file
24
src/globals/steam-client/Storage.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { OperationResponse } from "./shared";
|
||||
|
||||
/**
|
||||
* SteamClient.MachineStorage affects the "STEAMPATH/config/config.vdf" file.
|
||||
* SteamClient.RoamingStorage affects the "STEAMPATH/userdata/STEAMID3/7/remote/sharedconfig.vdf" file.
|
||||
* SteamClient.Storage affects the "STEAMPATH/userdata/STEAMID3/config/localconfig.vdf" file.
|
||||
*/
|
||||
export interface Storage {
|
||||
DeleteKey(key: string): Promise<OperationResponse | undefined>;
|
||||
|
||||
/**
|
||||
* @remarks Use {@link SetObject} to set.
|
||||
*/
|
||||
GetJSON(key: string): Promise<OperationResponse | string>;
|
||||
|
||||
GetString(key: string): Promise<OperationResponse | string>;
|
||||
|
||||
/**
|
||||
* @remarks Use {@link SetObject} to get.
|
||||
*/
|
||||
SetObject(key: string, value: object): Promise<OperationResponse | undefined>;
|
||||
|
||||
SetString(key: string, value: string): Promise<OperationResponse | undefined>;
|
||||
}
|
||||
59
src/globals/steam-client/Streaming.ts
Normal file
59
src/globals/steam-client/Streaming.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { EResult, Unregisterable } from "./shared";
|
||||
import {LaunchOption} from "./App";
|
||||
|
||||
export interface Streaming {
|
||||
AcceptStreamingEULA(appId: number, id: string, version: number): void;
|
||||
|
||||
CancelStreamGame(): void; // existing stream
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when the streaming client finishes.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForStreamingClientFinished(callback: (code: EResult, result: string) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when there is progress in the launch of the streaming client.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForStreamingClientLaunchProgress(
|
||||
callback: (actionType: string, taskDetails: string, done: number, total: number) => void,
|
||||
): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when the streaming client is started (e.g., when clicking the stream button).
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForStreamingClientStarted(callback: (appId: number) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when the streaming launch is complete.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForStreamingLaunchComplete(callback: (code: EResult, result: string) => void): Unregisterable;
|
||||
|
||||
RegisterForStreamingShowEula(callback: (appId: number) => void): Unregisterable;
|
||||
|
||||
RegisterForStreamingShowIntro(callback: (appId: number, param: string) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when the streaming client receives launch options from the host.
|
||||
* @param callback The callback function to be called.
|
||||
* @returns an object that can be used to unregister the callback.
|
||||
*/
|
||||
RegisterForStreamingShowLaunchOptions(
|
||||
callback: (appId: number, launchOptions: LaunchOption[]) => void,
|
||||
): Unregisterable; // Callback when streaming client receives launch options from host
|
||||
|
||||
StreamingContinueStreamGame(): void; // existing game running on another streaming capable device
|
||||
|
||||
/**
|
||||
* Chooses the launch option for the streamed app by its index
|
||||
* and restarts the stream.
|
||||
*/
|
||||
StreamingSetLaunchOption(index: number): void;
|
||||
}
|
||||
90
src/globals/steam-client/UI.ts
Normal file
90
src/globals/steam-client/UI.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { EUIMode, Unregisterable } from "./shared";
|
||||
import {EOSType} from "./system";
|
||||
|
||||
export interface UI {
|
||||
EnsureMainWindowCreated(): void;
|
||||
|
||||
ExitBigPictureMode(): void;
|
||||
|
||||
GetDesiredSteamUIWindows(): Promise<SteamWindow[]>;
|
||||
|
||||
/**
|
||||
* Gets information about whether your OS will be unsupported in the future or not.
|
||||
*/
|
||||
GetOSEndOfLifeInfo(): Promise<OSEndOfLifeInfo>;
|
||||
|
||||
/**
|
||||
* Retrieves the current UI mode.
|
||||
* @returns the current UI mode.
|
||||
*/
|
||||
GetUIMode(): Promise<EUIMode>;
|
||||
|
||||
NotifyAppInitialized(): void;
|
||||
|
||||
RegisterDesiredSteamUIWindowsChanged(callback: () => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* Registers a callback function to be called when a convar's value gets changed.
|
||||
*
|
||||
* Hard crashes if such a convar does not exist or if you can't set it.
|
||||
*
|
||||
* @param convar The ConVar to watch.
|
||||
* @param callback The callback function to be called.
|
||||
*/
|
||||
RegisterForClientConVar(convar: string, callback: (value: string) => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* @todo param{0,1} are enums
|
||||
*/
|
||||
RegisterForErrorCondition(callback: (param0: number, param1: number) => void): Unregisterable;
|
||||
|
||||
RegisterForKioskModeResetSignal(callback: () => void): Unregisterable;
|
||||
|
||||
/**
|
||||
* @todo This fires multiple times.
|
||||
*/
|
||||
RegisterForStartupFinished(callback: () => void): Unregisterable;
|
||||
|
||||
RegisterForUIModeChanged(callback: (mode: EUIMode) => void): Unregisterable;
|
||||
|
||||
ResetErrorCondition(): void;
|
||||
|
||||
/**
|
||||
* Sets the UI mode to the specified value.
|
||||
* @param mode The UI mode to set.
|
||||
*/
|
||||
SetUIMode(mode: EUIMode): void;
|
||||
}
|
||||
|
||||
export enum EWindowType {
|
||||
MainGamepadUI,
|
||||
OverlayGamepadUI,
|
||||
Keyboard,
|
||||
ControllerConfigurator,
|
||||
VR,
|
||||
MainDesktopUI,
|
||||
DesktopLogin,
|
||||
OverlayDesktopUI,
|
||||
SteamChinaReviewLauncher,
|
||||
}
|
||||
|
||||
export interface OSEndOfLifeInfo {
|
||||
bOSWillBeUnsupported: boolean;
|
||||
osType: EOSType;
|
||||
}
|
||||
|
||||
/**
|
||||
* The following might have more correct information:
|
||||
* https://github.com/SteamDatabase/SteamTracking/blob/master/Protobufs/webuimessages_sharedjscontext.proto
|
||||
*/
|
||||
export interface SteamWindow {
|
||||
appid: number;
|
||||
hwndParent: number;
|
||||
nBrowserID: number;
|
||||
strAppName: string;
|
||||
unID: number;
|
||||
unPID: number;
|
||||
windowType: EWindowType;
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user