Skip to content
Snippets Groups Projects
Commit 4aa3b20a authored by DD's avatar DD
Browse files

Add very simple end animation

parent 97d6308a
No related branches found
No related tags found
No related merge requests found
...@@ -112,3 +112,34 @@ ...@@ -112,3 +112,34 @@
75% {transform: rotate(-2deg) scale(1.05);} 75% {transform: rotate(-2deg) scale(1.05);}
100% {transform: rotate(0deg) scale(1.05);} 100% {transform: rotate(0deg) scale(1.05);}
} }
.receivedBlocks {
-webkit-animation: glowing 250ms;
-moz-animation: glowing 250ms;
-o-animation: glowing 250ms;
animation: glowing 250ms;
}
@-webkit-keyframes glowing {
10% { -webkit-box-shadow: 0 0 10px #7fff1e; }
90% { -webkit-box-shadow: 0 0 10px #7fff1e; }
100% { -webkit-box-shadow: none; }
}
@-moz-keyframes glowing {
10% { -moz-box-shadow: 0 0 10px #7fff1e; }
90% { -moz-box-shadow: 0 0 10px #7fff1e; }
100% { -moz-box-shadow: none; }
}
@-o-keyframes glowing {
10% { box-shadow: 0 0 10px #7fff1e; }
90% { box-shadow: 0 0 10px #7fff1e; }
100% { box-shadow: none; }
}
@keyframes glowing {
10% { box-shadow: 0 0 10px #7fff1e; }
90% { box-shadow: 0 0 10px #7fff1e; }
100% { box-shadow: none; }
}
\ No newline at end of file
...@@ -21,6 +21,8 @@ const messages = defineMessages({ ...@@ -21,6 +21,8 @@ const messages = defineMessages({
const SpriteSelectorComponent = function (props) { const SpriteSelectorComponent = function (props) {
const { const {
editingTarget,
hoveredTarget,
intl, intl,
onChangeSpriteDirection, onChangeSpriteDirection,
onChangeSpriteName, onChangeSpriteName,
...@@ -30,8 +32,6 @@ const SpriteSelectorComponent = function (props) { ...@@ -30,8 +32,6 @@ const SpriteSelectorComponent = function (props) {
onChangeSpriteY, onChangeSpriteY,
onDeleteSprite, onDeleteSprite,
onDuplicateSprite, onDuplicateSprite,
onMouseOutSprite,
onMouseOverSprite,
onNewSpriteClick, onNewSpriteClick,
onSelectSprite, onSelectSprite,
raised, raised,
...@@ -76,10 +76,12 @@ const SpriteSelectorComponent = function (props) { ...@@ -76,10 +76,12 @@ const SpriteSelectorComponent = function (props) {
.map(sprite => ( .map(sprite => (
<SpriteSelectorItem <SpriteSelectorItem
assetId={sprite.costume && sprite.costume.assetId} assetId={sprite.costume && sprite.costume.assetId}
className={ className={hoveredTarget.sprite === sprite.id &&
(raised && sprite.id !== selectedId) ? sprite.id !== editingTarget &&
classNames(styles.sprite, styles.raised) : styles.sprite hoveredTarget.receivedBlocks ?
} classNames(styles.sprite, styles.receivedBlocks) :
raised && sprite.id !== editingTarget ?
classNames(styles.sprite, styles.raised) : styles.sprite}
id={sprite.id} id={sprite.id}
key={sprite.id} key={sprite.id}
name={sprite.name} name={sprite.name}
...@@ -87,8 +89,6 @@ const SpriteSelectorComponent = function (props) { ...@@ -87,8 +89,6 @@ const SpriteSelectorComponent = function (props) {
onClick={onSelectSprite} onClick={onSelectSprite}
onDeleteButtonClick={onDeleteSprite} onDeleteButtonClick={onDeleteSprite}
onDuplicateButtonClick={onDuplicateSprite} onDuplicateButtonClick={onDuplicateSprite}
onMouseOut={onMouseOutSprite}
onMouseOver={onMouseOverSprite}
/> />
)) ))
} }
...@@ -105,6 +105,11 @@ const SpriteSelectorComponent = function (props) { ...@@ -105,6 +105,11 @@ const SpriteSelectorComponent = function (props) {
}; };
SpriteSelectorComponent.propTypes = { SpriteSelectorComponent.propTypes = {
editingTarget: PropTypes.string,
hoveredTarget: PropTypes.shape({
hoveredSprite: PropTypes.string,
receivedBlocks: PropTypes.bool
}),
intl: intlShape.isRequired, intl: intlShape.isRequired,
onChangeSpriteDirection: PropTypes.func, onChangeSpriteDirection: PropTypes.func,
onChangeSpriteName: PropTypes.func, onChangeSpriteName: PropTypes.func,
...@@ -114,8 +119,6 @@ SpriteSelectorComponent.propTypes = { ...@@ -114,8 +119,6 @@ SpriteSelectorComponent.propTypes = {
onChangeSpriteY: PropTypes.func, onChangeSpriteY: PropTypes.func,
onDeleteSprite: PropTypes.func, onDeleteSprite: PropTypes.func,
onDuplicateSprite: PropTypes.func, onDuplicateSprite: PropTypes.func,
onMouseOutSprite: PropTypes.func,
onMouseOverSprite: PropTypes.func,
onNewSpriteClick: PropTypes.func, onNewSpriteClick: PropTypes.func,
onSelectSprite: PropTypes.func, onSelectSprite: PropTypes.func,
raised: PropTypes.bool, raised: PropTypes.bool,
......
...@@ -19,6 +19,7 @@ import styles from './target-pane.css'; ...@@ -19,6 +19,7 @@ import styles from './target-pane.css';
const TargetPane = ({ const TargetPane = ({
backdropLibraryVisible, backdropLibraryVisible,
editingTarget, editingTarget,
hoveredTarget,
spriteLibraryVisible, spriteLibraryVisible,
onChangeSpriteDirection, onChangeSpriteDirection,
onChangeSpriteName, onChangeSpriteName,
...@@ -28,8 +29,6 @@ const TargetPane = ({ ...@@ -28,8 +29,6 @@ const TargetPane = ({
onChangeSpriteY, onChangeSpriteY,
onDeleteSprite, onDeleteSprite,
onDuplicateSprite, onDuplicateSprite,
onMouseOutSprite,
onMouseOverSprite,
onNewSpriteClick, onNewSpriteClick,
onRequestCloseSpriteLibrary, onRequestCloseSpriteLibrary,
onRequestCloseBackdropLibrary, onRequestCloseBackdropLibrary,
...@@ -46,6 +45,8 @@ const TargetPane = ({ ...@@ -46,6 +45,8 @@ const TargetPane = ({
> >
<SpriteSelectorComponent <SpriteSelectorComponent
editingTarget={editingTarget}
hoveredTarget={hoveredTarget}
raised={raiseSprites} raised={raiseSprites}
selectedId={editingTarget} selectedId={editingTarget}
sprites={sprites} sprites={sprites}
...@@ -57,8 +58,6 @@ const TargetPane = ({ ...@@ -57,8 +58,6 @@ const TargetPane = ({
onChangeSpriteY={onChangeSpriteY} onChangeSpriteY={onChangeSpriteY}
onDeleteSprite={onDeleteSprite} onDeleteSprite={onDeleteSprite}
onDuplicateSprite={onDuplicateSprite} onDuplicateSprite={onDuplicateSprite}
onMouseOutSprite={onMouseOutSprite}
onMouseOverSprite={onMouseOverSprite}
onNewSpriteClick={onNewSpriteClick} onNewSpriteClick={onNewSpriteClick}
onSelectSprite={onSelectSprite} onSelectSprite={onSelectSprite}
/> />
...@@ -113,6 +112,10 @@ TargetPane.propTypes = { ...@@ -113,6 +112,10 @@ TargetPane.propTypes = {
backdropLibraryVisible: PropTypes.bool, backdropLibraryVisible: PropTypes.bool,
editingTarget: PropTypes.string, editingTarget: PropTypes.string,
extensionLibraryVisible: PropTypes.bool, extensionLibraryVisible: PropTypes.bool,
hoveredTarget: PropTypes.shape({
hoveredSprite: PropTypes.string,
receivedBlocks: PropTypes.bool
}),
onChangeSpriteDirection: PropTypes.func, onChangeSpriteDirection: PropTypes.func,
onChangeSpriteName: PropTypes.func, onChangeSpriteName: PropTypes.func,
onChangeSpriteSize: PropTypes.func, onChangeSpriteSize: PropTypes.func,
...@@ -121,8 +124,6 @@ TargetPane.propTypes = { ...@@ -121,8 +124,6 @@ TargetPane.propTypes = {
onChangeSpriteY: PropTypes.func, onChangeSpriteY: PropTypes.func,
onDeleteSprite: PropTypes.func, onDeleteSprite: PropTypes.func,
onDuplicateSprite: PropTypes.func, onDuplicateSprite: PropTypes.func,
onMouseOutSprite: PropTypes.func,
onMouseOverSprite: PropTypes.func,
onNewSpriteClick: PropTypes.func, onNewSpriteClick: PropTypes.func,
onRequestCloseBackdropLibrary: PropTypes.func, onRequestCloseBackdropLibrary: PropTypes.func,
onRequestCloseExtensionLibrary: PropTypes.func, onRequestCloseExtensionLibrary: PropTypes.func,
......
import bindAll from 'lodash.bindall'; import bindAll from 'lodash.bindall';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {setHoveredSprite} from '../reducers/hovered-target';
import SpriteSelectorItemComponent from '../components/sprite-selector-item/sprite-selector-item.jsx'; import SpriteSelectorItemComponent from '../components/sprite-selector-item/sprite-selector-item.jsx';
class SpriteSelectorItem extends React.Component { class SpriteSelectorItem extends React.Component {
...@@ -33,10 +34,10 @@ class SpriteSelectorItem extends React.Component { ...@@ -33,10 +34,10 @@ class SpriteSelectorItem extends React.Component {
this.props.onDuplicateButtonClick(this.props.id); this.props.onDuplicateButtonClick(this.props.id);
} }
handleMouseOut () { handleMouseOut () {
this.props.onMouseOut(this.props.id); this.props.dispatchSetHoveredSprite(null);
} }
handleMouseOver () { handleMouseOver () {
this.props.onMouseOver(this.props.id); this.props.dispatchSetHoveredSprite(this.props.id);
} }
render () { render () {
const { const {
...@@ -46,8 +47,7 @@ class SpriteSelectorItem extends React.Component { ...@@ -46,8 +47,7 @@ class SpriteSelectorItem extends React.Component {
onClick, onClick,
onDeleteButtonClick, onDeleteButtonClick,
onDuplicateButtonClick, onDuplicateButtonClick,
onMouseOut, receivedBlocks,
onMouseOver,
/* eslint-enable no-unused-vars */ /* eslint-enable no-unused-vars */
...props ...props
} = this.props; } = this.props;
...@@ -56,8 +56,8 @@ class SpriteSelectorItem extends React.Component { ...@@ -56,8 +56,8 @@ class SpriteSelectorItem extends React.Component {
onClick={this.handleClick} onClick={this.handleClick}
onDeleteButtonClick={onDeleteButtonClick ? this.handleDelete : null} onDeleteButtonClick={onDeleteButtonClick ? this.handleDelete : null}
onDuplicateButtonClick={onDuplicateButtonClick ? this.handleDuplicate : null} onDuplicateButtonClick={onDuplicateButtonClick ? this.handleDuplicate : null}
onMouseOut={onMouseOut ? this.handleMouseOut : null} onMouseOut={this.handleMouseOut}
onMouseOver={onMouseOver ? this.handleMouseOver : null} onMouseOver={this.handleMouseOver}
{...props} {...props}
/> />
); );
...@@ -67,20 +67,28 @@ class SpriteSelectorItem extends React.Component { ...@@ -67,20 +67,28 @@ class SpriteSelectorItem extends React.Component {
SpriteSelectorItem.propTypes = { SpriteSelectorItem.propTypes = {
assetId: PropTypes.string, assetId: PropTypes.string,
costumeURL: PropTypes.string, costumeURL: PropTypes.string,
dispatchSetHoveredSprite: PropTypes.func.isRequired,
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
name: PropTypes.string, name: PropTypes.string,
onClick: PropTypes.func, onClick: PropTypes.func,
onDeleteButtonClick: PropTypes.func, onDeleteButtonClick: PropTypes.func,
onDuplicateButtonClick: PropTypes.func, onDuplicateButtonClick: PropTypes.func,
onMouseOut: PropTypes.func, receivedBlocks: PropTypes.bool,
onMouseOver: PropTypes.func,
selected: PropTypes.bool selected: PropTypes.bool
}; };
const mapStateToProps = (state, {assetId, costumeURL}) => ({ const mapStateToProps = (state, {assetId, costumeURL, id}) => ({
costumeURL: costumeURL || (assetId && state.vm.runtime.storage.get(assetId).encodeDataURI()) costumeURL: costumeURL || (assetId && state.vm.runtime.storage.get(assetId).encodeDataURI()),
receivedBlocks: state.hoveredTarget.receivedBlocks &&
state.hoveredTarget.sprite === id
});
const mapDispatchToProps = dispatch => ({
dispatchSetHoveredSprite: spriteId => {
dispatch(setHoveredSprite(spriteId));
}
}); });
export default connect( export default connect(
mapStateToProps mapStateToProps,
mapDispatchToProps
)(SpriteSelectorItem); )(SpriteSelectorItem);
...@@ -9,8 +9,6 @@ import { ...@@ -9,8 +9,6 @@ import {
closeSpriteLibrary closeSpriteLibrary
} from '../reducers/modals'; } from '../reducers/modals';
import {setHoveredSprite} from '../reducers/hovered-target-sprite';
import TargetPaneComponent from '../components/target-pane/target-pane.jsx'; import TargetPaneComponent from '../components/target-pane/target-pane.jsx';
class TargetPane extends React.Component { class TargetPane extends React.Component {
...@@ -25,8 +23,6 @@ class TargetPane extends React.Component { ...@@ -25,8 +23,6 @@ class TargetPane extends React.Component {
'handleChangeSpriteY', 'handleChangeSpriteY',
'handleDeleteSprite', 'handleDeleteSprite',
'handleDuplicateSprite', 'handleDuplicateSprite',
'handleMouseOutSprite',
'handleMouseOverSprite',
'handleSelectSprite' 'handleSelectSprite'
]); ]);
} }
...@@ -54,12 +50,6 @@ class TargetPane extends React.Component { ...@@ -54,12 +50,6 @@ class TargetPane extends React.Component {
handleDuplicateSprite (id) { handleDuplicateSprite (id) {
this.props.vm.duplicateSprite(id); this.props.vm.duplicateSprite(id);
} }
handleMouseOutSprite () {
this.props.setHoveredSprite(null);
}
handleMouseOverSprite (id) {
this.props.setHoveredSprite(id);
}
handleSelectSprite (id) { handleSelectSprite (id) {
this.props.vm.setEditingTarget(id); this.props.vm.setEditingTarget(id);
} }
...@@ -75,8 +65,6 @@ class TargetPane extends React.Component { ...@@ -75,8 +65,6 @@ class TargetPane extends React.Component {
onChangeSpriteY={this.handleChangeSpriteY} onChangeSpriteY={this.handleChangeSpriteY}
onDeleteSprite={this.handleDeleteSprite} onDeleteSprite={this.handleDeleteSprite}
onDuplicateSprite={this.handleDuplicateSprite} onDuplicateSprite={this.handleDuplicateSprite}
onMouseOutSprite={this.handleMouseOutSprite}
onMouseOverSprite={this.handleMouseOverSprite}
onSelectSprite={this.handleSelectSprite} onSelectSprite={this.handleSelectSprite}
/> />
); );
...@@ -94,6 +82,7 @@ TargetPane.propTypes = { ...@@ -94,6 +82,7 @@ TargetPane.propTypes = {
const mapStateToProps = state => ({ const mapStateToProps = state => ({
editingTarget: state.targets.editingTarget, editingTarget: state.targets.editingTarget,
hoveredTarget: state.hoveredTarget,
sprites: Object.keys(state.targets.sprites).reduce((sprites, k) => { sprites: Object.keys(state.targets.sprites).reduce((sprites, k) => {
let {direction, size, x, y, ...sprite} = state.targets.sprites[k]; let {direction, size, x, y, ...sprite} = state.targets.sprites[k];
if (typeof direction !== 'undefined') direction = Math.round(direction); if (typeof direction !== 'undefined') direction = Math.round(direction);
...@@ -118,9 +107,6 @@ const mapDispatchToProps = dispatch => ({ ...@@ -118,9 +107,6 @@ const mapDispatchToProps = dispatch => ({
}, },
onRequestCloseBackdropLibrary: () => { onRequestCloseBackdropLibrary: () => {
dispatch(closeBackdropLibrary()); dispatch(closeBackdropLibrary());
},
setHoveredSprite: spriteId => {
dispatch(setHoveredSprite(spriteId));
} }
}); });
......
...@@ -8,6 +8,7 @@ import {connect} from 'react-redux'; ...@@ -8,6 +8,7 @@ import {connect} from 'react-redux';
import {updateEditingTarget, updateTargets} from '../reducers/targets'; import {updateEditingTarget, updateTargets} from '../reducers/targets';
import {updateBlockDrag} from '../reducers/block-drag'; import {updateBlockDrag} from '../reducers/block-drag';
import {updateMonitors} from '../reducers/monitors'; import {updateMonitors} from '../reducers/monitors';
import {setReceivedBlocks} from '../reducers/hovered-target';
/* /*
* Higher Order Component to manage events emitted by the VM * Higher Order Component to manage events emitted by the VM
...@@ -51,8 +52,9 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -51,8 +52,9 @@ const vmListenerHOC = function (WrappedComponent) {
} }
} }
handleBlockDragEnd (blocks) { handleBlockDragEnd (blocks) {
if (this.props.hoveredTargetSprite && this.props.hoveredTargetSprite !== this.props.editingTarget) { if (this.props.hoveredSprite && this.props.hoveredSprite !== this.props.editingTarget) {
this.props.vm.shareBlocksToTarget(blocks, this.props.hoveredTargetSprite); this.props.vm.shareBlocksToTarget(blocks, this.props.hoveredSprite);
this.props.onReceivedBlocks(true);
} }
} }
handleKeyDown (e) { handleKeyDown (e) {
...@@ -86,10 +88,13 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -86,10 +88,13 @@ const vmListenerHOC = function (WrappedComponent) {
const { const {
/* eslint-disable no-unused-vars */ /* eslint-disable no-unused-vars */
attachKeyboardEvents, attachKeyboardEvents,
editingTarget,
hoveredSprite,
onBlockDragUpdate, onBlockDragUpdate,
onKeyDown, onKeyDown,
onKeyUp, onKeyUp,
onMonitorsUpdate, onMonitorsUpdate,
onReceivedBlocks,
onTargetsUpdate, onTargetsUpdate,
/* eslint-enable no-unused-vars */ /* eslint-enable no-unused-vars */
...props ...props
...@@ -100,11 +105,12 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -100,11 +105,12 @@ const vmListenerHOC = function (WrappedComponent) {
VMListener.propTypes = { VMListener.propTypes = {
attachKeyboardEvents: PropTypes.bool, attachKeyboardEvents: PropTypes.bool,
editingTarget: PropTypes.string, editingTarget: PropTypes.string,
hoveredTargetSprite: PropTypes.string, hoveredSprite: PropTypes.string,
onBlockDragUpdate: PropTypes.func.isRequired, onBlockDragUpdate: PropTypes.func.isRequired,
onKeyDown: PropTypes.func, onKeyDown: PropTypes.func,
onKeyUp: PropTypes.func, onKeyUp: PropTypes.func,
onMonitorsUpdate: PropTypes.func.isRequired, onMonitorsUpdate: PropTypes.func.isRequired,
onReceivedBlocks: PropTypes.func.isRequired,
onTargetsUpdate: PropTypes.func.isRequired, onTargetsUpdate: PropTypes.func.isRequired,
vm: PropTypes.instanceOf(VM).isRequired vm: PropTypes.instanceOf(VM).isRequired
}; };
...@@ -113,7 +119,7 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -113,7 +119,7 @@ const vmListenerHOC = function (WrappedComponent) {
}; };
const mapStateToProps = state => ({ const mapStateToProps = state => ({
vm: state.vm, vm: state.vm,
hoveredTargetSprite: state.hoveredTargetSprite, hoveredSprite: state.hoveredTarget.sprite,
editingTarget: state.targets.editingTarget editingTarget: state.targets.editingTarget
}); });
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
...@@ -126,6 +132,9 @@ const vmListenerHOC = function (WrappedComponent) { ...@@ -126,6 +132,9 @@ const vmListenerHOC = function (WrappedComponent) {
}, },
onBlockDragUpdate: areBlocksOverGui => { onBlockDragUpdate: areBlocksOverGui => {
dispatch(updateBlockDrag(areBlocksOverGui)); dispatch(updateBlockDrag(areBlocksOverGui));
},
onReceivedBlocks: receivedBlocks => {
dispatch(setReceivedBlocks(receivedBlocks));
} }
}); });
return connect( return connect(
......
...@@ -2,7 +2,7 @@ import {combineReducers} from 'redux'; ...@@ -2,7 +2,7 @@ import {combineReducers} from 'redux';
import colorPickerReducer from './color-picker'; import colorPickerReducer from './color-picker';
import customProceduresReducer from './custom-procedures'; import customProceduresReducer from './custom-procedures';
import blockDragReducer from './block-drag'; import blockDragReducer from './block-drag';
import hoveredTargetSpriteReducer from './hovered-target-sprite'; import hoveredTargetReducer from './hovered-target';
import intlReducer from './intl'; import intlReducer from './intl';
import modalReducer from './modals'; import modalReducer from './modals';
import monitorReducer from './monitors'; import monitorReducer from './monitors';
...@@ -17,7 +17,7 @@ export default combineReducers({ ...@@ -17,7 +17,7 @@ export default combineReducers({
blockDrag: blockDragReducer, blockDrag: blockDragReducer,
colorPicker: colorPickerReducer, colorPicker: colorPickerReducer,
customProcedures: customProceduresReducer, customProcedures: customProceduresReducer,
hoveredTargetSprite: hoveredTargetSpriteReducer, hoveredTarget: hoveredTargetReducer,
intl: intlReducer, intl: intlReducer,
stageSize: stageSizeReducer, stageSize: stageSizeReducer,
modals: modalReducer, modals: modalReducer,
......
const SET_HOVERED_SPRITE = 'scratch-gui/hovered-target-sprite/SET_HOVERED_SPRITE'; const SET_HOVERED_SPRITE = 'scratch-gui/hovered-target/SET_HOVERED_SPRITE';
const SET_RECEIVED_BLOCKS = 'scratch-gui/hovered-target/SET_RECEIVED_BLOCKS';
const initialState = null; const initialState = {
sprite: null,
receivedBlocks: false
};
const reducer = function (state, action) { const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState; if (typeof state === 'undefined') state = initialState;
switch (action.type) { switch (action.type) {
case SET_HOVERED_SPRITE: case SET_HOVERED_SPRITE:
return action.spriteId; return {
sprite: action.spriteId,
receivedBlocks: false
};
case SET_RECEIVED_BLOCKS:
return {
sprite: state.sprite,
receivedBlocks: action.receivedBlocks
};
default: default:
return state; return state;
} }
...@@ -22,7 +34,15 @@ const setHoveredSprite = function (spriteId) { ...@@ -22,7 +34,15 @@ const setHoveredSprite = function (spriteId) {
}; };
}; };
const setReceivedBlocks = function (receivedBlocks) {
return {
type: SET_RECEIVED_BLOCKS,
receivedBlocks: receivedBlocks
};
};
export { export {
reducer as default, reducer as default,
setHoveredSprite setHoveredSprite,
setReceivedBlocks
}; };
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment