From fb29e5a7c8e5dc30633f0aa95c99f77bc1a7435f Mon Sep 17 00:00:00 2001 From: Anthony Laibe Date: Thu, 18 Oct 2018 11:09:03 +0100 Subject: [PATCH] Add/remove breakpoints --- embark-ui/src/actions/index.js | 8 +++++ embark-ui/src/components/TextEditor.js | 32 ++++++++++++++++++- .../src/containers/TextEditorContainer.js | 22 +++++++++---- embark-ui/src/reducers/index.js | 21 ++++++++++-- embark-ui/src/reducers/selectors.js | 4 +++ 5 files changed, 76 insertions(+), 11 deletions(-) diff --git a/embark-ui/src/actions/index.js b/embark-ui/src/actions/index.js index d272a8dd3..366a617fc 100644 --- a/embark-ui/src/actions/index.js +++ b/embark-ui/src/actions/index.js @@ -399,4 +399,12 @@ export function updateBaseEther(value) { }; } +export const TOGGLE_BREAKPOINT = 'TOGGLE_BREAKPOINT'; +export function toggleBreakpoint(filename, lineNumber) { + return { + type: TOGGLE_BREAKPOINT, + payload: {filename, lineNumber} + }; +} + diff --git a/embark-ui/src/components/TextEditor.js b/embark-ui/src/components/TextEditor.js index 56ef9ea22..8d2c26cc1 100644 --- a/embark-ui/src/components/TextEditor.js +++ b/embark-ui/src/components/TextEditor.js @@ -5,6 +5,7 @@ import PropTypes from 'prop-types'; const SUPPORTED_LANGUAGES = ['css', 'sol', 'html', 'json']; const DEFAULT_LANGUAGE = 'javascript'; const EDITOR_ID = 'react-monaco-editor-container'; +const GUTTER_GLYPH_MARGIN = 3; let editor; @@ -14,6 +15,7 @@ const initMonaco = (value) => { model = editor.getModel() } editor = monaco.editor.create(document.getElementById(EDITOR_ID), { + glyphMargin: true, value, model }); @@ -21,6 +23,10 @@ const initMonaco = (value) => { }; class TextEditor extends React.Component { + constructor(props) { + super(props); + this.state = {decorations: []}; + } componentDidMount() { initMonaco(); editor.onDidChangeModelContent((event) => { @@ -29,6 +35,12 @@ class TextEditor extends React.Component { }); editor.layout(); window.addEventListener('resize', this.handleResize); + + editor.onMouseDown((e) => { + if (e.target.type === GUTTER_GLYPH_MARGIN){ + this.props.toggleBreakpoint(this.props.file.name, e.target.position.lineNumber); + } + }); } handleResize = () => editor.layout(); @@ -71,12 +83,28 @@ class TextEditor extends React.Component { } } + updateBreakpoints() { + const decorations = editor.deltaDecorations(this.state.decorations, this.props.breakpoints.map(breakpoint => ( + { + range: new monaco.Range(breakpoint,1,breakpoint,1), + options: { + isWholeLine: true, + glyphMarginClassName: 'bg-primary rounded-circle' + } + } + ))); + this.setState({decorations: decorations}); + } + componentDidUpdate(prevProps) { if (this.props.file.content !== prevProps.file.content) { editor.setValue(this.props.file.content); } this.updateMarkers(); + if (this.props.breakpoints.length !== this.state.decorations.length) { + this.updateBreakpoints(); + } this.updateLanguage(); } @@ -92,7 +120,9 @@ class TextEditor extends React.Component { TextEditor.propTypes = { onFileContentChange: PropTypes.func, file: PropTypes.object, - contractCompile: PropTypes.object + contractCompile: PropTypes.object, + toggleBreakpoint: PropTypes.func, + breakpoints: PropTypes.array }; export default TextEditor; \ No newline at end of file diff --git a/embark-ui/src/containers/TextEditorContainer.js b/embark-ui/src/containers/TextEditorContainer.js index feca915a4..2e76e84f9 100644 --- a/embark-ui/src/containers/TextEditorContainer.js +++ b/embark-ui/src/containers/TextEditorContainer.js @@ -13,9 +13,10 @@ import { saveFile as saveFileAction, removeFile as removeFileAction, contractCompile as contractCompileAction, - contractDeploy as postContractDeploy + contractDeploy as postContractDeploy, + toggleBreakpoint, } from '../actions'; -import {getCurrentFile, getContractCompile, getContractDeploys} from '../reducers/selectors'; +import {getCurrentFile, getContractCompile, getContractDeploys, getBreakpointsByFilename} from '../reducers/selectors'; class TextEditorContainer extends Component { constructor(props) { @@ -100,6 +101,8 @@ class TextEditorContainer extends Component { return ( this.onFileContentChange(newContent)} /> ); } @@ -110,13 +113,15 @@ function mapStateToProps(state, props) { const contractCompile = getContractCompile(state, currentFile) || {}; const contractName = contractCompile.result && Object.keys(contractCompile.result)[0]; const contractDeploys = getContractDeploys(state, contractName); + const breakpoints = getBreakpointsByFilename(state, currentFile.name); return { + compilingContract: state.compilingContract, + loading: state.loading, + error: state.errorMessage, currentFile, contractCompile, - compilingContract: state.compilingContract, contractDeploys, - loading: state.loading, - error: state.errorMessage + breakpoints, }; } @@ -133,7 +138,9 @@ TextEditorContainer.propTypes = { compilingContract: PropTypes.bool, contractDeploys: PropTypes.array, loading: PropTypes.bool, - error: PropTypes.string + error: PropTypes.string, + toggleBreakpoints: PropTypes.func, + breakpoints: PropTypes.array, }; export default connect( @@ -144,6 +151,7 @@ export default connect( saveFile: saveFileAction.request, removeFile: removeFileAction.request, postContractDeploy: postContractDeploy.post, - compileContract: contractCompileAction.post + compileContract: contractCompileAction.post, + toggleBreakpoint, }, )(TextEditorContainer); diff --git a/embark-ui/src/reducers/index.js b/embark-ui/src/reducers/index.js index c3844eef9..e74ff5259 100644 --- a/embark-ui/src/reducers/index.js +++ b/embark-ui/src/reducers/index.js @@ -1,7 +1,7 @@ import {combineReducers} from 'redux'; import {REQUEST, SUCCESS, FAILURE, CONTRACT_COMPILE, FILES, LOGOUT, AUTHENTICATE, FETCH_CREDENTIALS, UPDATE_BASE_ETHER, CHANGE_THEME, FETCH_THEME, EXPLORER_SEARCH, - SIGN_MESSAGE, VERIFY_MESSAGE} from "../actions"; + SIGN_MESSAGE, VERIFY_MESSAGE, TOGGLE_BREAKPOINT} from "../actions"; import {EMBARK_PROCESS_NAME, DARK_THEME} from '../constants'; const BN_FACTOR = 10000; @@ -281,7 +281,6 @@ const DEFAULT_MESSAGE_VERIFICATION_STATE = { }; function messageVerification(state = DEFAULT_MESSAGE_VERIFICATION_STATE, action) { - if (action.type === VERIFY_MESSAGE[REQUEST]) { return {...state, pending: true, error: null, payload: null }; } @@ -302,6 +301,21 @@ function messageVerification(state = DEFAULT_MESSAGE_VERIFICATION_STATE, action) return state; } +function breakpoints(state = {}, action) { + if (action.type === TOGGLE_BREAKPOINT) { + const {filename, lineNumber} = action.payload; + let lineNumbers = state[filename] || []; + if (lineNumbers.includes(lineNumber)){ + lineNumbers = lineNumbers.filter(ln => ln !== lineNumber); + } else { + lineNumbers.push(lineNumber); + } + return {...state, [filename]: lineNumbers}; + } + + return state; +} + const rootReducer = combineReducers({ entities, loading, @@ -313,7 +327,8 @@ const rootReducer = combineReducers({ theme, searchResult, messageSignature, - messageVerification + messageVerification, + breakpoints }); export default rootReducer; diff --git a/embark-ui/src/reducers/selectors.js b/embark-ui/src/reducers/selectors.js index 57167c39b..5e4f3ed11 100644 --- a/embark-ui/src/reducers/selectors.js +++ b/embark-ui/src/reducers/selectors.js @@ -204,3 +204,7 @@ export function getVerifiedAddressPayload(state) { export function getVerificationError(state) { return state.messageVerification.error; } + +export function getBreakpointsByFilename(state, filename) { + return state.breakpoints[filename] || []; +}