Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ npm-*
/build
/dist
/.opt-in
/embedded.provisionprofile
/*.provisionprofile

# don't store the assets downloaded with the `fetch` script
/static/assets/
Expand Down
4 changes: 4 additions & 0 deletions buildResources/entitlements.mac.plist
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
Expand Down
4 changes: 4 additions & 0 deletions buildResources/entitlements.mas.plist
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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>
Expand Down
4 changes: 4 additions & 0 deletions electron-builder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
13,933 changes: 5,707 additions & 8,226 deletions package-lock.json

Large diffs are not rendered by default.

60 changes: 30 additions & 30 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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"
Expand Down
12 changes: 7 additions & 5 deletions scripts/afterSign.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion scripts/electron-builder-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}`);
};
Expand Down
12 changes: 12 additions & 0 deletions src/common/log.js
Original file line number Diff line number Diff line change
@@ -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}`);
17 changes: 10 additions & 7 deletions src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ import {URL} from 'url';
import {getFilterForExtension} from './FileFilters';
import telemetry from './ScratchDesktopTelemetry';
import MacOSMenu from './MacOSMenu';
import log from '../common/log.js';

telemetry.appWasOpened();
// 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
Expand Down Expand Up @@ -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.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just always return a promise?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about this separately but just to record it here: functionally this is fine because it's called with await, which hides the difference between returning a promise and returning a raw Boolean. To avoid possible future problems I will make a followup change where this function always returns a promise, especially since there's basically no down-side to doing so in this context. (This isn't performance-critical, no synchronous work is happening around this call, etc.)

*/
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.
Expand Down Expand Up @@ -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}`)
);
}
});
Expand Down
6 changes: 4 additions & 2 deletions src/main/telemetry/TelemetryClient.js
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
16 changes: 0 additions & 16 deletions webpack.makeConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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'
Expand Down