Skip to content

Commit 11e725e

Browse files
authored
Add Ctrl + S shortcut to save file (#68)
* Add Ctrl+S shortcut to save file * Add case insensitivity for 's' * Save file on keyup, not keydown
1 parent c876f47 commit 11e725e

File tree

3 files changed

+33
-7
lines changed

3 files changed

+33
-7
lines changed

client/src/App.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useRef, useState } from 'react'
1+
import { useCallback, useEffect, useRef, useState } from 'react'
22
import Split from 'react-split'
33
import * as monaco from 'monaco-editor'
44
import CodeMirror, { EditorView } from '@uiw/react-codemirror'
@@ -14,6 +14,7 @@ import defaultSettings, { IPreferencesContext, lightThemes, preferenceParams } f
1414
import { Menu } from './Navigation'
1515
import { PreferencesContext } from './Popups/Settings'
1616
import { Entries } from './utils/Entries'
17+
import { save } from './utils/SaveToFile'
1718
import { fixedEncodeURIComponent, formatArgs, lookupUrl, parseArgs } from './utils/UrlParsing'
1819
import { useWindowDimensions } from './utils/WindowWidth'
1920

@@ -377,6 +378,30 @@ function App() {
377378
}
378379
}, [])
379380

381+
// Stop the browser's save dialog on Ctrl+S
382+
const handleKeyDown = useCallback((event: KeyboardEvent) => {
383+
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') {
384+
event.preventDefault()
385+
}
386+
}, [])
387+
388+
// Actually save the file on Ctrl+S
389+
const handleKeyUp = useCallback((event: KeyboardEvent) => {
390+
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 's') {
391+
event.preventDefault()
392+
save(code)
393+
}
394+
}, [code])
395+
396+
useEffect(() => {
397+
document.addEventListener('keydown', handleKeyDown)
398+
document.addEventListener('keyup', handleKeyUp)
399+
return () => {
400+
document.removeEventListener('keydown', handleKeyDown)
401+
document.removeEventListener('keyup', handleKeyUp)
402+
}
403+
}, [handleKeyDown, handleKeyUp])
404+
380405
return <PreferencesContext.Provider value={{preferences, setPreferences}}>
381406
<div className="app monaco-editor">
382407
<nav>

client/src/Navigation.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
33
import { IconDefinition, faArrowRotateRight, faCode, faInfoCircle } from '@fortawesome/free-solid-svg-icons'
44
import ZulipIcon from './assets/zulip.svg'
55
import { faArrowUpRightFromSquare, faDownload, faBars, faXmark, faShield, faHammer, faGear, faStar, faUpload, faCloudArrowUp } from '@fortawesome/free-solid-svg-icons'
6-
import { saveAs } from 'file-saver'
76

87
import SettingsPopup, { PreferencesContext } from './Popups/Settings'
98
import PrivacyPopup from './Popups/PrivacyPolicy'
@@ -15,6 +14,7 @@ import LoadZulipPopup from './Popups/LoadZulip'
1514
import lean4webConfig from './config/config'
1615
import './css/Modal.css'
1716
import './css/Navigation.css'
17+
import { save } from './utils/SaveToFile'
1818
import { lookupUrl } from './utils/UrlParsing'
1919

2020
/** A button to appear in the hamburger menu or to navigation bar. */
@@ -71,11 +71,6 @@ export const Popup: FC<{
7171
</div>
7272
}
7373

74-
const save = (content: string) => {
75-
var blob = new Blob([content], {type: "text/plain;charset=utf-8"});
76-
saveAs(blob, "Lean4WebDownload.lean");
77-
}
78-
7974
/** The menu items either appearing inside the dropdown or outside */
8075
const FlexibleMenu: FC <{
8176
isInDropdown: boolean,

client/src/utils/SaveToFile.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import saveAs from 'file-saver';
2+
3+
export const save = (content: string) => {
4+
var blob = new Blob([content], {type: "text/plain;charset=utf-8"});
5+
saveAs(blob, "Lean4WebDownload.lean");
6+
}

0 commit comments

Comments
 (0)