Skip to content
Snippets Groups Projects
Commit b17f6e85 authored by Karishma Chadha's avatar Karishma Chadha
Browse files

Restore deleted sprite.

parent 976e3b9b
No related branches found
No related tags found
No related merge requests found
......@@ -172,3 +172,7 @@
width: 0.5rem;
height: 0.5rem;
}
.disabled {
opacity: 0.5;
}
......@@ -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
......
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,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));
}
});
......
......@@ -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,
......
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
};
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