Merge remote-tracking branch 'origin/develop' into release/2023-08-01

This commit is contained in:
cwillisf 2023-08-01 16:04:51 +00:00
commit 7d53c65993
20 changed files with 557 additions and 236 deletions

275
package-lock.json generated
View file

@ -43,7 +43,7 @@
"babel-preset-react": "6.24.1",
"bowser": "1.9.4",
"canvas": "2.9.0",
"chromedriver": "105.0.0",
"chromedriver": "114.0.3",
"classnames": "2.2.5",
"cookie": "0.4.1",
"copy-webpack-plugin": "6.4.1",
@ -101,8 +101,8 @@
"regenerator-runtime": "0.13.9",
"sass": "1.49.7",
"sass-loader": "10.2.1",
"scratch-gui": "2.0.77",
"scratch-l10n": "3.15.20230718032211",
"scratch-gui": "2.0.80",
"scratch-l10n": "3.15.20230801032207",
"selenium-webdriver": "4.1.0",
"slick-carousel": "1.6.0",
"style-loader": "0.12.3",
@ -1897,9 +1897,9 @@
}
},
"node_modules/@testim/chrome-version": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.2.tgz",
"integrity": "sha512-1c4ZOETSRpI0iBfIFUqU4KqwBAB2lHUAlBjZz/YqOHqwM9dTTzjV6Km0ZkiEiSCx/tLr1BtESIKyWWMww+RUqw==",
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.3.tgz",
"integrity": "sha512-g697J3WxV/Zytemz8aTuKjTGYtta9+02kva3C1xc7KXB8GdbfE1akGJIsZLyY/FSh2QrnE+fiB7vmWU3XNcb6A==",
"dev": true
},
"node_modules/@transifex/api": {
@ -3025,13 +3025,14 @@
"dev": true
},
"node_modules/axios": {
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
"dev": true,
"dependencies": {
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
@ -5368,17 +5369,17 @@
}
},
"node_modules/chromedriver": {
"version": "105.0.0",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-105.0.0.tgz",
"integrity": "sha512-BX3GOUW5m6eiW9cVVF8hw+EFxvrGqYCxbwOqnpk8PjbNFqL5xjy7yel+e6ilJPjckAYFutMKs8XJvOs/W85vvg==",
"version": "114.0.3",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-114.0.3.tgz",
"integrity": "sha512-Qy5kqsAUrCDwpovM5pIWFkb3X3IgJLoorigwFEDgC1boL094svny3N7yw06marJHAuyX4CE/hhd25RarIcKvKg==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
"@testim/chrome-version": "^1.1.2",
"axios": "^0.27.2",
"del": "^6.0.0",
"@testim/chrome-version": "^1.1.3",
"axios": "^1.4.0",
"compare-versions": "^6.0.0",
"extract-zip": "^2.0.1",
"https-proxy-agent": "^5.0.0",
"https-proxy-agent": "^5.0.1",
"proxy-from-env": "^1.1.0",
"tcp-port-used": "^1.0.1"
},
@ -5386,7 +5387,7 @@
"chromedriver": "bin/chromedriver"
},
"engines": {
"node": ">=10"
"node": ">=16"
}
},
"node_modules/cipher-base": {
@ -5755,6 +5756,12 @@
"compare-cell": "^1.0.0"
}
},
"node_modules/compare-versions": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.0.0.tgz",
"integrity": "sha512-s2MzYxfRsE9f/ow8hjn7ysa7pod1xhHdQMsgiJtKx6XSNf4x2N1KG4fjrkUmXcP/e9Y2ZX4zB6sHIso0Lm6evQ==",
"dev": true
},
"node_modules/component-emitter": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
@ -7657,158 +7664,6 @@
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
"dev": true
},
"node_modules/del": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/del/-/del-6.0.0.tgz",
"integrity": "sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==",
"dev": true,
"dependencies": {
"globby": "^11.0.1",
"graceful-fs": "^4.2.4",
"is-glob": "^4.0.1",
"is-path-cwd": "^2.2.0",
"is-path-inside": "^3.0.2",
"p-map": "^4.0.0",
"rimraf": "^3.0.2",
"slash": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/del/node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/del/node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
"dev": true,
"dependencies": {
"path-type": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/del/node_modules/glob": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/del/node_modules/globby": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz",
"integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==",
"dev": true,
"dependencies": {
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
"fast-glob": "^3.1.1",
"ignore": "^5.1.4",
"merge2": "^1.3.0",
"slash": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/del/node_modules/graceful-fs": {
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
"integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==",
"dev": true
},
"node_modules/del/node_modules/ignore": {
"version": "5.1.8",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
"dev": true,
"engines": {
"node": ">= 4"
}
},
"node_modules/del/node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/del/node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/del/node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/del/node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/del/node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/delaunay-triangulate": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/delaunay-triangulate/-/delaunay-triangulate-1.1.6.tgz",
@ -12681,9 +12536,9 @@
"integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM="
},
"node_modules/https-proxy-agent": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"dev": true,
"dependencies": {
"agent-base": "6",
@ -13581,24 +13436,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-path-cwd": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
"integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/is-path-inside": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/is-plain-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
@ -23520,10 +23357,28 @@
"scratch-l10n": "3.15.20230718032211"
}
},
"node_modules/scratch-blocks/node_modules/scratch-l10n": {
"version": "3.15.20230718032211",
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230718032211.tgz",
"integrity": "sha512-USFDniZJP3QpTnBKKXBNw7w0jjvx6qCP5bWkNEF/xRIypSywJ1O2Os9CSSzm3tq7lHqXJRD5XVfxgvC+H0Xp2A==",
"dev": true,
"dependencies": {
"@babel/cli": "^7.1.2",
"@babel/core": "^7.1.2",
"@transifex/api": "4.2.5",
"babel-plugin-react-intl": "^3.0.1",
"download": "^8.0.0",
"transifex": "1.6.6"
},
"bin": {
"build-i18n-src": "scripts/build-i18n-src.js",
"tx-push-src": "scripts/tx-push-src.js"
}
},
"node_modules/scratch-gui": {
"version": "2.0.77",
"resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-2.0.77.tgz",
"integrity": "sha512-saaYzmcM0aeD3busS8xt91s4vdtLhom30FYxIVu8+YIbvoPeFChwE3c5b/PqeUgiprpubHs8K4UhDnzTfTYe0A==",
"version": "2.0.80",
"resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-2.0.80.tgz",
"integrity": "sha512-MTL7hGcTo8xVp7MR78RKMcBQnFTaem72oradRbpfSQkM0X4yDaM8FmqxYHle5laxA5CoL2WdfRLs01CgmsJ2kg==",
"dev": true,
"dependencies": {
"@microbit/microbit-universal-hex": "0.2.2",
@ -23579,13 +23434,13 @@
"redux-throttle": "0.1.1",
"scratch-audio": "0.1.0-prerelease.20221123180128",
"scratch-blocks": "0.2.0-prerelease.20230718081157",
"scratch-l10n": "3.15.20230718032211",
"scratch-paint": "2.0.21",
"scratch-l10n": "3.15.20230801032207",
"scratch-paint": "2.0.23",
"scratch-render": "0.1.0-prerelease.20230710194419",
"scratch-render-fonts": "1.0.0-prerelease.20221102164332",
"scratch-storage": "2.2.1",
"scratch-svg-renderer": "0.2.0-prerelease.20230710144521",
"scratch-vm": "1.5.90",
"scratch-vm": "1.5.92",
"startaudiocontext": "1.2.1",
"style-loader": "^0.23.0",
"text-encoding": "0.7.0",
@ -23935,9 +23790,9 @@
}
},
"node_modules/scratch-gui/node_modules/scratch-paint": {
"version": "2.0.21",
"resolved": "https://registry.npmjs.org/scratch-paint/-/scratch-paint-2.0.21.tgz",
"integrity": "sha512-LoEUU53rO5zJSp4dGOvAg0jFXkd/jiloETr2yz2AcNizCbPhWnQ0fz7bRR+pOEHzkMOsJk4rapfeSSyI1ed1VA==",
"version": "2.0.23",
"resolved": "https://registry.npmjs.org/scratch-paint/-/scratch-paint-2.0.23.tgz",
"integrity": "sha512-e7/wOnzzfUCNwpo3bIZc+zHaSWKHgsk5wM68eXDDlyToYbsybmpaz+cNJBLQ3kjQeKa1Co9fNnsfAatJPrcV9Q==",
"dev": true,
"dependencies": {
"@scratch/paper": "0.11.20200728195508",
@ -24004,9 +23859,9 @@
}
},
"node_modules/scratch-gui/node_modules/tslib": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
"integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==",
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz",
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==",
"dev": true,
"peer": true
},
@ -24023,9 +23878,9 @@
}
},
"node_modules/scratch-l10n": {
"version": "3.15.20230718032211",
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230718032211.tgz",
"integrity": "sha512-USFDniZJP3QpTnBKKXBNw7w0jjvx6qCP5bWkNEF/xRIypSywJ1O2Os9CSSzm3tq7lHqXJRD5XVfxgvC+H0Xp2A==",
"version": "3.15.20230801032207",
"resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.15.20230801032207.tgz",
"integrity": "sha512-q2ALpTqN08z+cxVvQjAhjz3ONOsMpVwMI4qqiYJkIVYjpA6gkXmSPEfQ9gstiIlREcKVyQB1Me7RMWqdy+ncJg==",
"dev": true,
"dependencies": {
"@babel/cli": "^7.1.2",
@ -24226,9 +24081,9 @@
"dev": true
},
"node_modules/scratch-vm": {
"version": "1.5.90",
"resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.5.90.tgz",
"integrity": "sha512-YfxsYhF8pS9VJMJVGQdE17QU0B76Zm+HDeI+7bxqqrSSNbxylRPr4wJS8juTY2RJgiYQZ0ajAHBGB8cNk7+vIA==",
"version": "1.5.92",
"resolved": "https://registry.npmjs.org/scratch-vm/-/scratch-vm-1.5.92.tgz",
"integrity": "sha512-c6jyS+cq70K36DxvqzBYdLok0Sky4Y1ZovAJWxtocw9HnspxCzDnOoAiHcJIZhj4i/gXEDMiV8N3WjpOX2cvNg==",
"dev": true,
"dependencies": {
"@vernier/godirect": "1.5.0",

View file

@ -78,7 +78,7 @@
"babel-preset-react": "6.24.1",
"bowser": "1.9.4",
"canvas": "2.9.0",
"chromedriver": "105.0.0",
"chromedriver": "114.0.3",
"classnames": "2.2.5",
"cookie": "0.4.1",
"copy-webpack-plugin": "6.4.1",
@ -136,8 +136,8 @@
"regenerator-runtime": "0.13.9",
"sass": "1.49.7",
"sass-loader": "10.2.1",
"scratch-gui": "2.0.77",
"scratch-l10n": "3.15.20230718032211",
"scratch-gui": "2.0.80",
"scratch-l10n": "3.15.20230801032207",
"selenium-webdriver": "4.1.0",
"slick-carousel": "1.6.0",
"style-loader": "0.12.3",

View file

@ -27,7 +27,7 @@ const ExtensionRequirements = props => (
alt=""
src="/svgs/extensions/mac.svg"
/>
macOS 10.13+
macOS 10.15+
</span>
)}
{!props.hideChromeOS && (

View file

@ -4,6 +4,9 @@ const React = require('react');
const ExtensionSection = require('./extension-section.jsx');
const OS_ENUM = require('../../lib/os-enum.js');
const {isDownloaded} = require('../install-scratch/install-util.js');
// TODO: after the Scratch Conference 2022, migrate from the individual extension landing pages all the
// troubleshooting steps which are common to all extensions.
const ExtensionTroubleshooting = props => {
@ -17,14 +20,24 @@ const ExtensionTroubleshooting = props => {
id="extensions.troubleshootingTitle"
values={sharedValues}
/></h2>
<h3 className="faq-title"><FormattedMessage
id="extensions.browserCompatibilityTitle"
values={sharedValues}
/></h3>
<p><FormattedMessage
id="extensions.browserCompatibilityText2"
values={sharedValues}
/></p>
{(isDownloaded(props.currentOS)) && (<React.Fragment>
<h3 className="faq-title"><FormattedMessage
id="extensions.scratchLinkRunning"
values={sharedValues}
/></h3>
<p><FormattedMessage
id={`extensions.startScratchLink.${
props.currentOS === OS_ENUM.WINDOWS ? 'Windows' : 'macOS'
}`}
/></p>
<h3 className="faq-title"><FormattedMessage
id="extensions.browserCompatibilityTitle"
values={sharedValues}
/></h3>
<p><FormattedMessage
id="extensions.browserCompatibilityText"
values={sharedValues}
/></p></React.Fragment>)}
{props.children}
{!props.scratchLinkOnly && (
<React.Fragment>
@ -44,6 +57,7 @@ const ExtensionTroubleshooting = props => {
ExtensionTroubleshooting.propTypes = {
children: PropTypes.node,
currentOS: PropTypes.string.isRequired,
deviceName: PropTypes.string.isRequired,
deviceNameShort: PropTypes.string,
scratchLinkOnly: PropTypes.bool

View file

@ -75,11 +75,6 @@ const InstallScratchLink = ({
}-toolbar.png`}
/>
</span>
<p className="step-description"><FormattedMessage
id={`installScratchLink.startScratchLink2.${
currentOS === OS_ENUM.WINDOWS ? 'Windows' : 'macOS'
}`}
/></p>
</Step>
<Step
compact

View file

@ -169,8 +169,6 @@
"installScratchLink.downloadAndInstall": "Download and install Scratch Link.",
"installScratchLink.startScratchLink.macOS": "Start Scratch Link and make sure it is running. It should appear in your menu bar.",
"installScratchLink.startScratchLink.Windows": "Start Scratch Link and make sure it is running. It should appear in your notification area (system tray).",
"installScratchLink.startScratchLink2.macOS": "If it does not appear, run Scratch Link from your Applications folder.",
"installScratchLink.startScratchLink2.Windows": "If it does not appear, run Scratch Link from your Start menu.",
"installScratchLink.learnMore.bodyText": "To learn more about Scratch Link, click {linkText}.",
"installScratchLink.learnMore.linkText": "here",
"installScratchLink.ifYouHaveTrouble.bodyText": "If you have trouble, see the {linkText} for tips.",
@ -446,11 +444,14 @@
"helpWidget.confirmation": "Thank you for your message.",
"extensions.troubleshootingTitle": "Troubleshooting",
"extensions.scratchLinkRunning": "Make sure Scratch Link is running",
"extensions.startScratchLink.macOS": "If Scratch Link does not appear in your menu bar, run Scratch Link from your Applications folder.",
"extensions.startScratchLink.Windows": "If Scratch Link does not appear in your notification area (system tray), run Scratch Link from your Start menu.",
"extensions.browserCompatibilityTitle": "Make sure your browser is compatible with Scratch Link",
"extensions.browserCompatibilityText2": "Scratch Link 1.4 is not compatible with Safari. If you use Safari, please upgrade to Scratch Link 2.0.",
"extensions.browserCompatibilityText": "Scratch Link is compatible with most browsers on macOS and Windows. For Safari, please update to Scratch Link 2.x, Safari 14 or newer, and macOS 10.15 or newer.",
"extensions.checkOSVersionTitle": "Make sure your operating system is compatible with Scratch Link",
"extensions.checkOSVersionText": "The minimum operating system versions are listed at the top of this page. See instructions for checking your version of {winOSVersionLink} or {macOSVersionLink}.",
"extensions.checkOsVersionText2": "If you are using macOS 12, please update to macOS 12.3 or newer. Earlier versions of macOS 12 do not work correctly with Scratch Link.",
"extensions.checkOsVersionText2": "If you are using macOS 12, please update to macOS 12.3 or newer. Earlier versions of macOS 12 may not work correctly with Scratch Link.",
"extensions.winOSVersionLinkText": "Windows",
"extensions.macOSVersionLinkText": "macOS",
"extensions.closeScratchCopiesTitle": "Close other copies of Scratch",

View file

@ -16,6 +16,7 @@ const banGoodListPaths = [
'/ip_ban_appeal',
'/vpn_required',
'/accounts/banned-response',
'/accounts/bad-username',
'/community_guidelines',
'/privacy_policy',
'/terms_of_use'
@ -85,7 +86,11 @@ const handleSessionResponse = (dispatch, body) => {
body.user.banned &&
banGoodListPaths.every(goodPath => window.location.pathname.indexOf(goodPath) === -1)
) {
window.location = '/accounts/banned-response/';
if (body.user.banned_status === 'far_banned'){
window.location = '/accounts/bad-username/';
} else {
window.location = '/accounts/banned-response/';
}
return;
} else if (
body.flags &&

View file

@ -430,6 +430,13 @@
"view": "microbit/microbit",
"title": "micro:bit"
},
{
"name": "bad-username-splash",
"pattern": "^/accounts/bad-username/?(\\?.*)?$",
"routeAlias": "/accounts/bad-username/?$",
"view": "bad-username-splash/bad-username-splash",
"title": "Account Blocked"
},
{
"name": "vernier",
"pattern": "^/vernier/?(\\?.*)?$",

View file

@ -0,0 +1,293 @@
const injectIntl = require('react-intl').injectIntl;
const React = require('react');
const FormattedMessage = require('react-intl').FormattedMessage;
import {connect} from 'react-redux';
import {selectUser, selectHasFetchedSession} from '../../redux/session';
const messageActions = require('../../redux/messages.js');
const JoinFlowStep = require('../../components/join-flow/join-flow-step.jsx');
const FormikInput = require('../../components/formik-forms/formik-input.jsx');
import {Formik} from 'formik';
const PropTypes = require('prop-types');
const Page = require('../../components/page/www/page.jsx');
const render = require('../../lib/render.jsx');
const api = require('../../lib/api');
import bannedIcon from './blocked-account.svg';
require('../../components/extension-landing/extension-landing.scss');
require('./bad-username-splash.scss');
const validateNewUsernameForm = values => {
const errors = {};
if (values.canValidate && (values.newUsername !== values.newUsernameConfirm && values.newUsernameConfirm !== '')){
errors.newUsernameConfirm = "usernames don't match";
}
return errors;
};
const PIIUsernameMessage = 'username appears to contain personal information';
const BadUsernameMessage = 'an inappropriate username';
const BannedSplash = ({hasSession, user, adminMessages, getAdminMessages}) => {
const [unauthorizedError, setUnauthorizedError] = React.useState(false);
const [badUsernameError, setBadUsernameError] = React.useState(false);
const [apiError, setAPIError] = React.useState(false);
const latestAdminMessage = adminMessages && adminMessages[0] && adminMessages[0].message;
React.useEffect(() => {
if (user && user.username && user.token){
getAdminMessages(user.username, user.token);
}
}, [user]);
const handleUpdateUsernameUnbanSubmit = (formData, formikBag) => {
setUnauthorizedError(false);
setBadUsernameError(false);
setAPIError(false);
formikBag.setSubmitting(false); // formik makes us do this ourselves
api({
host: '',
uri: '/accounts/update_username/',
method: 'post',
useCsrf: true,
json: {
new_username: formData.newUsername,
username: formData.username,
password: formData.password
}
}, (err, body, res) => {
if (res.body.error === 'Unauthorized'){
setUnauthorizedError('error message for unauthorized access');
} else if (res.body.error === 'Invalid username'){
setBadUsernameError('error message for invalid username');
} else if (res.body.error){
setAPIError('error message for API error');
} else {
window.location = '/';
}
});
};
if (hasSession && (!user || !user.banned)){
window.location = '/';
}
if (user && user.banned){
return (<div id="bad-username-splash">
<div id="force-account-rename">
<div id="force-account-rename-inner">
<div
id="force-account-rename-text"
className="col"
>
<span>
<img
className="banned-icon"
src={bannedIcon}
/>
<h1 className="inline"><FormattedMessage id="renameAccount.accountBlocked" /></h1>
</span>
<h3><FormattedMessage id="renameAccount.toRecover" /></h3>
{latestAdminMessage && latestAdminMessage.includes(PIIUsernameMessage) &&
(<div>
<p><FormattedMessage id="renameAccount.yourScratchAccount" /></p>
<p><FormattedMessage id="renameAccount.privacyIssue" /></p>
<p><FormattedMessage id="renameAccount.thingsToAvoid" /></p>
</div>)
}
{latestAdminMessage && latestAdminMessage.includes(BadUsernameMessage) &&
(<div>
<p><FormattedMessage id="renameAccount.yourScratchAccountInappropriate" /></p>
<p><FormattedMessage id="renameAccount.scratchIsForKids" /></p>
<p><FormattedMessage
id="renameAccount.rememberToFollow"
values={{
communityGuidelinesLink: (
<a
href="/community_guidelines"
className="white-underline-link"
>
<FormattedMessage id="renameAccount.CommunityGuidelines" />
</a>
)
}}
/></p>
</div>)
}
</div>
<div className="col">
<Formik
initialValues={{
newUsername: '',
newUsernameConfirm: '',
username: user.username,
password: '',
canValidate: false
}}
validate={validateNewUsernameForm}
validateOnBlur
validateOnChange={false}
/* eslint-disable react/jsx-no-bind */
onSubmit={handleUpdateUsernameUnbanSubmit}
>
{({
errors,
handleSubmit,
isSubmitting,
setFieldError,
setFieldTouched,
setFieldValue,
validateForm
}) => (
<JoinFlowStep
description={<FormattedMessage
id="renameAccount.makeSure"
values={{
communityGuidelinesLink: (
<a href="/community_guidelines">
<FormattedMessage id="renameAccount.scratchsCommunityGuidelines" />
</a>
)
}}
/>}
innerClassName="change-username-inner"
outerClassName="change-username-outer"
title={<FormattedMessage id="renameAccount.changeYourUsername" />}
waiting={isSubmitting}
onSubmit={handleSubmit}
nextButton={<FormattedMessage id="renameAccount.change" />}
>
<div>
<b>Create a new username</b>
<FormikInput
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className={'join-flow-input mt5'}
error={errors.newUsername}
id="newUsername"
name="newUsername"
placeholder={'Type your new username'}
spellCheck={false}
validationClassName="validation-left validation-full-width-input"
/* eslint-disable react/jsx-no-bind */
onChange={e => {
setFieldValue('newUsername', e.target.value.substring(0, 30));
setFieldValue('canValidate', false);
setFieldTouched('newUsername');
setFieldError('newUsername', null);
}}
/>
<FormikInput
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className={'join-flow-input'}
error={errors.newUsernameConfirm || badUsernameError}
id="newUsernameConfirm"
name="newUsernameConfirm"
placeholder={'Type your new username again'}
spellCheck={false}
validationClassName="validation-left validation-full-width-input"
onChange={e => {
setFieldValue('newUsernameConfirm', e.target.value.substring(0, 30));
setFieldTouched('newUsernameConfirm');
setFieldError('newUsernameConfirm', null);
setFieldValue('canValidate', false);
}}
onBlur={() => {
setFieldValue('canValidate', true).then(validateForm());
}}
/>
<b>Password</b>
<FormikInput
type="password"
autoCapitalize="off"
autoComplete="off"
autoCorrect="off"
className={'join-flow-input mt5'}
id="password"
name="password"
placeholder={'Enter your password'}
spellCheck={false}
error={unauthorizedError || apiError}
validationClassName="validation-left validation-full-width-input"
onChange={e => {
setFieldValue('password', e.target.value);
setFieldTouched('password');
setFieldError('password', null);
}}
/>
</div>
</JoinFlowStep>)}
</Formik>
</div>
</div>
</div>
<div id="admin-message-list">
<div id="admin-message-list-title">
<b><FormattedMessage id="renameAccount.pastNotifications" /></b>
</div>
{adminMessages.map(message => (
<div
className="admin-message"
key={message.id}
>
<div className="admin-message-date">
{new Date(message.datetime_created).toDateString()}
</div>
{/* eslint-disable-next-line react/no-danger */}
<div dangerouslySetInnerHTML={{__html: message.message}} />
</div>
))}
</div>
</div>
);
}
return <div />;
};
BannedSplash.propTypes = {
user: PropTypes.shape({
username: PropTypes.string,
banned: PropTypes.bool,
token: PropTypes.string
}),
hasSession: PropTypes.bool,
adminMessages: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number.isRequired,
datetimeCreated: PropTypes.string.isRequired,
message: PropTypes.string.isRequired
})),
getAdminMessages: PropTypes.func
};
const ConnectedBannedSplash = connect(
state => ({
user: selectUser(state),
hasSession: selectHasFetchedSession(state),
adminMessages: state.messages.messages &&
state.messages.messages.admin &&
state.messages.messages.admin.sort((a, b) =>
(b.id - a.id)
)
}),
dispatch => ({
getAdminMessages: (username, token) => {
dispatch(messageActions.getAdminMessages(
username, token, 0
));
}
})
)(BannedSplash);
const WrappedBannedSplash = injectIntl(ConnectedBannedSplash);
render(<Page><WrappedBannedSplash /></Page>, document.getElementById('app'),
{messages: messageActions.messagesReducer});

View file

@ -0,0 +1,134 @@
@import "../../colors";
@import "../../frameless";
.validation-left {
transform: translate(-20.5rem, 0);
}
@media #{$intermediate-and-smaller} {
.validation-full-width-input {
box-sizing: border-box;
transform: unset;
margin-bottom: .75rem;
max-width: 100%;
}
}
.inline{
display:inline;
}
#bad-username-splash{
display: flex;
flex-direction: column;
align-items: center;
}
#force-account-rename{
width: 100%;
display: flex;
justify-content: center;
#force-account-rename-inner{
max-width: 1094px;
display: flex;
flex-direction: row;
@media only screen and (max-width: 800px) {
flex-direction: column;
}
text-align: left;
input{
box-sizing: border-box;
width: 100%;
}
}
background-color: #575E75;
.col{
padding: 40px;
flex: 1;
}
}
#admin-message-list{
display: inline-block;
padding: 25px;
max-width: 1094px;
#admin-message-list-title{
text-align: left;
}
}
.admin-message{
text-align: left;
.admin-message-date{
color: #575E75;
font-size: 12px;
padding-bottom: 10px;
}
text-align: left;
border-radius: 8px;
padding: 16px;
background-color: #E5F0FF;
margin: 10px;
}
#force-account-rename-text{
h1, h3, p{
color: white;
}
}
.empty{
text-align: left;
.admin-message{
margin: 10px;
}
}
.banned-message-box{
margin: 20px;
text-align: left;
}
.join-flow-outer-content{
background-color: white;
border-radius: 16px;
color: #575e75;
max-width: 468px;
min-height: auto !important;
@media only screen and (max-width: 800px) {
margin: auto;
}
}
.banned-icon{
margin-right: 10px;
padding-top: 10px;
margin-bottom: -3px;
}
.modal-flush-bottom-button{
background-color: #855CD6;
}
.modal-flush-bottom-button:hover{
background-color: #855CD6;
}
.join-flow-outer-content{
border: solid 4px #818698;
border-radius: 21px;
}
.mt5{
margin-top: 5px;
}
.white-underline-link{
color: white !important;
text-decoration: underline !important;
}

View file

@ -0,0 +1,3 @@
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.66463 34.3035C3.16405 34.7261 3.91148 34.6638 4.33407 34.1643L30.3944 3.36576C30.817 2.86634 30.7547 2.11891 30.2553 1.69632C29.7559 1.27374 29.0084 1.33602 28.5859 1.83544L25.5707 5.39883H7.19999C4.21765 5.39883 1.79999 7.81649 1.79999 10.7988V25.1988C1.79999 27.2974 2.99711 29.1164 4.74571 30.0102L2.52551 32.634C2.10293 33.1335 2.16521 33.8809 2.66463 34.3035ZM6.59065 27.8298L18.6752 13.548H4.49999V25.1988C4.49999 26.4804 5.39295 27.5535 6.59065 27.8298ZM28.8 30.5988H10.4308L12.7154 27.8988H28.8C30.2912 27.8988 31.5 26.69 31.5 25.1988V13.548H24.8584L31.2553 5.98803C33.0033 6.88198 34.2 8.70066 34.2 10.7988V25.1988C34.2 28.1812 31.7823 30.5988 28.8 30.5988Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 838 B

View file

@ -193,7 +193,10 @@ class Boost extends ExtensionLanding {
/>
</Steps>
</ExtensionSection>
<ExtensionTroubleshooting deviceName="BOOST">
<ExtensionTroubleshooting
currentOS={this.state.OS}
deviceName="BOOST"
>
{isDownloaded(this.state.OS) && (
<React.Fragment>
<h3 className="faq-title"><FormattedMessage id="boost.updateScratchLinkTitle" /></h3>

View file

@ -103,6 +103,7 @@ const ScratchLink = ({intl}) => {
</div>
</ExtensionSection>
<ExtensionTroubleshooting
currentOS={os}
deviceName={intl.formatMessage({id: 'scratchLink.headerTitle'})}
scratchLinkOnly
>

View file

@ -283,6 +283,7 @@ class EV3 extends ExtensionLanding {
</Steps>
</ExtensionSection>
<ExtensionTroubleshooting
currentOS={this.state.OS}
deviceName="EV3"
scratchLinkOnly // EV3 is Bluetooth Classic so it's only available through Scratch Link
>
@ -315,6 +316,7 @@ class EV3 extends ExtensionLanding {
/>
</p>
<p><FormattedMessage id="extensions.checkOsVersionText2" /></p>
<p><FormattedMessage id="ev3.macCompatibility" /></p>
<h3 className="faq-title"><FormattedMessage id="ev3.tryScratchLink1.4" /></h3>
<p><a
href={`https://downloads.scratch.mit.edu/link/scratch-link-${

View file

@ -28,6 +28,7 @@
"ev3.troubleshootingTitle": "Troubleshooting",
"ev3.checkOSVersionTitle": "Make sure your operating system is compatible with Scratch Link",
"ev3.checkOSVersionText": "The minimum operating system versions are listed at the top of this page. See instructions for checking your version of {winOSVersionLink} or {macOSVersionLink}.",
"ev3.macCompatibility": "For best results with EV3 on macOS, please update to macOS 11 or newer.",
"ev3.tryScratchLink1.4": "If you have issues connecting EV3 with Scratch Link 2.0, please try Scratch Link 1.4",
"ev3.downloadScratchLink1.4": "Download Scratch Link 1.4",
"ev3.winOSVersionLinkText": "Windows",

View file

@ -207,6 +207,7 @@ class GdxFor extends ExtensionLanding {
</Steps>
</ExtensionSection>
<ExtensionTroubleshooting
currentOS={this.state.OS}
deviceName={this.props.intl.formatMessage({id: 'gdxfor.deviceName'})}
deviceNameShort={this.props.intl.formatMessage({id: 'gdxfor.deviceNameShort'})}
>

View file

@ -319,7 +319,10 @@ class MicroBit extends ExtensionLanding {
</FlexRow>
<hr />
</ExtensionSection>
<ExtensionTroubleshooting deviceName="micro:bit">
<ExtensionTroubleshooting
currentOS={this.state.OS}
deviceName="micro:bit"
>
{isDownloaded(this.state.OS) && (
<React.Fragment>
<h3 className="faq-title"><FormattedMessage id="microbit.checkOSVersionTitle" /></h3>

View file

@ -192,7 +192,10 @@ class Wedo2 extends ExtensionLanding {
/>
</Steps>
</ExtensionSection>
<ExtensionTroubleshooting deviceName="WeDo 2.0">
<ExtensionTroubleshooting
currentOS={this.state.OS}
deviceName="WeDo 2.0"
>
{isDownloaded(this.state.OS) && (
<React.Fragment>
<h3 className="faq-title"><FormattedMessage id="wedo2.checkOSVersionTitle" /></h3>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 188 KiB

View file

@ -10,7 +10,7 @@ describe('ExtensionRequirements', () => {
const requirements = component.find('.extension-requirements span').map(span => span.text());
expect(requirements).toEqual(
['Windows 10 version 1709+', 'macOS 10.13+', 'ChromeOS', 'Android 6.0+', 'Bluetooth', 'Scratch Link']
['Windows 10 version 1709+', 'macOS 10.15+', 'ChromeOS', 'Android 6.0+', 'Bluetooth', 'Scratch Link']
);
});