diff --git a/package-lock.json b/package-lock.json index d761ace81..830dc488b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,475 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@babel/cli": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.8.4.tgz", - "integrity": "sha512-XXLgAm6LBbaNxaGhMAznXXaxtCWfuv6PIDJ9Alsy9JYTOh+j2jJz+L/162kkfU1j/pTSxK1xGmlwI4pdIMkoag==", - "dev": true, - "requires": { - "chokidar": "^2.1.8", - "commander": "^4.0.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.0.0", - "lodash": "^4.17.13", - "make-dir": "^2.1.0", - "slash": "^2.0.0", - "source-map": "^0.5.0" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "optional": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "optional": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "optional": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "optional": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "optional": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "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" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "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, - "optional": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "optional": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "optional": true - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "optional": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "optional": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, "@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", @@ -16257,21 +15788,490 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20200415195503", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20200415195503.tgz", - "integrity": "sha512-QYZGxVmQj8QDbmgNvVtF7zAXi+QB+skK/wCnG/9o+ivFiZBAGpMh8hSqVvJe5lAen3ptVQ7yjJ1dEm1urjk7kw==", + "version": "0.1.0-prerelease.20200423001702", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20200423001702.tgz", + "integrity": "sha512-xLqqRRhdQCHj2fQ4OjmUeHcMzztgiVz6zbSYR9be7Bl9Gk+7yuo5XWOiqKqfsloAb0dco1og15zVQKVmLQ/A9A==", "dev": true }, "scratch-l10n": { - "version": "3.8.20200414213430", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.8.20200414213430.tgz", - "integrity": "sha512-+oLlx3wIWWubx1yGh4nMWSUzP9y3nArGXrMZf9x1oCO2b3k835oMfuhUZSZ7vi8gsruhw1iNQp+H1HkM9cKi+A==", + "version": "3.8.20200421213407", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.8.20200421213407.tgz", + "integrity": "sha512-cuFbyCX4v5oId7HJ5Ojm5dQwqW5sfZ7Bmo6xkNIOCwOMcIeo0JJpBbbZ8XtdodLjEDg37/weBWfYAxYIUphGIA==", "dev": true, "requires": { "@babel/cli": "^7.1.2", "@babel/core": "^7.1.2", "babel-plugin-react-intl": "^3.0.1", "transifex": "1.6.6" + }, + "dependencies": { + "@babel/cli": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.8.4.tgz", + "integrity": "sha512-XXLgAm6LBbaNxaGhMAznXXaxtCWfuv6PIDJ9Alsy9JYTOh+j2jJz+L/162kkfU1j/pTSxK1xGmlwI4pdIMkoag==", + "dev": true, + "requires": { + "chokidar": "^2.1.8", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.13", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "optional": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "optional": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "optional": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "optional": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "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" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "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, + "optional": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "optional": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "optional": true + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "optional": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, "scratch-parser": { diff --git a/package.json b/package.json index 83d815146..035e4e472 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,7 @@ "redux-mock-store": "^1.2.3", "redux-thunk": "2.0.1", "sass-loader": "6.0.6", - "scratch-gui": "0.1.0-prerelease.20200415195503", + "scratch-gui": "0.1.0-prerelease.20200423001702", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", diff --git a/src/components/extension-landing/extension-requirements.jsx b/src/components/extension-landing/extension-requirements.jsx index ede0ab304..efe498921 100644 --- a/src/components/extension-landing/extension-requirements.jsx +++ b/src/components/extension-landing/extension-requirements.jsx @@ -4,8 +4,6 @@ const React = require('react'); const FlexRow = require('../../components/flex-row/flex-row.jsx'); -const {CHROME_APP_RELEASED} = require('../../lib/feature-flags.js'); - require('./extension-landing.scss'); const ExtensionRequirements = props => ( @@ -30,24 +28,22 @@ const ExtensionRequirements = props => ( /> macOS 10.13+ - {CHROME_APP_RELEASED && ( - - - - ChromeOS - - - - Android 6.0+ - - - )} + + + + ChromeOS + + + + Android 6.0+ + + Bluetooth diff --git a/src/components/info-button/info-button.jsx b/src/components/info-button/info-button.jsx index f79890c05..92414f47b 100644 --- a/src/components/info-button/info-button.jsx +++ b/src/components/info-button/info-button.jsx @@ -11,19 +11,45 @@ class InfoButton extends React.Component { constructor (props) { super(props); bindAll(this, [ - 'handleHideMessage', - 'handleShowMessage' + 'handleClick', + 'handleMouseLeave', + 'handleShowMessage', + 'setButtonRef' ]); this.state = { + requireClickToClose: false, // default to closing on mouseout visible: false }; } - handleHideMessage () { - this.setState({visible: false}); + componentWillMount () { + window.addEventListener('mousedown', this.handleClick, false); + } + componentWillUnmount () { + window.removeEventListener('mousedown', this.handleClick, false); + } + handleClick (e) { + if (this.buttonRef) { // only handle click if we can tell whether it happened in this component + let newVisibleState = false; // for most clicks, hide the info message + if (this.buttonRef.contains(e.target)) { // if the click was inside the info icon... + newVisibleState = !this.state.requireClickToClose; // toggle it + } + this.setState({ + requireClickToClose: newVisibleState, + visible: newVisibleState + }); + } + } + handleMouseLeave () { + if (this.state.visible && !this.state.requireClickToClose) { + this.setState({visible: false}); + } } handleShowMessage () { this.setState({visible: true}); } + setButtonRef (element) { + this.buttonRef = element; + } render () { const messageJsx = this.state.visible && (
@@ -34,8 +60,8 @@ class InfoButton extends React.Component {
diff --git a/src/components/info-button/info-button.scss b/src/components/info-button/info-button.scss index f2d93303d..2e9e3e4f4 100644 --- a/src/components/info-button/info-button.scss +++ b/src/components/info-button/info-button.scss @@ -4,23 +4,21 @@ .info-button { position: relative; display: inline-block; - width: 1rem; - height: 1rem; - margin-left: .375rem; - margin-top: -.25rem; - border-radius: 50%; - background-color: $type-gray-60percent; + width: 2rem; + height: 2rem; + margin-left: -.125rem; + margin-top: -.75rem; background-image: url("/svgs/info-button/info-button.svg"); background-size: cover; - top: .1875rem; + top: .6875rem; } .info-button-message { $arrow-border-width: 1rem; display: block; position: absolute; - top: 0; - left: 0; + top: .375rem; + left: .5rem; transform: translate(1rem, -1rem); width: 16.5rem; min-height: 1rem; @@ -66,6 +64,7 @@ we need to center this element within its width. */ margin: 0 calc((100% - 16.5rem) / 2);; top: .125rem; + left: 0; &:before { display: none; diff --git a/src/components/install-scratch/install-scratch.jsx b/src/components/install-scratch/install-scratch.jsx index 0e022b609..00b005444 100644 --- a/src/components/install-scratch/install-scratch.jsx +++ b/src/components/install-scratch/install-scratch.jsx @@ -3,7 +3,6 @@ const FormattedMessage = require('react-intl').FormattedMessage; const React = require('react'); const OS_ENUM = require('../../lib/os-enum.js'); -const {CHROME_APP_RELEASED} = require('../../lib/feature-flags.js'); const {isDownloaded, isFromGooglePlay} = require('./install-util.js'); @@ -27,24 +26,10 @@ const InstallScratch = ({

- {CHROME_APP_RELEASED ? ( - - ) : ( - - {isDownloaded(currentOS) && ( - - )} - {isFromGooglePlay(currentOS) && ( - - )} - - )} +

@@ -56,14 +41,12 @@ const InstallScratch = ({ {currentOS === OS_ENUM.WINDOWS && ( )} {currentOS === OS_ENUM.MACOS && ( )} {isFromGooglePlay(currentOS) && ( diff --git a/src/components/join-flow/join-flow-steps.scss b/src/components/join-flow/join-flow-steps.scss index 3d7e1df30..6caa86d50 100644 --- a/src/components/join-flow/join-flow-steps.scss +++ b/src/components/join-flow/join-flow-steps.scss @@ -127,10 +127,11 @@ } .join-flow-privacy-message { - margin: 1rem auto; + margin: .5rem auto 1rem; font-size: .75rem; font-weight: 500; color: $type-gray-60percent; + text-align: center; } .join-flow-inner-username-step { diff --git a/src/components/os-chooser/os-chooser.jsx b/src/components/os-chooser/os-chooser.jsx index 5d77d19e2..c2821080a 100644 --- a/src/components/os-chooser/os-chooser.jsx +++ b/src/components/os-chooser/os-chooser.jsx @@ -4,8 +4,6 @@ const FormattedMessage = require('react-intl').FormattedMessage; const PropTypes = require('prop-types'); const React = require('react'); -const {CHROME_APP_RELEASED} = require('../../lib/feature-flags.js'); - const FlexRow = require('../../components/flex-row/flex-row.jsx'); const Button = require('../../components/forms/button.jsx'); @@ -35,28 +33,24 @@ const OSChooser = props => ( macOS - {CHROME_APP_RELEASED && ( - - - - - )} + +
); diff --git a/src/components/registration/steps.jsx b/src/components/registration/steps.jsx index 42fe4714f..42bdb2db4 100644 --- a/src/components/registration/steps.jsx +++ b/src/components/registration/steps.jsx @@ -28,6 +28,7 @@ const Spinner = require('../../components/spinner/spinner.jsx'); const StepNavigation = require('../../components/stepnavigation/stepnavigation.jsx'); const TextArea = require('../../components/forms/textarea.jsx'); const Tooltip = require('../../components/tooltip/tooltip.jsx'); +const ValidationMessage = require('../../components/forms/validation-message.jsx'); require('./steps.scss'); @@ -84,11 +85,13 @@ class UsernameStep extends React.Component { 'handleChangeShowPassword', 'handleUsernameBlur', 'handleValidSubmit', - 'validateUsername' + 'validateUsername', + 'handleFocus' ]); this.state = { showPassword: props.showPassword, waiting: false, + showUsernameTip: true, validUsername: '' }; } @@ -159,6 +162,9 @@ class UsernameStep extends React.Component { if (isValid) return this.props.onNextStep(formData); }); } + handleFocus () { + this.setState({showUsernameTip: false}); + } render () { return ( @@ -205,6 +211,13 @@ class UsernameStep extends React.Component { null )} + { this.state.showUsernameTip && + + }
+ { }; module.exports = { - CHROME_APP_RELEASED: true, CONTACT_US_POPUP: isStaging() && flagInUrl('CONTACT_US_POPUP') }; diff --git a/src/views/download/download.jsx b/src/views/download/download.jsx index 49664936b..26f0538bb 100644 --- a/src/views/download/download.jsx +++ b/src/views/download/download.jsx @@ -10,7 +10,6 @@ const Page = require('../../components/page/www/page.jsx'); const render = require('../../lib/render.jsx'); const detectOS = require('../../lib/detect-os.js').default; const OS_ENUM = require('../../lib/os-enum.js'); -const {CHROME_APP_RELEASED} = require('../../lib/feature-flags.js'); const OSChooser = require('../../components/os-chooser/os-chooser.jsx'); const InstallScratch = require('../../components/install-scratch/install-scratch.jsx'); const {isDownloaded, isFromGooglePlay} = require('../../components/install-scratch/install-util.js'); @@ -52,14 +51,12 @@ class Download extends React.Component { width="40" /> @@ -82,24 +79,20 @@ class Download extends React.Component { /> macOS 10.13+ - {CHROME_APP_RELEASED && ( - - - + + ChromeOS - - - + + + Android 6.0+ - - - )} + diff --git a/src/views/download/l10n.json b/src/views/download/l10n.json index 73118a67c..2de1f8572 100644 --- a/src/views/download/l10n.json +++ b/src/views/download/l10n.json @@ -1,6 +1,4 @@ { - "download.title": "Scratch Desktop", - "download.intro": "You can install the Scratch Desktop editor to work on projects without an internet connection. This version will work on Windows and MacOS.", "download.appTitle": "Download the Scratch App", "download.appIntro": "Would you like to create and save Scratch projects without an internet connection? Download the free Scratch app.", "download.requirements": "Requirements", @@ -23,7 +21,7 @@ "download.macMoveToApplications" : "Open the .dmg file. Move Scratch Desktop into Applications.", "download.winMoveToApplications" : "Run the .exe file.", "download.doIHaveToDownload" : "Do I have to download an app to use Scratch?", - "download.doIHaveToDownloadAnswer" : "No. You can also use the Scratch project editor in any web browser on any device by going to scratch.mit.edu and clicking \"Create\".", + "download.doIHaveToDownloadAnswer" : "No. You can also use the Scratch project editor in most web browsers on most devices by going to scratch.mit.edu and clicking \"Create\".", "download.canIUseScratchLink" : "Can I use Scratch Link to connect to extensions?", "download.canIUseScratchLinkAnswer" : "Yes. However, you will need an Internet connection to use Scratch Link.", "download.canIUseExtensions" : "Can I connect to hardware extensions?", diff --git a/src/views/splash/activity-rows/follow-studio.jsx b/src/views/splash/activity-rows/follow-studio.jsx new file mode 100644 index 000000000..ea97509c9 --- /dev/null +++ b/src/views/splash/activity-rows/follow-studio.jsx @@ -0,0 +1,43 @@ +const classNames = require('classnames'); +const FormattedMessage = require('react-intl').FormattedMessage; +const PropTypes = require('prop-types'); +const React = require('react'); + +const SocialMessage = require('../../../components/social-message/social-message.jsx'); + +const FollowStudioMessage = props => ( + + + {props.followerUsername} + + ), + studioLink: ( + + {props.studioTitle} + + ) + }} + /> + +); + +FollowStudioMessage.propTypes = { + className: PropTypes.string, + followDateTime: PropTypes.string.isRequired, + followerUsername: PropTypes.string.isRequired, + studioId: PropTypes.string.isRequired, + studioTitle: PropTypes.string.isRequired +}; + +module.exports = FollowStudioMessage; diff --git a/src/views/splash/activity-rows/follow-user.jsx b/src/views/splash/activity-rows/follow-user.jsx new file mode 100644 index 000000000..f730a2a6a --- /dev/null +++ b/src/views/splash/activity-rows/follow-user.jsx @@ -0,0 +1,42 @@ +const classNames = require('classnames'); +const FormattedMessage = require('react-intl').FormattedMessage; +const PropTypes = require('prop-types'); +const React = require('react'); + +const SocialMessage = require('../../../components/social-message/social-message.jsx'); + +const FollowUserMessage = props => ( + + + {props.followerUsername} + + ), + followeeLink: ( + + {props.followeeId} + + ) + }} + /> + +); + +FollowUserMessage.propTypes = { + className: PropTypes.string, + followDateTime: PropTypes.string.isRequired, + followeeId: PropTypes.string.isRequired, + followerUsername: PropTypes.string.isRequired +}; + +module.exports = FollowUserMessage; diff --git a/src/views/splash/activity-rows/follow.jsx b/src/views/splash/activity-rows/follow.jsx deleted file mode 100644 index bb1f13baa..000000000 --- a/src/views/splash/activity-rows/follow.jsx +++ /dev/null @@ -1,55 +0,0 @@ -const classNames = require('classnames'); -const FormattedMessage = require('react-intl').FormattedMessage; -const PropTypes = require('prop-types'); -const React = require('react'); - -const SocialMessage = require('../../../components/social-message/social-message.jsx'); - -const FollowMessage = props => { - let followeeLink = ''; - let followeeTitle = ''; - if (typeof props.followeeTitle === 'undefined') { - followeeLink = `/users/${props.followeeId}`; - followeeTitle = props.followeeId; - } else { - followeeLink = `/studios/${props.followeeId}`; - followeeTitle = props.followeeTitle; - } - - return ( - - - {props.followerUsername} - - ), - followeeLink: ( - - {followeeTitle} - - ) - }} - /> - - ); -}; - -FollowMessage.propTypes = { - className: PropTypes.string, - followDateTime: PropTypes.string.isRequired, - followeeId: PropTypes.string.isRequired, - followeeTitle: PropTypes.string, - followerUsername: PropTypes.string.isRequired -}; - -module.exports = FollowMessage; diff --git a/src/views/splash/l10n.json b/src/views/splash/l10n.json index 7ecb0fbc6..4694b40d6 100644 --- a/src/views/splash/l10n.json +++ b/src/views/splash/l10n.json @@ -13,7 +13,8 @@ "messages.becomeCuratorText": "{username} became a curator of {studio}", "messages.becomeManagerText": "{username} was promoted to manager of {studio}", "messages.favoriteText": "{profileLink} favorited {projectLink}", - "messages.followText": "{profileLink} is now following {followeeLink}", + "messages.followProfileText": "{profileLink} is now following {followeeLink}", + "messages.followStudioText": "{profileLink} is now following {studioLink}", "messages.loveText": "{profileLink} loved {projectLink}", "messages.remixText": "{profileLink} remixed {remixedProjectLink} as {projectLink}", "messages.shareText": "{profileLink} shared the project {projectLink}", diff --git a/src/views/splash/presentation.jsx b/src/views/splash/presentation.jsx index 030bb1b70..162b2e63c 100644 --- a/src/views/splash/presentation.jsx +++ b/src/views/splash/presentation.jsx @@ -26,7 +26,8 @@ const Welcome = require('../../components/welcome/welcome.jsx'); const BecomeCuratorMessage = require('./activity-rows/become-curator.jsx'); const BecomeManagerMessage = require('./activity-rows/become-manager.jsx'); const FavoriteProjectMessage = require('./activity-rows/favorite-project.jsx'); -const FollowMessage = require('./activity-rows/follow.jsx'); +const FollowUserMessage = require('./activity-rows/follow-user.jsx'); +const FollowStudioMessage = require('./activity-rows/follow-studio.jsx'); const LoveProjectMessage = require('./activity-rows/love-project.jsx'); const RemixProjectMessage = require('./activity-rows/remix-project.jsx'); const ShareProjectMessage = require('./activity-rows/share-project.jsx'); @@ -53,7 +54,7 @@ class ActivityList extends React.Component { switch (message.type) { case 'followuser': return ( - ); case 'loveproject': diff --git a/src/views/studentregistration/studentregistration.jsx b/src/views/studentregistration/studentregistration.jsx index 5b8ff8b39..3ad1d70ab 100644 --- a/src/views/studentregistration/studentregistration.jsx +++ b/src/views/studentregistration/studentregistration.jsx @@ -126,7 +126,7 @@ class StudentRegistration extends React.Component { id: 'registration.studentUsernameStepTooltip' })} usernameHelp={this.props.intl.formatMessage({ - id: 'registration.studentUsernameFieldHelpText' + id: 'registration.studentUsernameSuggestion' })} waiting={this.state.waiting} onNextStep={this.handleAdvanceStep} diff --git a/static/svgs/info-button/info-button.svg b/static/svgs/info-button/info-button.svg index 76edc37d8..a5bbdbd01 100644 --- a/static/svgs/info-button/info-button.svg +++ b/static/svgs/info-button/info-button.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/test/unit/components/info-button.test.jsx b/test/unit/components/info-button.test.jsx index e7e48231d..959e4208f 100644 --- a/test/unit/components/info-button.test.jsx +++ b/test/unit/components/info-button.test.jsx @@ -3,6 +3,15 @@ import {mountWithIntl} from '../../helpers/intl-helpers.jsx'; import InfoButton from '../../../src/components/info-button/info-button'; describe('InfoButton', () => { + // mock window.addEventListener + // for more on this technique, see discussion at https://github.com/airbnb/enzyme/issues/426#issuecomment-253515886 + const mockedAddEventListener = {}; + /* eslint-disable no-undef */ + window.addEventListener = jest.fn((event, cb) => { + mockedAddEventListener[event] = cb; + }); + /* eslint-enable no-undef */ + test('Info button defaults to not visible', () => { const component = mountWithIntl( { ); expect(component.find('div.info-button-message').exists()).toEqual(false); }); - test('mouseOver on info button makes info message visible', () => { + + test('mouseOver on info button makes info message visible', done => { const component = mountWithIntl( ); + + // mouseOver info button component.find('div.info-button').simulate('mouseOver'); - expect(component.find('div.info-button-message').exists()).toEqual(true); + setTimeout(function () { // necessary because mouseover uses debounce + // crucial: if we don't call update(), then find() below looks through an OLD + // version of the DOM! see https://github.com/airbnb/enzyme/issues/1233#issuecomment-358915200 + component.update(); + expect(component.find('div.info-button-message').exists()).toEqual(true); + done(); + }, 500); }); + test('clicking on info button makes info message visible', () => { const component = mountWithIntl( ); - component.find('div.info-button').simulate('click'); + const buttonRef = component.instance().buttonRef; + + // click on info button + mockedAddEventListener.mousedown({target: buttonRef}); + component.update(); + expect(component.find('div.info-button').exists()).toEqual(true); expect(component.find('div.info-button-message').exists()).toEqual(true); }); - test('after message is visible, mouseOut makes it vanish', () => { + + test('clicking on info button, then mousing out makes info message still appear', done => { const component = mountWithIntl( ); - component.find('div.info-button').simulate('mouseOver'); + const buttonRef = component.instance().buttonRef; + + // click on info button + mockedAddEventListener.mousedown({target: buttonRef}); + component.update(); + expect(component.find('div.info-button').exists()).toEqual(true); expect(component.find('div.info-button-message').exists()).toEqual(true); - component.find('div.info-button').simulate('mouseOut'); + + // mouseLeave from info button + component.find('div.info-button').simulate('mouseLeave'); + setTimeout(function () { // necessary because mouseover uses debounce + component.update(); + expect(component.find('div.info-button-message').exists()).toEqual(true); + done(); + }, 500); + }); + + test('clicking on info button, then clicking on it again makes info message go away', () => { + const component = mountWithIntl( + + ); + const buttonRef = component.instance().buttonRef; + + // click on info button + mockedAddEventListener.mousedown({target: buttonRef}); + component.update(); + expect(component.find('div.info-button').exists()).toEqual(true); + expect(component.find('div.info-button-message').exists()).toEqual(true); + + // click on info button again + mockedAddEventListener.mousedown({target: buttonRef}); + component.update(); + expect(component.find('div.info-button-message').exists()).toEqual(false); + }); + + test('clicking on info button, then clicking somewhere else', () => { + const component = mountWithIntl( + + ); + const buttonRef = component.instance().buttonRef; + + // click on info button + mockedAddEventListener.mousedown({target: buttonRef}); + component.update(); + expect(component.find('div.info-button').exists()).toEqual(true); + expect(component.find('div.info-button-message').exists()).toEqual(true); + + // click on some other target + mockedAddEventListener.mousedown({target: null}); + component.update(); + expect(component.find('div.info-button-message').exists()).toEqual(false); + }); + + test('after message is visible, mouseLeave makes it vanish', () => { + const component = mountWithIntl( + + ); + + // mouseOver info button + component.find('div.info-button').simulate('mouseOver'); + component.update(); + expect(component.find('div.info-button-message').exists()).toEqual(true); + + // mouseLeave away from info button + component.find('div.info-button').simulate('mouseLeave'); + component.update(); expect(component.find('div.info-button-message').exists()).toEqual(false); }); });