Add drag payload for backpack contents and drop handlers for editor tabs
This commit is contained in:
1 parent
9e51fc673d
commit
bbf0ba4e25
6 files changed
+66
-6
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
import DragConstants from '../../lib/drag-constants';
|
||||
import {ComingSoonTooltip} from '../coming-soon/coming-soon.jsx';
|
||||
import SpriteSelectorItem from '../../containers/sprite-selector-item.jsx';
|
||||
import styles from './backpack.css';
|
||||
@@ -8,6 +9,13 @@ import styles from './backpack.css';
|
||||
// TODO make sprite selector item not require onClick
|
||||
const noop = () => {};
|
||||
|
||||
const dragTypeMap = {
|
||||
costume: DragConstants.BACKPACK_COSTUME,
|
||||
sound: DragConstants.BACKPACK_SOUND,
|
||||
code: DragConstants.BACKPACK_CODE,
|
||||
sprite: DragConstants.BACKPACK_SPRITE
|
||||
};
|
||||
|
||||
const Backpack = ({contents, error, expanded, loading, onToggle}) => (
|
||||
<div className={styles.backpackContainer}>
|
||||
<div
|
||||
@@ -60,6 +68,8 @@ const Backpack = ({contents, error, expanded, loading, onToggle}) => (
|
||||
className={styles.backpackItem}
|
||||
costumeURL={item.thumbnailUrl}
|
||||
details={item.name}
|
||||
dragPayload={item}
|
||||
dragType={dragTypeMap[item.type]}
|
||||
key={item.id}
|
||||
name={item.type}
|
||||
selected={false}
|
||||
|
||||
@@ -4,6 +4,7 @@ import bindAll from 'lodash.bindall';
|
||||
import BackpackComponent from '../components/backpack/backpack.jsx';
|
||||
import {getBackpackContents} from '../lib/backpack-api';
|
||||
import {connect} from 'react-redux';
|
||||
import storage from '../lib/storage';
|
||||
|
||||
class Backpack extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -20,6 +21,14 @@ class Backpack extends React.Component {
|
||||
expanded: false,
|
||||
contents: []
|
||||
};
|
||||
|
||||
// If a host is given, add it as a web source to the storage module
|
||||
if (props.host) {
|
||||
storage.addWebSource(
|
||||
[storage.AssetType.ImageVector, storage.AssetType.ImageBitmap, storage.AssetType.Sound],
|
||||
asset => `${props.host}/${asset.assetId}.${asset.dataFormat}`
|
||||
);
|
||||
}
|
||||
}
|
||||
handleToggle () {
|
||||
const newState = !this.state.expanded;
|
||||
|
||||
@@ -19,6 +19,11 @@ import {
|
||||
openBackdropLibrary
|
||||
} from '../reducers/modals';
|
||||
|
||||
import {
|
||||
activateTab,
|
||||
SOUNDS_TAB_INDEX
|
||||
} from '../reducers/editor-tab';
|
||||
|
||||
import addLibraryBackdropIcon from '../components/asset-panel/icon--add-backdrop-lib.svg';
|
||||
import addLibraryCostumeIcon from '../components/asset-panel/icon--add-costume-lib.svg';
|
||||
import fileUploadIcon from '../components/action-menu/icon--file-upload.svg';
|
||||
@@ -191,14 +196,22 @@ class CostumeTab extends React.Component {
|
||||
this.fileInput.click();
|
||||
}
|
||||
handleDrop (dropInfo) {
|
||||
// Eventually will handle other kinds of drop events, right now just
|
||||
// the reordering events.
|
||||
if (dropInfo.dragType === DragConstants.COSTUME) {
|
||||
const sprite = this.props.vm.editingTarget.sprite;
|
||||
const activeCostume = sprite.costumes[this.state.selectedCostumeIndex];
|
||||
this.props.vm.reorderCostume(this.props.vm.editingTarget.id,
|
||||
dropInfo.index, dropInfo.newIndex);
|
||||
this.setState({selectedCostumeIndex: sprite.costumes.indexOf(activeCostume)});
|
||||
} else if (dropInfo.dragType === DragConstants.BACKPACK_COSTUME) {
|
||||
this.props.vm.addCostume(dropInfo.payload.body, {
|
||||
name: dropInfo.payload.name
|
||||
});
|
||||
} else if (dropInfo.dragType === DragConstants.BACKPACK_SOUND) {
|
||||
this.props.onActivateSoundsTab();
|
||||
this.props.vm.addSound({
|
||||
md5: dropInfo.payload.body,
|
||||
name: dropInfo.payload.name
|
||||
});
|
||||
}
|
||||
}
|
||||
setFileInput (input) {
|
||||
@@ -303,6 +316,7 @@ CostumeTab.propTypes = {
|
||||
cameraModalVisible: PropTypes.bool,
|
||||
editingTarget: PropTypes.string,
|
||||
intl: intlShape,
|
||||
onActivateSoundsTab: PropTypes.func.isRequired,
|
||||
onNewCostumeFromCameraClick: PropTypes.func.isRequired,
|
||||
onNewLibraryBackdropClick: PropTypes.func.isRequired,
|
||||
onNewLibraryCostumeClick: PropTypes.func.isRequired,
|
||||
@@ -333,6 +347,7 @@ const mapStateToProps = state => ({
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onActivateSoundsTab: () => dispatch(activateTab(SOUNDS_TAB_INDEX)),
|
||||
onNewLibraryBackdropClick: e => {
|
||||
e.preventDefault();
|
||||
dispatch(openBackdropLibrary());
|
||||
|
||||
@@ -28,6 +28,11 @@ import {
|
||||
openSoundRecorder
|
||||
} from '../reducers/modals';
|
||||
|
||||
import {
|
||||
activateTab,
|
||||
COSTUMES_TAB_INDEX
|
||||
} from '../reducers/editor-tab';
|
||||
|
||||
class SoundTab extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
@@ -120,8 +125,6 @@ class SoundTab extends React.Component {
|
||||
}
|
||||
|
||||
handleDrop (dropInfo) {
|
||||
// Eventually will handle other kinds of drop events, right now just
|
||||
// the reordering events.
|
||||
if (dropInfo.dragType === DragConstants.SOUND) {
|
||||
const sprite = this.props.vm.editingTarget.sprite;
|
||||
const activeSound = sprite.sounds[this.state.selectedSoundIndex];
|
||||
@@ -130,6 +133,16 @@ class SoundTab extends React.Component {
|
||||
dropInfo.index, dropInfo.newIndex);
|
||||
|
||||
this.setState({selectedSoundIndex: sprite.sounds.indexOf(activeSound)});
|
||||
} else if (dropInfo.dragType === DragConstants.BACKPACK_COSTUME) {
|
||||
this.props.onActivateCostumesTab();
|
||||
this.props.vm.addCostume(dropInfo.payload.body, {
|
||||
name: dropInfo.payload.name
|
||||
});
|
||||
} else if (dropInfo.dragType === DragConstants.BACKPACK_SOUND) {
|
||||
this.props.vm.addSound({
|
||||
md5: dropInfo.payload.body,
|
||||
name: dropInfo.payload.name
|
||||
}).then(this.handleNewSound);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,6 +248,7 @@ class SoundTab extends React.Component {
|
||||
SoundTab.propTypes = {
|
||||
editingTarget: PropTypes.string,
|
||||
intl: intlShape,
|
||||
onActivateCostumesTab: PropTypes.func.isRequired,
|
||||
onNewSoundFromLibraryClick: PropTypes.func.isRequired,
|
||||
onNewSoundFromRecordingClick: PropTypes.func.isRequired,
|
||||
onRequestCloseSoundLibrary: PropTypes.func.isRequired,
|
||||
@@ -264,6 +278,7 @@ const mapStateToProps = state => ({
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onActivateCostumesTab: () => dispatch(activateTab(COSTUMES_TAB_INDEX)),
|
||||
onNewSoundFromLibraryClick: e => {
|
||||
e.preventDefault();
|
||||
dispatch(openSoundLibrary());
|
||||
|
||||
@@ -52,7 +52,8 @@ class SpriteSelectorItem extends React.Component {
|
||||
currentOffset: currentOffset,
|
||||
dragging: true,
|
||||
dragType: this.props.dragType,
|
||||
index: this.props.index
|
||||
index: this.props.index,
|
||||
payload: this.props.dragPayload
|
||||
});
|
||||
this.noClick = true;
|
||||
}
|
||||
@@ -98,6 +99,7 @@ class SpriteSelectorItem extends React.Component {
|
||||
onClick,
|
||||
onDeleteButtonClick,
|
||||
onDuplicateButtonClick,
|
||||
dragPayload,
|
||||
receivedBlocks,
|
||||
/* eslint-enable no-unused-vars */
|
||||
...props
|
||||
@@ -120,6 +122,10 @@ SpriteSelectorItem.propTypes = {
|
||||
assetId: PropTypes.string,
|
||||
costumeURL: PropTypes.string,
|
||||
dispatchSetHoveredSprite: PropTypes.func.isRequired,
|
||||
dragPayload: PropTypes.shape({
|
||||
name: PropTypes.string,
|
||||
body: PropTypes.string
|
||||
}),
|
||||
dragType: PropTypes.string,
|
||||
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||
index: PropTypes.number,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
export default {
|
||||
SOUND: 'SOUND',
|
||||
COSTUME: 'COSTUME',
|
||||
SPRITE: 'SPRITE'
|
||||
SPRITE: 'SPRITE',
|
||||
|
||||
BACKPACK_SOUND: 'BACKPACK_SOUND',
|
||||
BACKPACK_COSTUME: 'BACKPACK_COSTUME',
|
||||
BACKPACK_SPRITE: 'BACKPACK_SPRITE',
|
||||
BACKPACK_CODE: 'BACKPACK_CODE'
|
||||
};
|
||||
Reference in new issue
Block a user