|  | 
|  | 1 | +// Patch for the startup theme. Customizes the `ThemeService.get().defaultTheme();` to dispatch the default IDE2 theme based on the OS' theme. | 
|  | 2 | +// For all subsequent starts of the IDE the theme applied will be the last one set by the user. | 
|  | 3 | + | 
|  | 4 | +// With the current version of Theia adopted (1.25) it is not possible to extend the `ThemeService`, it will be possible starting from Theia 1.27. | 
|  | 5 | +// Once the version of Theia is updated, this patch will be removed and this functionality will be implemented via dependency injection. | 
|  | 6 | +// Ideally, we should open a PR in Theia and add support for `light` and `dark` default themes in the app config. | 
|  | 7 | + | 
|  | 8 | +const { | 
|  | 9 | +  ThemeService, | 
|  | 10 | +  ThemeServiceSymbol, | 
|  | 11 | +  BuiltinThemeProvider, | 
|  | 12 | +} = require('@theia/core/lib/browser/theming'); | 
|  | 13 | +const { | 
|  | 14 | +  ApplicationProps, | 
|  | 15 | +} = require('@theia/application-package/lib/application-props'); | 
|  | 16 | + | 
|  | 17 | +// It is a mighty hack to support theme updates in the bundled IDE2. | 
|  | 18 | +// If the custom theme registration happens before the restoration of the existing monaco themes, then any custom theme changes will be ignored. | 
|  | 19 | +// This patch introduces a static deferred promise in the monaco-theming service that will be resolved when the restoration is ready. | 
|  | 20 | +// IDE2 cannot require the monaco theme service on the outer module level, as it requires the application config provider to be initialized, | 
|  | 21 | +// but the initialization happens only in the generated `index.js`. | 
|  | 22 | +// This patch customizes the monaco theme service behavior before loading the DI containers via the preload. | 
|  | 23 | +// The preload is called only once before the app loads. The Theia extensions are not loaded at that point, but the app config provider is ready. | 
|  | 24 | +const preloader = require('@theia/core/lib/browser/preloader'); | 
|  | 25 | +const originalPreload = preloader.preload; | 
|  | 26 | +preloader.preload = async function () { | 
|  | 27 | +  const { MonacoThemingService } = require('@theia/monaco/lib/browser/monaco-theming-service'); | 
|  | 28 | +  const { MonacoThemeServiceIsReady } = require('arduino-ide-extension/lib/browser/utils/window'); | 
|  | 29 | +  const { Deferred } = require('@theia/core/lib/common/promise-util'); | 
|  | 30 | +  const ready = new Deferred(); | 
|  | 31 | +  if (!window[MonacoThemeServiceIsReady]) { | 
|  | 32 | +    window[MonacoThemeServiceIsReady] = ready; | 
|  | 33 | +    console.log('Registered a custom monaco-theme service initialization signal on the window object.'); | 
|  | 34 | +  } | 
|  | 35 | +  // Here, it is safe to patch the theme service, app config provider is ready. | 
|  | 36 | +  MonacoThemingService.init = async function () { | 
|  | 37 | +    this.updateBodyUiTheme(); | 
|  | 38 | +    ThemeService.get().onDidColorThemeChange(() => this.updateBodyUiTheme()); | 
|  | 39 | +    await this.restore(); | 
|  | 40 | +    ready.resolve(); | 
|  | 41 | +  }.bind(MonacoThemingService); | 
|  | 42 | +  return originalPreload(); | 
|  | 43 | +}.bind(preloader); | 
|  | 44 | + | 
|  | 45 | +const lightTheme = 'arduino-theme'; | 
|  | 46 | +const darkTheme = 'arduino-theme-dark'; | 
|  | 47 | +const defaultTheme = | 
|  | 48 | +  window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches | 
|  | 49 | +    ? darkTheme | 
|  | 50 | +    : lightTheme; | 
|  | 51 | + | 
|  | 52 | +const arduinoDarkTheme = { | 
|  | 53 | +  id: 'arduino-theme-dark', | 
|  | 54 | +  type: 'dark', | 
|  | 55 | +  label: 'Dark (Arduino)', | 
|  | 56 | +  editorTheme: 'arduino-theme-dark', | 
|  | 57 | +  activate() { }, | 
|  | 58 | +  deactivate() { } | 
|  | 59 | +}; | 
|  | 60 | + | 
|  | 61 | +const arduinoLightTheme = { | 
|  | 62 | +  id: 'arduino-theme', | 
|  | 63 | +  type: 'light', | 
|  | 64 | +  label: 'Light (Arduino)', | 
|  | 65 | +  editorTheme: 'arduino-theme', | 
|  | 66 | +  activate() { }, | 
|  | 67 | +  deactivate() { } | 
|  | 68 | +}; | 
|  | 69 | + | 
|  | 70 | +if (!window[ThemeServiceSymbol]) { | 
|  | 71 | +  const themeService = new ThemeService(); | 
|  | 72 | +  Object.defineProperty(themeService, 'defaultTheme', { | 
|  | 73 | +    get: function () { | 
|  | 74 | +      return ( | 
|  | 75 | +        this.themes[defaultTheme] || | 
|  | 76 | +        this.themes[ApplicationProps.DEFAULT.frontend.config.defaultTheme] | 
|  | 77 | +      ); | 
|  | 78 | +    }, | 
|  | 79 | +  }); | 
|  | 80 | +  themeService.register(...BuiltinThemeProvider.themes, arduinoDarkTheme, arduinoLightTheme); | 
|  | 81 | +  themeService.startupTheme(); | 
|  | 82 | +  themeService.setCurrentTheme(defaultTheme); | 
|  | 83 | +  window[ThemeServiceSymbol] = themeService; | 
|  | 84 | +} | 
|  | 85 | + | 
|  | 86 | +// Require the original, generated `index.js` for `webpack` as the next entry for the `bundle.js`. | 
|  | 87 | +require('../../src-gen/frontend/index'); | 
0 commit comments