Make the backpack a drop area for workspace code

This commit is contained in:
Paul Kaplan committed 2018-10-31 10:22:08 -04:00
1 parent c973bf0e1a
commit 63ea5b4201
2 files changed
+92 -13

No files matched your search

+23 -7
View File
@@ -17,7 +17,19 @@ const dragTypeMap = { // Keys correspond with the backpack-server item types
sprite: DragConstants.BACKPACK_SPRITE
};
const Backpack = ({containerRef, contents, dragOver, error, expanded, loading, onToggle, onDelete}) => (
const Backpack = ({
blockDragOver,
containerRef,
contents,
dragOver,
error,
expanded,
loading,
onToggle,
onDelete,
onMouseEnter,
onMouseLeave
}) => (
<div className={styles.backpackContainer}>
<div
className={styles.backpackHeader}
@@ -44,8 +56,12 @@ const Backpack = ({containerRef, contents, dragOver, error, expanded, loading, o
</div>
{expanded ? (
<div
className={styles.backpackList}
className={classNames(styles.backpackList, {
[styles.dragOver]: dragOver || blockDragOver
})}
ref={containerRef}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
{error ? (
<div className={styles.statusMessage}>
@@ -66,11 +82,7 @@ const Backpack = ({containerRef, contents, dragOver, error, expanded, loading, o
</div>
) : (
contents.length > 0 ? (
<div
className={classNames(styles.backpackListInner, {
[styles.dragOver]: dragOver
})}
>
<div className={styles.backpackListInner}>
{contents.map(item => (
<SpriteSelectorItem
className={styles.backpackItem}
@@ -104,6 +116,7 @@ const Backpack = ({containerRef, contents, dragOver, error, expanded, loading, o
);
Backpack.propTypes = {
blockDragOver: PropTypes.bool,
containerRef: PropTypes.func,
contents: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string,
@@ -116,10 +129,13 @@ Backpack.propTypes = {
expanded: PropTypes.bool,
loading: PropTypes.bool,
onDelete: PropTypes.func,
onMouseEnter: PropTypes.func,
onMouseLeave: PropTypes.func,
onToggle: PropTypes.func
};
Backpack.defaultProps = {
blockDragOver: false,
contents: [],
dragOver: false,
expanded: false,
+69 -6
View File
@@ -8,7 +8,8 @@ import {
deleteBackpackObject,
soundPayload,
costumePayload,
spritePayload
spritePayload,
codePayload
} from '../lib/backpack-api';
import DragConstants from '../lib/drag-constants';
import DropAreaHOC from '../lib/drop-area-hoc.jsx';
@@ -28,10 +29,18 @@ class Backpack extends React.Component {
'handleToggle',
'handleDelete',
'getBackpackAssetURL',
'refreshContents'
'refreshContents',
'handleMouseEnter',
'handleMouseLeave',
'handleBlockDragEnd',
'handleBlockDragUpdate'
]);
this.state = {
dragOver: false,
// While the DroppableHOC manages drop interactions for asset tiles,
// we still need to micromanage drops coming from the block workspace.
// TODO this may be refactorable with the share-the-love logic in SpriteSelectorItem
blockDragOutsideWorkspace: false,
blockDragOverBackpack: false,
error: false,
offset: 0,
itemsPerPage: 20,
@@ -50,12 +59,23 @@ class Backpack extends React.Component {
storage._hasAddedBackpackSource = true;
}
}
componentDidMount () {
this.props.vm.addListener('BLOCK_DRAG_END', this.handleBlockDragEnd);
this.props.vm.addListener('BLOCK_DRAG_UPDATE', this.handleBlockDragUpdate);
}
componentWillUnmount () {
this.props.vm.removeListener('BLOCK_DRAG_END', this.handleBlockDragEnd);
this.props.vm.removeListener('BLOCK_DRAG_UPDATE', this.handleBlockDragUpdate);
}
getBackpackAssetURL (asset) {
return `${this.props.host}/${asset.assetId}.${asset.dataFormat}`;
}
handleToggle () {
const newState = !this.state.expanded;
this.setState({expanded: newState, offset: 0});
this.setState({expanded: newState, offset: 0}, () => {
// Emit resize on window to get blocks to resize
window.dispatchEvent(new Event('resize'));
});
if (newState) {
this.refreshContents();
}
@@ -72,6 +92,9 @@ class Backpack extends React.Component {
case DragConstants.SPRITE:
payloader = spritePayload;
break;
case DragConstants.CODE:
payloader = codePayload;
break;
}
if (!payloader) return;
@@ -110,15 +133,47 @@ class Backpack extends React.Component {
});
}
}
handleBlockDragUpdate (isOutsideWorkspace) {
this.setState({
blockDragOutsideWorkspace: isOutsideWorkspace
});
}
handleMouseEnter () {
if (this.state.blockDragOutsideWorkspace) {
this.setState({
blockDragOverBackpack: true
});
}
}
handleMouseLeave () {
this.setState({
blockDragOverBackpack: false
});
}
handleBlockDragEnd (blocks) {
if (this.state.blockDragOverBackpack) {
this.handleDrop({
dragType: DragConstants.CODE,
payload: blocks
});
}
this.setState({
blockDragOverBackpack: false,
blockDragOutsideWorkspace: false
});
}
render () {
return (
<DroppableBackpack
blockDragOver={this.state.blockDragOverBackpack}
contents={this.state.contents}
error={this.state.error}
expanded={this.state.expanded}
loading={this.state.loading}
onDelete={this.handleDelete}
onDrop={this.handleDrop}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onToggle={this.props.host ? this.handleToggle : null}
/>
);
@@ -152,9 +207,17 @@ const getTokenAndUsername = state => {
const mapStateToProps = state => Object.assign(
{
vm: state.scratchGui.vm
dragInfo: state.scratchGui.assetDrag,
vm: state.scratchGui.vm,
blockDrag: state.scratchGui.blockDrag
},
getTokenAndUsername(state)
);
export default connect(mapStateToProps)(Backpack);
const mapDispatchToProps = dispatch => ({
dispatchSetHoveredSprite: spriteId => {
dispatch(setHoveredSprite(spriteId));
}
});
export default connect(mapStateToProps, mapDispatchToProps)(Backpack);