diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 289fa27f369092b44550ee665fa4bf2ee529d908..6042ceaaac8003eb03e4594faa2a91eb5b563b77 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -4,7 +4,6 @@ import bindAll from 'lodash.bindall'; import {defineMessages, intlShape, injectIntl} from 'react-intl'; import VM from 'scratch-vm'; - import AssetPanel from '../components/asset-panel/asset-panel.jsx'; import PaintEditorWrapper from './paint-editor-wrapper.jsx'; import CostumeLibrary from './costume-library.jsx'; @@ -74,6 +73,7 @@ class CostumeTab extends React.Component { 'handleSelectCostume', 'handleDeleteCostume', 'handleDuplicateCostume', + 'handleNewCostume', 'handleNewBlankCostume', 'handleSurpriseCostume', 'handleSurpriseBackdrop', @@ -131,6 +131,9 @@ class CostumeTab extends React.Component { handleDuplicateCostume (costumeIndex) { this.props.vm.duplicateCostume(costumeIndex); } + handleNewCostume (costume) { + this.props.vm.addCostume(costume.md5, costume); + } handleNewBlankCostume () { const emptyItem = costumeLibraryContent.find(item => ( item.name === 'Empty' @@ -138,43 +141,44 @@ class CostumeTab extends React.Component { const name = this.props.vm.editingTarget.isStage ? `backdrop1` : `costume1`; const vmCostume = { name: name, + md5: emptyItem.md5, rotationCenterX: emptyItem.info[0], rotationCenterY: emptyItem.info[1], bitmapResolution: emptyItem.info.length > 2 ? emptyItem.info[2] : 1, skinId: null }; - this.props.vm.addCostume(emptyItem.md5, vmCostume); + this.handleNewCostume(vmCostume); } handleSurpriseCostume () { const item = costumeLibraryContent[Math.floor(Math.random() * costumeLibraryContent.length)]; const vmCostume = { name: item.name, + md5: item.md5, rotationCenterX: item.info[0], rotationCenterY: item.info[1], bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; - this.props.vm.addCostume(item.md5, vmCostume); + this.handleNewCostume(vmCostume); } handleSurpriseBackdrop () { const item = backdropLibraryContent[Math.floor(Math.random() * backdropLibraryContent.length)]; const vmCostume = { name: item.name, + md5: item.md5, rotationCenterX: item.info[0] && item.info[0] / 2, rotationCenterY: item.info[1] && item.info[1] / 2, bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; - this.props.vm.addCostume(item.md5, vmCostume); + this.handleNewCostume(vmCostume); } handleCostumeUpload (e) { const storage = this.props.vm.runtime.storage; - const handleNewCostume = function (md5Ext, vmCostume) { - this.props.vm.addCostume(md5Ext, vmCostume); - }.bind(this); - const costumeOnload = costumeUpload.bind(this, storage, handleNewCostume); - handleFileUpload(e.target, costumeOnload); + handleFileUpload(e.target, (buffer, fileType, fileName) => { + costumeUpload(buffer, fileType, fileName, storage, this.handleNewCostume); + }); } handleFileUploadClick () { this.fileInput.click(); diff --git a/src/containers/sound-tab.jsx b/src/containers/sound-tab.jsx index fee1b8b8b71cca3f19e8f7862114e5ffcd713b16..ab4c9062bdebc5fa1b5055919a0df50bc1c3f3a3 100644 --- a/src/containers/sound-tab.jsx +++ b/src/containers/sound-tab.jsx @@ -108,13 +108,12 @@ class SoundTab extends React.Component { handleSoundUpload (e) { const storage = this.props.vm.runtime.storage; - const handleSound = function (newSound) { - this.props.vm.addSound(newSound).then(() => { - this.handleNewSound(); - }); - }.bind(this); - const soundOnload = soundUpload.bind(this, storage, handleSound); - handleFileUpload(e.target, soundOnload); + const handleSound = newSound => this.props.vm.addSound(newSound) + .then(() => this.handleNewSound()); + + handleFileUpload(e.target, (buffer, fileType, fileName) => { + soundUpload(buffer, fileType, fileName, storage, handleSound); + }); } setFileInput (input) { diff --git a/src/containers/stage-selector.jsx b/src/containers/stage-selector.jsx index c5dc7f27c642021db43f5c49e98ab0c02b4af952..f3497a54cd9f2e187ffc5a5586b20f7492027f0c 100644 --- a/src/containers/stage-selector.jsx +++ b/src/containers/stage-selector.jsx @@ -17,6 +17,7 @@ class StageSelector extends React.Component { super(props); bindAll(this, [ 'handleClick', + 'handleNewBackdrop', 'handleSurpriseBackdrop', 'handleEmptyBackdrop', 'addBackdropFromLibraryItem', @@ -28,40 +29,38 @@ class StageSelector extends React.Component { addBackdropFromLibraryItem (item) { const vmBackdrop = { name: item.name, + md5: item.md5, rotationCenterX: item.info[0] && item.info[0] / 2, rotationCenterY: item.info[1] && item.info[1] / 2, bitmapResolution: item.info.length > 2 ? item.info[2] : 1, skinId: null }; - return this.props.vm.addBackdrop(item.md5, vmBackdrop); + this.handleNewBackdrop(vmBackdrop); } handleClick () { this.props.onSelect(this.props.id); } + handleNewBackdrop (backdrop) { + this.props.vm.addBackdrop(backdrop.md5, backdrop).then(() => + this.props.onActivateTab(COSTUMES_TAB_INDEX)); + } handleSurpriseBackdrop () { // @todo should this not add a backdrop you already have? const item = backdropLibraryContent[Math.floor(Math.random() * backdropLibraryContent.length)]; - this.addBackdropFromLibraryItem(item).then(() => { - this.props.onActivateTab(COSTUMES_TAB_INDEX); - }); + this.addBackdropFromLibraryItem(item); } handleEmptyBackdrop () { // @todo this is brittle, will need to be refactored for localized libraries const emptyItem = costumeLibraryContent.find(item => item.name === 'Empty'); if (emptyItem) { - this.addBackdropFromLibraryItem(emptyItem).then(() => { - this.props.onActivateTab(COSTUMES_TAB_INDEX); - }); + this.addBackdropFromLibraryItem(emptyItem); } } handleBackdropUpload (e) { const storage = this.props.vm.runtime.storage; - const handleNewBackdrop = function (md5Ext, vmBackdrop) { - this.props.vm.addBackdrop(md5Ext, vmBackdrop); - this.props.onActivateTab(COSTUMES_TAB_INDEX); - }.bind(this); - const costumeOnload = costumeUpload.bind(this, storage, handleNewBackdrop); - handleFileUpload(e.target, costumeOnload); + handleFileUpload(e.target, (buffer, fileType, fileName) => { + costumeUpload(buffer, fileType, fileName, storage, this.handleNewBackdrop); + }); } handleFileUploadClick () { this.fileInput.click(); diff --git a/src/lib/file-uploader.js b/src/lib/file-uploader.js index cfdff91f3a06789b68931c0431199eb34021fff4..cea0aaeb11abc1258672bd0220abd0522ea76b33 100644 --- a/src/lib/file-uploader.js +++ b/src/lib/file-uploader.js @@ -77,16 +77,15 @@ const cacheAsset = function (storage, fileName, assetType, dataFormat, data) { /** * Handles loading a costume or a backdrop using the provided, context-relevant information. - * @param {ScratchStorage} storage The ScratchStorage instance to cache the costume data - * @param {Function} then The function to execute on the costume object returned after - * caching this costume in storage - This function should be responsible for - * adding the costume to the VM and handling other UI flow that should come after adding the costume * @param {ArrayBuffer} fileData The costume data to load * @param {string} fileType The MIME type of this file * @param {string} costumeName The user-readable name to use for the costume. + * @param {ScratchStorage} storage The ScratchStorage instance to cache the costume data + * @param {Function} handleCostume The function to execute on the costume object returned after + * caching this costume in storage - This function should be responsible for + * adding the costume to the VM and handling other UI flow that should come after adding the costume */ -const costumeUpload = function (storage, then, fileData, fileType, costumeName) { - // Only handling png and svg right now +const costumeUpload = function (fileData, fileType, costumeName, storage, handleCostume) { let costumeFormat = null; let assetType = null; switch (fileType) { @@ -109,15 +108,15 @@ const costumeUpload = function (storage, then, fileData, fileType, costumeName) return; } - const addCostumeFromBuffer = (function (error, costumeBuffer) { + const addCostumeFromBuffer = function (error, costumeBuffer) { if (error) { log.warn(`An error occurred while trying to extract image data: ${error}`); return; } const vmCostume = cacheAsset(storage, costumeName, assetType, costumeFormat, costumeBuffer); - then(vmCostume.md5, vmCostume); - }); + handleCostume(vmCostume); + }; if (costumeFormat === storage.DataFormat.SVG) { // Must pass in file data as a Uint8Array, @@ -133,16 +132,16 @@ const costumeUpload = function (storage, then, fileData, fileType, costumeName) /** * Handles loading a sound using the provided, context-relevant information. - * @param {ScratchStorage} storage The ScratchStorage instance to cache the sound data - * @param {Function} then The function to execute on the sound object of type VMAsset - * This function should be responsible for adding the sound to the VM - * as well as handling other UI flow that should come after adding the sound * @param {ArrayBuffer} fileData The sound data to load * @param {string} fileType The MIME type of this file; This function will exit * early if the fileType is unexpected. * @param {string} soundName The user-readable name to use for the sound. + * @param {ScratchStorage} storage The ScratchStorage instance to cache the sound data + * @param {Function} handleSound The function to execute on the sound object of type VMAsset + * This function should be responsible for adding the sound to the VM + * as well as handling other UI flow that should come after adding the sound */ -const soundUpload = function (storage, then, fileData, fileType, soundName) { +const soundUpload = function (fileData, fileType, soundName, storage, handleSound) { let soundFormat; switch (fileType) { case 'audio/mp3': { @@ -164,7 +163,7 @@ const soundUpload = function (storage, then, fileData, fileType, soundName) { soundFormat, new Uint8Array(fileData)); - then(vmSound); + handleSound(vmSound); }; export {