diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx index 5df459150509e96d746bf03aec3fd1671fa6ee6a..2b71975c4e366a58ae876d67fe0cce479c40475b 100644 --- a/src/containers/costume-tab.jsx +++ b/src/containers/costume-tab.jsx @@ -13,6 +13,8 @@ import errorBoundaryHOC from '../lib/error-boundary-hoc.jsx'; import DragConstants from '../lib/drag-constants'; import {emptyCostume} from '../lib/empty-assets'; import sharedMessages from '../lib/shared-messages'; +import download from '../lib/download-url'; +import getCostumeUrl from '../lib/get-costume-url'; import { closeCameraCapture, @@ -86,6 +88,7 @@ class CostumeTab extends React.Component { 'handleSelectCostume', 'handleDeleteCostume', 'handleDuplicateCostume', + 'handleExportCostume', 'handleNewCostume', 'handleNewBlankCostume', 'handleSurpriseCostume', @@ -136,6 +139,12 @@ class CostumeTab extends React.Component { this.setState({selectedCostumeIndex: target.currentCostume}); } } + getCostumeData (costumeItem) { + if (costumeItem.url) return costumeItem.url; + if (!costumeItem.asset) return null; + + return getCostumeUrl(costumeItem.asset); + } handleSelectCostume (costumeIndex) { this.props.vm.editingTarget.setCostume(costumeIndex); this.setState({selectedCostumeIndex: costumeIndex}); @@ -150,6 +159,10 @@ class CostumeTab extends React.Component { handleDuplicateCostume (costumeIndex) { this.props.vm.duplicateCostume(costumeIndex); } + handleExportCostume (costumeIndex) { + const item = this.props.vm.editingTarget.sprite.costumes[costumeIndex]; + download(`${item.name}.${item.asset.dataFormat}`, this.getCostumeData(item)); + } handleNewCostume (costume, fromCostumeLibrary) { if (fromCostumeLibrary) { this.props.vm.addCostumeFromLibrary(costume.md5, costume); @@ -312,6 +325,7 @@ class CostumeTab extends React.Component { this.handleDeleteCostume : null} onDrop={this.handleDrop} onDuplicateClick={this.handleDuplicateCostume} + onExportClick={this.handleExportCostume} onItemClick={this.handleSelectCostume} > {target.costumes ? diff --git a/src/containers/monitor.jsx b/src/containers/monitor.jsx index e2c88222018d94c35d1c9ef31af8f6e8ec23b018..039fa060d616d2df878f75eff8140fcbdcb51ecb 100644 --- a/src/containers/monitor.jsx +++ b/src/containers/monitor.jsx @@ -8,7 +8,7 @@ import MonitorComponent, {monitorModes} from '../components/monitor/monitor.jsx' import {addMonitorRect, getInitialPosition, resizeMonitorRect, removeMonitorRect} from '../reducers/monitor-layout'; import {getVariable, setVariableValue} from '../lib/variable-utils'; import importCSV from '../lib/import-csv'; -import downloadText from '../lib/download-text'; +import download from '../lib/download-url'; import {connect} from 'react-redux'; import {Map} from 'immutable'; @@ -155,7 +155,8 @@ class Monitor extends React.Component { handleExport () { const {vm, targetId, id: variableId} = this.props; const variable = getVariable(vm, targetId, variableId); - downloadText(`${variable.name}.txt`, variable.value.join('\r\n')); + const text = variable.value.join('\r\n'); + download(`${variable.name}.txt`, `data:text/plain;charset=utf-8,${encodeURIComponent(text)}`); } render () { const monitorProps = monitorAdapter(this.props); diff --git a/src/containers/sound-tab.jsx b/src/containers/sound-tab.jsx index 3df93b1f6039e0945f73d9e804d73b9c11368df1..40e08dfb737321de558b278c011c4a2e9e980142 100644 --- a/src/containers/sound-tab.jsx +++ b/src/containers/sound-tab.jsx @@ -21,6 +21,7 @@ import soundLibraryContent from '../lib/libraries/sounds.json'; import {handleFileUpload, soundUpload} from '../lib/file-uploader.js'; import errorBoundaryHOC from '../lib/error-boundary-hoc.jsx'; import DragConstants from '../lib/drag-constants'; +import download from '../lib/download-url'; import {connect} from 'react-redux'; @@ -44,6 +45,7 @@ class SoundTab extends React.Component { 'handleSelectSound', 'handleDeleteSound', 'handleDuplicateSound', + 'handleExportSound', 'handleNewSound', 'handleSurpriseSound', 'handleFileUploadClick', @@ -86,6 +88,12 @@ class SoundTab extends React.Component { this.props.dispatchUpdateRestore({restoreFun, deletedItem: 'Sound'}); } + handleExportSound (soundIndex) { + const item = this.props.vm.editingTarget.sprite.sounds[soundIndex]; + const soundDataURL = item.asset.encodeDataURI(); + download(`${item.name}.${item.asset.dataFormat}`, soundDataURL); + } + handleDuplicateSound (soundIndex) { this.props.vm.duplicateSound(soundIndex).then(() => { this.setState({selectedSoundIndex: soundIndex + 1}); @@ -236,6 +244,7 @@ class SoundTab extends React.Component { onDeleteClick={this.handleDeleteSound} onDrop={this.handleDrop} onDuplicateClick={this.handleDuplicateSound} + onExportClick={this.handleExportSound} onItemClick={this.handleSelectSound} > {sprite.sounds && sprite.sounds[this.state.selectedSoundIndex] ? ( diff --git a/src/lib/download-text.js b/src/lib/download-url.js similarity index 70% rename from src/lib/download-text.js rename to src/lib/download-url.js index 2c0bc91a511b6f6d20011dbbc23a71d4cf0fdd1a..e01cb1f0890bf103d704c661b0795bce721418bd 100644 --- a/src/lib/download-text.js +++ b/src/lib/download-url.js @@ -1,6 +1,6 @@ -export default (filename, text) => { +export default (filename, url) => { const pom = document.createElement('a'); - pom.setAttribute('href', `data:text/plain;charset=utf-8,${encodeURIComponent(text)}`); + pom.setAttribute('href', url); pom.setAttribute('download', filename); if (document.createEvent) {