Skip to content

Commit c0549f0

Browse files
committed
Discourage copying code with a message
1 parent fd818eb commit c0549f0

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

frontend/src/App.js

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,17 @@ import "./css/main.scss"
55
import "./css/pygments.css"
66
import "./css/github-markdown.css"
77
import {connect} from "react-redux";
8-
import {bookSetState, bookState, closeMessage, movePage, moveStep, ranCode, setDeveloperMode, stepIndex} from "./book/store";
8+
import {
9+
addMessage,
10+
bookSetState,
11+
bookState,
12+
closeMessage,
13+
movePage,
14+
moveStep,
15+
ranCode,
16+
setDeveloperMode,
17+
stepIndex
18+
} from "./book/store";
919
import Popup from "reactjs-popup";
1020
import AceEditor from "react-ace";
1121
import "ace-builds/src-noconflict/mode-python";
@@ -91,7 +101,8 @@ class AppComponent extends React.Component {
91101
const showBirdseye = page_index >= _.findIndex(pages, {slug: "IntroducingBirdseye"});
92102

93103
return <div className="book-container">
94-
<div className="book-text markdown-body">
104+
<div className="book-text markdown-body"
105+
onCopy={checkCopy}>
95106
<h1 dangerouslySetInnerHTML={{__html: page.title}}/>
96107
{page.steps.slice(0, step_index + 1).map((part, index) =>
97108
<div key={index} id={`step-text-${index}`}>
@@ -313,6 +324,37 @@ const SettingsModal = ({user}) => (
313324
</div>
314325
)
315326

327+
const checkCopy = () => {
328+
const selection = document.getSelection();
329+
const codeElement = (node) => node.parentElement.closest("code");
330+
if (
331+
[...document.querySelectorAll(".book-text code")]
332+
.filter(node => selection.containsNode(node))
333+
.concat([
334+
codeElement(selection.anchorNode),
335+
codeElement(selection.focusNode),
336+
])
337+
.some((node) => node && !node.classList.contains("copyable"))
338+
) {
339+
addMessage(`
340+
<div>
341+
<p><strong>STOP!</strong></p>
342+
<p>
343+
Try to avoid copy pasting code. You will learn, absorb, and remember better if you
344+
type in the code yourself.
345+
</p>
346+
<p>
347+
When copying is appropriate, there will be a button to click to make it easy.
348+
If there's no button, try typing.
349+
</p>
350+
<p>
351+
Having said that, we're not going to force you. Copy if you really want to.
352+
</p>
353+
</div>
354+
`);
355+
}
356+
}
357+
316358

317359
export const App = connect(
318360
state => ({

frontend/src/book/store.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,15 +119,25 @@ export const ranCode = makeAction(
119119
processing: false,
120120
};
121121
}
122-
if (value.message && state.pastMessages.indexOf(value.message) === -1) {
123-
animateScroll.scrollToBottom({duration: 1000, delay: 500});
124-
state = ipush(state, "messages", value.message);
125-
state = ipush(state, "pastMessages", value.message);
126-
}
122+
state = addMessageToState(state, value.message);
127123
return state;
128124
},
129125
);
130126

127+
const addMessageToState = (state, message) => {
128+
if (message && state.pastMessages.indexOf(message) === -1) {
129+
animateScroll.scrollToBottom({duration: 1000, delay: 500});
130+
state = ipush(state, "messages", message);
131+
state = ipush(state, "pastMessages", message);
132+
}
133+
return state;
134+
}
135+
136+
export const addMessage = makeAction(
137+
'ADD_MESSAGE',
138+
(state, {value}) => addMessageToState(state, value)
139+
)
140+
131141
export const closeMessage = makeAction(
132142
'CLOSE_MESSAGE',
133143
(state, {value}) => iremove(state, "messages", value)

0 commit comments

Comments
 (0)