From 6e3c05072cb507e2a376b7019836bea7bf663cb0 Mon Sep 17 00:00:00 2001
From: AAGaming <aa@mail.catvibers.me>
Date: Sat, 15 Oct 2022 23:46:42 -0400
Subject: Developer menu (#211)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* add settings utils to use settings outside of components

* initial implementation of developer menu

* ✨ Add support for addScriptToEvaluateOnNewDocument

* React DevTools support

* increase chance of RDT successfully injecting

* Rewrite toaster hook to not re-create the window

* remove friends focus workaround because it's fixed

* Expose various DFL utilities as DFL in dev mode

* try to fix text field focuss

* move focusable to outside field

* add onTouchEnd and onClick to focusable

* Update pnpm-lock.yaml

Co-authored-by: FinalDoom <7464170-FinalDoom@users.noreply.gitlab.com>
Co-authored-by: TrainDoctor <traindoctor@protonmail.com>
---
 frontend/src/developer.tsx | 88 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100644 frontend/src/developer.tsx

(limited to 'frontend/src/developer.tsx')

diff --git a/frontend/src/developer.tsx b/frontend/src/developer.tsx
new file mode 100644
index 00000000..b1fe74d6
--- /dev/null
+++ b/frontend/src/developer.tsx
@@ -0,0 +1,88 @@
+import {
+  ReactRouter,
+  Router,
+  findModule,
+  findModuleChild,
+  gamepadDialogClasses,
+  gamepadSliderClasses,
+  playSectionClasses,
+  quickAccessControlsClasses,
+  quickAccessMenuClasses,
+  scrollClasses,
+  scrollPanelClasses,
+  sleep,
+  staticClasses,
+  updaterFieldClasses,
+} from 'decky-frontend-lib';
+import { FaReact } from 'react-icons/fa';
+
+import Logger from './logger';
+import { getSetting } from './utils/settings';
+
+const logger = new Logger('DeveloperMode');
+
+let removeSettingsObserver: () => void = () => {};
+
+export function setShowValveInternal(show: boolean) {
+  const settingsMod = findModuleChild((m) => {
+    if (typeof m !== 'object') return undefined;
+    for (let prop in m) {
+      if (typeof m[prop]?.settings?.bIsValveEmail !== 'undefined') return m[prop];
+    }
+  });
+
+  if (show) {
+    removeSettingsObserver = settingsMod[
+      Object.getOwnPropertySymbols(settingsMod).find((x) => x.toString() == 'Symbol(mobx administration)') as any
+    ].observe((e: any) => {
+      e.newValue.bIsValveEmail = true;
+    });
+    settingsMod.m_Settings.bIsValveEmail = true;
+    logger.log('Enabled Valve Internal menu');
+  } else {
+    removeSettingsObserver();
+    settingsMod.m_Settings.bIsValveEmail = false;
+    logger.log('Disabled Valve Internal menu');
+  }
+}
+
+export async function setShouldConnectToReactDevTools(enable: boolean) {
+  window.DeckyPluginLoader.toaster.toast({
+    title: (enable ? 'Enabling' : 'Disabling') + ' React DevTools',
+    body: 'Reloading in 5 seconds',
+    icon: <FaReact />,
+  });
+  await sleep(5000);
+  return enable
+    ? window.DeckyPluginLoader.callServerMethod('enable_rdt')
+    : window.DeckyPluginLoader.callServerMethod('disable_rdt');
+}
+
+export async function startup() {
+  const isValveInternalEnabled = await getSetting('developer.valve_internal', false);
+  const isRDTEnabled = await getSetting('developer.rdt.enabled', false);
+
+  if (isValveInternalEnabled) setShowValveInternal(isValveInternalEnabled);
+
+  if ((isRDTEnabled && !window.deckyHasConnectedRDT) || (!isRDTEnabled && window.deckyHasConnectedRDT))
+    setShouldConnectToReactDevTools(isRDTEnabled);
+
+  logger.log('Exposing decky-frontend-lib APIs as DFL');
+  window.DFL = {
+    findModuleChild,
+    findModule,
+    Router,
+    ReactRouter,
+    classes: {
+      scrollClasses,
+      staticClasses,
+      playSectionClasses,
+      scrollPanelClasses,
+      updaterFieldClasses,
+      gamepadDialogClasses,
+      gamepadSliderClasses,
+      quickAccessMenuClasses,
+      quickAccessControlsClasses,
+    },
+  };
+}
-- 
cgit v1.2.3

