diff --git a/packages/xod-client-electron/src/debugger/middleware.js b/packages/xod-client-electron/src/debugger/middleware.js index 9af944be..0beefa19 100644 --- a/packages/xod-client-electron/src/debugger/middleware.js +++ b/packages/xod-client-electron/src/debugger/middleware.js @@ -1,10 +1,7 @@ import client from 'xod-client'; import { ipcRenderer } from 'electron'; import { sendStopDebuggerSession } from './ipcActions'; -import { - DEBUG_SESSION_STOPPED_ON_CHANGE, - DEBUG_SESSION_STOPPED_ON_TAB_CLOSE, -} from '../shared/messages'; +import { DEBUG_SESSION_STOPPED_ON_TAB_CLOSE } from '../shared/messages'; export default store => next => action => { const state = store.getState(); @@ -16,8 +13,7 @@ export default store => next => action => { // Stop debug session if something changed in the Project if (isDebugSession && prevProject !== newProject) { - sendStopDebuggerSession(ipcRenderer); - store.dispatch(client.addError(DEBUG_SESSION_STOPPED_ON_CHANGE)); + store.dispatch(client.markDebugSessionOutdated()); } // Stop debug session if Debugger tab is closed diff --git a/packages/xod-client-electron/src/shared/messages.js b/packages/xod-client-electron/src/shared/messages.js index 4d590e0d..8f480855 100644 --- a/packages/xod-client-electron/src/shared/messages.js +++ b/packages/xod-client-electron/src/shared/messages.js @@ -20,11 +20,6 @@ export const SAVE_ALL_SUCCEED = { title: 'Saved successfully!', }; -export const DEBUG_SESSION_STOPPED_ON_CHANGE = { - title: 'Debug session stopped', - note: 'Your project has been changed.', - persistent: false, -}; export const DEBUG_SESSION_STOPPED_ON_TAB_CLOSE = { title: 'Debug session stopped', note: 'You closed the debugger tab.', diff --git a/packages/xod-client/src/core/styles/components/Debugger.scss b/packages/xod-client/src/core/styles/components/Debugger.scss index ce0fa9fb..b320d4ce 100644 --- a/packages/xod-client/src/core/styles/components/Debugger.scss +++ b/packages/xod-client/src/core/styles/components/Debugger.scss @@ -7,6 +7,17 @@ } } +.debugging-outdated { + color: $apricot-light; + font-family: $font-family-normal; + font-size: $font-size-m; + padding: 12px; + + span { + margin-left: .25em; + } +} + .Debugger { bottom: 0; height: 220px; diff --git a/packages/xod-client/src/debugger/actionTypes.js b/packages/xod-client/src/debugger/actionTypes.js index f2358ad6..5863ae15 100644 --- a/packages/xod-client/src/debugger/actionTypes.js +++ b/packages/xod-client/src/debugger/actionTypes.js @@ -9,3 +9,5 @@ export const DEBUG_SESSION_STARTED = 'DEBUG_SESSION_STARTED'; export const DEBUG_SESSION_STOPPED = 'DEBUG_SESSION_STOPPED'; export const DEBUG_DRILL_DOWN = 'DEBUG_DRILL_DOWN'; + +export const MARK_DEBUG_SESSION_OUTDATED = 'MARK_DEBUG_SESSION_OUTDATED'; diff --git a/packages/xod-client/src/debugger/actions.js b/packages/xod-client/src/debugger/actions.js index bc86c8ca..9ca75901 100644 --- a/packages/xod-client/src/debugger/actions.js +++ b/packages/xod-client/src/debugger/actions.js @@ -40,3 +40,7 @@ export const drillDown = (patchPath, nodeId) => ({ nodeId, }, }); + +export const markDebugSessionOutdated = () => ({ + type: AT.MARK_DEBUG_SESSION_OUTDATED, +}); diff --git a/packages/xod-client/src/debugger/reducer.js b/packages/xod-client/src/debugger/reducer.js index da2449b2..8f9c3fca 100644 --- a/packages/xod-client/src/debugger/reducer.js +++ b/packages/xod-client/src/debugger/reducer.js @@ -8,6 +8,7 @@ import { DEBUGGER_LOG_CLEAR, DEBUG_SESSION_STARTED, DEBUG_SESSION_STOPPED, + MARK_DEBUG_SESSION_OUTDATED, } from './actionTypes'; import { UPLOAD_STATUS, UPLOAD_MSG_TYPE } from './constants'; @@ -137,6 +138,7 @@ export default (state = initialState, action) => { addMessageToLog(action.payload.message), R.assoc('nodeIdsMap', invertMap(action.payload.nodeIdsMap)), R.assoc('isRunning', true), + R.assoc('isOutdated', false), showDebuggerPane )(state); case DEBUG_SESSION_STOPPED: @@ -146,6 +148,8 @@ export default (state = initialState, action) => { R.assoc('nodeIdsMap', {}), R.assoc('isRunning', false) )(state); + case MARK_DEBUG_SESSION_OUTDATED: + return R.assoc('isOutdated', true, state); default: return state; } diff --git a/packages/xod-client/src/debugger/selectors.js b/packages/xod-client/src/debugger/selectors.js index ed9a0e2f..af34db5b 100644 --- a/packages/xod-client/src/debugger/selectors.js +++ b/packages/xod-client/src/debugger/selectors.js @@ -18,6 +18,11 @@ export const isDebuggerVisible = R.compose( getDebuggerState ); +export const isDebugSessionOutdated = R.compose( + R.prop('isOutdated'), + getDebuggerState +); + export const getLog = R.compose(R.prop('log'), getDebuggerState); export const getUploadLog = R.compose(R.prop('uploadLog'), getDebuggerState); diff --git a/packages/xod-client/src/debugger/state.js b/packages/xod-client/src/debugger/state.js index 3e7a7806..967bafac 100644 --- a/packages/xod-client/src/debugger/state.js +++ b/packages/xod-client/src/debugger/state.js @@ -4,6 +4,7 @@ import { INTRODUCTION } from './messages'; export default { isVisible: false, isRunning: false, + isOutdated: false, log: [], uploadLog: [createSystemMessage(INTRODUCTION)], nodeIdsMap: {}, diff --git a/packages/xod-client/src/editor/containers/Editor.jsx b/packages/xod-client/src/editor/containers/Editor.jsx index 9707d97f..baf1e733 100644 --- a/packages/xod-client/src/editor/containers/Editor.jsx +++ b/packages/xod-client/src/editor/containers/Editor.jsx @@ -43,6 +43,7 @@ import SnackBar from '../../messages/containers/SnackBar'; import Helpbox from './Helpbox'; import Tooltip from '../../tooltip/components/Tooltip'; +import TooltipHOC from '../../tooltip/components/TooltipHOC'; import Tabs from './Tabs'; import DragLayer from './DragLayer'; @@ -225,11 +226,37 @@ class Editor extends React.Component { /> ) : null; + const renderProgramChangedWarning = () => + this.props.isDebugSessionOutdated ? ( + + The program on screen is newer than the program running on the + board.
+ Watches and overall behavior can be incorrect. Stop debugging and + upload again to synchronize. + + } + render={(onMouseOver, onMouseMove, onMouseLeave) => ( +
+ Program changed + +
+ )} + /> + ) : null; + const debuggerBreadcrumbs = foldMaybe( null, tab => tab.id === DEBUGGER_TAB_ID && this.props.isDebugSessionRunning ? ( + {renderProgramChangedWarning()}