feat: Code saveing to localStorage on Cmd/Ctrl + S (#38324)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com> Co-authored-by: mrugesh <1884376+raisedadead@users.noreply.github.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
||||
canFocusEditorSelector,
|
||||
executeChallenge,
|
||||
inAccessibilityModeSelector,
|
||||
saveEditorContent,
|
||||
setEditorFocusability,
|
||||
setAccessibilityMode,
|
||||
updateFile
|
||||
@@ -25,6 +26,7 @@ const propTypes = {
|
||||
ext: PropTypes.string,
|
||||
fileKey: PropTypes.string,
|
||||
inAccessibilityMode: PropTypes.bool.isRequired,
|
||||
saveEditorContent: PropTypes.func.isRequired,
|
||||
setAccessibilityMode: PropTypes.func.isRequired,
|
||||
setEditorFocusability: PropTypes.func,
|
||||
theme: PropTypes.string,
|
||||
@@ -44,9 +46,10 @@ const mapStateToProps = createSelector(
|
||||
);
|
||||
|
||||
const mapDispatchToProps = {
|
||||
setEditorFocusability,
|
||||
setAccessibilityMode,
|
||||
executeChallenge,
|
||||
saveEditorContent,
|
||||
setAccessibilityMode,
|
||||
setEditorFocusability,
|
||||
updateFile
|
||||
};
|
||||
|
||||
@@ -150,6 +153,14 @@ class Editor extends Component {
|
||||
this.props.setEditorFocusability(false);
|
||||
}
|
||||
});
|
||||
this._editor.addAction({
|
||||
id: 'save-editor-content',
|
||||
label: 'Save editor content to localStorage',
|
||||
keybindings: [
|
||||
monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S)
|
||||
],
|
||||
run: this.props.saveEditorContent
|
||||
});
|
||||
this._editor.addAction({
|
||||
id: 'toggle-accessibility',
|
||||
label: 'Toggle Accessibility Mode',
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { of } from 'rxjs';
|
||||
import { filter, switchMap, tap, ignoreElements } from 'rxjs/operators';
|
||||
import { filter, switchMap, map, tap, ignoreElements } from 'rxjs/operators';
|
||||
import { combineEpics, ofType } from 'redux-observable';
|
||||
import store from 'store';
|
||||
|
||||
@@ -16,6 +16,8 @@ import { types as appTypes } from '../../../redux';
|
||||
|
||||
import { setContent, isPoly } from '../utils/polyvinyl';
|
||||
|
||||
import { createFlashMessage } from '../../../components/Flash/redux';
|
||||
|
||||
const legacyPrefixes = [
|
||||
'Bonfire: ',
|
||||
'Waypoint: ',
|
||||
@@ -73,16 +75,38 @@ function clearCodeEpic(action$, state$) {
|
||||
|
||||
function saveCodeEpic(action$, state$) {
|
||||
return action$.pipe(
|
||||
ofType(types.executeChallenge),
|
||||
ofType(types.executeChallenge, types.saveEditorContent),
|
||||
// do not save challenge if code is locked
|
||||
filter(() => !isCodeLockedSelector(state$.value)),
|
||||
tap(() => {
|
||||
map(action => {
|
||||
const state = state$.value;
|
||||
const { id } = challengeMetaSelector(state);
|
||||
const files = challengeFilesSelector(state);
|
||||
try {
|
||||
store.set(id, files);
|
||||
// Possible fileType values: indexhtml indexjs indexjsx
|
||||
// The files Object always has one of these as the first/only attribute
|
||||
const fileType = Object.keys(files)[0];
|
||||
if (store.get(id)[fileType].contents !== files[fileType].contents) {
|
||||
throw Error('Failed to save to localStorage');
|
||||
}
|
||||
return action;
|
||||
} catch (e) {
|
||||
return { ...action, error: true };
|
||||
}
|
||||
}),
|
||||
ignoreElements()
|
||||
ofType(types.saveEditorContent),
|
||||
switchMap(({ error }) =>
|
||||
of(
|
||||
createFlashMessage({
|
||||
type: error ? 'warning' : 'success',
|
||||
message: error
|
||||
? // eslint-disable-next-line max-len
|
||||
"Oops, your code did not save, your browser's local storage may be full."
|
||||
: "Saved! Your code was saved to your browser's local storage."
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -70,6 +70,7 @@ export const types = createTypes(
|
||||
'disableBuildOnError',
|
||||
'storedCodeFound',
|
||||
'noStoredCodeFound',
|
||||
'saveEditorContent',
|
||||
|
||||
'closeModal',
|
||||
'openModal',
|
||||
@@ -147,6 +148,7 @@ export const unlockCode = createAction(types.unlockCode);
|
||||
export const disableBuildOnError = createAction(types.disableBuildOnError);
|
||||
export const storedCodeFound = createAction(types.storedCodeFound);
|
||||
export const noStoredCodeFound = createAction(types.noStoredCodeFound);
|
||||
export const saveEditorContent = createAction(types.saveEditorContent);
|
||||
|
||||
export const closeModal = createAction(types.closeModal);
|
||||
export const openModal = createAction(types.openModal);
|
||||
|
Reference in New Issue
Block a user