Compare commits

...

378 Commits

Author SHA1 Message Date
semantic-release-bot
cf6572cd7b chore(release): 4.10.6 [CI SKIP] 2025-09-01 00:41:34 +00:00
TrainDoctor
779b1ae0de fix(ci): update to resolve deprecation in sem. rel. due to octokit 2025-08-31 17:40:34 -07:00
semantic-release-bot
366357d9a3 chore(release): 4.10.5 [CI SKIP] 2025-08-20 19:36:27 +00:00
AAGaming
37dd88513e fix(DialogHeader): valve rewrote component on beta, update filter to search for both versions 2025-08-20 15:35:17 -04:00
semantic-release-bot
ed87f73602 chore(release): 4.10.4 [CI SKIP] 2025-07-13 06:23:11 +00:00
AAGaming
3d5de65077 fix(modals): fix ModalRoot on beta
Co-Authored-By: junkrunner <eben@sdk.co.nz>
2025-07-13 02:22:21 -04:00
semantic-release-bot
33d224bc3f chore(release): 4.10.3 [CI SKIP] 2025-07-09 03:21:17 +00:00
shadow
aa0678c857 fix(modals): fix <ConfirmModal /> for new Steam beta (#123) 2025-07-08 23:20:45 -04:00
semantic-release-bot
39fdde9481 chore(release): 4.10.2 [CI SKIP] 2025-06-28 18:03:43 +00:00
AAGaming
a4627a70c5 fix(SteamClient): export shared types for enums 2025-06-28 14:03:04 -04:00
semantic-release-bot
1f6611a10f chore(release): 4.10.1 [CI SKIP] 2025-06-15 19:51:28 +00:00
TrainDoctor
c149711265 Merge pull request #119 from shdwmtr/main
fix: fix <Menu /> for new Steam beta
2025-06-15 12:50:57 -07:00
shadow
7a4c2af6ec chore: improve optional chaining && nullish coalescing 2025-06-15 16:31:26 -03:00
shadow
fc5cde95d6 fix: fix <Menu /> for new Steam Client Beta 2025-06-15 16:20:28 -03:00
semantic-release-bot
c4579c8307 chore(release): 4.10.0 [CI SKIP] 2025-04-23 15:21:21 +00:00
Yao Chung Hu
131ab4cc11 feat(globals): Steam client reference (#92)
* change: Add SteamClient types

Steam Version:  1690583737
Steam Client Build Date:  Sat, Jul 29 02:44 UTC -08:00

* new: Document some SteamClient interfaces

Using the SDH discord server, GitHub and some personal findings, I tried to document as much SteamClient functions as I can.

* new: Document some SteamClient interfaces - part 2

* new: Document some SteamClient interfaces - part 3

* new: Document some SteamClient interfaces - part 4

* new: Document some SteamClient interfaces - part 5

* new: Document some SteamClient interfaces - part 6

* new: Document some SteamClient interfaces - part 7

* change: Update interfaces to Steam Version 1691097434

Steam Version:  1691097434
Steam Client Build Date:  Fri, Aug 4 04:54 UTC -08:00

* new: Document some SteamClient interfaces - part 8

* new: Document some SteamClient interfaces - part 9

* change: Update interfaces to Steam Version 1694466342

Steam Version:  1694466342
Steam Client Build Date:  Tue, Sep 12 04:59 UTC +08:00

* new: Document some SteamClient interfaces - part 10

* new: Document some SteamClient interfaces - part 11

* new: Document some SteamClient interfaces - part 12

* new: Document some SteamClient interfaces - part 13

* new: Document some SteamClient interfaces - part 14

* change: Update interfaces to Steam Version 1698260427

Steam Version:  1698260427
Steam Client Build Date:  Thu, Oct 26 2:40 AM UTC -08:00

* new: Document some SteamClient interfaces - part 10

* change: Update interfaces to Steam Version 1700160213

Steam Version:  1700160213
Steam Client Build Date:  Fri, Nov 17 2:23 AM UTC +08:00

* docs(SteamClient): document some interfaces

* change: Fix formatting style

* docs(SteamClient): document protobufs & System.Report

* docs(SteamClient): document CMsgMonitorInfo

* docs(SteamClient): document remaining messages

* docs(SteamClient): update interfaces to Steam Version 1702515219
Steam Version:  1702515219
Steam Client Build Date:  Thu, Dec 14 00:36 UTC -08:00

* docs(SteamClient): update interfaces to Steam Version 1704329464
Steam Version:  1704329464
Steam Client Build Date:  Thu, Jan 4 12:23 AM UTC -08:00

* docs(SteamClient): update interfaces to Steam Version 1705630720
Steam Version:  1705630720
Steam Client Build Date:  Fri, Jan 19 1:58 AM UTC -08:00

* docs(SteamClient): update interfaces to Steam Version 1706914901
Steam Version:  1706914901
Steam Client Build Date:  Fri, Feb 2 8:46 PM UTC -08:00

* docs(SteamClient): update interfaces to Steam Version 1709920887
Steam Version:  1709920887
Steam Client Build Date:  Thu, Mar 7 5:29 PM UTC -08:00

* docs(SteamClient): update interfaces to Steam Version 1710786209
Steam Version:  1710786209
Steam Client Build Date:  Mon, Mar 18 7:07 PM UTC -08:00

* docs(SteamClient): document even more interfaces

* new: Document some SteamClient interfaces - part 15

* Fix QAM button bit number

* new: Document some SteamClient interfaces - part 16

* change: Update interfaces to Steam Version 1714854927

Steam Version: 1714854927
Steam Client Build Date:  Sat, May 4 7:11 AM UTC -08:00

* change: Refactor and reorganize SteamClient

* docs(SteamClient): document more notification interfaces

* docs(SteamClient): document more interfaces

* docs(SteamClient): add some descriptions

* docs(SteamClient): remove duplicate types

* change: Fix rebase errors

* Updated ControllerStateChange

* Fix typo

* docs(SteamClient): update interfaces to Steam Version 1723601482

Steam Version:  1723601482
Steam Client Build Date:  Wed, Aug 14 01:51 UTC -08:00

* docs(SteamClient): update interfaces to 1725654351

* docs(SteamClient): update interfaces to 1730416762

* docs(SteamClient): forgot some stuff

* docs(SteamClient): add missed interfaces

* docs(SteamClient): update enums

* docs(SteamClient): add some things and move stuff around

* docs(SteamClient): move shared enums/interfaces to a separate file

* docs(SteamClient): add more stuff

* docs(SteamClient): reword some things

* docs(SteamClient): new BrowserView things

* docs(SteamClient): review fixes

* move to src/globals

---------

Co-authored-by: ricewind012 <58827198+ricewind012@users.noreply.github.com>
Co-authored-by: Party Wumpus <48649272+PartyWumpus@users.noreply.github.com>
Co-authored-by: Xander <xander@isxander.dev>
2025-04-23 11:20:48 -04:00
semantic-release-bot
7e7a325cd9 chore(release): 4.9.2 [CI SKIP] 2025-03-29 13:02:17 +00:00
Lukas Senionis
41d0555d31 fix(SidebarNavigation): change title to ReactNode type (#117) 2025-03-29 09:01:51 -04:00
semantic-release-bot
716f947710 chore(release): 4.9.1 [CI SKIP] 2025-01-29 04:57:54 +00:00
TrainDoctor
ed7ba9bbb6 Merge pull request #116 from ricewind012/patch-1
fix(Menu): add missing arg to showContextMenu and document it
2025-01-28 20:57:28 -08:00
ricewind012
c03db3e0d5 fix(Menu): add missing arg to showContextMenu and document it 2025-01-25 12:23:52 +00:00
TrainDoctor
aef063d2e2 Merge pull request #112 from SteamDeckHomebrew/dependabot/npm_and_yarn/micromatch-4.0.8
chore(deps): bump micromatch from 4.0.7 to 4.0.8
2025-01-14 12:40:51 -08:00
dependabot[bot]
33e5d8541d chore(deps): bump cross-spawn from 7.0.3 to 7.0.6 (#114)
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6.
- [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6)

---
updated-dependencies:
- dependency-name: cross-spawn
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 07:43:59 -05:00
semantic-release-bot
9c34100215 chore(release): 4.9.0 [CI SKIP] 2025-01-02 20:11:27 +00:00
Party Wumpus
a1507ac55b Merge pull request #115 from alvaro-cuesta/feat/menu-separator
feat: add `MenuSeparator` component
2025-01-02 20:11:00 +00:00
Álvaro Cuesta
484a882015 feat: add MenuSeparator component 2024-12-27 14:30:35 +01:00
semantic-release-bot
200125cb98 chore(release): 4.8.3 [CI SKIP] 2024-12-14 03:28:48 +00:00
AAGaming
5ab8472ffe Merge branch 'main' of github.com:steamdeckhomebrew/decky-frontend-lib 2024-12-13 22:28:22 -05:00
AAGaming
a43cd7f3c5 fix(utils): add new nav root name 2024-12-13 22:27:26 -05:00
semantic-release-bot
41401b1d01 chore(release): 4.8.2 [CI SKIP] 2024-11-20 19:50:37 +00:00
Lukas Senionis
8117693427 fix(Footer): add missing focus/nav properties (#113) 2024-11-20 14:50:10 -05:00
dependabot[bot]
d80c047580 chore(deps): bump micromatch from 4.0.7 to 4.0.8
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.7 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.7...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-15 17:46:54 +00:00
semantic-release-bot
d6ecba605d chore(release): 4.8.1 [CI SKIP] 2024-10-11 19:00:25 +00:00
AAGaming
bf58e08e4b fix(DialogCheckbox): prevent some potential issues in dialogcheckbox 2024-10-11 14:59:42 -04:00
AAGaming
e965816144 fix(*): prevent issues where toString may not be a function (what) 2024-10-11 14:47:27 -04:00
semantic-release-bot
59ce9e450c chore(release): 4.8.0 [CI SKIP] 2024-10-05 03:52:37 +00:00
AAGaming
980df687e7 fix(components/Router): dont break in desktop ui 2024-10-04 23:52:04 -04:00
AAGaming
bea9ac7774 fix(components/Modal): dont break in desktop ui 2024-10-04 23:51:49 -04:00
AAGaming
063dedbbc1 feat(utils/react): add some window-related utils 2024-10-04 23:51:36 -04:00
semantic-release-bot
723e2ff76e chore(release): 4.7.4 [CI SKIP] 2024-10-04 17:16:01 +00:00
AAGaming
241b22cad7 fix(DialogCheckbox): don't access getters to prevent their side effects from breaking the component 2024-10-04 13:15:29 -04:00
semantic-release-bot
93c59d8026 chore(release): 4.7.3 [CI SKIP] 2024-10-03 20:50:33 +00:00
AAGaming
0f9fb5a3b8 fix(components): fix missing components on oct 2 2024 beta 2024-10-03 16:46:50 -04:00
semantic-release-bot
8c6043b5a7 chore(release): 4.7.2 [CI SKIP] 2024-09-16 23:30:08 +00:00
AAGaming
3aa07dc9ce fix(utils): fix potential race condition in findSP 2024-09-16 19:29:38 -04:00
semantic-release-bot
3f335b3583 chore(release): 4.7.1 [CI SKIP] 2024-08-08 18:18:52 +00:00
AAGaming
4c97097757 fix(utils/react): fix potential race condition in injectFCTrampoline 2024-08-08 14:18:19 -04:00
AAGaming
1ee43e86d6 chore(utils/react): get rid of ts-expect-error 2024-08-03 13:50:33 -04:00
AAGaming
db6ab9c448 chore(docs): add note to CloseSideMenus 2024-07-28 18:51:08 -04:00
semantic-release-bot
4646f22b0c chore(release): 4.7.0 [CI SKIP] 2024-07-28 22:18:51 +00:00
AAGaming
7eb484d55c feat(router): support desktop bpm overlay 2024-07-28 18:17:52 -04:00
AAGaming
5164f980b3 chore(stores): add SteamUIStore, securitystore 2024-07-28 18:15:51 -04:00
AAGaming
0457feec95 chore(tabs): port back to normal find 2024-07-28 18:15:34 -04:00
semantic-release-bot
73b8d52c7f chore(release): 4.6.0 [CI SKIP] 2024-07-26 18:33:10 +00:00
AAGaming
2b8d2ae4db feat(classMapper): add findClassByName back 2024-07-26 14:32:34 -04:00
AAGaming
48de8928e4 chore(deprecation): deprecate useQuickAccessVisible as it has been moved to @decky/api 2024-07-26 14:07:58 -04:00
semantic-release-bot
d60715b755 chore(release): 4.5.0 [CI SKIP] 2024-07-24 04:59:59 +00:00
AAGaming
a370c1f7d3 feat(classMapper): add classModuleMap, make findClass require ID 2024-07-24 00:59:28 -04:00
AAGaming
d83bada4af feat(webpack): refactor to prepare for classMapper changes 2024-07-24 00:59:04 -04:00
semantic-release-bot
1f7178f175 chore(release): 4.4.0 [CI SKIP] 2024-07-18 04:55:06 +00:00
AAGaming
44fdf9ed3b feat(utils/react): add injectFCTrampoline 2024-07-18 00:54:29 -04:00
semantic-release-bot
1b5fd78bc2 chore(release): 4.3.1 [CI SKIP] 2024-07-17 23:30:02 +00:00
AAGaming
d64c42ac31 fix(Menu/MenuGroup): rewrite filter to work on beta and prevent future errors 2024-07-17 19:29:25 -04:00
semantic-release-bot
0ec60edf4d chore(release): 4.3.0 [CI SKIP] 2024-07-09 06:38:22 +00:00
AAGaming
2c3a9f81de feat(utils): react tree patching api 2024-07-09 02:37:46 -04:00
semantic-release-bot
00079a71cc chore(release): 4.2.2 [CI SKIP] 2024-07-04 05:18:57 +00:00
AAGaming
c04f024b34 fix(SteamSpinner): add background option 2024-07-04 01:18:27 -04:00
AAGaming
5dae77b003 chore(ci): update actions to remove deprecation warnings 2024-06-29 17:53:00 -04:00
semantic-release-bot
6b8c28e69c chore(release): 4.2.1 [CI SKIP] 2024-06-27 04:17:41 +00:00
AAGaming
3ef9648355 fix(errorboundary): work around broken react types
for the billionth time
2024-06-27 00:16:14 -04:00
semantic-release-bot
0da85355c2 chore(release): 4.2.0 [CI SKIP] 2024-06-27 04:07:06 +00:00
AAGaming
dcdbb2d6c7 feat(components): add ErrorBoundary 2024-06-27 00:06:32 -04:00
semantic-release-bot
58e3d35e1e chore(release): 4.1.1 [CI SKIP] 2024-06-27 03:19:49 +00:00
Ava Johnson
bd1dc85b92 fix(ReorderableList): avoid mutating props (#109)
Co-authored-by: AAGaming <aagaming@riseup.net>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 23:19:18 -04:00
semantic-release-bot
aa78f4c0a2 chore(release): 4.1.0 [CI SKIP] 2024-06-27 03:11:23 +00:00
AAGaming
b04044451a feat(release): release v4.1.0 2024-06-26 23:10:47 -04:00
semantic-release-bot
5d8f141114 chore(release): 4.0.1 [CI SKIP] 2024-06-27 03:10:04 +00:00
AAGaming
2bfe62409f fix(release): empty commit to bump to v4.0.1 2024-06-26 23:09:36 -04:00
semantic-release-bot
f5cefa9eea chore(release): 4.0.0 [CI SKIP] 2024-06-27 03:08:08 +00:00
AAGaming
abfd2c0105 fix(ci): temp remove npm publisher
BREAKING CHANGE: v4 release
2024-06-26 23:07:29 -04:00
AAGaming
8cb7c273eb fix(ci): empty commit so semantic-release shuts up
BREAKING CHANGE: v4 release
2024-06-26 23:03:39 -04:00
AAGaming
c440fa76b1 chore(ci): empty commit so semantic-release shuts up 2024-06-26 23:00:30 -04:00
AAGaming
4e4859deb6 chore(ci): empty commit so semantic-release shuts up 2024-06-26 22:56:50 -04:00
AAGaming
9579c41c6d chore(ci): empty commit so semantic-release shuts up 2024-06-26 22:53:34 -04:00
AAGaming
4dd6afd91b chore(ci): add v4-dev to release branches 2024-06-26 22:41:52 -04:00
AAGaming
b092d49bf8 chore(ci): return of the CI 2024-06-26 22:39:30 -04:00
AAGaming
7e0cb153b1 fix(*): fixes for jun 26 beta 2024-06-26 22:28:58 -04:00
AAGaming
b1e503853f fix(package): unbreak react 2024-06-13 18:26:38 -04:00
AAGaming
832ad697c7 chore(package): v4.0.3 2024-06-13 18:23:06 -04:00
AAGaming
62b454f712 fix(package): pin react properly 2024-06-13 18:22:18 -04:00
AAGaming
ea19d62dab fix(package): fix ts memes 2024-06-13 17:00:37 -04:00
AAGaming
9f262097b9 fix(Menu): work around ConfigContext error 2024-06-13 15:53:06 -04:00
AAGaming
e6e8c91ec7 fix(components): forgot one 2024-05-27 13:20:03 -04:00
AAGaming
688c7471cd fix(components): fix missing children prop
also remove unnessecary use of tsx
2024-05-27 13:19:11 -04:00
AAGaming
6c1b12b95f chore(ci): disable on v4 for now 2024-05-27 13:15:49 -04:00
semantic-release-bot
0dfb2cedb6 chore(release): 3.26.1 [CI SKIP] 2024-05-25 23:15:00 +00:00
AAGaming
2a78cc0116 fix(Field): add children prop 2024-05-25 19:14:30 -04:00
AAGaming
1716782183 chore(package): ver bump [skip ci] 2024-05-24 18:04:31 -04:00
AAGaming
0cd498beac fix(plugin): shim definePlugin for now [ci skip] 2024-05-24 18:04:05 -04:00
AAGaming
b728d90263 chore(plugin): delete 2024-05-24 17:10:51 -04:00
AAGaming
3384d2910d chore(*): fix version lol 2024-05-24 16:35:31 -04:00
semantic-release-bot
78c4cdb9e9 chore(release): 3.26.0 [CI SKIP] 2024-05-24 20:24:30 +00:00
AAGaming
d20659e073 chore(releaserc): add v4-dev branch 2024-05-24 16:23:59 -04:00
AAGaming
d91f49e728 fix(utils/react): shut it ts 2024-05-24 16:22:51 -04:00
AAGaming
735080fee3 chore(*): init v4 package.json and release.yaml 2024-05-24 16:21:58 -04:00
jbofill
86e6e4c0f5 chore(static-classes): add/fix/update css classes (#102) 2024-05-24 16:17:48 -04:00
shadow
46b1d6e8ea Dropdown contextMenuPositionOptions prop definition (#104) 2024-05-24 16:17:12 -04:00
AAGaming
a7635b6305 chore(*): run prettier 2024-05-12 15:48:13 -04:00
AAGaming
bffd530bda feat(*): add v4 webpack api and port everything to it
also restructures a bunch
2024-05-12 15:45:26 -04:00
AAGaming
9c79187d37 chore(package): init v4 2024-05-12 12:43:26 -04:00
semantic-release-bot
29e6439115 chore(release): 3.25.0 [CI SKIP] 2024-03-09 22:17:49 +00:00
AAGaming
a8eeb917e2 feat(classMapper): add class mapper
thanks valve
2024-03-09 17:13:39 -05:00
AAGaming
17b99dfed8 fix(staticclasses): unbreak on latest beta
unsure if this works for all of them but it works Enough
2024-03-09 17:13:05 -05:00
AAGaming
9ef419cee1 chore(modal): remove useless comments 2024-02-03 00:49:11 -05:00
semantic-release-bot
5aad952936 chore(release): 3.24.5 [CI SKIP] 2024-02-03 05:32:01 +00:00
AAGaming
c2b0fad298 fix(finds): make modal and scroll components work on latest betaa
THEY INCREASED THE MINIFIER PRESET AAAAAAAAAAAAAAAAAAAAAAAAAA
2024-02-03 00:31:29 -05:00
semantic-release-bot
4d4cfedfe0 chore(release): 3.24.4 [CI SKIP] 2024-01-22 19:56:22 +00:00
AAGaming
bb12921863 fix(types): fix incorrect as on many components leading to any types 2024-01-22 14:55:52 -05:00
semantic-release-bot
223739af25 chore(release): 3.24.3 [CI SKIP] 2024-01-20 03:44:07 +00:00
AAGaming
95d977df45 fix(router): wait 2s if internal navigators init fails 2024-01-19 22:43:38 -05:00
semantic-release-bot
0f2692a3f2 chore(release): 3.24.2 [CI SKIP] 2024-01-20 01:40:41 +00:00
Beebles
ebf496bf61 fix(navigation): Fix on chromium 109 (#100) 2024-01-19 18:40:11 -07:00
semantic-release-bot
0a5170e412 chore(release): 3.24.1 [CI SKIP] 2023-12-13 03:08:36 +00:00
AAGaming
11dd82bbb1 fix(utils/react): support react 18, add getReactRoot 2023-12-12 22:07:59 -05:00
semantic-release-bot
153bb209d1 chore(release): 3.24.0 [CI SKIP] 2023-12-03 22:29:55 +00:00
Lukas Senionis
e27b638d26 feat(static-classes): add BasicAppDetailsSectionStylerClasses (#99) 2023-12-03 17:29:30 -05:00
AAGaming
7d287f10d6 chore(releaserc): fix typo 2023-11-26 15:01:54 -05:00
AAGaming
9925bc8cfb chore(releaserc): add docs(steamclient) release patch target 2023-11-26 15:01:33 -05:00
semantic-release-bot
179a93d5e1 chore(release): 3.23.1 [CI SKIP] 2023-11-09 19:45:32 +00:00
AAGaming
5203ce348a fix(webpack): don't break if a module fails to load
doesn't matter now but could in the future so might as well fix it now
2023-11-09 14:44:41 -05:00
dependabot[bot]
3f47b5ccce chore(deps-dev): bump @babel/traverse from 7.21.4 to 7.23.2 (#98) 2023-10-20 13:58:41 +00:00
semantic-release-bot
d22d32677b chore(release): 3.23.0 [CI SKIP] 2023-10-11 16:06:34 +00:00
jbofill
30e319425b feat(static-classes): add more css classes (#94) 2023-10-11 12:06:01 -04:00
semantic-release-bot
aebdfaa089 chore(release): 3.22.1 [CI SKIP] 2023-10-10 13:38:32 +00:00
TrainDoctor
de914b1a35 Merge pull request #97 from FrogTheFrog/patch-29
fix(useQuickAccessVisible): use the "Page Visibility API" instead of focus/blur
2023-10-10 06:37:52 -07:00
Lukas Senionis
4c4fda47e3 fix(useQuickAccessVisible): use the "Page Visibility API" instead of focus/blur 2023-10-09 21:38:34 +03:00
semantic-release-bot
678084e4fd chore(release): 3.22.0 [CI SKIP] 2023-08-09 22:23:32 +00:00
TrainDoctor
4f8f65d429 feat: add components found while working on tabmaster 2023-08-09 15:22:56 -07:00
Tormak
8a352d288d chore: adjusted per aa's request 2023-08-09 13:17:52 -05:00
Tormak
fd0d011cbf feat: add components found while working on tabmaster 2023-07-10 07:47:03 -05:00
Travis Lane
70219d90bc Merge branch 'SteamDeckHomebrew:main' into main 2023-07-10 07:32:04 -05:00
semantic-release-bot
1ff9351f96 chore(release): 3.21.8 [CI SKIP] 2023-06-27 13:38:46 +00:00
Marco Rodolfi
c256d341c8 Merge pull request #89 from SteamDeckHomebrew/RodoMa92-patch-1
fix: the typescript compiler was eating the enum
2023-06-27 15:38:13 +02:00
Marco Rodolfi
c9b583945c fix: the typescript compiler was eating the enum
If not defined with a const keyword
2023-06-27 15:38:04 +02:00
semantic-release-bot
c213204ff4 chore(release): 3.21.7 [CI SKIP] 2023-06-26 16:30:09 +00:00
Travis Lane
9128c1e7da fix: add patch indicator to prevent crashes (#88) 2023-06-26 12:29:21 -04:00
Travis Lane
a06650cf09 Update react.ts with requested changes 2023-06-26 11:26:45 -05:00
Tormak
3170779c6b fix: add patch indicator to prevent crashes 2023-06-25 17:23:45 -05:00
semantic-release-bot
5ffa14bec8 chore(release): 3.21.6 [CI SKIP] 2023-06-22 15:27:59 +00:00
Marco Rodolfi
ee51dc5fc0 fix: reposition parameter for file picker V2 2023-06-22 17:27:14 +02:00
semantic-release-bot
b38ec17d8f chore(release): 3.21.5 [CI SKIP] 2023-06-22 10:16:29 +00:00
Marco Rodolfi
8b54ee990e fix: missing parameter 2023-06-22 12:15:08 +02:00
Marco Rodolfi
7e01781d40 chore: better order for file picker v2 call 2023-06-22 11:59:32 +02:00
semantic-release-bot
2b31473614 chore(release): 3.21.4 [CI SKIP] 2023-06-22 09:39:28 +00:00
Marco Rodolfi
8bfeae4b35 fix: move the new file picker api as v2 2023-06-22 11:38:45 +02:00
semantic-release-bot
a7761321bc chore(release): 3.21.3 [CI SKIP] 2023-06-22 08:41:58 +00:00
Marco Rodolfi
979a630f2b fix: total is not needed as a return value to plugins 2023-06-22 10:41:09 +02:00
Marco Rodolfi
a4d1fcf086 Merge pull request #86 from SteamDeckHomebrew/file_picker_call
chore: add new interface for openfilepicker
2023-06-22 10:13:39 +02:00
Marco Rodolfi
e9e7f5c026 chore: add new interface for openfilepicker 2023-06-22 10:09:01 +02:00
semantic-release-bot
9a691cea09 chore(release): 3.21.2 [CI SKIP] 2023-06-18 17:15:58 +00:00
AAGaming
44d9b90cdc fix(SidebarNavigation): allow ReactNode for page title 2023-06-18 13:15:21 -04:00
TrainDoctor
585c3b8348 Merge pull request #85 from Woovie/patch-1
Update Discord link
2023-06-07 17:35:53 -07:00
Jordan Banasik
1287493b63 Update Discord link 2023-06-07 17:15:40 -07:00
semantic-release-bot
bf01a0184b chore(release): 3.21.1 [CI SKIP] 2023-05-28 23:16:04 +00:00
Jonas Dellinger
fb5f043ba9 fix(reorderable-list): open label type from string to ReactNode 2023-05-29 01:14:59 +02:00
semantic-release-bot
26f2c92dce chore(release): 3.21.0 [CI SKIP] 2023-05-19 14:04:38 +00:00
TrainDoctor
01e53d4c13 Merge pull request #84 from Maclay74/feature/gamepad-ui-classes
Gamepad UI classes, fix findSP to return null when not found
2023-05-19 07:03:59 -07:00
Mikhail Kozlov
18d341f82a fix(Utils): return null when SP not found 2023-05-18 11:41:45 -07:00
Mikhail Kozlov
3ca8c43a54 feat(StaticClasses): add new GamepadUI classes 2023-05-18 11:40:41 -07:00
semantic-release-bot
99353467ad chore(release): 3.20.7 [CI SKIP] 2023-05-10 20:47:47 +00:00
Party Wumpus
b093ce93ba Merge pull request #83 from RodoMa92/main
fix(decky): fix decky on latest beta
2023-05-10 21:46:57 +01:00
Marco Rodolfi
74a7cbaf94 fix(decky): fix decky on latest beta
Thanks to AAGaming and McDjuady for fixing this stuff.
2023-05-10 20:38:14 +02:00
semantic-release-bot
8fb35e3c09 chore(release): 3.20.6 [CI SKIP] 2023-04-29 02:26:37 +00:00
AAGaming
5d5cb31638 fix(QuickAccessTab): set decky tab ID to 999 2023-04-28 22:25:56 -04:00
semantic-release-bot
21f1e5f0af chore(release): 3.20.5 [CI SKIP] 2023-04-04 21:27:14 +00:00
TrainDoctor
0fa43701a9 Merge pull request #82 from Tormak9970/main
fix: reorderable list no longer toggles on backout
2023-04-04 14:26:37 -07:00
Tormak
4d52eaea12 Merge branch 'main' of https://github.com/Tormak9970/decky-frontend-lib 2023-04-04 17:04:22 -05:00
Tormak
7e1182a83f fix: reorderable list no longer toggles on backout 2023-04-04 17:04:18 -05:00
semantic-release-bot
167ded103a chore(release): 3.20.4 [CI SKIP] 2023-04-04 03:16:30 +00:00
AAGaming
b8ddf3d927 fix(SteamSpinner): oh apparently the class was moved outside the component for some reason?????? 2023-04-03 23:15:51 -04:00
semantic-release-bot
62f4b354a8 chore(release): 3.20.3 [CI SKIP] 2023-04-04 02:53:53 +00:00
AAGaming
79d229be50 fix(SteamSpinner): fix the fix 2023-04-03 22:53:10 -04:00
semantic-release-bot
f43157fde5 chore(release): 3.20.2 [CI SKIP] 2023-04-04 02:50:17 +00:00
AAGaming
19819b7a5b fix(SteamSpinner): dont error on latest desktop beta 2023-04-03 22:49:31 -04:00
semantic-release-bot
8752f576a7 chore(release): 3.20.1 [CI SKIP] 2023-04-03 22:18:43 +00:00
TrainDoctor
102a441124 Merge pull request #79 from FrogTheFrog/main
fix(useQuickAccessVisible): make it work again
2023-04-03 15:18:07 -07:00
semantic-release-bot
62f40bd48f chore(release): 3.20.0 [CI SKIP] 2023-04-03 20:49:24 +00:00
TrainDoctor
a7acc9ae45 Merge pull request #80 from Tormak9970/main
Add save on backout to reorderable list component.
2023-04-03 13:48:35 -07:00
Travis Lane
be7f17a3c3 Merge pull request #2 from Tormak9970/reorderable-list
chore: bumped pnpm lockfile version
2023-04-03 16:47:18 -04:00
Tormak
5d097b6108 chore: bumped pnpm lockfile version 2023-04-03 16:44:13 -04:00
Travis Lane
ae98930eeb Merge pull request #1 from Tormak9970/reorderable-list
Reorderable list now saves on backout
2023-03-29 10:18:32 -04:00
Travis Lane
6ce0da996d Merge branch 'main' into reorderable-list 2023-03-29 10:18:23 -04:00
Tormak
b1591f86bb feat: reorderable list now saves on backout 2023-03-29 07:10:55 -05:00
TrainDoctor
f7318f0210 Merge pull request #78 from Tormak9970/patch-1 2023-03-23 07:40:28 -07:00
Travis Lane
1a34501868 updated to use 'separator' instead of string 2023-03-22 20:17:58 -05:00
FrogTheFrog
7dacb23e8b fix(useQuickAccessVisible): make it work again 2023-03-19 22:25:53 +02:00
semantic-release-bot
7e5c7b5ac3 chore(release): 3.19.2 [CI SKIP] 2023-03-07 23:48:45 +00:00
Beebles
f71e4dedc8 Merge pull request #71 from doZennn/patch-1
fix(Item): add highlightOnFocus prop
2023-03-07 16:48:10 -07:00
Travis Lane
419835204e Add support for SidebarNavigation separator
Looked into it and in order to render a separator you need to pass `"separator"`
2023-03-06 11:15:36 -06:00
semantic-release-bot
86f33de2c0 chore(release): 3.19.1 [CI SKIP] 2023-02-23 02:57:40 +00:00
AAGaming
0b6dc24c0d fix(*): refactoring to fix for feb 22 2023 beta 2023-02-22 21:56:46 -05:00
semantic-release-bot
18ce1ad790 chore(release): 3.19.0 [CI SKIP] 2023-02-22 03:38:02 +00:00
Travis Lane
5a074b5bb6 feat: added reorderable list and updated fieldProps (#57) 2023-02-22 03:37:26 +00:00
AAGaming
26fae13c8e feat(ReorderableList): add animations, clean up 2023-02-21 22:36:56 -05:00
AAGaming
53faf55df1 fix(Field): remove style 2023-02-21 22:36:35 -05:00
Tormak
b480d397c4 fix: fixed missing export 2023-02-21 19:06:08 -06:00
Tormak
dfcb3bec19 feat: added doc comments 2023-02-21 12:22:21 -06:00
Travis Lane
cf7dc26a0c Merge branch 'SteamDeckHomebrew:main' into main 2023-02-21 12:22:12 -05:00
semantic-release-bot
d3b87b26c5 chore(release): 3.18.11 [CI SKIP] 2023-02-18 23:24:21 +00:00
TrainDoctor
b64dd9f723 Merge pull request #75 from beebls/main
fix(Navigation): fix NavigateToExternalWeb and ModalRoot
2023-02-18 15:23:49 -08:00
beebls
82214fef4c fix(Navigation): fix NavigateToExternalWeb 2023-02-18 15:51:31 -07:00
Jozen Blue Martinez
e559a43af9 Add missing types (#76)
* feat(SteamAppOverview): Add types

* feat(SliderFieldProps): Add className type

* feat(ToggleFieldProps): Add highlightOnFocus type

* feat(AppDetails): Add types for libraryAssets.logoPosition

* feat(types): Add types to some globals
2023-02-18 19:58:50 +00:00
beebls
c53d7f8448 fix(Navigation): fix NavigateToExternalWeb 2023-02-17 18:21:48 -07:00
AAGaming
68a46263a4 chore(docs): update wikijs typedoc plugin 2023-02-04 19:45:51 -05:00
AAGaming
56e7b2c492 chore(docs): fix workflow oops 2023-02-04 19:39:32 -05:00
AAGaming
1282636b0b chore(docs): revert workflow changes 2023-02-04 19:38:47 -05:00
AAGaming
2343274a5b chore(docs): update wikijs typedoc plugin 2023-02-04 19:36:38 -05:00
AAGaming
f965c05c27 chore(docs): fix path 2023-02-04 17:20:34 -05:00
AAGaming
f8c8ae7c29 chore(docs): update typedoc-wikijs-theme to fix bug 2023-02-04 17:18:52 -05:00
AAGaming
3085efd439 chore(docs): fix mv 2023-02-04 17:17:05 -05:00
AAGaming
db8d91a7ff chore(docs): bump typedoc-wikijs-theme and update docs workflow 2023-02-04 17:14:27 -05:00
AAGaming
2091daaeac chore(docs): update doc generation to use typedoc-wikijs-theme, also bump typescript 2023-02-04 16:55:52 -05:00
Tormak
b1b2f4fa2d feat: made requested changes and ran prettier 2023-02-04 11:39:08 -06:00
Tormak
b146eab8d7 fix: list didn't update on prop change 2023-02-03 15:33:03 -06:00
Tormak
667933bd7c refactor: addressed change reqs 2023-02-01 17:42:03 -06:00
Tormak
dbd01b11ca feat: support for non-interactable reordering 2023-02-01 17:24:17 -06:00
Tormak
47a6fddc89 feat: support for user specified icon 2023-02-01 15:33:27 -06:00
Tormak
c57e0eed34 refactor: changes to improve deck cohesion 2023-02-01 15:25:23 -06:00
Tormak
5adc5e14ed refactor: updated to simpler reorderable list 2023-02-01 08:18:55 -06:00
Tormak
cea315a52c feat: refactoring mostly complete 2023-01-28 17:19:24 -06:00
Tormak
5b166d6db8 feat: changed ReorderableList to working version 2023-01-28 16:53:22 -06:00
semantic-release-bot
edcc43a6ee chore(release): 3.18.10 [CI SKIP] 2023-01-17 00:35:19 +00:00
AAGaming
9723854ddc fix(SuspensefulImage): fix changing src 2023-01-16 19:34:44 -05:00
semantic-release-bot
7501817b76 chore(release): 3.18.9 [CI SKIP] 2023-01-16 14:13:05 +00:00
AAGaming
4affd4aaec fix(Navigation): fix on stable 2023-01-16 09:12:16 -05:00
semantic-release-bot
6b3db72a14 chore(release): 3.18.8 [CI SKIP] 2023-01-16 01:23:38 +00:00
AAGaming
58b69f0d6c fix(Navigation): fix timing issue in decky-loader 2023-01-15 20:22:54 -05:00
semantic-release-bot
c62102e993 chore(release): 3.18.7 [CI SKIP] 2023-01-16 00:19:36 +00:00
AAGaming
2e66e5a555 fix: un-break navigation on stable 2023-01-15 19:18:47 -05:00
semantic-release-bot
ce525318d8 chore(release): 3.18.6 [CI SKIP] 2023-01-13 02:55:51 +00:00
AAGaming
aac2d520a6 fix(Router): fix Navigation for the millionth time 2023-01-12 21:55:08 -05:00
Travis Lane
e761ee02ba Merge branch 'SteamDeckHomebrew:main' into main 2023-01-07 20:14:33 -05:00
Jozen Blue Martinez
c53f87b4a9 fix(Item): add highlightOnFocus prop 2022-12-29 15:36:08 +08:00
semantic-release-bot
a656f4e57f chore(release): 3.18.5 [CI SKIP] 2022-12-21 15:57:16 +00:00
noot
0b50f2cf0b fix: fixed prop interfaces (#70) 2022-12-21 10:56:39 -05:00
semantic-release-bot
e48c7bbadd chore(release): 3.18.4 [CI SKIP] 2022-12-16 02:04:28 +00:00
TrainDoctor
727fcc8186 Merge pull request #67 from SteamDeckHomebrew/aa/fix-modals-dec2022
fix(modals): fix ModalRoot again
2022-12-15 18:03:27 -08:00
semantic-release-bot
dc196d53f5 chore(release): 3.18.3 [CI SKIP] 2022-12-12 23:49:39 +00:00
Beebles
f0379e5d19 fix(Router): update Router interface to SteamOS3.4 and add Navigation (#52) 2022-12-12 18:48:52 -05:00
AAGaming
fd94842647 fix(modals): fix ModalRoot again 2022-12-11 19:52:20 -05:00
semantic-release-bot
ef6be8c6ec chore(release): 3.18.2 [CI SKIP] 2022-12-11 20:12:52 +00:00
Lukas Senionis
767dc2fcee fix(useQuickAccessVisible): remove invalid prop access (#66) 2022-12-11 15:12:22 -05:00
semantic-release-bot
52305987c5 chore(release): 3.18.1 [CI SKIP] 2022-12-11 20:02:11 +00:00
Lukas Senionis
6f14da152a fix(findSP): fallback to last active context (#53) 2022-12-11 15:01:41 -05:00
semantic-release-bot
bb291b211c chore(release): 3.18.0 [CI SKIP] 2022-12-11 15:10:33 +00:00
Jozen Blue Martinez
88f245d476 feat(DialogCheckbox): Add DialogCheckbox component (#58)
* feat(DialogCheckbox): Add DialogCheckbox component

* fix(DialogCheckbox): Better sibling match

* fix(DialogCheckbox): Extend FocusableProps

* fix(DialogCheckbox): Extend FooterLegendProps

i should have probably tested that

* feat(DialogCheckbox): add onClick() prop

* fix(DialogCheckbox): replace default export with named export
2022-12-11 16:10:01 +01:00
semantic-release-bot
5bc78df918 chore(release): 3.17.0 [CI SKIP] 2022-12-11 15:08:02 +00:00
Jozen Blue Martinez
c586afb97d feat(ControlsList): Add ControlsList component (#61)
* feat(ControlsList): Add ControlsList component

* fix(ControlsList): replace default export with named export
2022-12-11 16:07:31 +01:00
semantic-release-bot
d9150c2556 chore(release): 3.16.2 [CI SKIP] 2022-12-11 14:48:15 +00:00
Jonas Dellinger
cd0635e94f fix(Marquee): replace default export with named export 2022-12-11 15:47:39 +01:00
semantic-release-bot
443c7850d7 chore(release): 3.16.1 [CI SKIP] 2022-12-11 14:46:16 +00:00
Jozen Blue Martinez
d24136ecb6 fix(FooterLegend): change description types to ReactNode (#62) 2022-12-11 15:45:40 +01:00
semantic-release-bot
55507446cc chore(release): 3.16.0 [CI SKIP] 2022-12-11 14:45:21 +00:00
Jozen Blue Martinez
925ea8c3ce feat(Marquee): Add Marquee component (#63) 2022-12-11 15:44:50 +01:00
semantic-release-bot
14c5210931 chore(release): 3.15.0 [CI SKIP] 2022-12-11 14:18:49 +00:00
Jozen Blue Martinez
cc29ddaf57 feat(Focusable): add noFocusRing prop type (#65) 2022-12-11 15:18:07 +01:00
semantic-release-bot
1e8979b641 chore(release): 3.14.0 [CI SKIP] 2022-12-10 00:14:13 +00:00
jurassicplayer
7ba1229a4e feat(toast): add showToast/playSound to ToastData (#64) 2022-12-09 19:13:37 -05:00
semantic-release-bot
4c2a715324 chore(release): 3.13.0 [CI SKIP] 2022-11-29 20:01:20 +00:00
Jozen Blue Martinez
678ba216f1 feat(Menu): add more missing props (#60) [CI SKIP]
* feat(Menu): extend FooterLegendProps

* feat(MenuItem): add more missing props
2022-11-29 21:00:45 +01:00
semantic-release-bot
07d15f5dca chore(release): 3.12.0 [CI SKIP] 2022-11-28 12:03:43 +00:00
Jozen Blue Martinez
c84a091469 feat(MenuItem): add missing props (#59) 2022-11-28 07:03:07 -05:00
Tormak
3c171cfb8f feat: added reorderable list and updated fieldProps 2022-11-25 18:32:55 -05:00
semantic-release-bot
47fd13692f chore(release): 3.11.1 [CI SKIP] 2022-11-20 01:13:29 +00:00
AAGaming
2ec9519b7d fix(Footer): add types for ActionDescriptionMap 2022-11-19 20:12:45 -05:00
semantic-release-bot
24606190e0 chore(release): 3.11.0 [CI SKIP] 2022-11-18 18:00:30 +00:00
Lukas Senionis
ed98d14b37 feat(classes): add "appDetailsClasses" (#55) 2022-11-18 12:59:57 -05:00
semantic-release-bot
b882612dfa chore(release): 3.10.0 [CI SKIP] 2022-11-18 17:37:50 +00:00
Lukas Senionis
32291620b4 feat(classes): add appDetailsHeaderClasses (#54) 2022-11-18 12:37:16 -05:00
semantic-release-bot
9b368c5f11 chore(release): 3.9.0 [CI SKIP] 2022-11-16 20:45:13 +00:00
Lukas Senionis
e167ef5a13 feat(Dialog): add "focusable" button prop (#51) 2022-11-16 15:44:36 -05:00
semantic-release-bot
2f3df00967 chore(release): 3.8.0 [CI SKIP] 2022-11-11 21:05:54 +00:00
AAGaming
215156d316 feat(routerhook): add global components support 2022-11-11 16:05:05 -05:00
semantic-release-bot
47d75db690 chore(release): 3.7.14 [CI SKIP] 2022-11-05 01:47:25 +00:00
AAGaming
82768e0415 fix(Menu): fix on Steam beta 2022-11-04 21:46:39 -04:00
AAGaming
e44187fe4b fix(Modal): fix on Steam beta 2022-11-04 21:46:22 -04:00
semantic-release-bot
72af32436e chore(release): 3.7.13 [CI SKIP] 2022-11-02 16:56:44 +00:00
Lukas Senionis
e1f64a38de fix(useQuickAccessVisible): make it work in beta (#49)
* fix(useQuickAccessVisible): make it work in beta

* fix(useQuickAccessVisible): rename for consistency

* fix(useQuickAccessVisible): update the exports

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

* fix(Field): remove the override
2022-10-26 17:49:14 -04:00
semantic-release-bot
28cbc1cfe1 chore(release): 3.7.6 [CI SKIP] 2022-10-26 21:42:37 +00:00
Lukas Senionis
fe75dfb5f4 fix(Field): add override for onClick type (#43) 2022-10-26 17:42:04 -04:00
semantic-release-bot
91c386a6cc chore(release): 3.7.5 [CI SKIP] 2022-10-26 12:19:45 +00:00
Lukas Senionis
bedb6b8bb9 fix(Field): add types for focusing field (#41) 2022-10-26 08:19:16 -04:00
semantic-release-bot
4cdcca0b5a chore(release): 3.7.4 [CI SKIP] 2022-10-26 00:16:38 +00:00
AAGaming
f16e0b29f8 fix(tabs): fix on stable 2022-10-25 20:16:06 -04:00
AAGaming
37a6658b95 chore(docs): how did i manage to do this 2022-10-24 20:45:01 -04:00
AAGaming
ed0b92de2e fix(docs): change arg format 2022-10-24 20:43:53 -04:00
AAGaming
dcba5c22f8 chore(docs): fix it 2022-10-24 20:42:47 -04:00
semantic-release-bot
fa50ca6a37 chore(release): 3.7.3 [CI SKIP] 2022-10-25 00:38:49 +00:00
AAGaming
19e986ed8b chore(ci): switch to npm 2022-10-24 20:38:18 -04:00
AAGaming
3c553a227d fix(tabs): it returns 2022-10-24 20:35:01 -04:00
AAGaming
1f2694aec8 chore(prettier): fix prettier 2022-10-24 20:33:40 -04:00
semantic-release-bot
2e52cca8a2 chore(release): 3.7.2 [CI SKIP] 2022-10-24 14:59:05 +00:00
AAGaming
3dbca1a056 fix(tabs): unkill build 2022-10-24 10:58:35 -04:00
semantic-release-bot
c6692138c6 chore(release): 3.7.1 [CI SKIP] 2022-10-24 05:01:13 +00:00
AAGaming
25c33b2a05 fix(Tabs): temp remove until we have a way to grab it on beta 2022-10-24 01:00:44 -04:00
semantic-release-bot
00d27d1373 chore(release): 3.7.0 [CI SKIP] 2022-10-24 00:22:31 +00:00
AAGaming
5f0470c351 feat(modal): support for latest steamos preview 2022-10-23 20:22:04 -04:00
semantic-release-bot
c77d6edaae chore(release): 3.6.1 [CI SKIP] 2022-10-19 19:57:14 +00:00
Lukas Senionis
c44c66facd fix(plugin): export RoutePatch (#39) 2022-10-19 15:44:13 -04:00
Tormak
ce3860f73b added jsdoc and SteamClient global declaration 2022-10-17 08:39:37 -04:00
Tormak
d8b10a2133 ran prettier 2022-10-15 22:46:41 -05:00
Tormak
1581304dcb restyled 2022-10-15 22:44:58 -05:00
Travis Lane
60ddf474e0 Merge branch 'SteamDeckHomebrew:main' into main 2022-10-15 13:46:50 -05:00
Tormak
52ae328e2e added some of the SteamClient types 2022-10-15 14:35:57 -05:00
semantic-release-bot
276e4eccd2 chore(release): 3.6.0 [CI SKIP] 2022-10-15 03:44:35 +00:00
AAGaming
2fc2060a6c feat(plugin): add alwaysRender 2022-10-14 23:43:45 -04:00
semantic-release-bot
1143a9f3e0 chore(release): 3.5.6 [CI SKIP] 2022-10-08 12:57:07 +00:00
Lukas Senionis
5a5218a7c4 fix(Dialog): remove not exported dialog button (#37) 2022-10-08 08:56:14 -04:00
semantic-release-bot
8a887ca858 chore(release): 3.5.5 [CI SKIP] 2022-10-08 05:54:20 +00:00
AAGaming
0ce1b5499d fix(sidebarnavigation): no dont 2022-10-08 01:53:35 -04:00
semantic-release-bot
554163cc5d chore(release): 3.5.4 [CI SKIP] 2022-10-08 05:51:16 +00:00
AAGaming
d6b00b0733 fix(sidebarnavigation): allow null pags 2022-10-08 01:50:25 -04:00
semantic-release-bot
f8ddf210f0 chore(release): 3.5.3 [CI SKIP] 2022-10-08 02:52:44 +00:00
AAGaming
4024b76918 fix(tabs): fix props and add example 2022-10-07 22:51:59 -04:00
semantic-release-bot
245dd0f3cf chore(release): 3.5.2 [CI SKIP] 2022-10-08 02:22:06 +00:00
AAGaming
7161e757e9 fix(Tabs): make onShowTab required 2022-10-07 22:21:30 -04:00
semantic-release-bot
c60d1e9787 chore(release): 3.5.1 [CI SKIP] 2022-10-08 02:11:59 +00:00
AAGaming
0e0e0d204a fix(Tabs): actually export it lmao 2022-10-07 22:11:23 -04:00
semantic-release-bot
e5120928d3 chore(release): 3.5.0 [CI SKIP] 2022-10-08 02:04:42 +00:00
AAGaming
abbd3cddae feat(Tabs): initial tabs component, props, docs 2022-10-07 22:04:02 -04:00
semantic-release-bot
621e47c6a0 chore(release): 3.4.0 [CI SKIP] 2022-10-06 01:43:25 +00:00
OMGDuke
e2920dd91e feat(hooks): Added useParams hook (#36) 2022-10-05 21:42:54 -04:00
semantic-release-bot
67a76e2691 chore(release): 3.3.5 [CI SKIP] 2022-10-02 16:38:31 +00:00
AAGaming
0f205e8916 fix(docs): set categorizeByGroup to true 2022-10-02 12:37:45 -04:00
semantic-release-bot
472307e4a4 chore(release): 3.3.4 [CI SKIP] 2022-10-02 16:34:00 +00:00
AAGaming
fbd936dc1f fix(docs): build each component as a seperate page 2022-10-02 12:33:20 -04:00
AAGaming
33dd4e5548 chore(docs): initial typedoc setup (#35) 2022-10-02 12:22:58 -04:00
semantic-release-bot
4b76ccd91a chore(release): 3.3.3 [CI SKIP] 2022-10-02 12:36:26 +00:00
Lukas Senionis
99ad7543a9 fix(modal): make children optional (#34) 2022-10-02 08:36:00 -04:00
semantic-release-bot
b5dc08a977 chore(release): 3.3.2 [CI SKIP] 2022-10-02 02:31:09 +00:00
AAGaming
40871af853 fix(modal): allow children 2022-10-01 22:30:33 -04:00
Lukas Senionis
c910dbde79 Add dialog components (#22) 2022-10-01 21:41:47 -04:00
Lukas Senionis
4cbb30c21c Add custom-hook: useQuickAccessVisible (#28) 2022-10-01 21:38:46 -04:00
semantic-release-bot
54a1ef6201 chore(release): 3.3.1 [CI SKIP] 2022-10-02 01:33:33 +00:00
Barend Du Toit
ed0be5e87e fix(SidebarNavigation): add more props (#29) 2022-10-01 21:33:02 -04:00
Travis Lane
a064163b49 updated static-classes (#26) 2022-10-01 21:32:23 -04:00
semantic-release-bot
0b4fcb8d49 chore(release): 3.3.0 [CI SKIP] 2022-10-02 01:31:47 +00:00
Barend Du Toit
4233128c7e feat(Menu): add nested menu groups + more props (#30) 2022-10-01 21:31:18 -04:00
TrainDoctor
43cb2726d8 chore(license): remove un-needed exceptions 2022-09-30 21:50:23 -07:00
TrainDoctor
5d9c506fe7 Update package.json 2022-09-30 21:48:33 -07:00
Tormak
aa0fad2ecf fixed typo 2022-09-29 13:24:15 -05:00
Tormak
dab9071d1e found name of static classes 2022-09-29 13:01:06 -05:00
semantic-release-bot
35a061759a chore(release): 3.2.2 [CI SKIP] 2022-09-29 16:36:04 +00:00
Lukas Senionis
1fbe55aa54 fix(modal): extend props for modals (#32) 2022-09-29 12:34:00 -04:00
Tormak
189a90ba31 Updated ScrollPanelClasses
marked the old variable as depreciated and moved the implementation to the new variable
2022-09-25 09:06:14 -05:00
Tormak
8509ae8f9a Merge branch 'main' of https://github.com/Tormak9970/decky-frontend-lib 2022-09-24 12:05:06 -05:00
Tormak
a6ebfdcd7d fixed includes 2022-09-24 12:05:04 -05:00
Tormak
5f7655baaf fixed bugs with static-classes and future proofing 2022-09-24 11:51:19 -05:00
Travis Lane
bca2dcc9bd Merge branch 'SteamDeckHomebrew:main' into main 2022-09-24 10:54:09 -05:00
Tormak
546a4da043 updated DialogButton props and added nav pref enum 2022-09-22 17:33:08 -05:00
141 changed files with 20104 additions and 23641 deletions

55
.github/workflows/docs.yaml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: Generate docs
on:
workflow_dispatch:
# push:
# branches:
# - main
jobs:
release:
name: Generate Docs
runs-on: ubuntu-22.04
steps:
- name: Setup | Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
path: lib
- name: Setup | Checkout wiki
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@v4
with:
node-version: 18
- name: Setup | Dependencies
run: |
cd lib
npm i -g pnpm
pnpm i --frozen-lockfile
- name: Build Docs
run: |
cd lib
pnpm run docs --out ../wiki/api-docs/decky-frontend-lib
- name: Commit files
run: |
cd wiki
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add -A ./api-docs/decky-frontend-lib
git commit -m "Update decky-frontend-lib API docs"
- name: Push changes
uses: ad-m/github-push-action@master
with:
ssh: true
directory: ./wiki
repository: SteamDeckHomebrew/wiki
branch: main

View File

@@ -1,6 +1,7 @@
name: Release
on:
pull_request:
push:
branches:
- main
@@ -11,19 +12,22 @@ jobs:
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: 20
- name: Setup | Dependencies
run: npm ci
run: npm i -g pnpm && pnpm i --frozen-lockfile
- name: Build
run: pnpm run build
- name: Test
run: npm test
run: pnpm run test
- name: Release
if: github.event_name != 'pull_request'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm exec semantic-release
NPM_TOKEN: ${{ secrets.NPM_TOKEN_DECKY_ORG }}
run: pnpm exec semantic-release

3
.gitignore vendored
View File

@@ -36,5 +36,4 @@ dist/
research/
# PNPM lockfile
pnpm-lock.yaml
docs/

View File

@@ -1,12 +1,14 @@
{
"branches": ["main", "dev"],
"branches": ["main", "v4-dev"],
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "angular",
"releaseRules": [
{"type": "chore", "scope": "classes", "release": "patch"}
{ "type": "chore", "scope": "classes", "release": "patch" },
{ "type": "docs", "scope": "steamclient", "release": "patch" },
{ "type": "*", "scope": "docs", "release": false }
]
}
],

26
.vscode/tasks.json vendored
View File

@@ -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
}
]
}

View File

@@ -1,3 +1,920 @@
## [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)
### Bug Fixes
* **modals:** fix ModalRoot again ([fd94842](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/fd94842647e51dd9a104e170e0c5ee2bebce12d6))
## [3.18.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.2...v3.18.3) (2022-12-12)
### Bug Fixes
* **Router:** update Router interface to SteamOS3.4 and add Navigation ([#52](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/52)) ([f0379e5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/f0379e5d19279863b571e66918bc9107efedb612))
## [3.18.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.1...v3.18.2) (2022-12-11)
### Bug Fixes
* **useQuickAccessVisible:** remove invalid prop access ([#66](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/66)) ([767dc2f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/767dc2fcee97d8b6c2d331ae29704d9b469de51a))
## [3.18.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.18.0...v3.18.1) (2022-12-11)
### Bug Fixes
* **findSP:** fallback to last active context ([#53](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/53)) ([6f14da1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/6f14da152acc4757b814844f1b77bf83dd98d77e))
# [3.18.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.17.0...v3.18.0) (2022-12-11)
### Features
* **DialogCheckbox:** Add DialogCheckbox component ([#58](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/58)) ([88f245d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/88f245d476a6477e9fc0cd35e9b675961ecbc26c))
# [3.17.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.16.2...v3.17.0) (2022-12-11)
### Features
* **ControlsList:** Add ControlsList component ([#61](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/61)) ([c586afb](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/c586afb97d59928ecb703b5a254ed1b9405e2c7e))
## [3.16.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.16.1...v3.16.2) (2022-12-11)
### Bug Fixes
* **Marquee:** replace default export with named export ([cd0635e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/cd0635e94f98499f9f5fc24a7fd4b93efe7dfc38))
## [3.16.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.16.0...v3.16.1) (2022-12-11)
### Bug Fixes
* **FooterLegend:** change description types to ReactNode ([#62](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/62)) ([d24136e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/d24136ecb6b0c5239b68723e8f92a4822aa7b590))
# [3.16.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.15.0...v3.16.0) (2022-12-11)
### Features
* **Marquee:** Add Marquee component ([#63](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/63)) ([925ea8c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/925ea8c3ceaaf6ff2f79b8808908a9b144a4fcff))
# [3.15.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.14.0...v3.15.0) (2022-12-11)
### Features
* **Focusable:** add noFocusRing prop type ([#65](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/65)) ([cc29dda](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/cc29ddaf578e21ab2abe1cd266f1d15debee0637))
# [3.14.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.13.0...v3.14.0) (2022-12-10)
### Features
* **toast:** add showToast/playSound to ToastData ([#64](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/64)) ([7ba1229](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/7ba1229a4e24fea587b96dc8b078200faf45ddee))
# [3.13.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.12.0...v3.13.0) (2022-11-29)
### Features
* **Menu:** add more missing props ([#60](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/60)) [CI SKIP] ([678ba21](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/678ba216f1e194986b0c391398e6f73536cd0102))
# [3.12.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.11.1...v3.12.0) (2022-11-28)
### Features
* **MenuItem:** add missing props ([#59](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/59)) ([c84a091](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/c84a09146935f0942265b7a1e4aadc40e8cf22dc))
## [3.11.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.11.0...v3.11.1) (2022-11-20)
### Bug Fixes
* **Footer:** add types for ActionDescriptionMap ([2ec9519](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/2ec9519b7d6d1cc0d232853ce05a773953b37c5a))
# [3.11.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.10.0...v3.11.0) (2022-11-18)
### Features
* **classes:** add "appDetailsClasses" ([#55](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/55)) ([ed98d14](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/ed98d14b37cf09500afd88e7c8e9c03749119b38))
# [3.10.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.9.0...v3.10.0) (2022-11-18)
### Features
* **classes:** add appDetailsHeaderClasses ([#54](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/54)) ([3229162](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/32291620b403f8b65cf378343454a3f2668fb6ee))
# [3.9.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.8.0...v3.9.0) (2022-11-16)
### Features
* **Dialog:** add "focusable" button prop ([#51](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/51)) ([e167ef5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e167ef5a138a3edc004db2365334f8455c177132))
# [3.8.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.14...v3.8.0) (2022-11-11)
### Features
* **routerhook:** add global components support ([215156d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/215156d31688faac9028627379e5a3ac4d64ec46))
## [3.7.14](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.13...v3.7.14) (2022-11-05)
### Bug Fixes
* **Menu:** fix on Steam beta ([82768e0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/82768e0415d084deb2af39beb3f9273a83e819de))
* **Modal:** fix on Steam beta ([e44187f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e44187fe4b9d3e3c9e94490669591599dc5246ba))
## [3.7.13](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.12...v3.7.13) (2022-11-02)
### Bug Fixes
* **useQuickAccessVisible:** make it work in beta ([#49](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/49)) ([e1f64a3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e1f64a38de85073e5cea74ecea4b9cde9a783ecc))
## [3.7.12](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.11...v3.7.12) (2022-10-29)
### Bug Fixes
* **Item:** change title and description types to ReactNode ([0ed054f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0ed054fae972ffd36299b142bd693f80388480a6))
## [3.7.11](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.10...v3.7.11) (2022-10-28)
### Bug Fixes
* **package.json:** train wtf ([789e163](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/789e16380fd01a6b46188c7a1174a55c18c8dead))
## [3.7.10](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.9...v3.7.10) (2022-10-28)
### Bug Fixes
* **tabs:** shut up typescript ([75f3588](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/75f35882f27252e1255208953a6e801c68d5dcec))
## [3.7.9](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.8...v3.7.9) (2022-10-28)
### Bug Fixes
* **tabs:** fix on stable for real this time i think ([a074277](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/a074277bb58428a64295154ebf96aceb96e654a7))
## [3.7.8](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.7...v3.7.8) (2022-10-26)
### Bug Fixes
* **Field:** fix this time for real ([#44](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/44)) ([cfef1dc](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/cfef1dc320a5f649d66c3af365cd6aa2d88e46ea))
## [3.7.7](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.6...v3.7.7) (2022-10-26)
### Bug Fixes
* **Field:** remove incompatible properties ([#42](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/42)) ([0010a1f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0010a1fceedc417aa25b709d066341da97d42444))
## [3.7.6](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.5...v3.7.6) (2022-10-26)
### Bug Fixes
* **Field:** add override for onClick type ([#43](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/43)) ([fe75dfb](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/fe75dfb5f4fb1ec9417cc07dc714c71820945748))
## [3.7.5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.4...v3.7.5) (2022-10-26)
### Bug Fixes
* **Field:** add types for focusing field ([#41](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/41)) ([bedb6b8](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/bedb6b8bb90e021a60e47a93709d6f48e0bd75c6))
## [3.7.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.3...v3.7.4) (2022-10-26)
### Bug Fixes
* **docs:** change arg format ([ed0b92d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/ed0b92de2ec13a585f6524b45eef0ab538d87448))
* **tabs:** fix on stable ([f16e0b2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/f16e0b29f8e1de500e8f436db659d1ad99d4eaa6))
## [3.7.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.2...v3.7.3) (2022-10-25)
### Bug Fixes
* **tabs:** it returns ([3c553a2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/3c553a227d1aa7b03c4431ff968f336b4f871801))
## [3.7.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.1...v3.7.2) (2022-10-24)
### Bug Fixes
* **tabs:** unkill build ([3dbca1a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/3dbca1a0567592a597e70ce5e9bef157f709c765))
## [3.7.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.7.0...v3.7.1) (2022-10-24)
### Bug Fixes
* **Tabs:** temp remove until we have a way to grab it on beta ([25c33b2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/25c33b2a05a30c3c72008c5f459c3b77f819db5a))
# [3.7.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.6.1...v3.7.0) (2022-10-24)
### Features
* **modal:** support for latest steamos preview ([5f0470c](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/5f0470c351dc4ecb24ea3e928ff0b0199c399fa4))
## [3.6.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.6.0...v3.6.1) (2022-10-19)
### Bug Fixes
* **plugin:** export RoutePatch ([#39](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/39)) ([c44c66f](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/c44c66facd4e158aa4fe0a69f62a2ca3add805c1))
# [3.6.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.5.6...v3.6.0) (2022-10-15)
### Features
* **plugin:** add alwaysRender ([2fc2060](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/2fc2060a6c0d9414d1c36a1a022fdc6f2cd7f8bb))
## [3.5.6](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.5.5...v3.5.6) (2022-10-08)
### Bug Fixes
* **Dialog:** remove not exported dialog button ([#37](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/37)) ([5a5218a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/5a5218a7c43f6a90fc4de5f7a0cd524d1cd298d6))
## [3.5.5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.5.4...v3.5.5) (2022-10-08)
### Bug Fixes
* **sidebarnavigation:** no dont ([0ce1b54](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0ce1b5499df699f602aa83ab87ad8b246d133eac))
## [3.5.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.5.3...v3.5.4) (2022-10-08)
### Bug Fixes
* **sidebarnavigation:** allow null pags ([d6b00b0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/d6b00b07337f7a9d38813eeec7c0a848d5c15f17))
## [3.5.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.5.2...v3.5.3) (2022-10-08)
### Bug Fixes
* **tabs:** fix props and add example ([4024b76](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/4024b76918eea43e43a24c162a937877f18627f0))
## [3.5.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.5.1...v3.5.2) (2022-10-08)
### Bug Fixes
* **Tabs:** make onShowTab required ([7161e75](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/7161e757e9c98d677510e03eb2606ce58152f3b1))
## [3.5.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.5.0...v3.5.1) (2022-10-08)
### Bug Fixes
* **Tabs:** actually export it lmao ([0e0e0d2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0e0e0d204adc8d888f05e98edb6c1a1a171d00bb))
# [3.5.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.4.0...v3.5.0) (2022-10-08)
### Features
* **Tabs:** initial tabs component, props, docs ([abbd3cd](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/abbd3cddae24039cbc9b7d955924431e8fbacf94))
# [3.4.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.3.5...v3.4.0) (2022-10-06)
### Features
* **hooks:** Added useParams hook ([#36](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/36)) ([e2920dd](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/e2920dd91e81d915a2319280d8473df71a4e4232))
## [3.3.5](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.3.4...v3.3.5) (2022-10-02)
### Bug Fixes
* **docs:** set categorizeByGroup to true ([0f205e8](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/0f205e891694e2cee211b0c2db74a6dda2432507))
## [3.3.4](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.3.3...v3.3.4) (2022-10-02)
### Bug Fixes
* **docs:** build each component as a seperate page ([fbd936d](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/fbd936dc1fe4c23c72f4ee27af95abc004382acd))
## [3.3.3](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.3.2...v3.3.3) (2022-10-02)
### Bug Fixes
* **modal:** make children optional ([#34](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/34)) ([99ad754](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/99ad7543a9966b8ff3f4ec01e6f05c94e5242c93))
## [3.3.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.3.1...v3.3.2) (2022-10-02)
### Bug Fixes
* **modal:** allow children ([40871af](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/40871af8539858f435c83123a56d4b31b63d627d))
## [3.3.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.3.0...v3.3.1) (2022-10-02)
### Bug Fixes
* **SidebarNavigation:** add more props ([#29](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/29)) ([ed0be5e](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/ed0be5e87e964ed57cc99b40ff55fe35a2f518b2))
# [3.3.0](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.2.2...v3.3.0) (2022-10-02)
### Features
* **Menu:** add nested menu groups + more props ([#30](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/30)) ([4233128](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/4233128c7ee8c6e5ab4ee74385c7b1b911d507a6))
## [3.2.2](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.2.1...v3.2.2) (2022-09-29)
### Bug Fixes
* **modal:** extend props for modals ([#32](https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues/32)) ([1fbe55a](https://github.com/SteamDeckHomebrew/decky-frontend-lib/commit/1fbe55aa544c9e84e2b3e2d6af9950db2fe7546c))
## [3.2.1](https://github.com/SteamDeckHomebrew/decky-frontend-lib/compare/v3.2.0...v3.2.1) (2022-09-24)

20
LICENSE
View File

@@ -1,4 +1,4 @@
GNU LESSER GENERAL PUBLIC LICENSE (DECKY-FRONTEND-LIB v1)
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
@@ -457,24 +457,6 @@ DAMAGES.
END OF TERMS AND CONDITIONS
EXCEPTION NOTICE
1. The exception is that you may use, copy, link, modify and distribute
under your own terms, binary object code versions of works based on the
Library.
2. If you copy code from files distributed under the terms of the GNU
General Public Licence or the GNU Library General Public Licence into a
copy of this library, as this licence permits, the exception does not apply
to the code that you add in this way. To avoid misleading anyone as to the
status of such modified files, you must delete this exception notice from
such code and/or adjust the licensing conditions notice accordingly.
3. If you write modifications of your own for this library, it is your
choice whether to permit this exception to apply to your modifications. If
you do not wish that, you must delete the exception notice from such code
and/or adjust the licensing conditions notice accordingly.
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest

View File

@@ -2,9 +2,9 @@
Library used to develop plugins used for use with [decky-loader](https://github.com/SteamDeckHomebrew/decky-loader).
## Decky Loader Discord [![Chat](https://img.shields.io/badge/chat-on%20discord-7289da.svg)](https://discord.gg/ZU74G2NJzk)
## Decky Loader Discord [![Chat](https://img.shields.io/discord/960281551428522045?color=%235865F2&label=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

View File

@@ -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'],
};

5
global.d.ts vendored Normal file
View File

@@ -0,0 +1,5 @@
declare global {
interface Window {
SP_REACT: typeof React;
}
}

5
globals.d.ts vendored
View File

@@ -1,5 +0,0 @@
declare global {
interface Window {
SP_REACT: typeof React;
}
}

22322
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "decky-frontend-lib",
"version": "3.2.1",
"description": "A library for building decky plugins",
"name": "@decky/ui",
"version": "4.10.6",
"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",
"prepack": "npm run build",
"docs": "typedoc --theme wiki-js --tsconfig ./tsconfig.json src/**/*",
"test": "echo 'No tests for now!'",
"prepare": "husky install",
"commit": "git-cz"
@@ -29,8 +29,8 @@
"steam",
"components"
],
"author": "Jonas Dellinger <jonas@dellinger.dev>",
"license": "LGPL-2.1-with-decky-exceptions",
"author": "SteamDeckHomebrew Team",
"license": "LGPL-2.1",
"bugs": {
"url": "https://github.com/SteamDeckHomebrew/decky-frontend-lib/issues"
},
@@ -41,23 +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": "18.3.3",
"@types/react-dom": "18.3.0",
"@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",
"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": "^24.2.7",
"shx": "^0.3.4",
"ts-jest": "^27.1.4",
"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": {
@@ -65,6 +72,12 @@
"react",
"react-dom"
]
},
"updateConfig": {
"ignoreDependencies": [
"react",
"react-dom"
]
}
},
"importSort": {
@@ -73,7 +86,8 @@
"parser": "typescript"
}
},
"dependencies": {
"minimist": "^1.2.6"
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"tag": "latest"
}
}

5952
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

40
src/class-mapper.ts Normal file
View 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;
}
}
}

8
src/components/Button.ts Normal file
View File

@@ -0,0 +1,8 @@
import { FC } from 'react';
import { DialogButton, DialogButtonProps } from './Dialog';
export interface ButtonProps extends DialogButtonProps {}
// Button isn't exported, so call DialogButton to grab it
export const Button = (DialogButton as any)?.render({}).type as FC<ButtonProps>;

View File

@@ -0,0 +1,16 @@
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 && buttonItemRegex.test(mod.render.toString())) ||
mod?.render?.toString?.().includes('childrenContainerWidth:"min"'),
) as FC<ButtonItemProps>;

View File

@@ -1,5 +1,6 @@
import { HTMLAttributes, ReactNode, RefAttributes, VFC } from "react";
import { findModuleChild } from "../webpack";
import { HTMLAttributes, ReactNode, RefAttributes, FC } from 'react';
import { Export, findModuleExport } from '../webpack';
export interface CarouselProps extends HTMLAttributes<HTMLDivElement> {
autoFocus?: boolean;
@@ -19,10 +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>
>;

View 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'),
);

95
src/components/Dialog.ts Normal file
View File

@@ -0,0 +1,95 @@
import { CSSProperties, FC, ReactNode, RefAttributes } from 'react';
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.
*/
noFocusRing?: boolean;
/**
* Disables the button - assigned `on*` methods will not be invoked if clicked.
*
* @note
* Depending on where it is, it might still get focus. In such case it can be
* partially disabled separately.
*
* @see focusable.
*/
disabled?: boolean;
/**
* Enables/disables the navigation based focus on button - you won't be able to navigate to
* it via the gamepad or keyboard.
*
* @note
* If set to `false`, it still can be clicked and **WILL** become focused until navigated away.
* Depending on the context of where the button is, even a disabled button can focused.
*/
focusable?: boolean;
onClick?(e: MouseEvent): void;
onPointerDown?(e: PointerEvent): void;
onPointerUp?(e: PointerEvent): void;
onPointerCancel?(e: PointerEvent): void;
onMouseDown?(e: MouseEvent): void;
onMouseUp?(e: MouseEvent): void;
onTouchStart?(e: TouchEvent): void;
onTouchEnd?(e: TouchEvent): void;
onTouchCancel?(e: TouchEvent): void;
onSubmit?(e: SubmitEvent): void;
}
const CommonDialogDivs = Object.values(CommonUIModule).filter(
(m: any) => typeof m === 'object' && m?.render?.toString().includes('createElement("div",{...') ||
m?.render?.toString().includes('createElement("div",Object.assign({},'),
);
const MappedDialogDivs = new Map(
Object.values(CommonDialogDivs).map((m: any) => {
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];
}
}),
);
// 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>;
export const DialogBodyText = MappedDialogDivs.get('DialogBodyText') as FC<DialogCommonProps>;
export const DialogBody = MappedDialogDivs.get('DialogBody') as FC<DialogCommonProps>;
export const DialogControlsSection = MappedDialogDivs.get('DialogControlsSection') as FC<DialogCommonProps>;
export const DialogControlsSectionHeader = MappedDialogDivs.get('DialogControlsSectionHeader') as FC<DialogCommonProps>;
export const DialogButtonPrimary = Object.values(CommonUIModule).find(
(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('"DialogButton","_DialogLayout","Secondary"')
) as FC<DialogButtonProps>;
// This is the "main" button. The Primary can act as a submit button,
// therefore secondary is chosen (also for backwards comp. reasons)
export const DialogButton = DialogButtonSecondary;

View 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>;

View File

@@ -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,11 @@ 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 {}
const dropdownItemRegex = createPropListRegex(["dropDownControlRef", "description"], false);
export const DropdownItem = Object.values(CommonUIModule).find((mod: any) =>
mod?.toString()?.includes('"dropDownControlRef","description"'),
) as VFC<DropdownItemProps>;
mod?.toString && dropdownItemRegex.test(mod.toString()),
) as FC<DropdownItemProps>;

View 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

View File

@@ -1,8 +1,10 @@
import { FC, HTMLAttributes, ReactNode, RefAttributes } from 'react';
import { findModuleChild } from '../webpack';
import { FC, ReactNode, RefAttributes } from 'react';
import { Export, findModuleExport } from '../webpack';
import { FooterLegendProps } from './FooterLegend';
export interface FieldProps extends HTMLAttributes<HTMLDivElement>, FooterLegendProps {
export interface FieldProps extends FooterLegendProps {
children?: ReactNode;
label?: ReactNode;
bottomSeparator?: 'standard' | 'thick' | 'none';
description?: ReactNode;
@@ -11,17 +13,17 @@ export interface FieldProps extends HTMLAttributes<HTMLDivElement>, FooterLegend
inlineWrap?: 'keep-inline' | 'shift-children-below'; // If label is too long it will move shildren below before starting to wrap label
childrenLayout?: 'below' | 'inline';
childrenContainerWidth?: 'min' | 'max' | 'fixed'; // Does not work with childrenLayout==='below'
spacingBetweenLabelAndChild?: 'none'; // This applies only when childrenLayout==='below'
spacingBetweenLabelAndChild?: 'none'; // This applies only when childrenLayout==='below'
padding?: 'none' | 'standard' | 'compact';
className?: string;
highlightOnFocus?: boolean;
indentLevel?: number;
verticalAlignment?: 'center' | 'none'; // Alligns inline label with children
focusable?: boolean; // Allows to get focus without any focusable children or on* callbacks
onActivate?: (e: CustomEvent | MouseEvent) => void;
onClick?: (e: CustomEvent | MouseEvent) => void;
}
export const Field = findModuleChild((m) => {
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>>;
export const Field = findModuleExport((e: Export) => e?.render?.toString().includes('"shift-children-below"')) as FC<
FieldProps & RefAttributes<HTMLDivElement>
>;

View 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>;

View 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) =>
e?.render?.toString && focusableRegex.test(e.render.toString())
) as FC<FocusableProps & RefAttributes<HTMLDivElement>>;

View 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;
}

View File

@@ -1,11 +1,13 @@
import { ReactNode } from 'react';
export interface ItemProps {
label?: string;
description?: string;
label?: ReactNode;
description?: ReactNode;
children?: ReactNode;
layout?: 'below' | 'inline';
icon?: ReactNode;
bottomSeparator?: 'standard' | 'thick' | 'none';
indentLevel?: number;
tooltip?: string;
highlightOnFocus?: boolean;
}

20
src/components/Marquee.ts Normal file
View 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
View 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)
*/

121
src/components/Modal.ts Executable file
View File

@@ -0,0 +1,121 @@
import { FC, ReactNode } from 'react';
import { findSP } from '../utils';
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;
bForcePopOut?: boolean;
bHideActionIcons?: boolean;
bHideMainWindowForPopouts?: boolean;
bNeverPopOut?: boolean;
fnOnClose?: () => void; // Seems to be the same as "closeModal" callback, but only when the modal is a popout. Will no longer work after "Update" invocation!
popupHeight?: number;
popupWidth?: number;
promiseRenderComplete?: Promise<void>; // Invoked once the render is complete. Currently, it seems to be used as image loading success/error callback...
strTitle?: string;
}
export interface ShowModalResult {
// This method will not invoke any of the variations of "closeModal" callbacks!
Close: () => void;
// This method will replace the modal element completely and will not update the callback chains,
// meaning that "closeModal" and etc. will not automatically close the modal anymore (also "fnOnClose"
// will not be even called upon close anymore)! You have to manually call the "Close" method when, for example,
// the "closeModal" is invoked in the newly updated modal:
// <ModalRoot closeModal={() => { console.log("ABOUT TO CLOSE"); showModalRes.Close(); }} />
Update: (modal: ReactNode) => void;
}
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,
parent?: EventTarget,
props: ShowModalProps = {
strTitle: 'Decky Dialog',
bHideMainWindowForPopouts: false,
},
): ShowModalResult => {
return showModalRaw(modal, parent || findSP() || window, props.strTitle, props, undefined, {
bHideActions: props.bHideActionIcons,
});
};
export interface ModalRootProps {
children?: ReactNode;
onCancel?(): void;
closeModal?(): void;
onOK?(): void;
onEscKeypress?(): void;
className?: string;
modalClassName?: string;
bAllowFullSize?: boolean;
bDestructiveWarning?: boolean;
bDisableBackgroundDismiss?: boolean;
bHideCloseIcon?: boolean;
bOKDisabled?: boolean;
bCancelDisabled?: boolean;
}
export interface ConfirmModalProps extends ModalRootProps {
onMiddleButton?(): void; // setting this prop will enable the middle button
strTitle?: ReactNode;
strDescription?: ReactNode;
strOKButtonText?: ReactNode;
strCancelButtonText?: ReactNode;
strMiddleButtonText?: ReactNode;
bAlertDialog?: boolean; // This will open a modal with only OK button enabled
bMiddleDisabled?: boolean;
}
export const ConfirmModal = findModuleExport(
(e: Export) => e?.toString()?.includes('bUpdateDisabled') && e?.toString()?.includes('closeModal') && e?.toString()?.includes('onGamepadCancel'),
) as FC<ConfirmModalProps>;
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]?.m_mapModalManager && Object.values(m)?.find((x: any) => x?.type)) {
return true;
}
}
return false;
}) || {},
)?.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
View 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>;

View File

@@ -0,0 +1,37 @@
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) =>
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>;

15
src/components/Scroll.ts Normal file
View File

@@ -0,0 +1,15 @@
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) =>
e?.render?.toString().includes('.FocusVisibleChild()),[])'),
);

View 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>;

View File

@@ -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
View File

@@ -0,0 +1,8 @@
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>>;

12
src/components/SteamSpinner.ts Executable file
View 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.tsx Normal file
View 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>;

View File

@@ -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>;

View File

@@ -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>;

View File

@@ -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>;

View File

@@ -1,21 +1,26 @@
export * from './Button';
export * from './ButtonItem';
export * from './Carousel';
export * from './ControlsList';
export * from './Dialog';
export * from './DialogCheckbox';
export * from './Dropdown';
export * from './ErrorBoundary';
export * from './Field';
export * from './Focusable';
export * from './FocusRing';
export * from './FooterLegend';
export * from './Marquee';
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 './Scroll';

View File

@@ -1,5 +1,7 @@
import { gamepadSliderClasses, ConfirmModal, SliderField } from "../deck-components";
import { useState, FC, CSSProperties } from "react";
import { CSSProperties, FC, useState } from 'react';
import { ConfirmModal, SliderField } from '../components';
import { gamepadSliderClasses } from '../utils/static-classes';
interface ColorPickerModalProps {
closeModal: () => void;
@@ -14,7 +16,7 @@ interface ColorPickerModalProps {
export const ColorPickerModal: FC<ColorPickerModalProps> = ({
closeModal,
onConfirm = () => {},
title = "Color Picker",
title = 'Color Picker',
defaultH = 0,
defaultS = 100,
defaultL = 50,
@@ -26,22 +28,22 @@ export const ColorPickerModal: FC<ColorPickerModalProps> = ({
const [A, setA] = useState<number>(defaultA);
const colorPickerCSSVars = {
"--decky-color-picker-hvalue": `${H}`,
"--decky-color-picker-svalue": `${S}%`,
"--decky-color-picker-lvalue": `${L}%`,
"--decky-color-picker-avalue": `${A}`,
'--decky-color-picker-hvalue': `${H}`,
'--decky-color-picker-svalue': `${S}%`,
'--decky-color-picker-lvalue': `${L}%`,
'--decky-color-picker-avalue': `${A}`,
} as CSSProperties;
return (
<ConfirmModal
bAllowFullSize
onCancel={closeModal}
onOK={() => {
onConfirm(`hsla(${H}, ${S}%, ${L}%, ${A})`);
closeModal();
}}
>
<style>
<ConfirmModal
bAllowFullSize
onCancel={closeModal}
onOK={() => {
onConfirm(`hsla(${H}, ${S}%, ${L}%, ${A})`);
closeModal();
}}
>
<style>
{`
/* This removes the cyan track color that is behind the slider head */
.ColorPicker_Container .${gamepadSliderClasses.SliderTrack} {
@@ -87,77 +89,44 @@ export const ColorPickerModal: FC<ColorPickerModalProps> = ({
}
`}
</style>
<div
className="ColorPicker_ColorDisplayContainer"
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: '1em',
// theres a large header by default on the modal, so this just pushes it up into that unused space
marginTop: '-2.5em',
}}
>
<div>
<span style={{ fontSize: '1.5em' }}>
<b>{title}</b>
</span>
</div>
<div
className="ColorPicker_ColorDisplayContainer"
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "1em",
// theres a large header by default on the modal, so this just pushes it up into that unused space
marginTop: "-2.5em",
backgroundColor: `hsla(${H}, ${S}%, ${L}%, ${A})`,
width: '40px',
height: '40px',
}}
>
<div>
<span style={{ fontSize: "1.5em" }}>
<b>{title}</b>
</span>
</div>
<div
style={{
backgroundColor: `hsla(${H}, ${S}%, ${L}%, ${A})`,
width: "40px",
height: "40px",
}}
></div>
></div>
</div>
<div className="ColorPicker_Container" style={colorPickerCSSVars}>
<div className="ColorPicker_HSlider">
<SliderField showValue editableValue label="Hue" value={H} min={0} max={360} onChange={setH} />
</div>
<div className="ColorPicker_Container" style={colorPickerCSSVars}>
<div className="ColorPicker_HSlider">
<SliderField
showValue
editableValue
label="Hue"
value={H}
min={0}
max={360}
onChange={setH}
/>
</div>
<div className="ColorPicker_SSlider">
<SliderField
showValue
editableValue
label="Saturation"
value={S}
min={0}
max={100}
onChange={setS}
/>
</div>
<div className="ColorPicker_LSlider">
<SliderField
showValue
editableValue
label="Lightness"
value={L}
min={0}
max={100}
onChange={setL}
/>
</div>
<div className="ColorPicker_ASlider">
<SliderField
showValue
editableValue
label="Alpha"
value={A}
step={0.1}
min={0}
max={1}
onChange={setA}
/>
</div>
<div className="ColorPicker_SSlider">
<SliderField showValue editableValue label="Saturation" value={S} min={0} max={100} onChange={setS} />
</div>
</ConfirmModal>
<div className="ColorPicker_LSlider">
<SliderField showValue editableValue label="Lightness" value={L} min={0} max={100} onChange={setL} />
</div>
<div className="ColorPicker_ASlider">
<SliderField showValue editableValue label="Alpha" value={A} step={0.1} min={0} max={1} onChange={setA} />
</div>
</div>
</ConfirmModal>
);
};

View 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 | 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>
);
}

View File

@@ -1,7 +1,8 @@
import { Spinner } from '../deck-components';
import { useEffect } from 'react';
import { FC, ImgHTMLAttributes, useState } from 'react';
import { Spinner } from '../components';
interface SuspensefulImageProps extends ImgHTMLAttributes<HTMLImageElement> {
suspenseWidth?: string | number;
suspenseHeight?: string | number;
@@ -12,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', () => {
@@ -20,7 +23,7 @@ export const SuspensefulImage: FC<SuspensefulImageProps> = (props) => {
img.addEventListener('error', () => {
setError(true);
});
}, []);
}, [props.src]);
return loading ? (
<div
@@ -38,4 +41,4 @@ export const SuspensefulImage: FC<SuspensefulImageProps> = (props) => {
) : (
<img {...props} />
);
};
};

View File

@@ -1,2 +1,3 @@
export * from './SuspensefulImage';
export * from './ColorPickerModal';
export * from './ReorderableList';

View File

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

View 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;
}

View File

@@ -1,22 +0,0 @@
import { CSSProperties, FC, RefAttributes } from 'react';
import { CommonUIModule } from '../webpack';
import { FooterLegendProps } from './FooterLegend';
export interface DialogButtonProps extends RefAttributes<HTMLDivElement>, FooterLegendProps {
label?: string;
style?: CSSProperties;
className?: string;
noFocusRing?: boolean;
description?: string;
layout?: 'below';
onClick?(e: MouseEvent): void;
disabled?: boolean;
bottomSeparator?: boolean;
}
export const DialogButton = Object.values(CommonUIModule).find(
(mod: any) =>
mod?.render?.toString()?.includes('Object.assign({type:"button"') &&
mod?.render?.toString()?.includes('DialogButton'),
) as FC<DialogButtonProps>;

View File

@@ -1,13 +0,0 @@
import { FC } from 'react';
import { CommonUIModule } from '../webpack';
import { ItemProps } from './Item';
export interface ButtonItemProps extends ItemProps {
onClick?(e: MouseEvent): void;
disabled?: boolean;
}
export const ButtonItem = Object.values(CommonUIModule).find((mod: any) =>
mod?.render?.toString()?.includes('"highlightOnFocus","childrenContainerWidth"') || mod?.render?.toString()?.includes('childrenContainerWidth:"min"'),
) as FC<ButtonItemProps>;

View File

@@ -1,18 +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>;

View File

@@ -1,20 +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;
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>>;

View File

@@ -1,66 +0,0 @@
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 {
FIRST,
LAST,
MAINTAIN_X,
MAINTAIN_Y,
PREFERRED_CHILD
}
export interface GamepadEventDetail {
button: number;
is_repeat?: boolean;
source: number;
}
export type GamepadEvent = CustomEvent<GamepadEventDetail>
export interface FooterLegendProps {
actionDescriptionMap?: unknown;
onOKActionDescription?: string;
onCancelActionDescription?: string;
onSecondaryActionDescription?: string;
onOptionsActionDescription?: string;
onMenuActionDescription?: string;
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;
}

View File

@@ -1,49 +0,0 @@
import { FC, ReactNode } from 'react';
import { findModuleChild } from '../webpack';
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 {
label: string;
onCancel?(): void;
cancelText?: string;
}
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 MenuItemProps {
onSelected?(): void;
}
export const MenuItem: FC<MenuItemProps> = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (m[prop]?.prototype?.OnOKButton && m[prop]?.prototype?.OnMouseEnter) {
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)
*/

View File

@@ -1,73 +0,0 @@
import { FC, ReactNode } from 'react';
import { findModuleChild } 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
bForcePopOut?: boolean;
bHideActionIcons?: boolean;
bHideMainWindowForPopouts?: boolean;
bNeverPopOut?: boolean;
fnOnClose?: () => void; // Seems to be the same as "closeModal" callback, but only when the modal is a popout. Will no longer work after "Update" invocation!
popupHeight?: number;
popupWidth?: number;
promiseRenderComplete?: Promise<void>; // Invoked once the render is complete. Currently, it seems to be used as image loading success/error callback...
strTitle?: string;
}
export interface ShowModalResult {
// This method will not invoke any of the variations of "closeModal" callbacks!
Close: () => void;
// This method will replace the modal element completely and will not update the callback chains,
// meaning that "closeModal" and etc. will not automatically close the modal anymore (also "fnOnClose"
// will not be even called upon close anymore)! You have to manually call the "Close" method when, for example,
// the "closeModal" is invoked in the newly updated modal:
// <ModalRoot closeModal={() => { console.log("ABOUT TO CLOSE"); showModalRes.Close(); }} />
Update: (modal: ReactNode) => void;
}
export const showModal: (modal: ReactNode, parent?: EventTarget, props?: ShowModalProps) => Promise<ShowModalResult> = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (typeof m[prop] === 'function' && m[prop].toString().includes('bHideMainWindowForPopouts:!0')) {
return m[prop];
}
}
});
export interface ModalRootProps {
onCancel?(): void;
closeModal?(): void;
onOK?(): void;
onEscKeypress?(): void;
className?: string;
modalClassName?: string;
bAllowFullSize?: boolean;
bDestructiveWarning?: boolean;
bDisableBackgroundDismiss?: boolean;
bHideCloseIcon?: boolean;
bOKDisabled?: boolean;
}
export interface ConfirmModalProps extends ModalRootProps {
onMiddleButton?(): void;
}
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 ModalRoot = findModuleChild((m) => {
if (typeof m !== 'object') return undefined;
for (let prop in m) {
if (m[prop]?.prototype?.OK && m[prop]?.prototype?.Cancel && m[prop]?.prototype?.render) {
return m[prop];
}
}
}) as FC<ModalRootProps>;

View File

@@ -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;

View File

@@ -1,44 +0,0 @@
import { VFC, ReactNode } 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>;

View File

@@ -1,98 +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 Router {
CloseSideMenus(): void;
OpenQuickAccessMenu(quickAccessTab?: QuickAccessTab): void;
GetQuickAccessTab(): QuickAccessTab;
Navigate(path: string): void;
NavigateBackOrOpenMenu(): void;
NavigateToAppProperties(): void
NavigateToBugForum(): void
NavigateToExternalWeb(url: string): void;
NavigateToHelp(): void
NavigateToInvites(): void
NavigateToRunningApp(replace?: boolean): void;
NavigateToStorage(): void
NavigateToStore(): void
NavigateToStoreApp(appId: number | string): void
NavigateToStoreFreeToPlay(): void
NavigateToStoreManual(): void
NavigateToStoreNewReleases(): void
NavigateToStoreOnSale(): void
ToggleSideMenu(sideMenu: SideMenu): void;
CloseSideMenus(): void;
OpenSideMenu(sideMenu: SideMenu): 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;

View File

@@ -1,25 +0,0 @@
import { ReactNode, VFC } from 'react';
import { Module, findModuleChild } from '../webpack';
export interface SidebarNavigationPages {
title: string;
route: string;
content: ReactNode;
}
export interface SidebarNavigationProps {
title?: string;
pages: SidebarNavigationPages[];
showTitle?: boolean;
disableRouteReporting?: boolean;
}
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>;

View File

@@ -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>>;

View File

@@ -1,9 +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>>;

View File

@@ -1,364 +0,0 @@
import { findModule } from '../webpack';
type StaticClasses = 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 ScrollClasses = 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
>;
export const staticClasses: StaticClasses = findModule((mod) => typeof mod === 'object' && mod.TransitionMenuDelay);
export const scrollClasses: ScrollClasses = findModule((mod) => typeof mod === 'object' && mod.ScrollPanel && mod.ScrollY);
export const gamepadDialogClasses: GamepadDialogClasses = findModule((mod) => typeof mod === 'object' && mod.WithFirstRow);
export const quickAccessControlsClasses: QuickAccessControlsClasses = findModule((mod) => typeof mod === 'object' && mod.PanelSectionRow);
export const updaterFieldClasses: UpdaterFieldClasses = findModule((mod) => typeof mod === 'object' && mod.PatchNotes && mod.PostedTime);
export const playSectionClasses: PlaySectionClasses = findModule((mod) => typeof mod === 'object' && mod.MenuButton && mod.MenuActive);
export const gamepadSliderClasses: GamepadSliderClasses = findModule((mod) => typeof mod === 'object' && mod.SliderTrack && mod.SliderHasNotches);

1
src/deck-hooks/index.ts Normal file
View File

@@ -0,0 +1 @@
export * from './useParams';

View File

@@ -0,0 +1,15 @@
import { ReactRouter } from '../webpack';
/**
* Get the current params from ReactRouter
*
* @returns an object with the current ReactRouter params
*
* @example
* import { useParams } from "decky-frontend-lib";
*
* const { appid } = useParams<{ appid: string }>()
*/
export const useParams = Object.values(ReactRouter).find((val) => /return (\w)\?\1\.params:{}/.test(`${val}`)) as <
T,
>() => T;

View 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
View File

@@ -0,0 +1,2 @@
export * from './SteamClient';
export * from './stores';

File diff suppressed because it is too large Load Diff

View 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,
}

View 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;
}

View 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,
}

View 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,
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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[];
}

View 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>;
}

View 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;
}

View 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;
}

View 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[];
}

View 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";
}

View File

@@ -0,0 +1,762 @@
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: (msgs: ControllerInputMessage[]) => 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,
}
// 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 ControllerInputMessage {
nA: number;
bS: boolean;
nC: number;
}
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;
}

View 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;
}

View 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,
}

View 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;
}

View 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,
}

View 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;
}

View 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,
}

View 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,
}

View 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,
}

View 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,
}

View 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,
}

View 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;
}

View 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,
}

View 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;
}

View 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;
}

View File

@@ -0,0 +1,3 @@
export interface SteamChina {
GetCustomLauncherAppID(): Promise<number>;
}

View 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>;
}

Some files were not shown because too many files have changed in this diff Show More