Merge remote-tracking branch 'upstream/develop' into scratch-desktop

This commit is contained in:
Christopher Willis-Ford committed 2019-03-12 16:13:27 -07:00
commit 94901b33fe
17 files changed
+136 -84

No files matched your search

+1
View File
@@ -4,6 +4,7 @@
# NPM
/node_modules
npm-*
/package-lock.json
# Testing
/.nyc_output
+4 -4
View File
@@ -56,7 +56,7 @@
"eslint": "^5.0.1",
"eslint-config-scratch": "^5.0.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-react": "^7.5.1",
"eslint-plugin-react": "7.11.1",
"file-loader": "2.0.0",
"get-float-time-domain-data": "0.1.0",
"get-user-media-promise": "1.1.4",
@@ -103,14 +103,14 @@
"redux-mock-store": "^1.2.3",
"redux-throttle": "0.1.1",
"rimraf": "^2.6.1",
"scratch-audio": "0.1.0-prerelease.20181023202904",
"scratch-audio": "0.1.0-prerelease.20190108181031",
"scratch-blocks": "0.1.0-prerelease.1545364693",
"scratch-l10n": "3.1.20181220222259",
"scratch-paint": "0.2.0-prerelease.20181220194927",
"scratch-render": "0.1.0-prerelease.20181226153401",
"scratch-render": "0.1.0-prerelease.20190108175224",
"scratch-storage": "1.2.2",
"scratch-svg-renderer": "0.2.0-prerelease.20181220183040",
"scratch-vm": "0.2.0-prerelease.20181226213940",
"scratch-vm": "0.2.0-prerelease.20190107184530",
"selenium-webdriver": "3.6.0",
"startaudiocontext": "1.2.1",
"style-loader": "^0.23.0",
+1 -1
View File
@@ -57,7 +57,7 @@
width: 100%;
height: 100%;
opacity: 0.75;
background-color: #8cbcff;
background-color: $drop-highlight;
transition: all 0.25s ease;
}
+1 -1
View File
@@ -13,7 +13,7 @@
width: 100%;
height: 100%;
opacity: 0.75;
background-color: #8cbcff;
background-color: $drop-highlight;
transition: all 0.25s ease;
}
@@ -32,7 +32,7 @@ const BrowserModal = ({intl, ...props}) => (
<p>
{ /* eslint-disable max-len */ }
<FormattedMessage
defaultMessage="We're very sorry, but Scratch 3.0 does not support Internet Explorer, Vivaldi, Opera or Silk. We recommend trying a newer browser such as Google Chrome, Mozilla Firefox, or Microsoft Edge."
defaultMessage="We are very sorry, but Scratch does not support this browser version. We recommend updating to the latest version of a supported browser such as Google Chrome, Mozilla Firefox, Microsoft Edge, or Apple Safari."
description="Unsupported browser description"
id="gui.unsupportedBrowser.description"
/>
@@ -79,6 +79,7 @@ $border-radius: 0.25rem;
font-size: 0.85rem;
transition: 0.2s;
user-select: none;
margin: 0px;
}
.button > img {
+54 -48
View File
@@ -34,62 +34,68 @@ const SpriteList = function (props) {
return (
<Box
className={styles.itemsWrapper}
className={classNames(styles.scrollWrapper, {
[styles.scrollWrapperDragging]: draggingType === DragConstants.BACKPACK_SPRITE
})}
componentRef={containerRef}
>
{items.map((sprite, index) => {
<Box
className={styles.itemsWrapper}
>
{items.map((sprite, index) => {
// If the sprite has just received a block drop, used for green highlight
const receivedBlocks = (
hoveredTarget.sprite === sprite.id &&
// If the sprite has just received a block drop, used for green highlight
const receivedBlocks = (
hoveredTarget.sprite === sprite.id &&
sprite.id !== editingTarget &&
hoveredTarget.receivedBlocks
);
);
// If the sprite is indicating it can receive block dropping, used for blue highlight
let isRaised = !receivedBlocks && raised && sprite.id !== editingTarget;
// If the sprite is indicating it can receive block dropping, used for blue highlight
let isRaised = !receivedBlocks && raised && sprite.id !== editingTarget;
// A sprite is also raised if a costume or sound is being dragged.
// Note the absence of the self-sharing check: a sprite can share assets with itself.
// This is a quirk of 2.0, but seems worth leaving possible, it
// allows quick (albeit unusual) duplication of assets.
isRaised = isRaised || [
DragConstants.COSTUME,
DragConstants.SOUND,
DragConstants.BACKPACK_COSTUME,
DragConstants.BACKPACK_SOUND,
DragConstants.BACKPACK_CODE].includes(draggingType);
// A sprite is also raised if a costume or sound is being dragged.
// Note the absence of the self-sharing check: a sprite can share assets with itself.
// This is a quirk of 2.0, but seems worth leaving possible, it
// allows quick (albeit unusual) duplication of assets.
isRaised = isRaised || [
DragConstants.COSTUME,
DragConstants.SOUND,
DragConstants.BACKPACK_COSTUME,
DragConstants.BACKPACK_SOUND,
DragConstants.BACKPACK_CODE].includes(draggingType);
return (
<SortableAsset
className={classNames(styles.spriteWrapper, {
[styles.placeholder]: isSpriteDrag && index === draggingIndex})}
index={isSpriteDrag ? ordering.indexOf(index) : index}
key={sprite.name}
onAddSortable={onAddSortable}
onRemoveSortable={onRemoveSortable}
>
<SpriteSelectorItem
asset={sprite.costume && sprite.costume.asset}
className={classNames(styles.sprite, {
[styles.raised]: isRaised,
[styles.receivedBlocks]: receivedBlocks
})}
dragPayload={sprite}
dragType={DragConstants.SPRITE}
id={sprite.id}
index={index}
key={sprite.id}
name={sprite.name}
selected={sprite.id === selectedId}
onClick={onSelectSprite}
onDeleteButtonClick={onDeleteSprite}
onDuplicateButtonClick={onDuplicateSprite}
onExportButtonClick={onExportSprite}
/>
</SortableAsset>
);
})}
return (
<SortableAsset
className={classNames(styles.spriteWrapper, {
[styles.placeholder]: isSpriteDrag && index === draggingIndex})}
index={isSpriteDrag ? ordering.indexOf(index) : index}
key={sprite.name}
onAddSortable={onAddSortable}
onRemoveSortable={onRemoveSortable}
>
<SpriteSelectorItem
asset={sprite.costume && sprite.costume.asset}
className={classNames(styles.sprite, {
[styles.raised]: isRaised,
[styles.receivedBlocks]: receivedBlocks
})}
dragPayload={sprite}
dragType={DragConstants.SPRITE}
id={sprite.id}
index={index}
key={sprite.id}
name={sprite.name}
selected={sprite.id === selectedId}
onClick={onSelectSprite}
onDeleteButtonClick={onDeleteSprite}
onDuplicateButtonClick={onDuplicateSprite}
onExportButtonClick={onExportSprite}
/>
</SortableAsset>
);
})}
</Box>
</Box>
);
};
@@ -55,6 +55,10 @@
overflow-y: auto;
}
.scroll-wrapper-dragging {
background-color: $drop-highlight;
}
.items-wrapper {
display: flex;
flex-wrap: wrap;
@@ -80,12 +84,12 @@
}
.raised {
background-color: #8cbcff;
background-color: $drop-highlight;
transition: all 0.25s ease;
}
.raised:hover {
background-color: #8cbcff;
background-color: $drop-highlight;
transform: scale(1.05);
}
@@ -94,7 +98,7 @@
animation-duration: 500ms;
animation-iteration-count: 1;
animation-timing-function: ease-in-out;
background-color: #8cbcff;
background-color: $drop-highlight;
}
@keyframes wiggle {
@@ -100,20 +100,18 @@ const SpriteSelectorComponent = function (props) {
onChangeY={onChangeSpriteY}
/>
<Box className={styles.scrollWrapper}>
<SpriteList
editingTarget={editingTarget}
hoveredTarget={hoveredTarget}
items={Object.keys(sprites).map(id => sprites[id])}
raised={raised}
selectedId={selectedId}
onDeleteSprite={onDeleteSprite}
onDrop={onDrop}
onDuplicateSprite={onDuplicateSprite}
onExportSprite={onExportSprite}
onSelectSprite={onSelectSprite}
/>
</Box>
<SpriteList
editingTarget={editingTarget}
hoveredTarget={hoveredTarget}
items={Object.keys(sprites).map(id => sprites[id])}
raised={raised}
selectedId={selectedId}
onDeleteSprite={onDeleteSprite}
onDrop={onDrop}
onDuplicateSprite={onDuplicateSprite}
onExportSprite={onExportSprite}
onSelectSprite={onSelectSprite}
/>
<ActionMenu
className={styles.addButton}
img={spriteIcon}
@@ -100,7 +100,7 @@ $header-height: calc($stage-menu-height - 2px);
}
.raised, .raised .header {
background-color: #8cbcff;
background-color: $drop-highlight;
transition: all 0.25s ease;
}
+1 -1
View File
@@ -9,9 +9,9 @@
*/
display: block;
/* Attach border radius directly to canvas to prevent needing overflow:hidden; */
border-radius: $space;
border: $stage-standard-border-width solid $ui-black-transparent;
overflow: hidden;
/* @todo: This is for overriding the value being set somewhere. Where is it being set? */
background-color: transparent;
+11 -4
View File
@@ -48,18 +48,25 @@ const StageComponent = props => {
}}
onDoubleClick={onDoubleClick}
>
<DOMElementRenderer
<Box
className={classNames(
styles.stage,
{[styles.stageOverlayContent]: isFullScreen}
)}
domElement={canvas}
style={{
height: stageDimensions.height,
width: stageDimensions.width
}}
{...boxProps}
/>
>
<DOMElementRenderer
domElement={canvas}
style={{
height: stageDimensions.height,
width: stageDimensions.width
}}
{...boxProps}
/>
</Box>
<Box className={styles.monitorWrapper}>
<MonitorList
draggable={useEditorDragStyle}
+2
View File
@@ -40,3 +40,5 @@ $extensions-primary: hsla(163, 85%, 40%, 1); /* #0FBD8C */
$extensions-tertiary: hsla(163, 85%, 30%, 1); /* #0B8E69 */
$extensions-transparent: hsla(163, 85%, 40%, 0.35); /* 35% transparent version of extensions-primary */
$extensions-light: hsla(163, 57%, 85%, 1); /* opaque version of extensions-transparent, on white bg */
$drop-highlight: hsla(215, 100%, 77%); /* lighter than motion-primary */
+17 -2
View File
@@ -4,6 +4,17 @@ import omit from 'lodash.omit';
import {connect} from 'react-redux';
import {setFontsLoaded} from '../reducers/fonts-loaded';
// This list is from scratch-render-fonts:
// https://github.com/LLK/scratch-render-fonts/blob/master/src/index.js#L4
const FONTS = [
'Sans Serif',
'Serif',
'Handwriting',
'Marker',
'Curly',
'Pixel',
'Scratch'
];
/* Higher Order Component to provide behavior for loading fonts.
* @param {React.Component} WrappedComponent component to receive fontsLoaded prop
* @returns {React.Component} component with font loading behavior
@@ -22,8 +33,12 @@ const FontLoaderHOC = function (WrappedComponent) {
typeof document.fonts.values === 'function' &&
typeof document.fonts.values()[Symbol.iterator] === 'function') {
for (const fontFace of document.fonts.values()) {
fontPromises.push(fontFace.loaded);
fontFace.load();
// Only load fonts from this list. If we load all fonts on the document, we may block on
// loading fonts from things like chrome extensions.
if (FONTS.indexOf(fontFace.family) !== -1) {
fontPromises.push(fontFace.loaded);
fontFace.load();
}
}
}
return fontPromises;
+8 -1
View File
@@ -210,6 +210,13 @@ const ProjectSaverHOC = function (WrappedComponent) {
storeProject (projectId, requestParams) {
requestParams = requestParams || {};
this.clearAutoSaveTimeout();
// Serialize VM state now before embarking on
// the asynchronous journey of storing assets to
// the server. This ensures that assets don't update
// while in the process of saving a project (e.g. the
// serialized project refers to a newer asset than what
// we just finished saving).
const savedVMState = this.props.vm.toJSON();
return Promise.all(this.props.vm.assets
.filter(asset => !asset.clean)
.map(
@@ -224,7 +231,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
)
).then(() => {
const opts = {
body: this.props.vm.toJSON(),
body: savedVMState,
// If we set json:true then the body is double-stringified, so don't
headers: {
'Content-Type': 'application/json'
+4
View File
@@ -69,6 +69,10 @@ const getStageDimensions = (stageSize, isFullScreen) => {
stageDimensions.width = stageDimensions.scale * stageDimensions.widthDefault;
}
// Round off dimensions to prevent resampling/blurriness
stageDimensions.height = Math.round(stageDimensions.height);
stageDimensions.width = Math.round(stageDimensions.width);
return stageDimensions;
};
+10 -3
View File
@@ -6,11 +6,18 @@ import bowser from 'bowser';
*/
export default function () {
if (bowser.msie ||
bowser.vivaldi ||
bowser.opera ||
bowser.silk) {
return false;
}
// @todo Should also test for versions of supported browsers
return true;
// IMPORTANT: If you change versions here, also change them in www
// minimum versions for recommended browsers
const minVersions = {
chrome: '63',
msedge: '15',
firefox: '57',
safari: '11'
};
// strict mode == false so any browser not mentioned in the min Versions is ok
return bowser.check(minVersions, false);
}