Merge pull request #120 from cwillisf/electron-8

Electron 8 & fix App Store submission
This commit is contained in:
Chris Willis-Ford 2020-06-03 16:09:03 -07:00 committed by GitHub
commit 6d9ab116bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 4361 additions and 6863 deletions

2
.gitignore vendored
View file

@ -17,7 +17,7 @@ npm-*
/build
/dist
/.opt-in
/embedded.provisionprofile
/*.provisionprofile
# don't store the assets downloaded with the `fetch` script
/static/assets/

View file

@ -2,6 +2,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-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
@ -10,6 +12,8 @@
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.microphone</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>

View file

@ -4,6 +4,8 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
@ -12,6 +14,8 @@
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.microphone</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>

View file

@ -24,7 +24,11 @@ mas:
category: public.app-category.education
entitlements: buildResources/entitlements.mas.plist
entitlementsInherit: buildResources/entitlements.mas.inherit.plist
hardenedRuntime: false
icon: buildResources/ScratchDesktop.icns
masDev:
type: development
provisioningProfile: macDeveloperThisDevice.provisionprofile
win:
icon: buildResources/ScratchDesktop.ico
target:

11079
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@
"productName": "Scratch Desktop",
"description": "Scratch 3.0 as a self-contained desktop application",
"author": "Scratch Foundation",
"version": "3.10.2",
"version": "3.10.4",
"license": "BSD-3-Clause",
"scripts": {
"start": "electron-webpack dev --bail --display-error-details --env.minify=false",
@ -21,46 +21,46 @@
"url": "git+ssh://git@github.com/LLK/scratch-desktop.git"
},
"dependencies": {
"source-map-support": "^0.5.12"
"source-map-support": "^0.5.19"
},
"devDependencies": {
"@babel/core": "^7.5.4",
"@babel/plugin-proposal-object-rest-spread": "^7.5.4",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/plugin-transform-async-to-generator": "^7.5.0",
"@babel/preset-env": "^7.5.4",
"@babel/preset-react": "^7.0.0",
"async": "^2.6.2",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"babel-plugin-react-intl": "^2.3.1",
"copy-webpack-plugin": "^4.6.0",
"electron": "^6.1.7",
"electron-builder": "^22.2.0",
"electron-devtools-installer": "^2.2.4",
"electron-notarize": "^0.2.1",
"electron-store": "^3.3.0",
"electron-webpack": "^2.7.4",
"eslint": "^5.16.0",
"eslint-config-scratch": "^5.0.0",
"eslint-plugin-import": "^2.18.0",
"eslint-plugin-react": "^7.14.2",
"@babel/core": "^7.9.6",
"@babel/plugin-proposal-object-rest-spread": "^7.9.6",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-async-to-generator": "^7.8.3",
"@babel/preset-env": "^7.9.6",
"@babel/preset-react": "^7.9.4",
"async": "^3.2.0",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.1.0",
"babel-plugin-react-intl": "^7.5.7",
"copy-webpack-plugin": "^5.1.1",
"electron": "^8.2.5",
"electron-builder": "^22.6.0",
"electron-devtools-installer": "^3.0.0",
"electron-notarize": "^0.3.0",
"electron-store": "^5.1.1",
"electron-webpack": "^2.8.2",
"eslint": "^7.0.0",
"eslint-config-scratch": "^6.0.0",
"eslint-plugin-import": "^2.20.0",
"eslint-plugin-react": "^7.20.0",
"intl": "1.2.5",
"lodash.bindall": "^4.4.0",
"lodash.defaultsdeep": "^4.6.1",
"mkdirp": "^0.5.1",
"minilog": "^3.1.0",
"mkdirp": "^1.0.4",
"nets": "^3.2.0",
"react": "16.2.0",
"react-dom": "16.2.1",
"react-intl": "2.4.0",
"react-intl": "2.8.0",
"react-redux": "5.0.7",
"redux": "3.7.2",
"rimraf": "^2.7.1",
"redux": "3.5.2",
"rimraf": "^3.0.2",
"scratch-gui": "github:LLK/scratch-gui#scratch-desktop-v3.10.2",
"source-map-loader": "^0.2.4",
"uglifyjs-webpack-plugin": "^2.1.3",
"uuid": "^3.3.3",
"webpack": "^4.39.3"
"uuid": "^8.0.0",
"webpack": "^4.43.0"
},
"resolutions": {
"upath": "^1.0.5"

View file

@ -5,11 +5,13 @@ const notarizeMacBuild = async function (context) {
const appId = 'edu.mit.scratch.scratch-desktop';
if (!process.env.AC_USERNAME) {
throw new Error(
'Notarizing the macOS build requires an Apple ID.\n' +
'Please set the environment variable AC_USERNAME.\n' +
'Make sure your keychain has an item for "Application Loader: your@apple.id"'
);
console.error([
'Notarizing the macOS build requires an Apple ID.',
'Please set the environment variable AC_USERNAME.',
'Make sure your keychain has an item for "Application Loader: your@apple.id"',
'This build will not run on newer versions of macOS!'
].join('\n'));
return;
}
const appleId = process.env.AC_USERNAME;

View file

@ -82,7 +82,9 @@ const calculateTargets = function () {
// Running 'dmg' and 'mas' in the same pass causes electron-builder to skip signing the non-MAS app copy.
// Running them as separate passes means they both get signed.
// Seems like a bug in electron-builder...
return ['dmg', 'mas'];
// Running the 'mas' build first means that its output is available while we wait for 'dmg' notarization.
// Add 'mas-dev' here to test a 'mas'-like build locally. You'll need a Mac Developer provisioning profile.
return ['mas', 'dmg'];
}
throw new Error(`Could not determine targets for platform: ${process.platform}`);
};

12
src/common/log.js Normal file
View file

@ -0,0 +1,12 @@
import minilog from 'minilog';
minilog.enable();
const namespace = (() => {
switch (process.type) {
case 'browser': return 'main';
case 'renderer': return 'web';
default: return process.type; // probably 'worker' for a web worker
}
})();
export default minilog(`app-${namespace}`);

View file

@ -6,10 +6,13 @@ import {URL} from 'url';
import {getFilterForExtension} from './FileFilters';
import telemetry from './ScratchDesktopTelemetry';
import MacOSMenu from './MacOSMenu';
import log from '../common/log.js';
// suppress deprecation warning; this will be the default in Electron 9
app.allowRendererProcessReuse = true;
telemetry.appWasOpened();
// const defaultSize = {width: 1096, height: 715}; // minimum
const defaultSize = {width: 1280, height: 800}; // good for MAS screenshots
@ -74,13 +77,15 @@ const makeFullUrl = (url, search = null) => {
* Prompt in a platform-specific way for permission to access the microphone or camera, if Electron supports doing so.
* Any application-level checks, such as whether or not a particular frame or document should be allowed to ask,
* should be done before calling this function.
* This function may return a Promise!
*
* @param {string} mediaType - one of Electron's media types, like 'microphone' or 'camera'
* @returns {boolean} - true if permission granted, false otherwise.
* @returns {boolean|Promise.<boolean>} - true if permission granted, false otherwise.
*/
const askForMediaAccess = async mediaType => {
const askForMediaAccess = mediaType => {
if (systemPreferences.askForMediaAccess) {
// Electron currently only implements this on macOS
// This returns a Promise
return systemPreferences.askForMediaAccess(mediaType);
}
// For other platforms we can't reasonably do anything other than assume we have access.
@ -288,10 +293,8 @@ app.on('ready', () => {
// WARNING: depending on a lot of things including the version of Electron `installExtension` might
// return a promise that never resolves, especially if the extension is already installed.
installExtension(extension).then(
// eslint-disable-next-line no-console
extensionName => console.log(`Installed dev extension: ${extensionName}`),
// eslint-disable-next-line no-console
errorMessage => console.error(`Error installing dev extension: ${errorMessage}`)
extensionName => log(`Installed dev extension: ${extensionName}`),
errorMessage => log.error(`Error installing dev extension: ${errorMessage}`)
);
}
});

View file

@ -1,8 +1,10 @@
import ElectronStore from 'electron-store';
import nets from 'nets';
import * as os from 'os';
import uuidv1 from 'uuid/v1'; // semi-persistent client ID
import uuidv4 from 'uuid/v4'; // random ID
import {
v1 as uuidv1, // semi-persistent client ID
v4 as uuidv4 // random ID
} from 'uuid';
/**
* Basic telemetry event data. These fields are filled automatically by the `addEvent` call.

View file

@ -4,9 +4,9 @@
const route = new URLSearchParams(window.location.search).get('route') || 'app';
switch (route) {
case 'app':
import('./app.jsx');
import('./app.jsx'); // eslint-disable-line no-unused-expressions
break;
case 'about':
import('./about.jsx');
import('./about.jsx'); // eslint-disable-line no-unused-expressions
break;
}

View file

@ -2,7 +2,6 @@ const childProcess = require('child_process');
const electronPath = require('electron');
const webpack = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const isProduction = (process.env.NODE_ENV === 'production');
@ -61,21 +60,6 @@ const makeConfig = function (options) {
}
]
},
optimization: {
// Use `--env.minify=false` to disable the UglifyJsPlugin instance automatically injected by
// electron-webpack. Otherwise it will do double-duty with this one.
minimizer: isProduction ? [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true, // disable this if UglifyJSPlugin takes too long and/or runs out of memory
uglifyOptions: {
compress: isProduction ? {} : false,
mangle: isProduction
}
})
] : []
},
plugins: [
new webpack.SourceMapDevToolPlugin({
filename: '[file].map'