Restore deleted sprite.

This commit is contained in:
Karishma Chadha committed 2018-08-09 17:25:54 -04:00
1 parent 976e3b9b4a
commit b17f6e8533
6 files changed
+136 -9

No files matched your search

+4
View File
@@ -172,3 +172,7 @@
width: 0.5rem;
height: 0.5rem;
}
.disabled {
opacity: 0.5;
}
+19 -8
View File
@@ -14,6 +14,7 @@ import ProjectLoader from '../../containers/project-loader.jsx';
import Menu from '../../containers/menu.jsx';
import {MenuItem, MenuSection} from '../menu/menu.jsx';
import ProjectSaver from '../../containers/project-saver.jsx';
import DeletionRestorer from '../../containers/deletion-restorer.jsx';
import TurboMode from '../../containers/turbo-mode.jsx';
import {openTipsLibrary} from '../../reducers/modals';
@@ -279,15 +280,25 @@ class MenuBar extends React.Component {
open={this.props.editMenuOpen}
onRequestClose={this.props.onRequestCloseEdit}
>
<MenuItemTooltip id="undo">
<MenuItem>
<FormattedMessage
defaultMessage="Undo"
description="Menu bar item for undoing"
id="gui.menuBar.undo"
/>
<DeletionRestorer>{(handleRestore, {restorable, deletedItem}) => (
<MenuItem
className={classNames({[styles.disabled]:!restorable})}
onClick={handleRestore}
>
{deletedItem === 'Sprite' ?
<FormattedMessage
defaultMessage="Restore Sprite"
description="Menu bar item for restoring the last deleted sprite."
id="gui.menuBar.restoreSprite"
/> :
<FormattedMessage
defaultMessage="Restore"
description="Menu bar item for restoring the last deleted item in its disabled state."
id="gui.menuBar.restore"
/>
}
</MenuItem>
</MenuItemTooltip>
)}</DeletionRestorer>
<MenuItemTooltip id="redo">
<MenuItem>
<FormattedMessage
+67
View File
@@ -0,0 +1,67 @@
import bindAll from 'lodash.bindall';
import PropTypes from 'prop-types';
import React from 'react';
import {connect} from 'react-redux';
import {setRestore} from '../reducers/restore-deletion';
/**
* DeletionRestorer component passes a restoreDeletion function to its child.
* It expects this child to be a function with the signature
* function (restoreDeletion, props) {}
* The component can then be used to attach deletion restoring functionality
* to any other component:
*
* <DeletionRestorer>{(restoreDeletion, props) => (
* <MyCoolComponent
* onClick={restoreDeletion}
* {...props}
* />
* )}</DeletionRestorer>
*/
class DeletionRestorer extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'restoreDeletion'
]);
}
restoreDeletion () {
if (typeof this.props.restore === 'function') {
this.props.restore();
this.props.dispatchUpdateRestore({restoreFun: null, deletedItem: ''});
}
}
render () {
const {
/* eslint-disable no-unused-vars */
children,
/* eslint-enable no-unused-vars */
...props
} = this.props;
props.restorable = typeof this.props.restore === 'function';
props.deletedItem = this.props.deletedItem;
return this.props.children(this.restoreDeletion, props);
}
}
DeletionRestorer.propTypes = {
children: PropTypes.func,
deletedItem: PropTypes.string,
dispatchUpdateRestore: PropTypes.func,
restore: PropTypes.func
};
const mapStateToProps = state => ({
deletedItem: state.scratchGui.restoreDeletion.deletedItem,
restore: state.scratchGui.restoreDeletion.restoreFun
});
const mapDispatchToProps = dispatch => ({
dispatchUpdateRestore: updatedState => {
dispatch(setRestore(updatedState));
}
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(DeletionRestorer);
+10 -1
View File
@@ -10,6 +10,7 @@ import {
import {activateTab, COSTUMES_TAB_INDEX} from '../reducers/editor-tab';
import {setReceivedBlocks} from '../reducers/hovered-target';
import {setRestore} from '../reducers/restore-deletion';
import DragConstants from '../lib/drag-constants';
import TargetPaneComponent from '../components/target-pane/target-pane.jsx';
import spriteLibraryContent from '../lib/libraries/sprites.json';
@@ -68,7 +69,12 @@ class TargetPane extends React.Component {
this.props.vm.postSpriteInfo({y});
}
handleDeleteSprite (id) {
this.props.vm.deleteSprite(id);
const restoreFun = this.props.vm.deleteSprite(id);
this.props.dispatchUpdateRestore({
restoreFun: restoreFun,
deletedItem: 'Sprite'
});
}
handleDuplicateSprite (id) {
this.props.vm.duplicateSprite(id);
@@ -240,6 +246,9 @@ const mapDispatchToProps = dispatch => ({
},
onReceivedBlocks: receivedBlocks => {
dispatch(setReceivedBlocks(receivedBlocks));
},
dispatchUpdateRestore: restoreState => {
dispatch(setRestore(restoreState));
}
});
+3
View File
@@ -11,6 +11,7 @@ import modalReducer, {modalsInitialState} from './modals';
import modeReducer, {modeInitialState} from './mode';
import monitorReducer, {monitorsInitialState} from './monitors';
import monitorLayoutReducer, {monitorLayoutInitialState} from './monitor-layout';
import restoreDeletionReducer, {restoreDeletionInitialState} from './restore-deletion';
import stageSizeReducer, {stageSizeInitialState} from './stage-size';
import targetReducer, {targetsInitialState} from './targets';
import toolboxReducer, {toolboxInitialState} from './toolbox';
@@ -34,6 +35,7 @@ const guiInitialState = {
modals: modalsInitialState,
monitors: monitorsInitialState,
monitorLayout: monitorLayoutInitialState,
restoreDeletion: restoreDeletionInitialState,
targets: targetsInitialState,
toolbox: toolboxInitialState,
vm: vmInitialState,
@@ -75,6 +77,7 @@ const guiReducer = combineReducers({
modals: modalReducer,
monitors: monitorReducer,
monitorLayout: monitorLayoutReducer,
restoreDeletion: restoreDeletionReducer,
targets: targetReducer,
toolbox: toolboxReducer,
vm: vmReducer,
+33
View File
@@ -0,0 +1,33 @@
const RESTORE_UPDATE = 'scratch-gui/restore-deletion/RESTORE_UPDATE';
const initialState = {
restoreFun: null,
deletedItem: ''
};
const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
case RESTORE_UPDATE:
return Object.assign({}, state, action.state);
default:
return state;
}
};
const setRestore = function (state) {
return {
type: RESTORE_UPDATE,
state: {
restoreFun: state.restoreFun,
deletedItem: state.deletedItem
}
};
};
export {
reducer as default,
initialState as restoreDeletionInitialState,
setRestore
};