mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-04-19 12:57:17 +00:00
Replaced the splash screen with a preload.
Added a bare minimum example. Closes #193 Closes #324 Closes #327 Closes #717 Closes #851 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
parent
aebec0f942
commit
92bc5ecf7b
1
.vscode/launch.json
vendored
1
.vscode/launch.json
vendored
@ -20,7 +20,6 @@
|
||||
"--no-app-auto-install",
|
||||
"--plugins=local-dir:../plugins",
|
||||
"--hosted-plugin-inspect=9339",
|
||||
"--nosplash",
|
||||
"--content-trace",
|
||||
"--open-devtools"
|
||||
],
|
||||
|
@ -6,10 +6,6 @@ import {
|
||||
ElectronMainWindowServiceExt,
|
||||
electronMainWindowServiceExtPath,
|
||||
} from '../../../electron-common/electron-main-window-service-ext';
|
||||
import {
|
||||
SplashService,
|
||||
splashServicePath,
|
||||
} from '../../../electron-common/splash-service';
|
||||
import { ElectronWindowService } from './electron-window-service';
|
||||
|
||||
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
@ -24,9 +20,4 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
)
|
||||
)
|
||||
.inSingletonScope();
|
||||
bind(SplashService)
|
||||
.toDynamicValue(({ container }) =>
|
||||
ElectronIpcConnectionProvider.createProxy(container, splashServicePath)
|
||||
)
|
||||
.inSingletonScope();
|
||||
});
|
||||
|
@ -1,17 +1,15 @@
|
||||
import * as remote from '@theia/core/electron-shared/@electron/remote';
|
||||
import {
|
||||
ConnectionStatus,
|
||||
ConnectionStatusService,
|
||||
} from '@theia/core/lib/browser/connection-status-service';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { ElectronWindowService as TheiaElectronWindowService } from '@theia/core/lib/electron-browser/window/electron-window-service';
|
||||
import {
|
||||
inject,
|
||||
injectable,
|
||||
postConstruct,
|
||||
} from '@theia/core/shared/inversify';
|
||||
import * as remote from '@theia/core/electron-shared/@electron/remote';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import {
|
||||
ConnectionStatus,
|
||||
ConnectionStatusService,
|
||||
} from '@theia/core/lib/browser/connection-status-service';
|
||||
import { ElectronWindowService as TheiaElectronWindowService } from '@theia/core/lib/electron-browser/window/electron-window-service';
|
||||
import { SplashService } from '../../../electron-common/splash-service';
|
||||
import { nls } from '@theia/core/lib/common';
|
||||
import { WindowServiceExt } from '../../../browser/theia/core/window-service-ext';
|
||||
import { ElectronMainWindowServiceExt } from '../../../electron-common/electron-main-window-service-ext';
|
||||
|
||||
@ -23,20 +21,14 @@ export class ElectronWindowService
|
||||
@inject(ConnectionStatusService)
|
||||
private readonly connectionStatusService: ConnectionStatusService;
|
||||
|
||||
@inject(SplashService)
|
||||
private readonly splashService: SplashService;
|
||||
|
||||
@inject(FrontendApplicationStateService)
|
||||
private readonly appStateService: FrontendApplicationStateService;
|
||||
|
||||
@inject(ElectronMainWindowServiceExt)
|
||||
private readonly mainWindowServiceExt: ElectronMainWindowServiceExt;
|
||||
|
||||
@postConstruct()
|
||||
protected override init(): void {
|
||||
this.appStateService
|
||||
.reachedAnyState('initialized_layout')
|
||||
.then(() => this.splashService.requestClose());
|
||||
// NOOP
|
||||
// Does not listen on Theia's `window.zoomLevel` changes.
|
||||
// TODO: IDE2 must switch to the Theia preferences and drop the custom one.
|
||||
}
|
||||
|
||||
protected shouldUnload(): boolean {
|
||||
|
@ -1,5 +0,0 @@
|
||||
export const splashServicePath = '/services/splash-service';
|
||||
export const SplashService = Symbol('SplashService');
|
||||
export interface SplashService {
|
||||
requestClose(): Promise<void>;
|
||||
}
|
@ -16,13 +16,8 @@ import {
|
||||
ElectronMainWindowServiceExt,
|
||||
electronMainWindowServiceExtPath,
|
||||
} from '../electron-common/electron-main-window-service-ext';
|
||||
import {
|
||||
SplashService,
|
||||
splashServicePath,
|
||||
} from '../electron-common/splash-service';
|
||||
import { ElectronMainWindowServiceExtImpl } from './electron-main-window-service-ext-impl';
|
||||
import { IDEUpdaterImpl } from './ide-updater/ide-updater-impl';
|
||||
import { SplashServiceImpl } from './splash/splash-service-impl';
|
||||
import { ElectronMainApplication } from './theia/electron-main-application';
|
||||
import { ElectronMainWindowServiceImpl } from './theia/electron-main-window-service';
|
||||
import { TheiaElectronWindow } from './theia/theia-electron-window';
|
||||
@ -34,17 +29,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
||||
bind(ElectronMainWindowServiceImpl).toSelf().inSingletonScope();
|
||||
rebind(ElectronMainWindowService).toService(ElectronMainWindowServiceImpl);
|
||||
|
||||
bind(SplashServiceImpl).toSelf().inSingletonScope();
|
||||
bind(SplashService).toService(SplashServiceImpl);
|
||||
bind(ElectronConnectionHandler)
|
||||
.toDynamicValue(
|
||||
(context) =>
|
||||
new JsonRpcConnectionHandler(splashServicePath, () =>
|
||||
context.container.get(SplashService)
|
||||
)
|
||||
)
|
||||
.inSingletonScope();
|
||||
|
||||
// IDE updater bindings
|
||||
bind(IDEUpdaterImpl).toSelf().inSingletonScope();
|
||||
bind(IDEUpdater).toService(IDEUpdaterImpl);
|
||||
|
@ -1,158 +0,0 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Troy McKinnon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
// Copied from https://raw.githubusercontent.com/trodi/electron-splashscreen/2f5052a133be021cbf9a438d0ef4719cd1796b75/index.ts
|
||||
|
||||
/**
|
||||
* Module handles configurable splashscreen to show while app is loading.
|
||||
*/
|
||||
|
||||
import { Event } from '@theia/core/lib/common/event';
|
||||
import { BrowserWindow } from 'electron';
|
||||
|
||||
/**
|
||||
* When splashscreen was shown.
|
||||
* @ignore
|
||||
*/
|
||||
let splashScreenTimestamp = 0;
|
||||
/**
|
||||
* Splashscreen is loaded and ready to show.
|
||||
* @ignore
|
||||
*/
|
||||
let splashScreenReady = false;
|
||||
/**
|
||||
* Main window has been loading for a min amount of time.
|
||||
* @ignore
|
||||
*/
|
||||
let slowStartup = false;
|
||||
/**
|
||||
* True when expected work is complete and we've closed splashscreen, else user prematurely closed splashscreen.
|
||||
* @ignore
|
||||
*/
|
||||
let done = false;
|
||||
/**
|
||||
* Show splashscreen if criteria are met.
|
||||
* @ignore
|
||||
*/
|
||||
const showSplash = () => {
|
||||
if (splashScreen && splashScreenReady && slowStartup) {
|
||||
splashScreen.show();
|
||||
splashScreenTimestamp = Date.now();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Close splashscreen / show main screen. Ensure screen is visible for a min amount of time.
|
||||
* @ignore
|
||||
*/
|
||||
const closeSplashScreen = (main: Electron.BrowserWindow, min: number): void => {
|
||||
if (splashScreen) {
|
||||
const timeout = min - (Date.now() - splashScreenTimestamp);
|
||||
setTimeout(() => {
|
||||
done = true;
|
||||
if (splashScreen) {
|
||||
splashScreen.isDestroyed() || splashScreen.close(); // Avoid `Error: Object has been destroyed` (#19)
|
||||
splashScreen = null;
|
||||
}
|
||||
if (!main.isDestroyed()) {
|
||||
main.show();
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
};
|
||||
/** `electron-splashscreen` config object. */
|
||||
export interface Config {
|
||||
/** Options for the window that is loading and having a splashscreen tied to. */
|
||||
windowOpts: Electron.BrowserWindowConstructorOptions;
|
||||
/**
|
||||
* URL to the splashscreen template. This is the path to an `HTML` or `SVG` file.
|
||||
* If you want to simply show a `PNG`, wrap it in an `HTML` file.
|
||||
*/
|
||||
templateUrl: string;
|
||||
|
||||
/**
|
||||
* Full set of browser window options for the splashscreen. We override key attributes to
|
||||
* make it look & feel like a splashscreen; the rest is up to you!
|
||||
*/
|
||||
splashScreenOpts: Electron.BrowserWindowConstructorOptions;
|
||||
/** Number of ms the window will load before splashscreen appears (default: 500ms). */
|
||||
delay?: number;
|
||||
/** Minimum ms the splashscreen will be visible (default: 500ms). */
|
||||
minVisible?: number;
|
||||
/** Close window that is loading if splashscreen is closed by user (default: true). */
|
||||
closeWindow?: boolean;
|
||||
}
|
||||
/**
|
||||
* The actual splashscreen browser window.
|
||||
* @ignore
|
||||
*/
|
||||
let splashScreen: Electron.BrowserWindow | null;
|
||||
/**
|
||||
* Initializes a splashscreen that will show/hide smartly (and handle show/hiding of main window).
|
||||
* @param config - Configures splashscreen
|
||||
* @returns {BrowserWindow} the main browser window ready for loading
|
||||
*/
|
||||
export const initSplashScreen = async (
|
||||
config: Config,
|
||||
windowFactory: (
|
||||
options: Electron.BrowserViewConstructorOptions
|
||||
) => Promise<BrowserWindow>,
|
||||
onCloseRequested?: Event<void>
|
||||
): Promise<BrowserWindow> => {
|
||||
const xConfig: Required<Config> = {
|
||||
windowOpts: config.windowOpts,
|
||||
templateUrl: config.templateUrl,
|
||||
splashScreenOpts: config.splashScreenOpts,
|
||||
delay: config.delay ?? 500,
|
||||
minVisible: config.minVisible ?? 500,
|
||||
closeWindow: config.closeWindow ?? true,
|
||||
};
|
||||
xConfig.splashScreenOpts.center = true;
|
||||
xConfig.splashScreenOpts.frame = false;
|
||||
xConfig.windowOpts.show = false;
|
||||
const window = await windowFactory(xConfig.windowOpts);
|
||||
splashScreen = new BrowserWindow(xConfig.splashScreenOpts);
|
||||
splashScreen.loadURL(`file://${xConfig.templateUrl}`);
|
||||
xConfig.closeWindow &&
|
||||
splashScreen.on('close', () => {
|
||||
done || window.close();
|
||||
});
|
||||
// Splashscreen is fully loaded and ready to view.
|
||||
splashScreen.webContents.on('did-finish-load', () => {
|
||||
splashScreenReady = true;
|
||||
showSplash();
|
||||
});
|
||||
// Startup is taking enough time to show a splashscreen.
|
||||
setTimeout(() => {
|
||||
slowStartup = true;
|
||||
showSplash();
|
||||
}, xConfig.delay);
|
||||
if (onCloseRequested) {
|
||||
onCloseRequested(() => closeSplashScreen(window, xConfig.minVisible));
|
||||
} else {
|
||||
window.webContents.on('did-finish-load', () => {
|
||||
closeSplashScreen(window, xConfig.minVisible);
|
||||
});
|
||||
}
|
||||
window.on('closed', () => closeSplashScreen(window, 0)); // XXX: close splash when main window is closed
|
||||
return window;
|
||||
};
|
@ -1,20 +0,0 @@
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { Event, Emitter } from '@theia/core/lib/common/event';
|
||||
import { SplashService } from '../../electron-common/splash-service';
|
||||
|
||||
@injectable()
|
||||
export class SplashServiceImpl implements SplashService {
|
||||
protected requested = false;
|
||||
protected readonly onCloseRequestedEmitter = new Emitter<void>();
|
||||
|
||||
get onCloseRequested(): Event<void> {
|
||||
return this.onCloseRequestedEmitter.event;
|
||||
}
|
||||
|
||||
async requestClose(): Promise<void> {
|
||||
if (!this.requested) {
|
||||
this.requested = true;
|
||||
this.onCloseRequestedEmitter.fire();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<style>
|
||||
.container {
|
||||
width: auto;
|
||||
text-align: center;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 95%;
|
||||
height: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<p><img src="splash.png"></p>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
Binary file not shown.
Before Width: | Height: | Size: 103 KiB |
@ -1,18 +1,15 @@
|
||||
import { inject, injectable } from '@theia/core/shared/inversify';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import {
|
||||
app,
|
||||
BrowserWindow,
|
||||
BrowserWindowConstructorOptions,
|
||||
contentTracing,
|
||||
ipcMain,
|
||||
screen,
|
||||
Event as ElectronEvent,
|
||||
} from '@theia/core/electron-shared/electron';
|
||||
import { fork } from 'child_process';
|
||||
import { AddressInfo } from 'net';
|
||||
import { join, dirname } from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
import { initSplashScreen } from '../splash/splash-screen';
|
||||
import { MaybePromise } from '@theia/core/lib/common/types';
|
||||
import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token';
|
||||
import { FrontendApplicationConfig } from '@theia/application-package/lib/application-props';
|
||||
@ -20,7 +17,6 @@ import {
|
||||
ElectronMainApplication as TheiaElectronMainApplication,
|
||||
ElectronMainExecutionParams,
|
||||
} from '@theia/core/lib/electron-main/electron-main-application';
|
||||
import { SplashServiceImpl } from '../splash/splash-service-impl';
|
||||
import { URI } from '@theia/core/shared/vscode-uri';
|
||||
import { Deferred } from '@theia/core/lib/common/promise-util';
|
||||
import * as os from '@theia/core/lib/common/os';
|
||||
@ -42,14 +38,6 @@ interface WorkspaceOptions {
|
||||
|
||||
const WORKSPACES = 'workspaces';
|
||||
|
||||
/**
|
||||
* Purely a dev thing. If you start the app with the `--nosplash` argument,
|
||||
* then you won't have the splash screen (which is always on top :confused:) and can debug the app at startup.
|
||||
* Note: if you start the app from VS Code with the `App (Electron)` config, the splash screen will be disabled.
|
||||
*/
|
||||
const APP_STARTED_WITH_NOSPLASH =
|
||||
typeof process !== 'undefined' && process.argv.indexOf('--nosplash') !== -1;
|
||||
|
||||
/**
|
||||
* If the app is started with `--open-devtools` argument, the `Dev Tools` will be opened.
|
||||
*/
|
||||
@ -70,9 +58,6 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
private _firstWindowId: number | undefined;
|
||||
private openFilePromise = new Deferred();
|
||||
|
||||
@inject(SplashServiceImpl)
|
||||
private readonly splashService: SplashServiceImpl;
|
||||
|
||||
override async start(config: FrontendApplicationConfig): Promise<void> {
|
||||
// Explicitly set the app name to have better menu items on macOS. ("About", "Hide", and "Quit")
|
||||
// See: https://github.com/electron-userland/electron-builder/issues/2468
|
||||
@ -289,69 +274,10 @@ export class ElectronMainApplication extends TheiaElectronMainApplication {
|
||||
super.onSecondInstance(event, argv, cwd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this rather than creating `BrowserWindow` instances from scratch, since some security parameters need to be set, this method will do it.
|
||||
*
|
||||
* @param options
|
||||
*/
|
||||
override async createWindow(
|
||||
asyncOptions: MaybePromise<TheiaBrowserWindowOptions> = this.getDefaultTheiaWindowOptions()
|
||||
): Promise<BrowserWindow> {
|
||||
let options = await asyncOptions;
|
||||
options = this.avoidOverlap(options);
|
||||
let electronWindow: BrowserWindow | undefined;
|
||||
if (this.windows.size || APP_STARTED_WITH_NOSPLASH) {
|
||||
electronWindow = await this.doCreateWindow(options);
|
||||
} else {
|
||||
const { bounds } = screen.getDisplayNearestPoint(
|
||||
screen.getCursorScreenPoint()
|
||||
);
|
||||
const splashHeight = 450;
|
||||
const splashWidth = 600;
|
||||
const splashY = Math.floor(bounds.y + (bounds.height - splashHeight) / 2);
|
||||
const splashX = Math.floor(bounds.x + (bounds.width - splashWidth) / 2);
|
||||
const splashScreenOpts: BrowserWindowConstructorOptions = {
|
||||
height: splashHeight,
|
||||
width: splashWidth,
|
||||
x: splashX,
|
||||
y: splashY,
|
||||
transparent: true,
|
||||
alwaysOnTop: true,
|
||||
focusable: false,
|
||||
minimizable: false,
|
||||
maximizable: false,
|
||||
hasShadow: false,
|
||||
resizable: false,
|
||||
};
|
||||
electronWindow = await initSplashScreen(
|
||||
{
|
||||
windowOpts: options,
|
||||
templateUrl: join(
|
||||
__dirname,
|
||||
'..',
|
||||
'..',
|
||||
'..',
|
||||
'src',
|
||||
'electron-main',
|
||||
'splash',
|
||||
'static',
|
||||
'splash.html'
|
||||
),
|
||||
delay: 0,
|
||||
minVisible: 2000,
|
||||
splashScreenOpts,
|
||||
},
|
||||
(windowOptions) => this.doCreateWindow(windowOptions),
|
||||
this.splashService.onCloseRequested
|
||||
);
|
||||
}
|
||||
return electronWindow;
|
||||
}
|
||||
|
||||
private async doCreateWindow(
|
||||
options: TheiaBrowserWindowOptions
|
||||
): Promise<BrowserWindow> {
|
||||
const electronWindow = await super.createWindow(options);
|
||||
const electronWindow = await super.createWindow(asyncOptions);
|
||||
if (APP_STARTED_WITH_DEV_TOOLS) {
|
||||
electronWindow.webContents.openDevTools();
|
||||
}
|
||||
|
@ -61,7 +61,7 @@
|
||||
},
|
||||
"generator": {
|
||||
"config": {
|
||||
"preloadTemplate": "<div class='theia-preload' style='background-color: rgb(237, 241, 242);'></div>"
|
||||
"preloadTemplate": "./resources/preload.html"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
114
electron-app/resources/preload.html
Normal file
114
electron-app/resources/preload.html
Normal file
@ -0,0 +1,114 @@
|
||||
<head>
|
||||
<style>
|
||||
/* The colors are hard-coded and based on the `editor.background` and `editor.foreground` values from `./arduino-ide-extension/src/browser/data/default.color-theme.json` */
|
||||
@media (prefers-color-scheme: light) {
|
||||
html {
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* The colors are hard-coded and based on the `editor.background` and `editor.foreground` values from `./arduino-ide-extension/src/browser/data/dark.color-theme.json` */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
background: #1f272a;
|
||||
}
|
||||
}
|
||||
|
||||
.theia-preload {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
/* Above styles copied from https://github.com/eclipse-theia/theia/blob/5aeef6c0c683b4e91713ab736957e6655b486adc/packages/core/src/browser/style/index.css#L147-L161 */
|
||||
/* Otherwise, there is a flickering when Theia's CSS loads. */
|
||||
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.theia-preload::after {
|
||||
/* remove default loading animation */
|
||||
content: none;
|
||||
}
|
||||
|
||||
.spinner-container {
|
||||
display: flex;
|
||||
flex-direction: center;
|
||||
align-self: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.custom-spinner {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.custom-spinner svg {
|
||||
width: 16vw;
|
||||
height: 16vh;
|
||||
animation-delay: 0;
|
||||
animation-duration: 2s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-name: preload-spinner;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
@keyframes preload-spinner {
|
||||
0% {
|
||||
transform: scale(1.0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(0.8);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1.0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class='spinner-container'>
|
||||
<div class='custom-spinner'>
|
||||
<svg id="spinner" xmlns="http://www.w3.org/2000/svg" width="2499" height="2500"
|
||||
viewBox="0 0 1372.201 1372.684">
|
||||
<path fill="#00979D" stroke="#81C9CB" stroke-width=".932" stroke-miterlimit="10"
|
||||
d="M1371.701 686.024c0 378.658-306.972 685.605-685.549 685.605C307.451 1371.629.5 1064.682.5 686.024.5 307.455 307.451.483 686.152.483c378.594.001 685.549 306.972 685.549 685.541z" />
|
||||
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="-16.3" y1="16.071" x2="1354.901" y2="16.071"
|
||||
gradientTransform="matrix(1 0 0 -1 16.8 702.696)">
|
||||
<stop offset=".117" stop-color="#fff" stop-opacity="0" />
|
||||
<stop offset=".252" stop-color="#c0d1d3" stop-opacity=".153" />
|
||||
<stop offset=".387" stop-color="#91b3b7" stop-opacity=".306" />
|
||||
<stop offset=".52" stop-color="#6d9fa3" stop-opacity=".457" />
|
||||
<stop offset=".65" stop-color="#4d9195" stop-opacity=".604" />
|
||||
<stop offset=".776" stop-color="#30888b" stop-opacity=".746" />
|
||||
<stop offset=".895" stop-color="#148386" stop-opacity=".881" />
|
||||
<stop offset="1" stop-color="#008184" />
|
||||
</linearGradient>
|
||||
<linearGradient id="b" gradientUnits="userSpaceOnUse" x1="-16.8" y1="16.071" x2="1355.401" y2="16.071"
|
||||
gradientTransform="matrix(1 0 0 -1 16.8 702.696)">
|
||||
<stop offset="0" stop-color="#fff" stop-opacity="0" />
|
||||
<stop offset=".153" stop-color="#c0d1d3" stop-opacity=".153" />
|
||||
<stop offset=".306" stop-color="#91b3b7" stop-opacity=".306" />
|
||||
<stop offset=".457" stop-color="#6d9fa3" stop-opacity=".457" />
|
||||
<stop offset=".604" stop-color="#4d9195" stop-opacity=".604" />
|
||||
<stop offset=".746" stop-color="#30888b" stop-opacity=".746" />
|
||||
<stop offset=".881" stop-color="#148386" stop-opacity=".881" />
|
||||
<stop offset="1" stop-color="#008184" />
|
||||
</linearGradient>
|
||||
<path opacity=".5" fill="url(#a)" stroke="url(#b)" stroke-miterlimit="10"
|
||||
d="M1371.701 686.595c0 378.65-306.972 685.606-685.549 685.606C307.451 1372.201.5 1065.23.5 686.595.5 308.019 307.451 1.048 686.152 1.048c378.594.016 685.549 306.97 685.549 685.547z" />
|
||||
<g fill="#FFF">
|
||||
<path
|
||||
d="M947.959 931.196c-12.909 0-26.127-.929-39.127-2.864-108.978-15.554-181.848-93.822-222.665-153.989-40.946 60.166-113.811 138.512-222.74 154.045a275.864 275.864 0 0 1-39.133 2.785c-67.753 0-131.358-25.217-179.201-71.003-48.299-46.165-74.951-108.114-74.951-174.171 0-66.14 26.651-128.004 75.021-174.253 47.797-45.793 111.449-70.936 179.231-70.936 12.918 0 26.067.928 39.023 2.783 108.932 15.535 181.794 93.813 222.743 153.99 40.825-60.177 113.689-138.432 222.658-153.99 13-1.863 26.148-2.783 39.066-2.783 67.753 0 131.401 25.208 179.197 70.936 48.345 46.249 74.937 108.113 74.937 174.253 0 66.057-26.524 128.006-74.868 174.171-47.881 45.785-111.434 71.026-179.191 71.026M734.42 686.024c21.283 40.534 84.067 141.676 186.692 156.375 8.984 1.236 18.028 1.923 26.839 1.923 92.185 0 167.225-71.002 167.225-158.322s-75.023-158.321-167.291-158.321c-8.812 0-17.853.629-26.753 1.921-102.644 14.664-165.428 115.806-186.712 156.424M424.393 527.702c-92.308 0-167.36 70.998-167.36 158.321 0 87.305 75.021 158.322 167.245 158.322 8.852 0 17.897-.688 26.879-1.922 102.629-14.697 165.394-115.783 186.689-156.375-21.237-40.535-84.061-141.761-186.689-156.376-8.877-1.341-17.945-1.97-26.764-1.97" />
|
||||
<path
|
||||
d="M354.37 662.051h152.625v49.181H354.37zM1016.484 662.051h-51.671v-51.747h-49.348v51.747h-51.648v49.181h51.648v51.737h49.348v-51.737h51.671z" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
6
electron/.gitignore
vendored
6
electron/.gitignore
vendored
@ -15,4 +15,8 @@ dist/
|
||||
electron-builder.env
|
||||
|
||||
# The generated `package.json` under the `build` folder.
|
||||
build/package.json
|
||||
build/package.json
|
||||
|
||||
# Resources the packager copies from dev to prod
|
||||
build/resources/preload.html
|
||||
build/patch/frontend/index.js
|
||||
|
@ -1,100 +0,0 @@
|
||||
// Patch for the startup theme. Customizes the `ThemeService.get().defaultTheme();` to dispatch the default IDE2 theme based on the OS' theme.
|
||||
// For all subsequent starts of the IDE the theme applied will be the last one set by the user.
|
||||
|
||||
// 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.
|
||||
// Once the version of Theia is updated, this patch will be removed and this functionality will be implemented via dependency injection.
|
||||
// Ideally, we should open a PR in Theia and add support for `light` and `dark` default themes in the app config.
|
||||
|
||||
const {
|
||||
ThemeService,
|
||||
ThemeServiceSymbol,
|
||||
BuiltinThemeProvider,
|
||||
} = require('@theia/core/lib/browser/theming');
|
||||
const {
|
||||
ApplicationProps,
|
||||
} = require('@theia/application-package/lib/application-props');
|
||||
const {
|
||||
FrontendApplicationConfigProvider,
|
||||
} = require('@theia/core/lib/browser/frontend-application-config-provider');
|
||||
|
||||
// It is a mighty hack to support theme updates in the bundled IDE2.
|
||||
// If the custom theme registration happens before the restoration of the existing monaco themes, then any custom theme changes will be ignored.
|
||||
// This patch introduces a static deferred promise in the monaco-theming service that will be resolved when the restoration is ready.
|
||||
// IDE2 cannot require the monaco theme service on the outer module level, as it requires the application config provider to be initialized,
|
||||
// but the initialization happens only in the generated `index.js`.
|
||||
// This patch customizes the monaco theme service behavior before loading the DI containers via the preload.
|
||||
// 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.
|
||||
const preloader = require('@theia/core/lib/browser/preloader');
|
||||
const originalPreload = preloader.preload;
|
||||
preloader.preload = async function () {
|
||||
const { MonacoThemingService } = require('@theia/monaco/lib/browser/monaco-theming-service');
|
||||
const { MonacoThemeServiceIsReady } = require('arduino-ide-extension/lib/browser/utils/window');
|
||||
const { Deferred } = require('@theia/core/lib/common/promise-util');
|
||||
const ready = new Deferred();
|
||||
if (!window[MonacoThemeServiceIsReady]) {
|
||||
window[MonacoThemeServiceIsReady] = ready;
|
||||
console.log('Registered a custom monaco-theme service initialization signal on the window object.');
|
||||
}
|
||||
// Here, it is safe to patch the theme service, app config provider is ready.
|
||||
MonacoThemingService.init = async function () {
|
||||
this.updateBodyUiTheme();
|
||||
ThemeService.get().onDidColorThemeChange(() => this.updateBodyUiTheme());
|
||||
await this.restore();
|
||||
ready.resolve();
|
||||
}.bind(MonacoThemingService);
|
||||
return originalPreload();
|
||||
}.bind(preloader);
|
||||
|
||||
const lightTheme = 'arduino-theme';
|
||||
const darkTheme = 'arduino-theme-dark';
|
||||
const defaultTheme =
|
||||
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
? darkTheme
|
||||
: lightTheme;
|
||||
|
||||
const originalGet = FrontendApplicationConfigProvider.get;
|
||||
FrontendApplicationConfigProvider.get = function () {
|
||||
const originalProps = originalGet.bind(FrontendApplicationConfigProvider)();
|
||||
return { ...originalProps, defaultTheme };
|
||||
}.bind(FrontendApplicationConfigProvider);
|
||||
|
||||
const arduinoDarkTheme = {
|
||||
id: 'arduino-theme-dark',
|
||||
type: 'dark',
|
||||
label: 'Dark (Arduino)',
|
||||
editorTheme: 'arduino-theme-dark',
|
||||
activate() {},
|
||||
deactivate() {},
|
||||
};
|
||||
|
||||
const arduinoLightTheme = {
|
||||
id: 'arduino-theme',
|
||||
type: 'light',
|
||||
label: 'Light (Arduino)',
|
||||
editorTheme: 'arduino-theme',
|
||||
activate() {},
|
||||
deactivate() {},
|
||||
};
|
||||
|
||||
if (!window[ThemeServiceSymbol]) {
|
||||
const themeService = new ThemeService();
|
||||
Object.defineProperty(themeService, 'defaultTheme', {
|
||||
get: function () {
|
||||
return (
|
||||
this.themes[defaultTheme] ||
|
||||
this.themes[ApplicationProps.DEFAULT.frontend.config.defaultTheme]
|
||||
);
|
||||
},
|
||||
});
|
||||
themeService.register(
|
||||
...BuiltinThemeProvider.themes,
|
||||
arduinoDarkTheme,
|
||||
arduinoLightTheme
|
||||
);
|
||||
themeService.startupTheme();
|
||||
themeService.setCurrentTheme(defaultTheme);
|
||||
window[ThemeServiceSymbol] = themeService;
|
||||
}
|
||||
|
||||
// Require the original, generated `index.js` for `webpack` as the next entry for the `bundle.js`.
|
||||
require('../../src-gen/frontend/index');
|
@ -7,6 +7,8 @@
|
||||
const glob = require('glob');
|
||||
const isCI = require('is-ci');
|
||||
shell.env.THEIA_ELECTRON_SKIP_REPLACE_FFMPEG = '1'; // Do not run the ffmpeg validation for the packager.
|
||||
// Note, this will crash on PI if the available memory is less than desired heap size.
|
||||
// https://github.com/shelljs/shelljs/issues/1024#issuecomment-1001552543
|
||||
shell.env.NODE_OPTIONS = '--max_old_space_size=4096'; // Increase heap size for the CI
|
||||
shell.env.PUPPETEER_SKIP_CHROMIUM_DOWNLOAD = 'true'; // Skip download and avoid `ERROR: Failed to download Chromium`.
|
||||
const template = require('./config').generateTemplate(
|
||||
@ -14,7 +16,7 @@
|
||||
);
|
||||
const utils = require('./utils');
|
||||
const merge = require('deepmerge');
|
||||
const { isRelease, isElectronPublish, getChannelFile } = utils;
|
||||
const { isRelease, getChannelFile } = utils;
|
||||
const { version } = template;
|
||||
const { productName } = template.build;
|
||||
|
||||
@ -58,6 +60,11 @@
|
||||
.filter((filename) => resourcesToKeep.indexOf(filename) === -1)
|
||||
.forEach((filename) => rm('-rf', path('..', 'build', filename)));
|
||||
|
||||
// Clean up the `./electron/build/patch` and `./electron/build/resources` folder with Git.
|
||||
// To avoid file duplication between bundled app and dev mode, some files are copied from `./electron-app` to `./electron/build` folder.
|
||||
const foldersToSyncFromDev = ['patch', 'resources'];
|
||||
foldersToSyncFromDev.forEach(filename => shell.exec(`git -C ${path('..', 'build', filename)} clean -ffxdq`, { async: false }));
|
||||
|
||||
const extensions = require('./extensions.json');
|
||||
echo(
|
||||
`Building the application with the following extensions:\n${extensions
|
||||
@ -70,20 +77,28 @@
|
||||
// Copy the following items into the `working-copy` folder. Make sure to reuse the `yarn.lock`. |
|
||||
//----------------------------------------------------------------------------------------------+
|
||||
mkdir('-p', path('..', workingCopy));
|
||||
for (const name of [
|
||||
for (const filename of [
|
||||
...allDependencies,
|
||||
'yarn.lock',
|
||||
'package.json',
|
||||
'lerna.json',
|
||||
'i18n'
|
||||
]) {
|
||||
cp('-rf', path(rootPath, name), path('..', workingCopy));
|
||||
cp('-rf', path(rootPath, filename), path('..', workingCopy));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------+
|
||||
// Copy the patched `index.js` for the frontend, the Theia preload, etc. from `./electron-app` |
|
||||
//---------------------------------------------------------------------------------------------+
|
||||
for (const filename of foldersToSyncFromDev) {
|
||||
cp('-rf', path('..', workingCopy, 'electron-app', filename), path('..', 'build'));
|
||||
}
|
||||
|
||||
//----------------------------------------------+
|
||||
// Sanity check: all versions must be the same. |
|
||||
//----------------------------------------------+
|
||||
verifyVersions(allDependencies);
|
||||
|
||||
//----------------------------------------------------------------------+
|
||||
// Use the nightly patch version if not a release but requires publish. |
|
||||
//----------------------------------------------------------------------+
|
||||
@ -438,6 +453,12 @@ ${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('fs').PathLike} file
|
||||
* @param {string|undefined} [algorithm="sha512"]
|
||||
* @param {BufferEncoding|undefined} [encoding="base64"]
|
||||
* @param {object|undefined} [options]
|
||||
*/
|
||||
async function hashFile(
|
||||
file,
|
||||
algorithm = 'sha512',
|
||||
|
Loading…
x
Reference in New Issue
Block a user