Skip to content
Snippets Groups Projects
Unverified Commit 6fc77d2b authored by Andrew Sliwinski's avatar Andrew Sliwinski Committed by GitHub
Browse files

Merge branch 'develop' into greenkeeper/scratch-l10n-3.0.20180918211645

parents 6e30eeae 3a88e418
No related branches found
No related tags found
No related merge requests found
......@@ -5,7 +5,7 @@ import locales from 'scratch-l10n';
import styles from './language-selector.css';
// supported languages to exclude from the menu, but allow as a URL option
const ignore = ['he'];
const ignore = [];
const LanguageSelector = ({currentLocale, label, onChange}) => (
<select
......
......@@ -32,7 +32,17 @@ class SpriteSelectorItem extends React.Component {
]);
this.svgRenderer = new SVGRenderer();
// Asset ID of the SVG currently in SVGRenderer
this.svgRendererAssetId = null;
this.decodedAssetId = null;
}
shouldComponentUpdate (nextProps) {
// Ignore dragPayload due to https://github.com/LLK/scratch-gui/issues/3172.
// This function should be removed once the issue is fixed.
for (const property in nextProps) {
if (property !== 'dragPayload' && this.props[property] !== nextProps[property]) {
return true;
}
}
return false;
}
getCostumeUrl () {
if (this.props.costumeURL) return this.props.costumeURL;
......@@ -44,18 +54,20 @@ class SpriteSelectorItem extends React.Component {
// Avoid parsing the SVG when possible, since it's expensive.
if (asset.assetType === storage.AssetType.ImageVector) {
// If the asset ID has not changed, no need to re-parse
if (this.svgRendererAssetId === this.props.assetId) {
if (this.decodedAssetId === this.props.assetId) {
// @todo consider caching more than one URL.
return this.cachedUrl;
}
this.decodedAssetId = this.props.assetId;
const svgString = this.props.vm.runtime.storage.get(this.props.assetId).decodeText();
if (svgString.match(HAS_FONT_REGEXP)) {
this.svgRendererAssetId = this.props.assetId;
this.svgRenderer.loadString(svgString);
const svgText = this.svgRenderer.toString(true /* shouldInjectFonts */);
this.cachedUrl = `data:image/svg+xml;utf8,${encodeURIComponent(svgText)}`;
return this.cachedUrl;
} else {
this.cachedUrl = this.props.vm.runtime.storage.get(this.props.assetId).encodeDataURI();
}
return this.cachedUrl;
}
return this.props.vm.runtime.storage.get(this.props.assetId).encodeDataURI();
}
......
......@@ -52,9 +52,9 @@ class Stage extends React.Component {
colorInfo: null,
question: null
};
if (this.props.vm.runtime.renderer) {
this.renderer = this.props.vm.runtime.renderer;
this.canvas = this.props.vm.runtime.renderer._gl.canvas;
if (this.props.vm.renderer) {
this.renderer = this.props.vm.renderer;
this.canvas = this.renderer.canvas;
} else {
this.canvas = document.createElement('canvas');
this.renderer = new Renderer(this.canvas);
......
......@@ -10,6 +10,7 @@ import {setPlayer, setFullScreen} from '../reducers/mode.js';
import locales from 'scratch-l10n';
import {detectLocale} from './detect-locale';
import {detectTutorialId} from './tutorial-from-url';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
......@@ -50,16 +51,27 @@ const AppStateHOC = function (WrappedComponent, localesOnly) {
guiInitialState,
guiMiddleware,
initFullScreen,
initPlayer
initPlayer,
initTutorialCard
} = guiRedux;
const {ScratchPaintReducer} = require('scratch-paint');
let initializedGui = guiInitialState;
if (props.isFullScreen) {
initializedGui = initFullScreen(initializedGui);
}
if (props.isPlayerOnly) {
initializedGui = initPlayer(initializedGui);
if (props.isFullScreen || props.isPlayerOnly) {
if (props.isFullScreen) {
initializedGui = initFullScreen(initializedGui);
}
if (props.isPlayerOnly) {
initializedGui = initPlayer(initializedGui);
}
} else {
const tutorialId = detectTutorialId();
if (tutorialId !== null) {
// When loading a tutorial from the URL,
// load w/o preview modal
// open requested tutorial card
initializedGui = initTutorialCard(initializedGui, tutorialId);
}
}
reducers = {
locales: localesReducer,
......
......@@ -99,7 +99,8 @@ export default {
'add-sprite'
]
}
]
],
urlId: 1
},
'animate-a-name': {
name: (
......@@ -172,7 +173,8 @@ export default {
'glide-around'
]
}
]
],
urlId: 2
},
'Make-Music': {
name: (
......@@ -239,7 +241,8 @@ export default {
'add-sprite'
]
}
]
],
urlId: 3
},
'Make-A-Game': {
name: (
......@@ -323,7 +326,8 @@ export default {
'move-around-with-arrow-keys'
]
}
]
],
urlId: 4
},
'Chase-Game': {
......@@ -425,7 +429,8 @@ export default {
'move-around-with-arrow-keys'
]
}
]
],
urlId: 5
},
'add-sprite': {
name: (
......@@ -453,7 +458,8 @@ export default {
'switch-costume'
]
}
]
],
urlId: 6
},
'add-a-backdrop': {
name: (
......@@ -471,7 +477,8 @@ export default {
'change-size',
'switch-costume'
]
}]
}],
urlId: 7
},
'change-size': {
name: (
......@@ -489,7 +496,8 @@ export default {
'glide-around',
'spin-video'
]
}]
}],
urlId: 8
},
'glide-around': {
name: (
......@@ -507,7 +515,8 @@ export default {
'add-a-backdrop',
'switch-costume'
]
}]
}],
urlId: 9
},
'record-a-sound': {
......@@ -526,8 +535,8 @@ export default {
'Make-Music',
'switch-costume'
]
}]
}],
urlId: 10
},
'spin-video': {
name: (
......@@ -545,7 +554,8 @@ export default {
'add-a-backdrop',
'switch-costume'
]
}]
}],
urlId: 11
},
'hide-and-show': {
name: (
......@@ -563,7 +573,8 @@ export default {
'add-a-backdrop',
'switch-costume'
]
}]
}],
urlId: 12
},
'switch-costume': {
......@@ -582,7 +593,8 @@ export default {
'add-a-backdrop',
'add-effects'
]
}]
}],
urlId: 13
},
'move-around-with-arrow-keys': {
......@@ -601,7 +613,8 @@ export default {
'add-a-backdrop',
'switch-costume'
]
}]
}],
urlId: 14
},
'add-effects': {
name: (
......@@ -619,6 +632,7 @@ export default {
'add-a-backdrop',
'switch-costume'
]
}]
}],
urlId: 15
}
};
/**
* @fileoverview
* Utility function to detect tutorial id from query paramenter on the URL.
*/
import tutorials from './libraries/decks/index.jsx';
import analytics from './analytics';
/**
* Get the tutorial id from the given numerical id (representing the
* url id of the tutorial).
* @param {number} urlId The URL Id for the tutorial
* @returns {string} The string id for the tutorial, or null if the URL ID
* was not found.
*/
const getDeckIdFromUrlId = urlId => {
for (const deckId in tutorials) {
if (tutorials[deckId].urlId === urlId) {
analytics.event({
category: 'how-to',
action: 'load from url',
label: `${deckId}`
});
return deckId;
}
}
return null;
};
/**
* Check if there's a tutorial id provided as a query parameter in the URL.
* Return the corresponding tutorial id or null if not found.
* @return {string} The ID of the requested tutorial or null if no tutorial was
* requested or found.
*/
const detectTutorialId = () => {
if (window.location.search.indexOf('tutorial=') !== -1) {
const urlTutorialId = window.location.search.match(/(?:tutorial)=(\d+)/)[1];
if (urlTutorialId) {
return getDeckIdFromUrlId(Number(urlTutorialId));
}
}
return null;
};
export {
detectTutorialId
};
......@@ -21,6 +21,8 @@ import vmReducer, {vmInitialState} from './vm';
import vmStatusReducer, {vmStatusInitialState} from './vm-status';
import throttle from 'redux-throttle';
import decks from '../lib/libraries/decks/index.jsx';
const guiMiddleware = compose(applyMiddleware(throttle(300, {leading: true, trailing: true})));
const guiInitialState = {
......@@ -67,6 +69,27 @@ const initFullScreen = function (currentState) {
);
};
const initTutorialCard = function (currentState, deckId) {
return Object.assign(
{},
currentState,
{
modals: {
previewInfo: false
},
cards: {
visible: true,
content: decks,
activeDeckId: deckId,
step: 0,
x: 0,
y: 0,
dragging: false
}
}
);
};
const guiReducer = combineReducers({
assetDrag: assetDragReducer,
blockDrag: blockDragReducer,
......@@ -95,5 +118,6 @@ export {
guiInitialState,
guiMiddleware,
initFullScreen,
initPlayer
initPlayer,
initTutorialCard
};
......@@ -72,7 +72,7 @@ describe('Loading scratch gui', () => {
const projectId = '96708228';
await loadUri(`${uri}#${projectId}`);
await clickXpath('//button[@title="Try It"]');
await new Promise(resolve => setTimeout(resolve, 2000));
await new Promise(resolve => setTimeout(resolve, 3000));
await clickXpath('//img[@title="Go"]');
await new Promise(resolve => setTimeout(resolve, 2000));
await clickXpath('//img[@title="Stop"]');
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment