summaryrefslogtreecommitdiff
path: root/frontend/src/developer.tsx
blob: 56d28fbfbd926dc4eb332d7c3474369924c572f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import {
  Navigation,
  ReactRouter,
  Router,
  fakeRenderComponent,
  findInReactTree,
  findInTree,
  findModule,
  findModuleChild,
  gamepadDialogClasses,
  gamepadSliderClasses,
  playSectionClasses,
  quickAccessControlsClasses,
  quickAccessMenuClasses,
  scrollClasses,
  scrollPanelClasses,
  sleep,
  staticClasses,
  updaterFieldClasses,
} from 'decky-frontend-lib';
import { useTranslation } from 'react-i18next';
import { FaReact } from 'react-icons/fa';

import Logger from './logger';
import { getSetting } from './utils/settings';

const logger = new Logger('DeveloperMode');

let removeSettingsObserver: () => void = () => {};

export async function setShowValveInternal(show: boolean) {
  let settingsMod: any;
  while (!settingsMod) {
    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 (!settingsMod) {
      logger.debug('[ValveInternal] waiting for settingsMod');
      await sleep(1000);
    }
  }

  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) {
  const { t } = useTranslation();

  window.DeckyPluginLoader.toaster.toast({
    title: (enable ? t('Developer.enabling') : t('Developer.disabling')) + ' React DevTools',
    body: t('Developer.5secreload'),
    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,
    Navigation,
    Router,
    ReactRouter,
    ReactUtils: {
      fakeRenderComponent,
      findInReactTree,
      findInTree,
    },
    classes: {
      scrollClasses,
      staticClasses,
      playSectionClasses,
      scrollPanelClasses,
      updaterFieldClasses,
      gamepadDialogClasses,
      gamepadSliderClasses,
      quickAccessMenuClasses,
      quickAccessControlsClasses,
    },
  };
}