Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab8642ce74 |
@@ -27,6 +27,7 @@ compile_commands.json
|
||||
.cache
|
||||
yarn-error.log
|
||||
.DS_Store
|
||||
.webpack
|
||||
|
||||
# Coverage
|
||||
coverage
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ os:
|
||||
- linux
|
||||
- osx
|
||||
dist: trusty
|
||||
osx_image: xcode10
|
||||
osx_image: xcode8.3
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
|
||||
+19
-37
@@ -7,14 +7,14 @@ const packageJson = require('./package.json')
|
||||
const { version } = packageJson
|
||||
const iconDir = path.resolve(__dirname, 'assets', 'icons')
|
||||
|
||||
const config = {
|
||||
module.exports = {
|
||||
hooks: {
|
||||
generateAssets: require('./tools/generateAssets')
|
||||
//generateAssets: require('./tools/generateAssets')
|
||||
},
|
||||
packagerConfig: {
|
||||
name: 'Electron Fiddle',
|
||||
executableName: 'electron-fiddle',
|
||||
asar: true,
|
||||
asar: false,
|
||||
icon: path.resolve(__dirname, 'assets', 'icons', 'fiddle'),
|
||||
// TODO: FIXME?
|
||||
// ignore: [
|
||||
@@ -32,12 +32,7 @@ const config = {
|
||||
OriginalFilename: 'Electron Fiddle',
|
||||
},
|
||||
osxSign: {
|
||||
identity: 'Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)',
|
||||
'hardened-runtime': true,
|
||||
'gatekeeper-assess': false,
|
||||
'entitlements': 'static/entitlements.plist',
|
||||
'entitlements-inherit': 'static/entitlements.plist',
|
||||
'signature-flags': 'library'
|
||||
identity: 'Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)'
|
||||
}
|
||||
},
|
||||
makers: [
|
||||
@@ -98,33 +93,20 @@ const config = {
|
||||
prerelease: false
|
||||
}
|
||||
}
|
||||
],
|
||||
plugins: [
|
||||
['@electron-forge/plugin-webpack', {
|
||||
mainConfig: './webpack.main.config.js',
|
||||
renderer: {
|
||||
config: './webpack.renderer.config.js',
|
||||
entryPoints: [
|
||||
{
|
||||
html: './static/index.html',
|
||||
js: './src/renderer/app.tsx',
|
||||
name: 'main_window'
|
||||
}
|
||||
]
|
||||
}
|
||||
}]
|
||||
]
|
||||
}
|
||||
|
||||
function notarizeMaybe() {
|
||||
if (process.platform !== 'darwin') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!process.env.CI) {
|
||||
console.log(`Not in CI, skipping notarization`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!process.env.APPLE_ID || !process.env.APPLE_ID_PASSWORD) {
|
||||
console.warn('Should be notarizing, but environment variables APPLE_ID or APPLE_ID_PASSWORD are missing!');
|
||||
return;
|
||||
}
|
||||
|
||||
config.packagerConfig.osxNotarize = {
|
||||
appBundleId: 'com.electron.fiddle',
|
||||
appleId: process.env.APPLE_ID,
|
||||
appleIdPassword: process.env.APPLE_ID_PASSWORD,
|
||||
ascProvider: 'LT94ZKYDCJ'
|
||||
}
|
||||
}
|
||||
|
||||
notarizeMaybe()
|
||||
|
||||
// Finally, export it
|
||||
module.exports = config
|
||||
|
||||
Generated
+2828
-4300
File diff suppressed because it is too large
Load Diff
+27
-18
@@ -1,24 +1,21 @@
|
||||
{
|
||||
"name": "electron-fiddle",
|
||||
"productName": "Electron Fiddle",
|
||||
"version": "0.11.1",
|
||||
"version": "0.10.0",
|
||||
"description": "The easiest way to get started with Electron",
|
||||
"repository": "https://github.com/electron/fiddle",
|
||||
"main": "./dist/src/main/main",
|
||||
"main": ".webpack/main",
|
||||
"scripts": {
|
||||
"contributors": "node ./tools/contributors.js",
|
||||
"less": "node ./tools/lessc.js",
|
||||
"lint:style": "stylelint ./src/less/*.less --fix",
|
||||
"lint:ts": "tslint -c tslint.json -p tsconfig.json -e \"node_modules/**/*.ts\" --fix",
|
||||
"lint:tests": "tslint ./tests/**/*.ts{,x} -c tslint.json --fix",
|
||||
"lint:templates": "standard ./static/show-me/**/*.js",
|
||||
"lint": "npm-run-all lint:*",
|
||||
"make": "electron-forge make",
|
||||
"package": "electron-forge package",
|
||||
"parcel:build": "node ./tools/parcel-build.js",
|
||||
"parcel:watch": "node ./tools/parcel-watch.js",
|
||||
"publish": "electron-forge publish",
|
||||
"start": "rimraf ./dist && electron-forge start",
|
||||
"make": "npm run contributors && electron-forge make",
|
||||
"package": "npm run contributors && electron-forge package",
|
||||
"publish": "npm run contributors && electron-forge publish",
|
||||
"start": "electron-forge start",
|
||||
"test": "jest --config=jest.json --coverage",
|
||||
"test:ci": "jest --config=jest.json --coverage --runInBand",
|
||||
"test:coverage": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
|
||||
@@ -63,12 +60,14 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.6.4",
|
||||
"@electron-forge/cli": "^6.0.0-beta.46",
|
||||
"@electron-forge/maker-deb": "^6.0.0-beta.46",
|
||||
"@electron-forge/maker-rpm": "^6.0.0-beta.46",
|
||||
"@electron-forge/maker-squirrel": "^6.0.0-beta.46",
|
||||
"@electron-forge/maker-zip": "^6.0.0-beta.46",
|
||||
"@electron-forge/publisher-github": "^6.0.0-beta.46",
|
||||
"@electron-forge/cli": "^6.0.0-beta.45",
|
||||
"@electron-forge/maker-deb": "^6.0.0-beta.45",
|
||||
"@electron-forge/maker-rpm": "^6.0.0-beta.45",
|
||||
"@electron-forge/maker-squirrel": "^6.0.0-beta.45",
|
||||
"@electron-forge/maker-zip": "^6.0.0-beta.45",
|
||||
"@electron-forge/plugin-webpack": "^6.0.0-beta.45",
|
||||
"@electron-forge/publisher-github": "^6.0.0-beta.45",
|
||||
"@marshallofsound/webpack-asset-relocator-loader": "^0.5.0",
|
||||
"@types/builtin-modules": "^3.1.1",
|
||||
"@types/classnames": "^2.2.9",
|
||||
"@types/enzyme": "^3.10.3",
|
||||
@@ -82,27 +81,37 @@
|
||||
"@types/tmp": "0.1.0",
|
||||
"chokidar": "^3.2.2",
|
||||
"coveralls": "^3.0.7",
|
||||
"electron": "7.1.3",
|
||||
"css-loader": "^3.2.0",
|
||||
"electron": "7.0.0",
|
||||
"enzyme": "^3.10.0",
|
||||
"enzyme-adapter-react-16": "^1.15.1",
|
||||
"enzyme-to-json": "^3.4.3",
|
||||
"file-loader": "^4.2.0",
|
||||
"jest": "^24.9.0",
|
||||
"jest-fetch-mock": "^2.1.2",
|
||||
"less": "^3.10.3",
|
||||
"less-loader": "^5.0.0",
|
||||
"loader-utils": "^1.2.3",
|
||||
"log-symbols": "^3.0.0",
|
||||
"mini-css-extract-plugin": "^0.8.0",
|
||||
"monaco-editor-webpack-plugin": "^1.7.0",
|
||||
"node-abi": "^2.12.0",
|
||||
"node-fetch": "^2.6.0",
|
||||
"node-loader": "^0.6.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"parcel-bundler": "^1.12.4",
|
||||
"react-test-renderer": "^16.11.0",
|
||||
"rimraf": "^3.0.0",
|
||||
"standard": "^14.3.1",
|
||||
"style-loader": "^1.0.0",
|
||||
"stylelint": "^11.1.1",
|
||||
"stylelint-config-standard": "^19.0.0",
|
||||
"ts-jest": "^24.1.0",
|
||||
"ts-loader": "^6.2.1",
|
||||
"tslint": "^5.20.0",
|
||||
"tslint-microsoft-contrib": "^6.2.0",
|
||||
"tslint-react": "^4.1.0",
|
||||
"typescript": "^3.6.4"
|
||||
"typescript": "^3.6.4",
|
||||
"url-loader": "^2.2.0",
|
||||
"webpack-bundle-analyzer": "^3.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
+3
-9
@@ -19,18 +19,14 @@ export enum IpcEvents {
|
||||
SHOW_WARNING_DIALOG = 'SHOW_WARNING_DIALOG',
|
||||
SHOW_CONFIRMATION_DIALOG = 'SHOW_CONFIRMATION_DIALOG',
|
||||
SHOW_WELCOME_TOUR = 'SHOW_WELCOME_TOUR',
|
||||
CLEAR_CONSOLE = 'CLEAR_CONSOLE',
|
||||
LOAD_LOCAL_VERSION_FOLDER = 'LOAD_LOCAL_VERSION_FOLDER',
|
||||
SHOW_LOCAL_VERSION_FOLDER_DIALOG = 'SHOW_LOCAL_VERSION_FOLDER_DIALOG',
|
||||
BISECT_COMMANDS_TOGGLE = 'BISECT_COMMANDS_TOGGLE',
|
||||
CLEAR_CONSOLE = 'CLEAR_CONSOLE'
|
||||
}
|
||||
|
||||
export const ipcMainEvents = [
|
||||
IpcEvents.FS_SAVE_FIDDLE_DIALOG,
|
||||
IpcEvents.FS_SAVE_FIDDLE,
|
||||
IpcEvents.SHOW_WARNING_DIALOG,
|
||||
IpcEvents.SHOW_CONFIRMATION_DIALOG,
|
||||
IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG
|
||||
IpcEvents.SHOW_CONFIRMATION_DIALOG
|
||||
];
|
||||
|
||||
export const ipcRendererEvents = [
|
||||
@@ -50,9 +46,7 @@ export const ipcRendererEvents = [
|
||||
IpcEvents.FS_SAVE_FIDDLE_FORGE,
|
||||
IpcEvents.FS_SAVE_FIDDLE_GIST,
|
||||
IpcEvents.SHOW_WELCOME_TOUR,
|
||||
IpcEvents.CLEAR_CONSOLE,
|
||||
IpcEvents.LOAD_LOCAL_VERSION_FOLDER,
|
||||
IpcEvents.BISECT_COMMANDS_TOGGLE
|
||||
IpcEvents.CLEAR_CONSOLE
|
||||
];
|
||||
|
||||
export const WEBCONTENTS_READY_FOR_IPC_SIGNAL = 'WEBCONTENTS_READY_FOR_IPC_SIGNAL';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@import (inline) "../../node_modules/@blueprintjs/core/lib/css/blueprint.css";
|
||||
@import (inline) "../../node_modules/@blueprintjs/select/lib/css/blueprint-select.css";
|
||||
@import (inline) "../../node_modules/@blueprintjs/icons/lib/css/blueprint-icons.css";
|
||||
@import (inline) "../../node_modules/@blueprintjs/core/lib/less/variables.less";
|
||||
@import "~@blueprintjs/core/lib/css/blueprint.css";
|
||||
@import "~@blueprintjs/select/lib/css/blueprint-select.css";
|
||||
@import "~@blueprintjs/icons/lib/css/blueprint-icons.css";
|
||||
@import "~@blueprintjs/core/lib/less/variables.less";
|
||||
|
||||
// Override some of the colors
|
||||
.fiddle.bp3-dark {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
button.version-chooser.bp3-button {
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
header {
|
||||
box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.2), 0 0 0 rgba(16, 22, 26, 0), 0 1px 1px rgba(16, 22, 26, 0.4);
|
||||
//border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background-color: @background-3;
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
@@ -19,7 +20,6 @@ header {
|
||||
select {
|
||||
-webkit-app-region: no-drag;
|
||||
margin-bottom: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
select {
|
||||
|
||||
@@ -16,4 +16,5 @@
|
||||
@import "components/chrome-mac.less";
|
||||
@import "components/editors.less";
|
||||
@import "components/tour.less";
|
||||
@import "components/commands-version-chooser.less";
|
||||
@import "components/show-me.less";
|
||||
|
||||
@@ -7,7 +7,7 @@ import { isDevMode } from '../utils/devmode';
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function setupDevTools(): Promise<void> {
|
||||
if (!isDevMode()) return;
|
||||
if (!isDevMode) return;
|
||||
|
||||
const {
|
||||
default: installExtension,
|
||||
|
||||
+1
-18
@@ -1,4 +1,4 @@
|
||||
import { dialog, IpcMainEvent } from 'electron';
|
||||
import { dialog } from 'electron';
|
||||
import { IpcEvents } from '../ipc-events';
|
||||
import { ipcMainManager } from './ipc';
|
||||
import { getOrCreateMainWindow } from './windows';
|
||||
@@ -17,10 +17,6 @@ export function setupDialogs() {
|
||||
showConfirmationDialog(args);
|
||||
});
|
||||
|
||||
ipcMainManager.on(IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG, async (event) => {
|
||||
await showOpenDialog(event);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,16 +42,3 @@ function showConfirmationDialog(args: Electron.MessageBoxOptions) {
|
||||
...args
|
||||
});
|
||||
}
|
||||
|
||||
async function showOpenDialog(event: IpcMainEvent) {
|
||||
const { filePaths } = await dialog.showOpenDialog({
|
||||
title: 'Open Folder',
|
||||
properties: ['openDirectory']
|
||||
});
|
||||
|
||||
if (!filePaths || filePaths.length < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.reply(IpcEvents.LOAD_LOCAL_VERSION_FOLDER, [filePaths[0]]);
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,6 +1,5 @@
|
||||
import { app } from 'electron';
|
||||
|
||||
import { isDevMode } from '../utils/devmode';
|
||||
import { setupAboutPanel } from '../utils/set-about-panel';
|
||||
import { setupDevTools } from './devtools';
|
||||
import { setupDialogs } from './dialogs';
|
||||
@@ -16,7 +15,6 @@ import { getOrCreateMainWindow } from './windows';
|
||||
*/
|
||||
export async function onReady() {
|
||||
await onFirstRunMaybe();
|
||||
if (!isDevMode()) process.env.NODE_ENV = 'production';
|
||||
|
||||
getOrCreateMainWindow();
|
||||
setupAboutPanel();
|
||||
@@ -60,6 +58,8 @@ export function onWindowsAllClosed() {
|
||||
* Exported for testing purposes.
|
||||
*/
|
||||
export function main() {
|
||||
console.log(`Welcome to Fiddle ${app.getVersion()}`);
|
||||
|
||||
// Handle creating/removing shortcuts on Windows when
|
||||
// installing/uninstalling.
|
||||
if (shouldQuit()) {
|
||||
|
||||
+7
-12
@@ -144,7 +144,7 @@ function getShowMeMenuItem(key: string, item: string | Templates): MenuItemConst
|
||||
if (typeof item === 'string') {
|
||||
return {
|
||||
label: key,
|
||||
click: () => ipcMainManager.send(IpcEvents.FS_OPEN_TEMPLATE, [key])
|
||||
click: () => ipcMainManager.send(IpcEvents.FS_OPEN_TEMPLATE, [ key ])
|
||||
};
|
||||
}
|
||||
|
||||
@@ -160,10 +160,10 @@ function getShowMeMenu(): MenuItemConstructorOptions {
|
||||
const showMeMenu: Array<MenuItemConstructorOptions> = Object.keys(SHOW_ME_TEMPLATES)
|
||||
.map((key) => getShowMeMenuItem(key, SHOW_ME_TEMPLATES[key]));
|
||||
|
||||
return {
|
||||
label: 'Show Me',
|
||||
submenu: showMeMenu
|
||||
};
|
||||
return {
|
||||
label: 'Show Me',
|
||||
submenu: showMeMenu
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,16 +251,11 @@ export function setupMenu() {
|
||||
item.submenu.push({ type: 'separator' }, { role: 'resetZoom' }, { role: 'zoomIn' }, { role: 'zoomOut' }); // Add zooming actions
|
||||
item.submenu.push({ type: 'separator' }, {
|
||||
label: 'Toggle Soft Wrap',
|
||||
click: () => ipcMainManager.send(IpcEvents.MONACO_TOGGLE_OPTION, ['wordWrap']),
|
||||
click: () => ipcMainManager.send(IpcEvents.MONACO_TOGGLE_OPTION, [ 'wordWrap' ]),
|
||||
});
|
||||
item.submenu.push({ type: 'separator' }, {
|
||||
label: 'Toggle Mini Map',
|
||||
click: () => ipcMainManager.send(IpcEvents.MONACO_TOGGLE_OPTION, ['minimap.enabled']),
|
||||
});
|
||||
item.submenu.push({ type: 'separator' }, {
|
||||
label: 'Toggle Bisect Helper',
|
||||
click: () => ipcMainManager.send(IpcEvents.BISECT_COMMANDS_TOGGLE),
|
||||
accelerator: 'CommandorControl+Shift+B',
|
||||
click: () => ipcMainManager.send(IpcEvents.MONACO_TOGGLE_OPTION, [ 'minimap.enabled' ]),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@ export function getMainWindowOptions(): Electron.BrowserWindowConstructorOptions
|
||||
height: 900,
|
||||
minHeight: 600,
|
||||
minWidth: 600,
|
||||
show: true,
|
||||
titleBarStyle: process.platform === 'darwin' ? 'hidden' : undefined,
|
||||
acceptFirstMouse: true,
|
||||
backgroundColor: '#1d2427',
|
||||
@@ -36,7 +37,7 @@ export function getMainWindowOptions(): Electron.BrowserWindowConstructorOptions
|
||||
export function createMainWindow(): Electron.BrowserWindow {
|
||||
console.log(`Creating main window`);
|
||||
const browserWindow = new BrowserWindow(getMainWindowOptions());
|
||||
browserWindow.loadFile('./dist/static/index.html');
|
||||
browserWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
|
||||
|
||||
browserWindow.webContents.once('dom-ready', () => {
|
||||
browserWindow.show();
|
||||
|
||||
@@ -21,6 +21,9 @@ import { appState } from './state';
|
||||
import { getTheme } from './themes';
|
||||
import { TouchBarManager } from './touch-bar-manager';
|
||||
|
||||
// Import style
|
||||
require('../less/root.less');
|
||||
|
||||
/**
|
||||
* The top-level class controlling the whole app. This is *not* a React component,
|
||||
* but it does eventually render all components.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as fsType from 'fs-extra';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
|
||||
import { fancyImport } from '../utils/import';
|
||||
import { normalizeVersion } from '../utils/normalize-version';
|
||||
import { USER_DATA_PATH } from './constants';
|
||||
import { getOfflineTypeDefinitionPath } from './fetch-types';
|
||||
@@ -24,7 +23,6 @@ export class BinaryManager {
|
||||
*/
|
||||
public async remove(iVersion: string): Promise<void> {
|
||||
const version = normalizeVersion(iVersion);
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
let isDeleted = false;
|
||||
|
||||
// utility to re-run removal functions upon failure
|
||||
@@ -74,7 +72,6 @@ export class BinaryManager {
|
||||
*/
|
||||
public async setup(iVersion: string): Promise<void> {
|
||||
const version = normalizeVersion(iVersion);
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
const { promisify } = await import('util');
|
||||
const eDownload = promisify(require('electron-download'));
|
||||
|
||||
@@ -143,7 +140,6 @@ export class BinaryManager {
|
||||
* @returns {Promise<Array<string>>}
|
||||
*/
|
||||
public async getDownloadedVersions(): Promise<Array<string>> {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
const downloadPath = path.join(USER_DATA_PATH, 'electron-bin');
|
||||
console.log(`BinaryManager: Checking for downloaded versions`);
|
||||
|
||||
@@ -173,13 +169,11 @@ export class BinaryManager {
|
||||
*/
|
||||
public async getIsDownloaded(version: string, dir?: string): Promise<boolean> {
|
||||
const expectedPath = this.getElectronBinaryPath(version, dir);
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
|
||||
return fs.existsSync(expectedPath);
|
||||
}
|
||||
|
||||
public async removeTypeDefsForVersion(version: string) {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
const _version = normalizeVersion(version);
|
||||
const typeDefsDir = path.dirname(getOfflineTypeDefinitionPath(_version));
|
||||
|
||||
@@ -212,7 +206,7 @@ export class BinaryManager {
|
||||
*/
|
||||
private unzip(zipPath: string, extractPath: string): Promise<void> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const extract = (await fancyImport<any>('extract-zip')).default;
|
||||
const extract = require('extract-zip');
|
||||
|
||||
process.noAsar = true;
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import { ElectronVersion } from '../interfaces';
|
||||
|
||||
export class Bisector {
|
||||
public revList: Array<ElectronVersion>;
|
||||
public minRev: number;
|
||||
public maxRev: number;
|
||||
private pivot: number;
|
||||
|
||||
constructor(revList: Array<ElectronVersion>) {
|
||||
this.getCurrentVersion = this.getCurrentVersion.bind(this);
|
||||
this.continue = this.continue.bind(this);
|
||||
this.calculatePivot = this.calculatePivot.bind(this);
|
||||
|
||||
this.revList = revList;
|
||||
this.minRev = 0;
|
||||
this.maxRev = revList.length - 1;
|
||||
this.calculatePivot();
|
||||
}
|
||||
|
||||
public getCurrentVersion() {
|
||||
return this.revList[this.pivot];
|
||||
}
|
||||
|
||||
public continue(isGoodVersion: boolean) {
|
||||
let isBisectOver = false;
|
||||
if (this.maxRev - this.minRev <= 1) {
|
||||
isBisectOver = true;
|
||||
}
|
||||
|
||||
if (isGoodVersion) {
|
||||
const upPivot = Math.floor((this.maxRev - this.pivot) / 2) + this.pivot;
|
||||
this.minRev = this.pivot;
|
||||
if (upPivot !== this.maxRev && upPivot !== this.pivot) {
|
||||
this.pivot = upPivot;
|
||||
} else {
|
||||
isBisectOver = true;
|
||||
}
|
||||
} else {
|
||||
const downPivot = Math.floor((this.pivot - this.minRev) / 2) + this.minRev;
|
||||
this.maxRev = this.pivot;
|
||||
if (downPivot !== this.minRev && downPivot !== this.pivot) {
|
||||
this.pivot = downPivot;
|
||||
} else {
|
||||
isBisectOver = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isBisectOver) {
|
||||
return [this.revList[this.minRev], this.revList[this.maxRev]];
|
||||
} else {
|
||||
return this.revList[this.pivot];
|
||||
}
|
||||
}
|
||||
|
||||
private calculatePivot() {
|
||||
this.pivot = Math.floor((this.maxRev - this.minRev) / 2);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
import { Button } from '@blueprintjs/core';
|
||||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { AppState } from '../state';
|
||||
|
||||
interface BisectHandlerProps {
|
||||
appState: AppState;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class BisectHandler extends React.Component<BisectHandlerProps> {
|
||||
constructor(props: BisectHandlerProps) {
|
||||
super(props);
|
||||
|
||||
this.continueBisect = this.continueBisect.bind(this);
|
||||
this.terminateBisect = this.terminateBisect.bind(this);
|
||||
}
|
||||
|
||||
public continueBisect(isGood: boolean) {
|
||||
const { appState } = this.props;
|
||||
const response = appState.Bisector!.continue(isGood);
|
||||
if (Array.isArray(response)) {
|
||||
this.terminateBisect();
|
||||
const [minRev, maxRev] = response;
|
||||
appState.pushOutput(`[BISECT] Complete: Check between versions ${minRev.version} and ${maxRev.version}.`);
|
||||
} else {
|
||||
appState.setVersion(response.version);
|
||||
}
|
||||
}
|
||||
|
||||
public terminateBisect() {
|
||||
const { appState } = this.props;
|
||||
appState.Bisector = undefined;
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { appState } = this.props;
|
||||
if (!!appState.Bisector) {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
icon={'thumbs-up'}
|
||||
onClick={() => this.continueBisect(true)}
|
||||
/>
|
||||
<Button
|
||||
icon={'thumbs-down'}
|
||||
onClick={() => this.continueBisect(false)}
|
||||
/>
|
||||
<Button
|
||||
icon={'cross'}
|
||||
onClick={this.terminateBisect}
|
||||
>
|
||||
Cancel Bisect
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Button
|
||||
icon='git-branch'
|
||||
text='Bisect'
|
||||
onClick={appState.toggleBisectDialog}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, ButtonGroup, MenuItem } from '@blueprintjs/core';
|
||||
import { Button, MenuItem } from '@blueprintjs/core';
|
||||
import { ItemPredicate, ItemRenderer, Select } from '@blueprintjs/select';
|
||||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
@@ -71,7 +71,7 @@ export const filterItem: ItemPredicate<ElectronVersion> = (query, { version }) =
|
||||
*/
|
||||
export const renderItem: ItemRenderer<ElectronVersion> = (item, { handleClick, modifiers, query }) => {
|
||||
if (!modifiers.matchesPredicate) {
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -95,30 +95,6 @@ export interface VersionChooserProps {
|
||||
appState: AppState;
|
||||
}
|
||||
|
||||
|
||||
export const getVersionsFromAppState = (appState: AppState) => {
|
||||
const { versions, versionsToShow, statesToShow } = appState;
|
||||
|
||||
return sortedElectronMap<ElectronVersion>(versions, (_key, item) => item)
|
||||
.filter((item) => {
|
||||
if (!item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we want to show the version
|
||||
if (!versionsToShow.includes(getReleaseChannel(item))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we want to show the state
|
||||
if (!statesToShow.includes(item.state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* A dropdown allowing the selection of Electron versions. The actual
|
||||
* download is managed in the state.
|
||||
@@ -144,29 +120,48 @@ export class VersionChooser extends React.Component<VersionChooserProps, Version
|
||||
this.props.appState.setVersion(version);
|
||||
}
|
||||
|
||||
public getItems(): Array<ElectronVersion> {
|
||||
const { versions, versionsToShow, statesToShow } = this.props.appState;
|
||||
|
||||
return sortedElectronMap<ElectronVersion>(versions, (_key, item) => item)
|
||||
.filter((item) => {
|
||||
if (!item) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we want to show the version
|
||||
if (!versionsToShow.includes(getReleaseChannel(item))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we want to show the state
|
||||
if (!statesToShow.includes(item.state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { currentElectronVersion, Bisector } = this.props.appState;
|
||||
const { currentElectronVersion } = this.props.appState;
|
||||
const { version } = currentElectronVersion;
|
||||
|
||||
return (
|
||||
<ButtonGroup>
|
||||
<ElectronVersionSelect
|
||||
filterable={true}
|
||||
items={getVersionsFromAppState(this.props.appState)}
|
||||
itemRenderer={renderItem}
|
||||
itemPredicate={filterItem}
|
||||
onItemSelect={this.onItemSelect}
|
||||
noResults={<MenuItem disabled={true} text='No results.' />}
|
||||
disabled={!!Bisector}
|
||||
>
|
||||
<Button
|
||||
className='version-chooser'
|
||||
text={`Electron v${version}`}
|
||||
icon={getItemIcon(currentElectronVersion)}
|
||||
disabled={!!Bisector}
|
||||
/>
|
||||
</ElectronVersionSelect>
|
||||
</ButtonGroup>
|
||||
<ElectronVersionSelect
|
||||
filterable={true}
|
||||
items={this.getItems()}
|
||||
itemRenderer={renderItem}
|
||||
itemPredicate={filterItem}
|
||||
onItemSelect={this.onItemSelect}
|
||||
noResults={<MenuItem disabled={true} text='No results.' />}
|
||||
>
|
||||
<Button
|
||||
className='version-chooser'
|
||||
text={`Electron v${version}`}
|
||||
icon={getItemIcon(currentElectronVersion)}
|
||||
/>
|
||||
</ElectronVersionSelect>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import * as React from 'react';
|
||||
|
||||
import { AppState } from '../state';
|
||||
import { AddressBar } from './commands-address-bar';
|
||||
import { BisectHandler } from './commands-bisect';
|
||||
import { EditorDropdown } from './commands-editors';
|
||||
import { PublishButton } from './commands-publish-button';
|
||||
import { Runner } from './commands-runner';
|
||||
@@ -29,7 +28,6 @@ export class Commands extends React.Component<CommandsProps, {}> {
|
||||
|
||||
public render() {
|
||||
const { appState } = this.props;
|
||||
const { isBisectCommandShowing: isBisectCommandShowing } = appState;
|
||||
|
||||
return (
|
||||
<div className='commands'>
|
||||
@@ -38,15 +36,6 @@ export class Commands extends React.Component<CommandsProps, {}> {
|
||||
<VersionChooser appState={appState} />
|
||||
<Runner appState={appState} />
|
||||
</ControlGroup>
|
||||
{
|
||||
// tslint:disable-next-line jsx-no-multiline-js
|
||||
isBisectCommandShowing &&
|
||||
(
|
||||
<ControlGroup fill={true} vertical={false}>
|
||||
<BisectHandler appState={appState} />
|
||||
</ControlGroup>
|
||||
)
|
||||
}
|
||||
<ControlGroup fill={true} vertical={false}>
|
||||
<Button
|
||||
active={appState.isConsoleShowing}
|
||||
|
||||
@@ -6,9 +6,7 @@ import * as React from 'react';
|
||||
import * as semver from 'semver';
|
||||
|
||||
import { NpmVersion } from '../../interfaces';
|
||||
import { IpcEvents } from '../../ipc-events';
|
||||
import { getElectronNameForPlatform } from '../../utils/electron-name';
|
||||
import { ipcRendererManager } from '../ipc';
|
||||
import { AppState } from '../state';
|
||||
|
||||
export interface AddVersionDialogProps {
|
||||
@@ -18,7 +16,7 @@ export interface AddVersionDialogProps {
|
||||
export interface AddVersionDialogState {
|
||||
isValidElectron: boolean;
|
||||
isValidVersion: boolean;
|
||||
folderPath?: string;
|
||||
file?: File;
|
||||
version: string;
|
||||
}
|
||||
|
||||
@@ -41,15 +39,8 @@ export class AddVersionDialog extends React.Component<AddVersionDialogProps, Add
|
||||
|
||||
this.onSubmit = this.onSubmit.bind(this);
|
||||
this.onClose = this.onClose.bind(this);
|
||||
this.onChangeFile = this.onChangeFile.bind(this);
|
||||
this.onChangeVersion = this.onChangeVersion.bind(this);
|
||||
|
||||
ipcRendererManager.on(IpcEvents.LOAD_LOCAL_VERSION_FOLDER, (_event, [file]) => {
|
||||
this.setFolderPath(file);
|
||||
});
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
ipcRendererManager.removeAllListeners(IpcEvents.LOAD_LOCAL_VERSION_FOLDER);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,11 +48,16 @@ export class AddVersionDialog extends React.Component<AddVersionDialogProps, Add
|
||||
*
|
||||
* @param {React.ChangeEvent<HTMLInputElement>} event
|
||||
*/
|
||||
public async setFolderPath(folderPath: string) {
|
||||
public async onChangeFile(event: React.FormEvent<HTMLInputElement>) {
|
||||
const { files } = event.target as any;
|
||||
const { binaryManager } = this.props.appState;
|
||||
const isValidElectron = !!await binaryManager.getIsDownloaded('custom', folderPath);
|
||||
const file = files && files[0] ? files[0] : undefined;
|
||||
|
||||
this.setState({ folderPath, isValidElectron });
|
||||
const isValidElectron = !!(file
|
||||
&& file.path
|
||||
&& await binaryManager.getIsDownloaded('custom', file.path));
|
||||
|
||||
this.setState({ file, isValidElectron });
|
||||
}
|
||||
|
||||
public onChangeVersion(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
@@ -71,7 +67,7 @@ export class AddVersionDialog extends React.Component<AddVersionDialogProps, Add
|
||||
this.setState({
|
||||
version,
|
||||
isValidVersion,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,18 +76,18 @@ export class AddVersionDialog extends React.Component<AddVersionDialogProps, Add
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async onSubmit(): Promise<void> {
|
||||
const { folderPath, version } = this.state;
|
||||
const { file, version } = this.state;
|
||||
|
||||
if (!folderPath) return;
|
||||
if (!file) return;
|
||||
|
||||
const name = folderPath
|
||||
const name = file.path
|
||||
.slice(-20)
|
||||
.split(path.sep)
|
||||
.slice(1)
|
||||
.join(path.sep);
|
||||
|
||||
const toAdd: NpmVersion = {
|
||||
localPath: folderPath,
|
||||
localPath: file.path,
|
||||
version,
|
||||
name
|
||||
};
|
||||
@@ -133,16 +129,12 @@ export class AddVersionDialog extends React.Component<AddVersionDialogProps, Add
|
||||
|
||||
public render() {
|
||||
const { isAddVersionDialogShowing } = this.props.appState;
|
||||
const inputProps = {
|
||||
onClick: (e: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
|
||||
e.preventDefault();
|
||||
ipcRendererManager.send(IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG);
|
||||
}
|
||||
};
|
||||
const { folderPath } = this.state;
|
||||
const inputProps = { webkitdirectory: 'true' };
|
||||
const { file } = this.state;
|
||||
|
||||
const text = folderPath ||
|
||||
`Select the folder containing ${getElectronNameForPlatform()}...`;
|
||||
const text = file && file.path
|
||||
? file.path
|
||||
: `Select the folder containing ${getElectronNameForPlatform()}...`;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
@@ -153,6 +145,7 @@ export class AddVersionDialog extends React.Component<AddVersionDialogProps, Add
|
||||
>
|
||||
<div className='bp3-dialog-body'>
|
||||
<FileInput
|
||||
onInputChange={this.onChangeFile}
|
||||
id='custom-electron-version'
|
||||
inputProps={inputProps as any}
|
||||
text={text}
|
||||
@@ -170,9 +163,9 @@ export class AddVersionDialog extends React.Component<AddVersionDialogProps, Add
|
||||
}
|
||||
|
||||
private renderPath(): JSX.Element | null {
|
||||
const { folderPath, isValidElectron } = this.state;
|
||||
const { file, isValidElectron } = this.state;
|
||||
|
||||
if (!folderPath) return null;
|
||||
if (!file || !file.path) return null;
|
||||
|
||||
const info = isValidElectron
|
||||
? `We found an ${getElectronNameForPlatform()} in this folder.`
|
||||
@@ -215,7 +208,7 @@ export class AddVersionDialog extends React.Component<AddVersionDialogProps, Add
|
||||
isValidElectron: false,
|
||||
isValidVersion: false,
|
||||
version: '',
|
||||
folderPath: undefined
|
||||
file: undefined
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
import { Button, Dialog, Label, MenuItem } from '@blueprintjs/core';
|
||||
import { Select } from '@blueprintjs/select';
|
||||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { ElectronVersion } from '../../interfaces';
|
||||
import { Bisector } from '../bisect';
|
||||
import { AppState } from '../state';
|
||||
import { filterItem, getItemIcon, getVersionsFromAppState, renderItem } from './commands-version-chooser';
|
||||
|
||||
const ElectronVersionSelect = Select.ofType<ElectronVersion>();
|
||||
|
||||
export interface BisectDialogProps {
|
||||
appState: AppState;
|
||||
}
|
||||
|
||||
export interface BisectDialogState {
|
||||
startIndex?: number;
|
||||
endIndex?: number;
|
||||
allVersions: Array<ElectronVersion>;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "add version" dialog allows users to add custom builds of Electron.
|
||||
*
|
||||
* @class AddVersionDialog
|
||||
* @extends {React.Component<BisectDialogProps, BisectDialogState>}
|
||||
*/
|
||||
@observer
|
||||
export class BisectDialog extends React.Component<BisectDialogProps, BisectDialogState> {
|
||||
constructor(props: BisectDialogProps) {
|
||||
super(props);
|
||||
|
||||
this.onSubmit = this.onSubmit.bind(this);
|
||||
this.onClose = this.onClose.bind(this);
|
||||
this.onBeginSelect = this.onBeginSelect.bind(this);
|
||||
this.onEndSelect = this.onEndSelect.bind(this);
|
||||
|
||||
const allVersions = getVersionsFromAppState(this.props.appState);
|
||||
this.state = { allVersions };
|
||||
}
|
||||
|
||||
public onBeginSelect(version: ElectronVersion) {
|
||||
this.setState({ startIndex: this.state.allVersions.indexOf(version) });
|
||||
}
|
||||
|
||||
public onEndSelect(version: ElectronVersion) {
|
||||
this.setState({ endIndex: this.state.allVersions.indexOf(version) });
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the submission of the dialog
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async onSubmit(): Promise<void> {
|
||||
const { endIndex, startIndex, allVersions } = this.state;
|
||||
const { appState } = this.props;
|
||||
|
||||
if (endIndex === undefined || startIndex === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bisectRange = allVersions
|
||||
.slice(endIndex, startIndex + 1)
|
||||
.reverse();
|
||||
|
||||
appState.Bisector = new Bisector(bisectRange);
|
||||
const initialBisectPivot = appState.Bisector.getCurrentVersion().version;
|
||||
appState.setVersion(initialBisectPivot);
|
||||
this.onClose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the dialog
|
||||
*/
|
||||
public onClose() {
|
||||
this.props.appState.isBisectDialogShowing = false;
|
||||
}
|
||||
|
||||
get buttons() {
|
||||
const canSubmit =
|
||||
!!this.state.startIndex &&
|
||||
!!this.state.endIndex &&
|
||||
this.state.startIndex > this.state.endIndex;
|
||||
|
||||
return [
|
||||
(
|
||||
<Button
|
||||
icon='play'
|
||||
key='submit'
|
||||
disabled={!canSubmit}
|
||||
onClick={this.onSubmit}
|
||||
text='Begin'
|
||||
/>
|
||||
), (
|
||||
<Button
|
||||
icon='cross'
|
||||
key='cancel'
|
||||
onClick={this.onClose}
|
||||
text='Cancel'
|
||||
/>
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { isBisectDialogShowing } = this.props.appState;
|
||||
const { startIndex, endIndex, allVersions } = this.state;
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
isOpen={isBisectDialogShowing}
|
||||
onClose={this.onClose}
|
||||
title='Start a bisect session'
|
||||
className='dialog-add-version'
|
||||
>
|
||||
<div className='bp3-dialog-body'>
|
||||
<Label>
|
||||
Earliest Version
|
||||
<ElectronVersionSelect
|
||||
filterable={true}
|
||||
items={allVersions}
|
||||
itemRenderer={renderItem}
|
||||
itemPredicate={filterItem}
|
||||
onItemSelect={this.onBeginSelect}
|
||||
noResults={<MenuItem disabled={true} text='No results.' />}
|
||||
>
|
||||
<Button
|
||||
text={startIndex ? `v${allVersions[startIndex].version}` : ``}
|
||||
icon={startIndex ? getItemIcon(allVersions[startIndex]) : 'small-minus'}
|
||||
fill={true}
|
||||
/>
|
||||
</ElectronVersionSelect>
|
||||
</Label>
|
||||
<Label>
|
||||
Latest Version
|
||||
<ElectronVersionSelect
|
||||
filterable={true}
|
||||
items={allVersions.slice(0, startIndex!)}
|
||||
itemRenderer={renderItem}
|
||||
itemPredicate={filterItem}
|
||||
onItemSelect={this.onEndSelect}
|
||||
noResults={<MenuItem disabled={true} text='No results.' />}
|
||||
disabled={!startIndex}
|
||||
>
|
||||
<Button
|
||||
text={endIndex ? `v${allVersions[endIndex].version}` : ``}
|
||||
icon={endIndex ? getItemIcon(allVersions[endIndex]) : 'small-minus'}
|
||||
fill={true}
|
||||
disabled={!startIndex}
|
||||
/>
|
||||
</ElectronVersionSelect>
|
||||
</Label>
|
||||
</div>
|
||||
<div className='bp3-dialog-footer'>
|
||||
<div className='bp3-dialog-footer-actions'>
|
||||
{this.buttons}
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import * as React from 'react';
|
||||
import { AppState } from '../state';
|
||||
import { AddThemeDialog } from './dialog-add-theme';
|
||||
import { AddVersionDialog } from './dialog-add-version';
|
||||
import { BisectDialog } from './dialog-bisect';
|
||||
import { ConfirmDialog } from './dialog-confirm';
|
||||
import { TokenDialog } from './dialog-token';
|
||||
import { WarningDialog } from './dialog-warning';
|
||||
@@ -24,13 +23,7 @@ export interface DialogsProps {
|
||||
export class Dialogs extends React.Component<DialogsProps, {}> {
|
||||
public render() {
|
||||
const { appState } = this.props;
|
||||
const {
|
||||
isTokenDialogShowing,
|
||||
isSettingsShowing,
|
||||
isAddVersionDialogShowing,
|
||||
isThemeDialogShowing,
|
||||
isBisectDialogShowing
|
||||
} = appState;
|
||||
const { isTokenDialogShowing, isSettingsShowing, isAddVersionDialogShowing, isThemeDialogShowing } = appState;
|
||||
const maybeToken = isTokenDialogShowing
|
||||
? <TokenDialog key='dialogs' appState={appState} />
|
||||
: null;
|
||||
@@ -42,12 +35,9 @@ export class Dialogs extends React.Component<DialogsProps, {}> {
|
||||
: null;
|
||||
const maybeMonaco = isThemeDialogShowing ? <AddThemeDialog appState={appState} />
|
||||
: null;
|
||||
const maybeBisect = isBisectDialogShowing
|
||||
? <BisectDialog key='bisect-dialog' appState={appState} />
|
||||
: null;
|
||||
const eitherWarningOrPrompt = appState.isWarningDialogShowing
|
||||
? <WarningDialog appState={appState} />
|
||||
: <ConfirmDialog appState={appState} />;
|
||||
: <ConfirmDialog appState={appState}/>;
|
||||
|
||||
return (
|
||||
<div key='dialogs' className='dialogs'>
|
||||
@@ -55,7 +45,6 @@ export class Dialogs extends React.Component<DialogsProps, {}> {
|
||||
{maybeSettings}
|
||||
{maybeAddLocalVersion}
|
||||
{maybeMonaco}
|
||||
{maybeBisect}
|
||||
{eitherWarningOrPrompt}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { reaction } from 'mobx';
|
||||
import { observer } from 'mobx-react';
|
||||
import * as MonacoType from 'monaco-editor';
|
||||
// tslint:disable-next-line:no-submodule-imports
|
||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
||||
import * as React from 'react';
|
||||
import { Mosaic, MosaicBranch, MosaicNode, MosaicWindow, MosaicWindowProps } from 'react-mosaic-component';
|
||||
|
||||
@@ -20,7 +21,7 @@ import { renderNonIdealState } from './editors-non-ideal-state';
|
||||
import { DocsDemoGoHomeButton, MaximizeButton, RemoveButton } from './editors-toolbar-button';
|
||||
import { ShowMe } from './show-me';
|
||||
|
||||
const defaultMonacoOptions: MonacoType.editor.IEditorOptions = {
|
||||
const defaultMonacoOptions: monaco.editor.IEditorOptions = {
|
||||
minimap: {
|
||||
enabled: false
|
||||
},
|
||||
@@ -40,9 +41,9 @@ export interface EditorsProps {
|
||||
}
|
||||
|
||||
export interface EditorsState {
|
||||
monaco?: typeof MonacoType;
|
||||
monaco?: typeof monaco;
|
||||
isMounted?: boolean;
|
||||
monacoOptions: MonacoType.editor.IEditorOptions;
|
||||
monacoOptions: monaco.editor.IEditorOptions;
|
||||
}
|
||||
|
||||
@observer
|
||||
@@ -132,7 +133,7 @@ export class Editors extends React.Component<EditorsProps, EditorsState> {
|
||||
|
||||
Object.keys(window.ElectronFiddle.editors)
|
||||
.forEach((key) => {
|
||||
const editor: MonacoType.editor.IStandaloneCodeEditor | null
|
||||
const editor: monaco.editor.IStandaloneCodeEditor | null
|
||||
= window.ElectronFiddle.editors[key];
|
||||
|
||||
if (editor) {
|
||||
@@ -229,7 +230,6 @@ export class Editors extends React.Component<EditorsProps, EditorsState> {
|
||||
*/
|
||||
public renderEditor(id: EditorId): JSX.Element | null {
|
||||
const { appState } = this.props;
|
||||
const { monaco } = this.state;
|
||||
|
||||
return (
|
||||
<Editor
|
||||
@@ -243,7 +243,6 @@ export class Editors extends React.Component<EditorsProps, EditorsState> {
|
||||
|
||||
public render() {
|
||||
const { appState } = this.props;
|
||||
const { monaco } = this.state;
|
||||
|
||||
if (!monaco) return null;
|
||||
|
||||
@@ -273,8 +272,6 @@ export class Editors extends React.Component<EditorsProps, EditorsState> {
|
||||
*/
|
||||
public async loadMonaco(): Promise<void> {
|
||||
const { app } = window.ElectronFiddle;
|
||||
const loader = require('monaco-loader');
|
||||
const monaco = app.monaco || await loader();
|
||||
|
||||
if (!app.monaco) {
|
||||
app.monaco = monaco;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Button, Callout, FormGroup, MenuItem } from '@blueprintjs/core';
|
||||
import { ItemPredicate, ItemRenderer, Select } from '@blueprintjs/select';
|
||||
import { shell } from 'electron';
|
||||
import * as fsType from 'fs-extra';
|
||||
import * as fs from 'fs-extra';
|
||||
import { observer } from 'mobx-react';
|
||||
import * as path from 'path';
|
||||
import * as React from 'react';
|
||||
@@ -113,7 +113,6 @@ export class AppearanceSettings extends React.Component<
|
||||
*/
|
||||
public async createNewThemeFromCurrent(): Promise<boolean> {
|
||||
const { appState } = this.props;
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
const theme = await getTheme(appState.theme);
|
||||
|
||||
try {
|
||||
@@ -147,8 +146,6 @@ export class AppearanceSettings extends React.Component<
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
public async openThemeFolder(): Promise<boolean> {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
|
||||
try {
|
||||
await fs.ensureDir(THEMES_PATH);
|
||||
await shell.showItemInFolder(THEMES_PATH);
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import * as fsType from 'fs-extra';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as MonacoType from 'monaco-editor';
|
||||
import * as path from 'path';
|
||||
|
||||
import { ElectronVersion, ElectronVersionSource } from '../interfaces';
|
||||
import { callIn } from '../utils/call-in';
|
||||
import { fancyImport } from '../utils/import';
|
||||
import { USER_DATA_PATH } from './constants';
|
||||
|
||||
const definitionPath = path.join(USER_DATA_PATH, 'electron-typedef');
|
||||
@@ -53,7 +52,6 @@ export function getOfflineTypeDefinitionPath(version: string): string {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export async function getOfflineTypeDefinitions(version: string): Promise<boolean> {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
return fs.existsSync(getOfflineTypeDefinitionPath(version));
|
||||
}
|
||||
|
||||
@@ -65,7 +63,6 @@ export async function getOfflineTypeDefinitions(version: string): Promise<boolea
|
||||
* @returns {void}
|
||||
*/
|
||||
export async function getDownloadedVersionTypeDefs(version: ElectronVersion): Promise<string | null> {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
await fs.mkdirp(definitionPath);
|
||||
const offlinePath = getOfflineTypeDefinitionPath(version.version);
|
||||
|
||||
@@ -93,7 +90,6 @@ export async function getDownloadedVersionTypeDefs(version: ElectronVersion): Pr
|
||||
|
||||
export async function getLocalVersionTypeDefs(version: ElectronVersion) {
|
||||
if (version.source === ElectronVersionSource.local && !!version.localPath) {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
const typesPath = getLocalTypePathForVersion(version);
|
||||
if (!!typesPath && fs.existsSync(typesPath)) {
|
||||
return fs.readFile(typesPath, 'utf-8');
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import * as fsType from 'fs-extra';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
|
||||
import { EditorValues, Files, FileTransform } from '../interfaces';
|
||||
import { IpcEvents } from '../ipc-events';
|
||||
import { INDEX_HTML_NAME, MAIN_JS_NAME, PACKAGE_NAME, PRELOAD_JS_NAME, RENDERER_JS_NAME } from '../shared-constants';
|
||||
import { DEFAULT_OPTIONS, PackageJsonOptions } from '../utils/get-package';
|
||||
import { fancyImport } from '../utils/import';
|
||||
import { ipcRendererManager } from './ipc';
|
||||
import { AppState } from './state';
|
||||
import { getTemplateValues } from './templates';
|
||||
@@ -149,8 +148,6 @@ export class FileManager {
|
||||
*/
|
||||
public async cleanup(dir?: string): Promise<boolean> {
|
||||
if (dir) {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
|
||||
if (fs.existsSync(dir)) {
|
||||
try {
|
||||
await fs.remove(dir);
|
||||
@@ -175,7 +172,6 @@ export class FileManager {
|
||||
public async saveToTemp(
|
||||
options: PackageJsonOptions, ...transforms: Array<FileTransform>
|
||||
): Promise<string> {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
const tmp = await import('tmp');
|
||||
const files = await this.getFiles(options, ...transforms);
|
||||
const dir = tmp.dirSync();
|
||||
@@ -203,7 +199,6 @@ export class FileManager {
|
||||
*/
|
||||
private async readFile(filePath: string): Promise<string> {
|
||||
try {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
return await fs.readFile(filePath, 'utf-8');
|
||||
} catch (error) {
|
||||
console.log(`FileManager: Could not read ${filePath}`, error);
|
||||
@@ -221,7 +216,6 @@ export class FileManager {
|
||||
*/
|
||||
private async saveFile(filePath: string, content: string): Promise<void> {
|
||||
try {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
return await fs.outputFile(filePath, content, { encoding: 'utf-8' });
|
||||
} catch (error) {
|
||||
console.log(`FileManager: Could not save ${filePath}`, error);
|
||||
@@ -239,7 +233,6 @@ export class FileManager {
|
||||
*/
|
||||
private async removeFile(filePath: string): Promise<void> {
|
||||
try {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
return await fs.remove(filePath);
|
||||
} catch (error) {
|
||||
console.log(`FileManager: Could not remove ${filePath}`, error);
|
||||
|
||||
+35
-55
@@ -1,4 +1,4 @@
|
||||
import * as fsType from 'fs-extra';
|
||||
import * as fs from 'fs-extra';
|
||||
import { action, autorun, computed, observable, when } from 'mobx';
|
||||
import { MosaicNode } from 'react-mosaic-component';
|
||||
|
||||
@@ -20,11 +20,9 @@ import { arrayToStringMap } from '../utils/array-to-stringmap';
|
||||
import { EditorBackup, getEditorBackup } from '../utils/editor-backup';
|
||||
import { createMosaicArrangement, getVisibleMosaics } from '../utils/editors-mosaic-arrangement';
|
||||
import { getName } from '../utils/get-title';
|
||||
import { fancyImport } from '../utils/import';
|
||||
import { normalizeVersion } from '../utils/normalize-version';
|
||||
import { isEditorBackup, isEditorId, isPanelId } from '../utils/type-checks';
|
||||
import { BinaryManager } from './binary';
|
||||
import { Bisector } from './bisect';
|
||||
import { DEFAULT_MOSAIC_ARRANGEMENT } from './constants';
|
||||
import { getContent, isContentUnchanged } from './content';
|
||||
import { getLocalTypePathForVersion, updateEditorTypeDefinitions } from './fetch-types';
|
||||
@@ -67,6 +65,7 @@ export class AppState {
|
||||
// -- Persisted settings ------------------
|
||||
@observable public version: string = defaultVersion;
|
||||
@observable public theme: string | null = localStorage.getItem('theme');
|
||||
@observable public isClearingConsoleOnRun: boolean = !!this.retrieve('isClearingConsoleOnRun');
|
||||
@observable public gitHubAvatarUrl: string | null = localStorage.getItem('gitHubAvatarUrl');
|
||||
@observable public gitHubName: string | null = localStorage.getItem('gitHubName');
|
||||
@observable public gitHubLogin: string | null = localStorage.getItem('gitHubLogin');
|
||||
@@ -74,43 +73,39 @@ export class AppState {
|
||||
@observable public gitHubPublishAsPublic: boolean = !!this.retrieve('gitHubPublishAsPublic');
|
||||
@observable public versionsToShow: Array<ElectronReleaseChannel> =
|
||||
this.retrieve('versionsToShow') as Array<ElectronReleaseChannel>
|
||||
|| [ElectronReleaseChannel.stable, ElectronReleaseChannel.beta];
|
||||
|| [ ElectronReleaseChannel.stable, ElectronReleaseChannel.beta ];
|
||||
@observable public statesToShow: Array<ElectronVersionState> =
|
||||
this.retrieve('statesToShow') as Array<ElectronVersionState>
|
||||
|| [ElectronVersionState.downloading, ElectronVersionState.ready, ElectronVersionState.unknown];
|
||||
this.retrieve('statesToShow') as Array<ElectronVersionState>
|
||||
|| [ ElectronVersionState.downloading, ElectronVersionState.ready, ElectronVersionState.unknown ];
|
||||
@observable public isKeepingUserDataDirs: boolean = !!this.retrieve('isKeepingUserDataDirs');
|
||||
@observable public isEnablingElectronLogging: boolean = !!this.retrieve('isEnablingElectronLogging');
|
||||
@observable public isClearingConsoleOnRun: boolean = !!this.retrieve('isClearingConsoleOnRun');
|
||||
|
||||
@observable public binaryManager: BinaryManager = new BinaryManager();
|
||||
|
||||
// -- Various session-only state ------------------
|
||||
@observable public gistId: string = '';
|
||||
@observable public isPublishing: boolean = false;
|
||||
@observable public versions: Record<string, ElectronVersion> = arrayToStringMap(knownVersions);
|
||||
@observable public output: Array<OutputEntry> = [];
|
||||
@observable public localPath: string | undefined;
|
||||
@observable public isUpdatingElectronVersions = false;
|
||||
@observable public warningDialogTexts = { label: '', ok: 'Okay', cancel: 'Cancel' };
|
||||
@observable public confirmationDialogTexts = { label: '', ok: 'Okay', cancel: 'Cancel' };
|
||||
@observable public warningDialogLastResult: boolean | null = null;
|
||||
@observable public confirmationPromptLastResult: boolean | null = null;
|
||||
@observable public isRunning = false;
|
||||
@observable public mosaicArrangement: MosaicNode<MosaicId> | null = DEFAULT_MOSAIC_ARRANGEMENT;
|
||||
@observable public templateName: string | undefined;
|
||||
@observable public currentDocsDemoPage: DocsDemoPage = DocsDemoPage.DEFAULT;
|
||||
@observable public localTypeWatcher: fsType.FSWatcher | undefined;
|
||||
@observable public binaryManager: BinaryManager = new BinaryManager();
|
||||
@observable public Bisector: Bisector | undefined;
|
||||
|
||||
@observable public isPublishing: boolean = false;
|
||||
@observable public isRunning: boolean = false;
|
||||
@observable public isUnsaved: boolean = false;
|
||||
@observable public isUpdatingElectronVersions: boolean = false;
|
||||
|
||||
// -- Various "isShowing" settings ------------------
|
||||
@observable public isBisectCommandShowing: boolean;
|
||||
@observable public isConsoleShowing: boolean = false;
|
||||
@observable public isTokenDialogShowing: boolean = false;
|
||||
@observable public isWarningDialogShowing: boolean = false;
|
||||
@observable public isConfirmationPromptShowing: boolean = false;
|
||||
@observable public isSettingsShowing: boolean = false;
|
||||
@observable public isBisectDialogShowing: boolean = false;
|
||||
@observable public isUnsaved: boolean = false;
|
||||
@observable public isAddVersionDialogShowing: boolean = false;
|
||||
@observable public isThemeDialogShowing: boolean = false;
|
||||
@observable public isTourShowing: boolean = !localStorage.getItem('hasShownTour');
|
||||
@@ -132,18 +127,15 @@ export class AppState {
|
||||
this.setVersion = this.setVersion.bind(this);
|
||||
this.showTour = this.showTour.bind(this);
|
||||
this.signOutGitHub = this.signOutGitHub.bind(this);
|
||||
this.toggleBisectCommands = this.toggleBisectCommands.bind(this);
|
||||
this.toggleAuthDialog = this.toggleAuthDialog.bind(this);
|
||||
this.toggleConsole = this.toggleConsole.bind(this);
|
||||
this.clearConsole = this.clearConsole.bind(this);
|
||||
this.toggleSettings = this.toggleSettings.bind(this);
|
||||
this.toggleBisectDialog = this.toggleBisectDialog.bind(this);
|
||||
this.updateElectronVersions = this.updateElectronVersions.bind(this);
|
||||
|
||||
ipcRendererManager.on(IpcEvents.OPEN_SETTINGS, this.toggleSettings);
|
||||
ipcRendererManager.on(IpcEvents.SHOW_WELCOME_TOUR, this.showTour);
|
||||
ipcRendererManager.on(IpcEvents.CLEAR_CONSOLE, this.clearConsole);
|
||||
ipcRendererManager.on(IpcEvents.BISECT_COMMANDS_TOGGLE, this.toggleBisectCommands);
|
||||
|
||||
// Setup auto-runs
|
||||
autorun(() => this.save('theme', this.theme));
|
||||
@@ -249,13 +241,6 @@ export class AppState {
|
||||
this.output = [];
|
||||
}
|
||||
|
||||
@action public toggleBisectCommands() {
|
||||
// guard against hiding the commands when executing a bisect
|
||||
if (!this.Bisector && !this.isBisectDialogShowing) {
|
||||
this.isBisectCommandShowing = !this.isBisectCommandShowing;
|
||||
}
|
||||
}
|
||||
|
||||
@action public toggleAddVersionDialog() {
|
||||
this.isAddVersionDialogShowing = !this.isAddVersionDialogShowing;
|
||||
}
|
||||
@@ -276,10 +261,6 @@ export class AppState {
|
||||
}
|
||||
}
|
||||
|
||||
@action public toggleBisectDialog() {
|
||||
this.isBisectDialogShowing = !this.isBisectDialogShowing;
|
||||
}
|
||||
|
||||
@action public toggleConfirmationPromptDialog() {
|
||||
this.isConfirmationPromptShowing = !this.isConfirmationPromptShowing;
|
||||
|
||||
@@ -336,12 +317,12 @@ export class AppState {
|
||||
this.updateDownloadedVersionState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a version of Electron
|
||||
*
|
||||
* @param {string} input
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
/**
|
||||
* Remove a version of Electron
|
||||
*
|
||||
* @param {string} input
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
@action public async removeVersion(input: string) {
|
||||
const version = normalizeVersion(input);
|
||||
const release = this.versions[version];
|
||||
@@ -375,12 +356,12 @@ export class AppState {
|
||||
this.updateDownloadedVersionState();
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a version of Electron.
|
||||
*
|
||||
* @param {string} input
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
/**
|
||||
* Download a version of Electron.
|
||||
*
|
||||
* @param {string} input
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
@action public async downloadVersion(input: string) {
|
||||
const version = normalizeVersion(input);
|
||||
console.log(`State: Downloading Electron ${version}`);
|
||||
@@ -404,12 +385,12 @@ export class AppState {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a version of Electron (and download it if necessary).
|
||||
*
|
||||
* @param {string} input
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
/**
|
||||
* Select a version of Electron (and download it if necessary).
|
||||
*
|
||||
* @param {string} input
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
@action public async setVersion(input: string) {
|
||||
const version = normalizeVersion(input);
|
||||
|
||||
@@ -434,7 +415,6 @@ export class AppState {
|
||||
const versionObject = this.versions[version];
|
||||
|
||||
if (versionObject.source === ElectronVersionSource.local) {
|
||||
const fs = await fancyImport<typeof fsType>('fs-extra');
|
||||
const typePath = getLocalTypePathForVersion(versionObject);
|
||||
console.info(`TypeDefs: Watching file for local version ${version} at path ${typePath}`);
|
||||
this.localTypeWatcher = fs.watch(typePath!, async () => {
|
||||
@@ -454,11 +434,11 @@ export class AppState {
|
||||
await this.downloadVersion(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Go and check which versions have already been downloaded.
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
/**
|
||||
* Go and check which versions have already been downloaded.
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
@action public async updateDownloadedVersionState(): Promise<void> {
|
||||
const downloadedVersions = await this.binaryManager.getDownloadedVersions();
|
||||
const updatedVersions = { ...this.versions };
|
||||
@@ -595,7 +575,7 @@ export class AppState {
|
||||
*/
|
||||
@action public showMosaic(id: MosaicId) {
|
||||
const currentlyVisible = getVisibleMosaics(this.mosaicArrangement);
|
||||
this.setVisibleMosaics([...currentlyVisible, id]);
|
||||
this.setVisibleMosaics([ ...currentlyVisible, id ]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import * as fsExtraType from 'fs-extra';
|
||||
import * as pathType from 'path';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
|
||||
import { EditorValues } from '../interfaces';
|
||||
import { INDEX_HTML_NAME, MAIN_JS_NAME, PRELOAD_JS_NAME, RENDERER_JS_NAME } from '../shared-constants';
|
||||
import { fancyImport } from '../utils/import';
|
||||
|
||||
/**
|
||||
* Returns expected content for a given name.
|
||||
@@ -12,8 +11,6 @@ import { fancyImport } from '../utils/import';
|
||||
* @returns {Promise<EditorValues>}
|
||||
*/
|
||||
export async function getTemplateValues(name: string): Promise<EditorValues> {
|
||||
const path = await fancyImport<typeof pathType>('path');
|
||||
const fs = await fancyImport<typeof fsExtraType>('fs-extra');
|
||||
const templatesPath = path.join(__dirname, '../../static/show-me');
|
||||
const templatePath = path.join(templatesPath, name.toLowerCase());
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -6,11 +6,9 @@
|
||||
<title>Electron Fiddle</title>
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="../src/less/root.less">
|
||||
<style id="fiddle-theme"></style>
|
||||
</head>
|
||||
<body class="fiddle">
|
||||
<div id="app"></div>
|
||||
<script src="../src/renderer/app.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -12,16 +12,13 @@ app.on('ready', () => {
|
||||
|
||||
// Show an "Open File" dialog and attempt to open
|
||||
// the chosen file in our window.
|
||||
dialog.showOpenDialog(mainWindow, {
|
||||
//
|
||||
// If you provide a callback, the method will be asynchronous,
|
||||
// but in thise case, we'll just use the synchronous variant.
|
||||
const file = dialog.showOpenDialog({
|
||||
title: 'Hello!',
|
||||
properties: ['openFile']
|
||||
}).then(result => {
|
||||
if (result.canceled) {
|
||||
console.log('Dialog was canceled')
|
||||
} else {
|
||||
const file = result.filePaths[0]
|
||||
mainWindow.loadURL(`file://${file}`)
|
||||
}
|
||||
}).catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
mainWindow.loadURL(`file://${file}`)
|
||||
})
|
||||
|
||||
+12
-19
@@ -1,6 +1,12 @@
|
||||
import { setupDevTools } from '../../src/main/devtools';
|
||||
import { isDevMode } from '../../src/utils/devmode';
|
||||
jest.mock('../../src/utils/devmode');
|
||||
|
||||
let mockIsDevMode = false;
|
||||
|
||||
jest.mock('../../src/utils/devmode', () => ({
|
||||
get isDevMode() {
|
||||
return mockIsDevMode;
|
||||
}
|
||||
}));
|
||||
|
||||
jest.mock('electron-devtools-installer', () => ({
|
||||
default: jest.fn(),
|
||||
@@ -11,31 +17,18 @@ jest.mock('electron-devtools-installer', () => ({
|
||||
describe('devtools', () => {
|
||||
it('does not set up developer tools if not in dev mode', () => {
|
||||
const devtools = require('electron-devtools-installer');
|
||||
(isDevMode as jest.Mock).mockReturnValue(false);
|
||||
|
||||
setupDevTools();
|
||||
|
||||
expect(devtools.default).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('sets up developer tools if in dev mode', () => {
|
||||
it('sets up developer tools if not in dev mode', () => {
|
||||
const devtools = require('electron-devtools-installer');
|
||||
(isDevMode as jest.Mock).mockReturnValue(true);
|
||||
|
||||
mockIsDevMode = true;
|
||||
setupDevTools();
|
||||
|
||||
expect(devtools.default).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('catch error in setting up developer tools', async (done) => {
|
||||
const devtools = require('electron-devtools-installer');
|
||||
// throw devtool error
|
||||
devtools.default.mockRejectedValue(new Error('devtool error'));
|
||||
(isDevMode as jest.Mock).mockReturnValue(true);
|
||||
|
||||
try {
|
||||
await setupDevTools();
|
||||
done();
|
||||
} catch (e) {
|
||||
expect(e).toMatch('error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,96 +3,26 @@ import { setupDialogs } from '../../src/main/dialogs';
|
||||
import { ipcMainManager } from '../../src/main/ipc';
|
||||
|
||||
import { dialog } from 'electron';
|
||||
import { flushPromises } from '../utils';
|
||||
|
||||
jest.mock('../../src/main/windows');
|
||||
|
||||
describe('dialogs', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
setupDialogs();
|
||||
});
|
||||
|
||||
it('sets up dialogs', () => {
|
||||
setupDialogs();
|
||||
|
||||
expect(ipcMainManager.eventNames()).toEqual([
|
||||
IpcEvents.SHOW_WARNING_DIALOG,
|
||||
IpcEvents.SHOW_CONFIRMATION_DIALOG,
|
||||
IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG
|
||||
IpcEvents.SHOW_CONFIRMATION_DIALOG
|
||||
]);
|
||||
});
|
||||
|
||||
describe('warning dialog', () => {
|
||||
it('shows dialog when triggering IPC event', () => {
|
||||
ipcMainManager.emit(IpcEvents.SHOW_WARNING_DIALOG, {}, { hi: 'hello' });
|
||||
expect(dialog.showMessageBox).toHaveBeenCalledWith(undefined, {
|
||||
type: 'warning',
|
||||
hi: 'hello'
|
||||
});
|
||||
});
|
||||
});
|
||||
it('tries to show a dialog if triggered', () => {
|
||||
setupDialogs();
|
||||
|
||||
describe('confirmation dialog', () => {
|
||||
it('shows dialog when triggering IPC event', () => {
|
||||
ipcMainManager.emit(IpcEvents.SHOW_CONFIRMATION_DIALOG, {}, { hi: 'hello' });
|
||||
expect(dialog.showMessageBox).toHaveBeenCalledWith(undefined, {
|
||||
type: 'warning',
|
||||
hi: 'hello'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('local version folder dialog', () => {
|
||||
it('shows dialog when triggering IPC event', () => {
|
||||
(dialog.showOpenDialog as jest.Mock).mockResolvedValue({
|
||||
filePaths: []
|
||||
});
|
||||
|
||||
ipcMainManager.emit(IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG, {
|
||||
reply: jest.fn()
|
||||
});
|
||||
expect(dialog.showOpenDialog).toHaveBeenCalledWith(expect.objectContaining({
|
||||
properties: ['openDirectory']
|
||||
}));
|
||||
});
|
||||
|
||||
it('triggers IPC load local version event', async () => {
|
||||
const replyFn = jest.fn();
|
||||
const paths = ['/test/path/'];
|
||||
|
||||
(dialog.showOpenDialog as jest.Mock).mockResolvedValue({
|
||||
filePaths: paths
|
||||
});
|
||||
|
||||
ipcMainManager.emit(IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG, {
|
||||
reply: replyFn
|
||||
});
|
||||
|
||||
await flushPromises();
|
||||
expect(replyFn).toHaveBeenCalledWith(IpcEvents.LOAD_LOCAL_VERSION_FOLDER, paths);
|
||||
});
|
||||
|
||||
it('does nothing if not given a path', async () => {
|
||||
const replyFn = jest.fn();
|
||||
|
||||
// empty array
|
||||
(dialog.showOpenDialog as jest.Mock).mockResolvedValue({
|
||||
filePaths: []
|
||||
});
|
||||
ipcMainManager.emit(IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG, {
|
||||
reply: replyFn
|
||||
});
|
||||
|
||||
await flushPromises();
|
||||
expect(replyFn).not.toHaveBeenCalled();
|
||||
|
||||
// nothing in response
|
||||
(dialog.showOpenDialog as jest.Mock).mockResolvedValue({});
|
||||
ipcMainManager.emit(IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG, {
|
||||
reply: replyFn
|
||||
});
|
||||
|
||||
await flushPromises();
|
||||
expect(replyFn).not.toHaveBeenCalled();
|
||||
ipcMainManager.emit(IpcEvents.SHOW_WARNING_DIALOG, {}, { hi: 'hello' });
|
||||
expect(dialog.showMessageBox).toHaveBeenCalledWith(undefined, {
|
||||
type: 'warning',
|
||||
hi: 'hello'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+2
-16
@@ -78,20 +78,6 @@ describe('menu', () => {
|
||||
(toggleMap as any).click();
|
||||
expect(ipcMainManager.send).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('adds Bisect toggle', () => {
|
||||
overridePlatform('linux');
|
||||
|
||||
setupMenu();
|
||||
|
||||
const result = (electron.Menu.buildFromTemplate as any).mock.calls[0][0];
|
||||
const submenu = result[2].submenu as Array<Electron.MenuItemConstructorOptions>;
|
||||
|
||||
const toggleSoftWrap = submenu.find(({ label }) => label === 'Toggle Bisect Helper');
|
||||
(toggleSoftWrap as any).click();
|
||||
expect(ipcMainManager.send).toHaveBeenCalledWith(IpcEvents.BISECT_COMMANDS_TOGGLE);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('menu groups', () => {
|
||||
@@ -188,7 +174,7 @@ describe('menu', () => {
|
||||
it('attempts to open a template on click', () => {
|
||||
showMe.submenu[0].submenu[0].click();
|
||||
expect(ipcMainManager.send)
|
||||
.toHaveBeenCalledWith(IpcEvents.FS_OPEN_TEMPLATE, ['App']);
|
||||
.toHaveBeenCalledWith(IpcEvents.FS_OPEN_TEMPLATE, [ 'App' ]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -196,7 +182,7 @@ describe('menu', () => {
|
||||
let tasks: any;
|
||||
|
||||
beforeEach(() => {
|
||||
const mock = (electron.Menu.buildFromTemplate as any).mock;
|
||||
const mock = (electron.Menu.buildFromTemplate as any).mock;
|
||||
const menu = mock.calls[0][0];
|
||||
tasks = menu[menu.length - 3];
|
||||
});
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import { ElectronVersionSource, ElectronVersionState } from '../../src/interfaces';
|
||||
import { Bisector } from '../../src/renderer/bisect';
|
||||
|
||||
const generateVersionRange = (rangeLength: number) =>
|
||||
(new Array(rangeLength)).fill(0).map((_, i) => ({
|
||||
state: ElectronVersionState.ready,
|
||||
version: `${i + 1}.0.0`,
|
||||
source: ElectronVersionSource.local
|
||||
}));
|
||||
|
||||
describe('bisect', () => {
|
||||
let bisector: Bisector;
|
||||
|
||||
beforeEach(() => {
|
||||
const versions = generateVersionRange(9);
|
||||
bisector = new Bisector(versions);
|
||||
});
|
||||
|
||||
it('selects a pivot in the middle of the array', () => {
|
||||
const pivot = bisector.getCurrentVersion();
|
||||
const middleIndex = Math.floor(bisector.revList.length / 2);
|
||||
expect(pivot).toBe(bisector.revList[middleIndex]);
|
||||
});
|
||||
|
||||
describe('continue()', () => {
|
||||
it('returns the current version', () => {
|
||||
const result = bisector.continue(true);
|
||||
const version = bisector.getCurrentVersion();
|
||||
expect(result).toBe(version);
|
||||
});
|
||||
|
||||
it('discards lower half of the range if pivot is good version', () => {
|
||||
const pivotVersion = bisector.getCurrentVersion();
|
||||
bisector.continue(true);
|
||||
expect(bisector.revList[bisector.minRev]).toBe(pivotVersion);
|
||||
});
|
||||
|
||||
it('discards upper half of the range if pivot is bad version', () => {
|
||||
const pivotVersion = bisector.getCurrentVersion();
|
||||
bisector.continue(false);
|
||||
expect(bisector.revList[bisector.maxRev]).toBe(pivotVersion);
|
||||
});
|
||||
|
||||
it('terminates if fewer than 2 items are left', () => {
|
||||
const versions = generateVersionRange(2);
|
||||
bisector = new Bisector(versions);
|
||||
|
||||
expect(bisector.revList.length).toBe(2);
|
||||
const responseGood = bisector.continue(true);
|
||||
expect(responseGood).toHaveLength(2);
|
||||
expect(versions).toContain(responseGood[0]);
|
||||
expect(versions).toContain(responseGood[1]);
|
||||
|
||||
bisector = new Bisector(versions);
|
||||
|
||||
expect(bisector.revList.length).toBe(2);
|
||||
const responseBad = bisector.continue(false);
|
||||
expect(responseBad).toHaveLength(2);
|
||||
expect(versions).toContain(responseBad[0]);
|
||||
expect(versions).toContain(responseBad[1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCurrentVersion()', () => {
|
||||
it('returns a version within the range', () => {
|
||||
const version = bisector.getCurrentVersion();
|
||||
expect(bisector.revList).toContain(version);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,27 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Bisect commands component renders bisect dialog button if no bisect instance 1`] = `
|
||||
<Blueprint3.Button
|
||||
icon="git-branch"
|
||||
text="Bisect"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Bisect commands component renders helper buttons if bisect instance is active 1`] = `
|
||||
<Fragment>
|
||||
<Blueprint3.Button
|
||||
icon="thumbs-up"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
<Blueprint3.Button
|
||||
icon="thumbs-down"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
<Blueprint3.Button
|
||||
icon="cross"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Cancel Bisect
|
||||
</Blueprint3.Button>
|
||||
</Fragment>
|
||||
`;
|
||||
@@ -1,50 +1,46 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`VersionChooser component handles corrupt data 1`] = `
|
||||
<Blueprint3.ButtonGroup>
|
||||
<Blueprint3.Select
|
||||
disabled={false}
|
||||
filterable={true}
|
||||
itemPredicate={[Function]}
|
||||
itemRenderer={[Function]}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "2.0.2",
|
||||
},
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "2.0.1",
|
||||
},
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "1.8.7",
|
||||
},
|
||||
]
|
||||
}
|
||||
noResults={
|
||||
<Blueprint3.MenuItem
|
||||
disabled={true}
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
shouldDismissPopover={true}
|
||||
text="No results."
|
||||
/>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
className="version-chooser"
|
||||
disabled={false}
|
||||
icon="saved"
|
||||
text="Electron v2.0.2"
|
||||
<Blueprint3.Select
|
||||
filterable={true}
|
||||
itemPredicate={[Function]}
|
||||
itemRenderer={[Function]}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "2.0.2",
|
||||
},
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "2.0.1",
|
||||
},
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "1.8.7",
|
||||
},
|
||||
]
|
||||
}
|
||||
noResults={
|
||||
<Blueprint3.MenuItem
|
||||
disabled={true}
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
shouldDismissPopover={true}
|
||||
text="No results."
|
||||
/>
|
||||
</Blueprint3.Select>
|
||||
</Blueprint3.ButtonGroup>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
className="version-chooser"
|
||||
icon="saved"
|
||||
text="Electron v2.0.2"
|
||||
/>
|
||||
</Blueprint3.Select>
|
||||
`;
|
||||
|
||||
exports[`VersionChooser component renderItem() renders an item 1`] = `
|
||||
@@ -66,48 +62,44 @@ exports[`VersionChooser component renderItem() renders an item 1`] = `
|
||||
`;
|
||||
|
||||
exports[`VersionChooser component renders 1`] = `
|
||||
<Blueprint3.ButtonGroup>
|
||||
<Blueprint3.Select
|
||||
disabled={false}
|
||||
filterable={true}
|
||||
itemPredicate={[Function]}
|
||||
itemRenderer={[Function]}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "2.0.2",
|
||||
},
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "2.0.1",
|
||||
},
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "1.8.7",
|
||||
},
|
||||
]
|
||||
}
|
||||
noResults={
|
||||
<Blueprint3.MenuItem
|
||||
disabled={true}
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
shouldDismissPopover={true}
|
||||
text="No results."
|
||||
/>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
className="version-chooser"
|
||||
disabled={false}
|
||||
icon="saved"
|
||||
text="Electron v2.0.2"
|
||||
<Blueprint3.Select
|
||||
filterable={true}
|
||||
itemPredicate={[Function]}
|
||||
itemRenderer={[Function]}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "2.0.2",
|
||||
},
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "2.0.1",
|
||||
},
|
||||
Object {
|
||||
"source": "remote",
|
||||
"state": "ready",
|
||||
"version": "1.8.7",
|
||||
},
|
||||
]
|
||||
}
|
||||
noResults={
|
||||
<Blueprint3.MenuItem
|
||||
disabled={true}
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
shouldDismissPopover={true}
|
||||
text="No results."
|
||||
/>
|
||||
</Blueprint3.Select>
|
||||
</Blueprint3.ButtonGroup>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
className="version-chooser"
|
||||
icon="saved"
|
||||
text="Electron v2.0.2"
|
||||
/>
|
||||
</Blueprint3.Select>
|
||||
`;
|
||||
|
||||
@@ -16,9 +16,10 @@ exports[`AddVersionDialog component renders 1`] = `
|
||||
id="custom-electron-version"
|
||||
inputProps={
|
||||
Object {
|
||||
"onClick": [Function],
|
||||
"webkitdirectory": "true",
|
||||
}
|
||||
}
|
||||
onInputChange={[Function]}
|
||||
text="/test/file"
|
||||
/>
|
||||
<br />
|
||||
@@ -78,9 +79,10 @@ exports[`AddVersionDialog component renders 2`] = `
|
||||
id="custom-electron-version"
|
||||
inputProps={
|
||||
Object {
|
||||
"onClick": [Function],
|
||||
"webkitdirectory": "true",
|
||||
}
|
||||
}
|
||||
onInputChange={[Function]}
|
||||
text="/test/file"
|
||||
/>
|
||||
<br />
|
||||
|
||||
@@ -1,413 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`BisectDialog component renders 1`] = `
|
||||
<Blueprint3.Dialog
|
||||
canOutsideClickClose={true}
|
||||
className="dialog-add-version"
|
||||
isOpen={false}
|
||||
onClose={[Function]}
|
||||
title="Start a bisect session"
|
||||
>
|
||||
<div
|
||||
className="bp3-dialog-body"
|
||||
>
|
||||
<Component>
|
||||
Earliest Version
|
||||
<Blueprint3.Select
|
||||
filterable={true}
|
||||
itemPredicate={[Function]}
|
||||
itemRenderer={[Function]}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "2.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "3.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "4.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "5.0.0",
|
||||
},
|
||||
]
|
||||
}
|
||||
noResults={
|
||||
<Blueprint3.MenuItem
|
||||
disabled={true}
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
shouldDismissPopover={true}
|
||||
text="No results."
|
||||
/>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
fill={true}
|
||||
icon="saved"
|
||||
text="v4.0.0"
|
||||
/>
|
||||
</Blueprint3.Select>
|
||||
</Component>
|
||||
<Component>
|
||||
Latest Version
|
||||
<Blueprint3.Select
|
||||
disabled={false}
|
||||
filterable={true}
|
||||
itemPredicate={[Function]}
|
||||
itemRenderer={[Function]}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "2.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "3.0.0",
|
||||
},
|
||||
]
|
||||
}
|
||||
noResults={
|
||||
<Blueprint3.MenuItem
|
||||
disabled={true}
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
shouldDismissPopover={true}
|
||||
text="No results."
|
||||
/>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
disabled={false}
|
||||
fill={true}
|
||||
icon="small-minus"
|
||||
text=""
|
||||
/>
|
||||
</Blueprint3.Select>
|
||||
</Component>
|
||||
</div>
|
||||
<div
|
||||
className="bp3-dialog-footer"
|
||||
>
|
||||
<div
|
||||
className="bp3-dialog-footer-actions"
|
||||
>
|
||||
<Blueprint3.Button
|
||||
disabled={true}
|
||||
icon="play"
|
||||
key="submit"
|
||||
onClick={[Function]}
|
||||
text="Begin"
|
||||
/>
|
||||
<Blueprint3.Button
|
||||
icon="cross"
|
||||
key="cancel"
|
||||
onClick={[Function]}
|
||||
text="Cancel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Blueprint3.Dialog>
|
||||
`;
|
||||
|
||||
exports[`BisectDialog component renders 2`] = `
|
||||
<Blueprint3.Dialog
|
||||
canOutsideClickClose={true}
|
||||
className="dialog-add-version"
|
||||
isOpen={false}
|
||||
onClose={[Function]}
|
||||
title="Start a bisect session"
|
||||
>
|
||||
<div
|
||||
className="bp3-dialog-body"
|
||||
>
|
||||
<Component>
|
||||
Earliest Version
|
||||
<Blueprint3.Select
|
||||
filterable={true}
|
||||
itemPredicate={[Function]}
|
||||
itemRenderer={[Function]}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "2.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "3.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "4.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "5.0.0",
|
||||
},
|
||||
]
|
||||
}
|
||||
noResults={
|
||||
<Blueprint3.MenuItem
|
||||
disabled={true}
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
shouldDismissPopover={true}
|
||||
text="No results."
|
||||
/>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
fill={true}
|
||||
icon="small-minus"
|
||||
text=""
|
||||
/>
|
||||
</Blueprint3.Select>
|
||||
</Component>
|
||||
<Component>
|
||||
Latest Version
|
||||
<Blueprint3.Select
|
||||
disabled={true}
|
||||
filterable={true}
|
||||
itemPredicate={[Function]}
|
||||
itemRenderer={[Function]}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "2.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "3.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "4.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "5.0.0",
|
||||
},
|
||||
]
|
||||
}
|
||||
noResults={
|
||||
<Blueprint3.MenuItem
|
||||
disabled={true}
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
shouldDismissPopover={true}
|
||||
text="No results."
|
||||
/>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
disabled={true}
|
||||
fill={true}
|
||||
icon="small-minus"
|
||||
text=""
|
||||
/>
|
||||
</Blueprint3.Select>
|
||||
</Component>
|
||||
</div>
|
||||
<div
|
||||
className="bp3-dialog-footer"
|
||||
>
|
||||
<div
|
||||
className="bp3-dialog-footer-actions"
|
||||
>
|
||||
<Blueprint3.Button
|
||||
disabled={true}
|
||||
icon="play"
|
||||
key="submit"
|
||||
onClick={[Function]}
|
||||
text="Begin"
|
||||
/>
|
||||
<Blueprint3.Button
|
||||
icon="cross"
|
||||
key="cancel"
|
||||
onClick={[Function]}
|
||||
text="Cancel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Blueprint3.Dialog>
|
||||
`;
|
||||
|
||||
exports[`BisectDialog component renders 3`] = `
|
||||
<Blueprint3.Dialog
|
||||
canOutsideClickClose={true}
|
||||
className="dialog-add-version"
|
||||
isOpen={false}
|
||||
onClose={[Function]}
|
||||
title="Start a bisect session"
|
||||
>
|
||||
<div
|
||||
className="bp3-dialog-body"
|
||||
>
|
||||
<Component>
|
||||
Earliest Version
|
||||
<Blueprint3.Select
|
||||
filterable={true}
|
||||
itemPredicate={[Function]}
|
||||
itemRenderer={[Function]}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "2.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "3.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "4.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "5.0.0",
|
||||
},
|
||||
]
|
||||
}
|
||||
noResults={
|
||||
<Blueprint3.MenuItem
|
||||
disabled={true}
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
shouldDismissPopover={true}
|
||||
text="No results."
|
||||
/>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
fill={true}
|
||||
icon="saved"
|
||||
text="v4.0.0"
|
||||
/>
|
||||
</Blueprint3.Select>
|
||||
</Component>
|
||||
<Component>
|
||||
Latest Version
|
||||
<Blueprint3.Select
|
||||
disabled={false}
|
||||
filterable={true}
|
||||
itemPredicate={[Function]}
|
||||
itemRenderer={[Function]}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "1.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "2.0.0",
|
||||
},
|
||||
Object {
|
||||
"source": "local",
|
||||
"state": "ready",
|
||||
"version": "3.0.0",
|
||||
},
|
||||
]
|
||||
}
|
||||
noResults={
|
||||
<Blueprint3.MenuItem
|
||||
disabled={true}
|
||||
multiline={false}
|
||||
popoverProps={Object {}}
|
||||
shouldDismissPopover={true}
|
||||
text="No results."
|
||||
/>
|
||||
}
|
||||
onItemSelect={[Function]}
|
||||
>
|
||||
<Blueprint3.Button
|
||||
disabled={false}
|
||||
fill={true}
|
||||
icon="small-minus"
|
||||
text=""
|
||||
/>
|
||||
</Blueprint3.Select>
|
||||
</Component>
|
||||
</div>
|
||||
<div
|
||||
className="bp3-dialog-footer"
|
||||
>
|
||||
<div
|
||||
className="bp3-dialog-footer-actions"
|
||||
>
|
||||
<Blueprint3.Button
|
||||
disabled={true}
|
||||
icon="play"
|
||||
key="submit"
|
||||
onClick={[Function]}
|
||||
text="Begin"
|
||||
/>
|
||||
<Blueprint3.Button
|
||||
icon="cross"
|
||||
key="cancel"
|
||||
onClick={[Function]}
|
||||
text="Cancel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Blueprint3.Dialog>
|
||||
`;
|
||||
@@ -1,86 +0,0 @@
|
||||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import * as React from 'react';
|
||||
import { BisectHandler } from '../../../src/renderer/components/commands-bisect';
|
||||
|
||||
describe('Bisect commands component', () => {
|
||||
let store: any;
|
||||
|
||||
beforeEach(() => {
|
||||
store = {
|
||||
Bisector: {
|
||||
continue: jest.fn(),
|
||||
getCurrentVersion: jest.fn()
|
||||
},
|
||||
setVersion: jest.fn(),
|
||||
version: '1.0.0',
|
||||
pushOutput: jest.fn()
|
||||
};
|
||||
});
|
||||
|
||||
it('renders helper buttons if bisect instance is active', () => {
|
||||
const wrapper = shallow(<BisectHandler appState={store} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders bisect dialog button if no bisect instance', () => {
|
||||
delete store.Bisector;
|
||||
const wrapper = shallow(<BisectHandler appState={store} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('buttons', () => {
|
||||
let wrapper: ShallowWrapper;
|
||||
let instance: BisectHandler;
|
||||
beforeEach(() => {
|
||||
wrapper = shallow(<BisectHandler appState={store} />);
|
||||
instance = wrapper.instance() as any;
|
||||
instance.continueBisect = jest.fn();
|
||||
});
|
||||
|
||||
it('passes in Version=Good when thumbs up button is pressed', () => {
|
||||
wrapper.find('[icon="thumbs-up"]').simulate('click');
|
||||
expect(instance.continueBisect).toHaveBeenCalledWith(true);
|
||||
});
|
||||
|
||||
it('passes in Version=Bad when thumbs down button is pressed', () => {
|
||||
wrapper.find('[icon="thumbs-down"]').simulate('click');
|
||||
expect(instance.continueBisect).toHaveBeenCalledWith(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('continueBisect()', () => {
|
||||
it('sets version assigned by bisect algorithm', () => {
|
||||
const wrapper = shallow(<BisectHandler appState={store} />);
|
||||
const instance: BisectHandler = wrapper.instance() as any;
|
||||
|
||||
store.Bisector.continue.mockReturnValue({
|
||||
version: '2.0.0'
|
||||
});
|
||||
instance.continueBisect(true);
|
||||
expect(store.setVersion).toHaveBeenCalledWith('2.0.0');
|
||||
});
|
||||
|
||||
it('terminates bisect if algorithm returns array', () => {
|
||||
const wrapper = shallow(<BisectHandler appState={store} />);
|
||||
const instance: BisectHandler = wrapper.instance() as any;
|
||||
instance.terminateBisect = jest.fn();
|
||||
|
||||
// same value is only returned when there is only 1 version left
|
||||
store.Bisector.continue.mockReturnValue(['minRev', 'maxRev']);
|
||||
instance.continueBisect(true);
|
||||
expect(store.setVersion).not.toHaveBeenCalled();
|
||||
expect(instance.terminateBisect).toHaveBeenCalled();
|
||||
expect(store.pushOutput).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('terminateBisect()', () => {
|
||||
it('removes the bisect instance from the app state', () => {
|
||||
const wrapper = shallow(<BisectHandler appState={store} />);
|
||||
const instance: BisectHandler = wrapper.instance() as any;
|
||||
|
||||
instance.terminateBisect();
|
||||
expect(store.Bisector).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,16 +1,15 @@
|
||||
import { shallow } from 'enzyme';
|
||||
import * as React from 'react';
|
||||
|
||||
import { IpcEvents } from '../../../src/ipc-events';
|
||||
import { AddVersionDialog } from '../../../src/renderer/components/dialog-add-version';
|
||||
import { ipcRendererManager } from '../../../src/renderer/ipc';
|
||||
import { overridePlatform, resetPlatform } from '../../utils';
|
||||
jest.mock('../../../src/renderer/ipc');
|
||||
|
||||
describe('AddVersionDialog component', () => {
|
||||
let store: any;
|
||||
|
||||
const mockFile = '/test/file';
|
||||
const mockFile = {
|
||||
path: '/test/file'
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
// We render the buttons different depending on the
|
||||
@@ -38,7 +37,7 @@ describe('AddVersionDialog component', () => {
|
||||
wrapper.setState({
|
||||
isValidVersion: true,
|
||||
isValidElectron: true,
|
||||
folderPath: mockFile
|
||||
file: mockFile
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
@@ -46,32 +45,35 @@ describe('AddVersionDialog component', () => {
|
||||
wrapper.setState({
|
||||
isValidVersion: false,
|
||||
isValidElectron: true,
|
||||
folderPath: mockFile
|
||||
file: mockFile
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('overrides default input with Electron dialog', () => {
|
||||
const preventDefault = jest.fn();
|
||||
|
||||
const wrapper = shallow(<AddVersionDialog appState={store} />);
|
||||
const inp = wrapper.find('#custom-electron-version');
|
||||
inp.dive().find('input[type="file"]').simulate('click', { preventDefault });
|
||||
|
||||
expect(ipcRendererManager.send as jest.Mock)
|
||||
.toHaveBeenCalledWith(IpcEvents.SHOW_LOCAL_VERSION_FOLDER_DIALOG);
|
||||
expect(preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('setFolderPath()', () => {
|
||||
it('does something', async () => {
|
||||
store.binaryManager.getIsDownloaded.mockResolvedValue(true);
|
||||
describe('onChangeFile()', () => {
|
||||
it('handles the change event', async () => {
|
||||
const wrapper = shallow(<AddVersionDialog appState={store} />);
|
||||
await (wrapper.instance() as any).setFolderPath('/test/');
|
||||
|
||||
expect(wrapper.state('isValidElectron')).toBe(true);
|
||||
expect(wrapper.state('folderPath')).toBe('/test/');
|
||||
await (wrapper.instance() as any).onChangeFile({ target: { files: [ mockFile ] } });
|
||||
expect(wrapper.state('file')).toBe(mockFile);
|
||||
});
|
||||
|
||||
it('handles invalid input', async () => {
|
||||
const wrapper = shallow(<AddVersionDialog appState={store} />);
|
||||
|
||||
await (wrapper.instance() as any).onChangeFile({ target: { files: [] } });
|
||||
expect(wrapper.state('file')).toBe(undefined);
|
||||
});
|
||||
|
||||
it('handles the change event and checks for Electron', async () => {
|
||||
const wrapper = shallow(<AddVersionDialog appState={store} />);
|
||||
|
||||
store.binaryManager.getIsDownloaded.mockReturnValueOnce(false);
|
||||
|
||||
await (wrapper.instance() as any).onChangeFile({ target: { files: [ mockFile ] } });
|
||||
expect(wrapper.state('file')).toBe(mockFile);
|
||||
expect(wrapper.state('isValidElectron')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -91,7 +93,7 @@ describe('AddVersionDialog component', () => {
|
||||
expect(wrapper.state('isValidVersion')).toBe(false);
|
||||
expect(wrapper.state('version')).toBe('foo');
|
||||
|
||||
(wrapper.instance() as any).onChangeVersion({ target: {} });
|
||||
(wrapper.instance() as any).onChangeVersion({ target: { } });
|
||||
expect(wrapper.state('isValidVersion')).toBe(false);
|
||||
expect(wrapper.state('version')).toBe('');
|
||||
});
|
||||
@@ -111,7 +113,9 @@ describe('AddVersionDialog component', () => {
|
||||
|
||||
wrapper.setState({
|
||||
version: '3.3.3',
|
||||
folderPath: '/test/path'
|
||||
file: {
|
||||
path: '/test/path'
|
||||
}
|
||||
});
|
||||
|
||||
await (wrapper.instance() as any).onSubmit();
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
import { shallow } from 'enzyme';
|
||||
import * as React from 'react';
|
||||
import { ElectronVersionSource, ElectronVersionState } from '../../../src/interfaces';
|
||||
import { Bisector } from '../../../src/renderer/bisect';
|
||||
import { BisectDialog } from '../../../src/renderer/components/dialog-bisect';
|
||||
import { ElectronReleaseChannel } from '../../../src/renderer/versions';
|
||||
|
||||
jest.mock('../../../src/renderer/bisect');
|
||||
|
||||
describe('BisectDialog component', () => {
|
||||
let store: any;
|
||||
|
||||
const generateVersionRange = (rangeLength: number) =>
|
||||
(new Array(rangeLength)).fill(0).map((_, i) => ({
|
||||
state: ElectronVersionState.ready,
|
||||
version: `${i + 1}.0.0`,
|
||||
source: ElectronVersionSource.local
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
store = {
|
||||
versions: generateVersionRange(5),
|
||||
versionsToShow: [ElectronReleaseChannel.stable],
|
||||
statesToShow: [ElectronVersionState.ready],
|
||||
setVersion: jest.fn()
|
||||
};
|
||||
});
|
||||
|
||||
it('renders', () => {
|
||||
const wrapper = shallow(<BisectDialog appState={store} />);
|
||||
// start and end selected
|
||||
wrapper.setState({
|
||||
startIndex: 3,
|
||||
endIndex: 0,
|
||||
allVersions: generateVersionRange(5)
|
||||
});
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
// no selection
|
||||
wrapper.setState({
|
||||
startIndex: undefined,
|
||||
endIndex: undefined,
|
||||
allVersions: generateVersionRange(5)
|
||||
});
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
|
||||
// only start selected
|
||||
wrapper.setState({
|
||||
startIndex: 3,
|
||||
endIndex: undefined,
|
||||
allVersions: generateVersionRange(5)
|
||||
});
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('onBeginSelect()', () => {
|
||||
it('sets the begin version', () => {
|
||||
const wrapper = shallow(<BisectDialog appState={store} />);
|
||||
const instance: BisectDialog = wrapper.instance() as any;
|
||||
|
||||
expect(instance.state.startIndex).toBeUndefined();
|
||||
instance.onBeginSelect(store.versions[2]);
|
||||
expect(instance.state.startIndex).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onEndSelect()', () => {
|
||||
it('sets the end version', () => {
|
||||
const wrapper = shallow(<BisectDialog appState={store} />);
|
||||
const instance: BisectDialog = wrapper.instance() as any;
|
||||
|
||||
expect(instance.state.endIndex).toBeUndefined();
|
||||
instance.onEndSelect(store.versions[2]);
|
||||
expect(instance.state.endIndex).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSubmit()', () => {
|
||||
it('initiates a bisect instance and sets a version', async () => {
|
||||
const version = '1.0.0';
|
||||
(Bisector as jest.Mock).mockImplementation(() => {
|
||||
return {
|
||||
getCurrentVersion: () => ({ version })
|
||||
};
|
||||
});
|
||||
|
||||
const versions = generateVersionRange(5);
|
||||
|
||||
const wrapper = shallow(<BisectDialog appState={store} />);
|
||||
wrapper.setState({
|
||||
startIndex: 4,
|
||||
endIndex: 0,
|
||||
allVersions: versions
|
||||
});
|
||||
|
||||
const instance: BisectDialog = wrapper.instance() as any;
|
||||
await instance.onSubmit();
|
||||
expect(Bisector).toHaveBeenCalledWith(versions.slice(0, 5).reverse());
|
||||
expect(store.Bisector).toBeDefined();
|
||||
expect(store.setVersion).toHaveBeenCalledWith(version);
|
||||
});
|
||||
|
||||
it('does nothing if endIndex or startIndex are falsy', async () => {
|
||||
const wrapper = shallow(<BisectDialog appState={store} />);
|
||||
|
||||
wrapper.setState({
|
||||
startIndex: undefined,
|
||||
endIndex: 0
|
||||
});
|
||||
const instance1: BisectDialog = wrapper.instance() as any;
|
||||
await instance1.onSubmit();
|
||||
expect(Bisector).not.toHaveBeenCalled();
|
||||
|
||||
wrapper.setState({
|
||||
startIndex: 4,
|
||||
endIndex: undefined
|
||||
});
|
||||
const instance2: BisectDialog = wrapper.instance() as any;
|
||||
await instance2.onSubmit();
|
||||
expect(Bisector).not.toHaveBeenCalled();
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ALL_MOSAICS, EditorId, ElectronVersionSource, ElectronVersionState, PanelId } from '../../src/interfaces';
|
||||
import { Bisector } from '../../src/renderer/bisect';
|
||||
import { DEFAULT_MOSAIC_ARRANGEMENT } from '../../src/renderer/constants';
|
||||
import { getContent, isContentUnchanged } from '../../src/renderer/content';
|
||||
import { ipcRendererManager } from '../../src/renderer/ipc';
|
||||
@@ -143,7 +142,7 @@ describe('AppState', () => {
|
||||
|
||||
expect(appState.currentElectronVersion).toEqual(mockVersions['2.0.2']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleConsole()', () => {
|
||||
it('toggles the console', () => {
|
||||
@@ -180,33 +179,6 @@ describe('AppState', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleBisectCommands()', () => {
|
||||
it('toggles visibility of the bisect commands', () => {
|
||||
const isVisible = appState.isBisectCommandShowing;
|
||||
appState.toggleBisectCommands();
|
||||
expect(isVisible).not.toBe(appState.isBisectCommandShowing);
|
||||
});
|
||||
|
||||
it('takes no action if bisect dialog is active', () => {
|
||||
const isVisible = appState.isBisectCommandShowing;
|
||||
|
||||
expect(appState.isBisectDialogShowing).toBe(false);
|
||||
appState.toggleBisectDialog();
|
||||
|
||||
appState.toggleBisectCommands();
|
||||
expect(isVisible).toBe(appState.isBisectCommandShowing);
|
||||
});
|
||||
|
||||
it('takes no action if bisect instance is active', () => {
|
||||
const isVisible = appState.isBisectCommandShowing;
|
||||
|
||||
appState.Bisector = new Bisector([]);
|
||||
|
||||
appState.toggleBisectCommands();
|
||||
expect(isVisible).toBe(appState.isBisectCommandShowing);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggleAddVersionDialog()', () => {
|
||||
it('toggles the add version dialog', () => {
|
||||
appState.toggleAddVersionDialog();
|
||||
@@ -324,7 +296,7 @@ describe('AppState', () => {
|
||||
await appState.setVersion('v1.0.0');
|
||||
|
||||
expect(getContent).toHaveBeenCalledTimes(1);
|
||||
expect(window.ElectronFiddle.app.setEditorValues).toHaveBeenCalledTimes(1);
|
||||
expect(window.ElectronFiddle.app.setEditorValues).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -369,7 +341,7 @@ describe('AppState', () => {
|
||||
// refreshed - we didn't actually add the local version
|
||||
// above, since versions.ts is mocked
|
||||
expect(Object.keys(appState.versions)).toEqual(
|
||||
['2.0.2', '2.0.1', '1.8.7']
|
||||
[ '2.0.2', '2.0.1', '1.8.7' ]
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -454,7 +426,7 @@ describe('AppState', () => {
|
||||
it('updates the visible editors and creates a backup', () => {
|
||||
appState.mosaicArrangement = createMosaicArrangement(ALL_MOSAICS);
|
||||
appState.closedPanels = {};
|
||||
appState.setVisibleMosaics([EditorId.main]);
|
||||
appState.setVisibleMosaics([ EditorId.main ]);
|
||||
|
||||
expect(appState.mosaicArrangement).toEqual(EditorId.main);
|
||||
expect(appState.closedPanels[EditorId.renderer]).toBeTruthy();
|
||||
|
||||
@@ -13,7 +13,3 @@ export function resetPlatform() {
|
||||
writable: true
|
||||
});
|
||||
}
|
||||
|
||||
export function flushPromises() {
|
||||
return new Promise((resolve) => setImmediate(resolve));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { isDevMode } from '../../src/utils/devmode';
|
||||
|
||||
describe('devMode', () => {
|
||||
const old = (process as any).defaultApp; // for tsconfig error
|
||||
const old = process.defaultApp;
|
||||
|
||||
afterEach(() => {
|
||||
Object.defineProperty(process, 'defaultApp', { value: old });
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
/* tslint:disable */
|
||||
|
||||
const { maybeFetchContributors } = require('./contributors')
|
||||
const { compileParcel } = require('./parcel-build')
|
||||
|
||||
module.exports = async () => {
|
||||
await Promise.all([maybeFetchContributors(), compileParcel()])
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/* tslint:disable */
|
||||
|
||||
const Bundler = require('parcel-bundler')
|
||||
const path = require('path')
|
||||
|
||||
async function compileParcel (options = {}) {
|
||||
const entryFiles = [
|
||||
path.join(__dirname, '../static/index.html'),
|
||||
path.join(__dirname, '../src/main/main.ts')
|
||||
]
|
||||
|
||||
const bundlerOptions = {
|
||||
outDir: './dist', // The out directory to put the build files in, defaults to dist
|
||||
outFile: undefined, // The name of the outputFile
|
||||
publicUrl: '../', // The url to server on, defaults to dist
|
||||
watch: false, // whether to watch the files and rebuild them on change, defaults to process.env.NODE_ENV !== 'production'
|
||||
cache: false, // Enabled or disables caching, defaults to true
|
||||
cacheDir: '.cache', // The directory cache gets put in, defaults to .cache
|
||||
contentHash: false, // Disable content hash from being included on the filename
|
||||
minify: false, // Minify files, enabled if process.env.NODE_ENV === 'production'
|
||||
scopeHoist: false, // turn on experimental scope hoisting/tree shaking flag, for smaller production bundles
|
||||
target: 'electron', // browser/node/electron, defaults to browser
|
||||
// https: { // Define a custom {key, cert} pair, use true to generate one or false to use http
|
||||
// cert: './ssl/c.crt', // path to custom certificate
|
||||
// key: './ssl/k.key' // path to custom key
|
||||
// },
|
||||
logLevel: 3, // 3 = log everything, 2 = log warnings & errors, 1 = log errors
|
||||
hmr: true, // Enable or disable HMR while watching
|
||||
hmrPort: 0, // The port the HMR socket runs on, defaults to a random free port (0 in node.js resolves to a random free port)
|
||||
sourceMaps: true, // Enable or disable sourcemaps, defaults to enabled (minified builds currently always create sourcemaps)
|
||||
hmrHostname: '', // A hostname for hot module reload, default to ''
|
||||
detailedReport: false, // Prints a detailed report of the bundles, assets, filesizes and times, defaults to false, reports are only printed if watch is disabled,
|
||||
...options
|
||||
}
|
||||
|
||||
const bundler = new Bundler(entryFiles, bundlerOptions)
|
||||
|
||||
// Run the bundler, this returns the main bundle
|
||||
// Use the events if you're using watch mode as this promise will only trigger once and not for every rebuild
|
||||
await bundler.bundle()
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
compileParcel
|
||||
}
|
||||
|
||||
if (require.main === module) compileParcel()
|
||||
@@ -1,11 +0,0 @@
|
||||
const { compileParcel } = require('./parcel-build')
|
||||
|
||||
async function watchParcel () {
|
||||
return compileParcel({ watch: true })
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
watchParcel
|
||||
}
|
||||
|
||||
if (require.main === module) watchParcel()
|
||||
@@ -0,0 +1,27 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* This is the main entry point for your application, it's the first file
|
||||
* that runs in the main process.
|
||||
*/
|
||||
entry: './src/main/main.ts',
|
||||
// Put your normal webpack config below here
|
||||
module: {
|
||||
rules: require('./webpack.rules'),
|
||||
},
|
||||
resolve: {
|
||||
/**
|
||||
* Determines which file extensions are okay to leave off from
|
||||
* the ends of require / import paths. Has no impact on what file types
|
||||
* webpack will process.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* import { logger } from './logger';
|
||||
*
|
||||
* Instead of:
|
||||
*
|
||||
* import { logger } from './logger.ts';
|
||||
*/
|
||||
extensions: [ '.ts', '.tsx', '.js', '.jsx', '.json' ],
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,83 @@
|
||||
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
|
||||
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const webpack = require('webpack');
|
||||
|
||||
const rules = require('./webpack.rules');
|
||||
|
||||
rules.push({
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{ loader: MiniCssExtractPlugin.loader },
|
||||
{ loader: 'css-loader' }
|
||||
],
|
||||
});
|
||||
|
||||
rules.push({
|
||||
test: /\.less$/,
|
||||
use: [
|
||||
{ loader: MiniCssExtractPlugin.loader },
|
||||
{ loader: 'css-loader' },
|
||||
{
|
||||
loader: 'less-loader',
|
||||
options: {
|
||||
noIeCompat: true
|
||||
}
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
rules.push({
|
||||
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[ext]',
|
||||
outputPath: 'fonts/'
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
// Put your normal webpack config below here
|
||||
module: {
|
||||
rules,
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'monaco-editor': 'monaco-editor/esm/vs/editor/editor.api'
|
||||
},
|
||||
/**
|
||||
* Determines which file extensions are okay to leave off from
|
||||
* the ends of require / import paths. Has no impact on what file types
|
||||
* webpack will process.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* import { logger } from './logger';
|
||||
*
|
||||
* Instead of:
|
||||
*
|
||||
* import { logger } from './logger.ts';
|
||||
*/
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
|
||||
},
|
||||
plugins: [
|
||||
new MonacoWebpackPlugin({
|
||||
languages: [
|
||||
'typescript',
|
||||
'javascript',
|
||||
'html',
|
||||
'css'
|
||||
]
|
||||
}),
|
||||
new BundleAnalyzerPlugin(),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "./css/[name].css"
|
||||
}),
|
||||
new webpack.optimize.LimitChunkCountPlugin({
|
||||
maxChunks: 1
|
||||
})
|
||||
],
|
||||
externals: {
|
||||
'es6-promise': 'es6-promise'
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
module.exports = [
|
||||
// Add support for native node modules
|
||||
{
|
||||
test: /\.node$/,
|
||||
use: 'node-loader',
|
||||
},
|
||||
{
|
||||
test: /\.(m?js|node)$/,
|
||||
parser: { amd: false },
|
||||
use: {
|
||||
loader: '@marshallofsound/webpack-asset-relocator-loader',
|
||||
options: {
|
||||
outputAssetBase: 'native_modules',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
exclude: /(node_modules|.webpack)/,
|
||||
loaders: [{
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
transpileOnly: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
];
|
||||
Reference in New Issue
Block a user