summaryrefslogtreecommitdiff
path: root/frontend/src/hooks/vr-dashboard-bar.tsx
diff options
context:
space:
mode:
authorAAGaming <aagaming@riseup.net>2026-10-26 23:50:59 -0400
committerAAGaming <aagaming@riseup.net>2026-10-26 23:50:59 -0400
commite82a55e9582fbd6d84f3f4510b04480c35e41fe4 (patch)
tree1fe05c2296bbedbf301137a67a28ef542804fd69 /frontend/src/hooks/vr-dashboard-bar.tsx
parent6301508037b30489c42ee9ea8acee97cdea76297 (diff)
downloaddecky-loader-e82a55e9582fbd6d84f3f4510b04480c35e41fe4.tar.gz
decky-loader-e82a55e9582fbd6d84f3f4510b04480c35e41fe4.zip
feat: initial VERY VERY incomplete steam frame support
Diffstat (limited to 'frontend/src/hooks/vr-dashboard-bar.tsx')
-rw-r--r--frontend/src/hooks/vr-dashboard-bar.tsx105
1 files changed, 105 insertions, 0 deletions
diff --git a/frontend/src/hooks/vr-dashboard-bar.tsx b/frontend/src/hooks/vr-dashboard-bar.tsx
new file mode 100644
index 00000000..905aee03
--- /dev/null
+++ b/frontend/src/hooks/vr-dashboard-bar.tsx
@@ -0,0 +1,105 @@
+// Hook the SteamVR Hotbar
+import { ErrorBoundary, Patch, afterPatch, findInReactTree, findModuleExport, getReactRoot } from '@decky/ui';
+import { ReactNode, createElement } from 'react';
+
+import Logger from '../logger';
+
+declare global {
+ interface Window {
+ __VR_DASHBAORD_BAR_HOOK_INSTANCE: any;
+ }
+}
+
+// TODO kinda dumb
+enum VRDashboardBarButtonID {
+ Decky = 999,
+}
+
+export interface VRDashboardBarButton {
+ id: VRDashboardBarButtonID | number;
+ active?: boolean;
+ children?: ReactNode;
+ tooltip?: ReactNode;
+ popupContents?: ReactNode;
+ onActivate?: () => void;
+ refBarPopupHandle?: any; // TODO idk
+ onPopupVisibilityChanged?: (visible: boolean) => void;
+}
+
+class VRDashboardBarHook extends Logger {
+ rightSideButtons: VRDashboardBarButton[] = [];
+ private rendererdRightSideButtons: ReactNode[] = [];
+ private barPatch?: Patch;
+ private barButton?: any;
+
+ constructor() {
+ super('VRDashboardBarHook');
+
+ this.log('Initialized');
+ window.__VR_DASHBAORD_BAR_HOOK_INSTANCE?.deinit?.();
+ window.__VR_DASHBAORD_BAR_HOOK_INSTANCE = this;
+ }
+
+ init() {
+ this.barButton = findModuleExport((e) => e?.render?.toString()?.includes('VRDashboardBarSmallButtonActive'));
+ const barComponent = findModuleExport((e) => e?.type?.toString()?.includes('vrLocation=="dashboard-bar"'));
+
+ this.barPatch = afterPatch(barComponent, 'type', (_, ret) => {
+ const nodes = findInReactTree(ret, (x) => x?.length > 6);
+ if (!window?.securitystore?.IsLockScreenActive?.()) nodes.splice(4, 0, this.rendererdRightSideButtons);
+ return ret;
+ });
+
+ // Patch already rendered bar
+ const root = getReactRoot(document.getElementById('root') as any);
+ const barNode =
+ root &&
+ findInReactTree(
+ root,
+ (n: any) => n.elementType == barComponent || (barComponent != null && n.elementType == barComponent),
+ ); // need elementType, because case where type is actually mobx wrapper
+ if (barNode) {
+ // Only affects this fiber node so we don't need to unpatch here
+ barNode.type = barNode.elementType.type;
+ if (barNode?.alternate) {
+ barNode.alternate.type = barNode.type;
+ }
+ }
+ }
+
+ deinit() {
+ this.barPatch?.unpatch();
+ }
+
+ addRightSideButton(button: VRDashboardBarButton) {
+ this.debug('Adding RSB', button.id, 'to render array');
+ this.rightSideButtons.push(button);
+ this.renderRightSideButtons();
+ }
+
+ removeRightSideButton(id: number) {
+ this.debug('Removing RSB', id);
+ this.rightSideButtons = this.rightSideButtons.filter((button) => button.id !== id);
+ this.renderRightSideButtons();
+ }
+
+ renderRightSideButtons() {
+ const arr = [];
+ for (const button of this.rightSideButtons) {
+ arr.push(
+ createElement(this.barButton, {
+ active: button.active,
+ children: <ErrorBoundary>{button.children}</ErrorBoundary>,
+ tooltip: button.tooltip,
+ popupContents: <ErrorBoundary>{button.popupContents}</ErrorBoundary>,
+ onActivate: button.onActivate,
+ refBarPopupHandle: button.refBarPopupHandle,
+ onPopupVisibilityChanged: button.onPopupVisibilityChanged,
+ }),
+ );
+ }
+ this.rendererdRightSideButtons = arr;
+ }
+}
+
+export default VRDashboardBarHook;