From 2a36f49d7ca160a37c7885266adf38fd64038585 Mon Sep 17 00:00:00 2001
From: apple502j <apple502j@yahoo.co.jp>
Date: Sun, 27 Jan 2019 19:21:15 +0900
Subject: [PATCH] Export costumes and sounds

---
 src/containers/costume-tab.jsx | 14 ++++++++++++++
 src/containers/sound-tab.jsx   |  9 +++++++++
 src/lib/download-url.js        | 13 +++++++++++++
 3 files changed, 36 insertions(+)
 create mode 100644 src/lib/download-url.js

diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx
index 5df459150..2b71975c4 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/sound-tab.jsx b/src/containers/sound-tab.jsx
index 3df93b1f6..40e08dfb7 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-url.js b/src/lib/download-url.js
new file mode 100644
index 000000000..e01cb1f08
--- /dev/null
+++ b/src/lib/download-url.js
@@ -0,0 +1,13 @@
+export default (filename, url) => {
+    const pom = document.createElement('a');
+    pom.setAttribute('href', url);
+    pom.setAttribute('download', filename);
+
+    if (document.createEvent) {
+        const event = document.createEvent('MouseEvents');
+        event.initEvent('click', true, true);
+        pom.dispatchEvent(event);
+    } else {
+        pom.click();
+    }
+};
-- 
GitLab