Merge pull request #4938 from LLK/touch-share
Allow sharing blocks/costumes/sounds on touch devices
This commit is contained in:
3 files changed
+43
-2
No files matched your search
@@ -25,6 +25,7 @@ const SpriteSelectorItem = props => (
|
||||
}}
|
||||
disable={props.preventContextMenu}
|
||||
id={`${props.name}-${contextMenuId}`}
|
||||
ref={props.componentRef}
|
||||
>
|
||||
{typeof props.number === 'undefined' ? null : (
|
||||
<div className={styles.number}>{props.number}</div>
|
||||
@@ -89,6 +90,7 @@ const SpriteSelectorItem = props => (
|
||||
|
||||
SpriteSelectorItem.propTypes = {
|
||||
className: PropTypes.string,
|
||||
componentRef: PropTypes.func,
|
||||
costumeURL: PropTypes.string,
|
||||
details: PropTypes.string,
|
||||
name: PropTypes.string.isRequired,
|
||||
|
||||
@@ -9,6 +9,7 @@ import storage from '../lib/storage';
|
||||
import VM from 'scratch-vm';
|
||||
import getCostumeUrl from '../lib/get-costume-url';
|
||||
import DragRecognizer from '../lib/drag-recognizer';
|
||||
import {getEventXY} from '../lib/touch-utils';
|
||||
|
||||
import SpriteSelectorItemComponent from '../components/sprite-selector-item/sprite-selector-item.jsx';
|
||||
|
||||
@@ -17,6 +18,7 @@ class SpriteSelectorItem extends React.PureComponent {
|
||||
super(props);
|
||||
bindAll(this, [
|
||||
'getCostumeData',
|
||||
'setRef',
|
||||
'handleClick',
|
||||
'handleDelete',
|
||||
'handleDuplicate',
|
||||
@@ -25,7 +27,8 @@ class SpriteSelectorItem extends React.PureComponent {
|
||||
'handleMouseLeave',
|
||||
'handleMouseDown',
|
||||
'handleDragEnd',
|
||||
'handleDrag'
|
||||
'handleDrag',
|
||||
'handleTouchEnd'
|
||||
]);
|
||||
|
||||
this.dragRecognizer = new DragRecognizer({
|
||||
@@ -33,7 +36,11 @@ class SpriteSelectorItem extends React.PureComponent {
|
||||
onDragEnd: this.handleDragEnd
|
||||
});
|
||||
}
|
||||
componentDidMount () {
|
||||
document.addEventListener('touchend', this.handleTouchEnd);
|
||||
}
|
||||
componentWillUnmount () {
|
||||
document.removeEventListener('touchend', this.handleTouchEnd);
|
||||
this.dragRecognizer.reset();
|
||||
}
|
||||
getCostumeData () {
|
||||
@@ -67,6 +74,13 @@ class SpriteSelectorItem extends React.PureComponent {
|
||||
});
|
||||
this.noClick = true;
|
||||
}
|
||||
handleTouchEnd (e) {
|
||||
const {x, y} = getEventXY(e);
|
||||
const {top, left, bottom, right} = this.ref.getBoundingClientRect();
|
||||
if (x >= left && x <= right && y >= top && y <= bottom) {
|
||||
this.handleMouseEnter();
|
||||
}
|
||||
}
|
||||
handleMouseDown (e) {
|
||||
this.dragRecognizer.start(e);
|
||||
}
|
||||
@@ -94,6 +108,10 @@ class SpriteSelectorItem extends React.PureComponent {
|
||||
handleMouseEnter () {
|
||||
this.props.dispatchSetHoveredSprite(this.props.id);
|
||||
}
|
||||
setRef (component) {
|
||||
// Access the DOM node using .elem because it is going through ContextMenuTrigger
|
||||
this.ref = component && component.elem;
|
||||
}
|
||||
render () {
|
||||
const {
|
||||
/* eslint-disable no-unused-vars */
|
||||
@@ -113,6 +131,7 @@ class SpriteSelectorItem extends React.PureComponent {
|
||||
} = this.props;
|
||||
return (
|
||||
<SpriteSelectorItemComponent
|
||||
componentRef={this.setRef}
|
||||
costumeURL={this.getCostumeData()}
|
||||
preventContextMenu={this.dragRecognizer.gestureInProgress()}
|
||||
onClick={this.handleClick}
|
||||
|
||||
@@ -15,6 +15,7 @@ import ThrottledPropertyHOC from '../lib/throttled-property-hoc.jsx';
|
||||
import {emptyCostume} from '../lib/empty-assets';
|
||||
import sharedMessages from '../lib/shared-messages';
|
||||
import {fetchCode} from '../lib/backpack-api';
|
||||
import {getEventXY} from '../lib/touch-utils';
|
||||
|
||||
import StageSelectorComponent from '../components/stage-selector/stage-selector.jsx';
|
||||
|
||||
@@ -46,10 +47,25 @@ class StageSelector extends React.Component {
|
||||
'handleBackdropUpload',
|
||||
'handleMouseEnter',
|
||||
'handleMouseLeave',
|
||||
'handleTouchEnd',
|
||||
'handleDrop',
|
||||
'setFileInput'
|
||||
'setFileInput',
|
||||
'setRef'
|
||||
]);
|
||||
}
|
||||
componentDidMount () {
|
||||
document.addEventListener('touchend', this.handleTouchEnd);
|
||||
}
|
||||
componentWillUnmount () {
|
||||
document.removeEventListener('touchend', this.handleTouchEnd);
|
||||
}
|
||||
handleTouchEnd (e) {
|
||||
const {x, y} = getEventXY(e);
|
||||
const {top, left, bottom, right} = this.ref.getBoundingClientRect();
|
||||
if (x >= left && x <= right && y >= top && y <= bottom) {
|
||||
this.handleMouseEnter();
|
||||
}
|
||||
}
|
||||
addBackdropFromLibraryItem (item, shouldActivateTab = true) {
|
||||
const vmBackdrop = {
|
||||
name: item.name,
|
||||
@@ -137,12 +153,16 @@ class StageSelector extends React.Component {
|
||||
setFileInput (input) {
|
||||
this.fileInput = input;
|
||||
}
|
||||
setRef (ref) {
|
||||
this.ref = ref;
|
||||
}
|
||||
render () {
|
||||
const componentProps = omit(this.props, [
|
||||
'asset', 'dispatchSetHoveredSprite', 'id', 'intl',
|
||||
'onActivateTab', 'onSelect', 'onShowImporting', 'onCloseImporting']);
|
||||
return (
|
||||
<DroppableThrottledStage
|
||||
componentRef={this.setRef}
|
||||
fileInputRef={this.setFileInput}
|
||||
onBackdropFileUpload={this.handleBackdropUpload}
|
||||
onBackdropFileUploadClick={this.handleFileUploadClick}
|
||||
|
||||
Reference in new issue
Block a user