diff --git a/client/src/Editor.tsx b/client/src/Editor.tsx
index beae1f61..6219fa26 100644
--- a/client/src/Editor.tsx
+++ b/client/src/Editor.tsx
@@ -29,8 +29,8 @@ const Editor: React.FC<{setRestart?, onDidChangeContent?, value: string, theme:
const [restartMessage, setRestartMessage] = useState(false)
useEffect(() => {
- if (theme == 'lightPlus') {
- monaco.editor.setTheme('lightPlus')
+ if (['lightPlus', 'custom'].includes(theme)) {
+ monaco.editor.setTheme(theme)
} else {
//monaco.editor.setTheme(theme)
fetch(`./themes/${theme}.json`,{
diff --git a/client/src/Settings.tsx b/client/src/Settings.tsx
index dec255d1..f604ed82 100644
--- a/client/src/Settings.tsx
+++ b/client/src/Settings.tsx
@@ -6,7 +6,8 @@ import { useEffect } from 'react'
import Switch from '@mui/material/Switch';
import Select from '@mui/material/Select';
import { useWindowDimensions } from './window_width';
-import { FormControl, InputLabel, MenuItem } from '@mui/material';
+import { Button, FormControl, InputLabel, MenuItem } from '@mui/material';
+import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
const Settings: React.FC<{closeNav, theme, setTheme}> =
({closeNav, theme, setTheme}) => {
@@ -22,6 +23,7 @@ const Settings: React.FC<{closeNav, theme, setTheme}> =
If screen width is below 800, default to vertical layout instead. */
const {width, height} = useWindowDimensions()
const [verticalLayout, setVerticalLayout] = React.useState(width < 800)
+ const [customTheme, setCustomTheme] = React.useState('initial')
// Synchronize state with initial local store
useEffect(() => {
@@ -29,6 +31,7 @@ const Settings: React.FC<{closeNav, theme, setTheme}> =
let _verticalLayout = window.localStorage.getItem("verticalLayout")
let _theme = window.localStorage.getItem("theme")
let _savingAllowed = window.localStorage.getItem("savingAllowed")
+ let _customTheme = window.localStorage.getItem("customTheme")
if (_abbreviationCharacter) {
setAbbreviationCharacter(_abbreviationCharacter)
setSavingAllowed(true)
@@ -41,7 +44,18 @@ const Settings: React.FC<{closeNav, theme, setTheme}> =
setTheme(_theme)
setSavingAllowed(true)
}
-
+ if (_customTheme) {
+ setCustomTheme(_customTheme)
+ setSavingAllowed(true)
+ try {
+ var loadedTheme = JSON.parse(_customTheme)
+ monaco.editor.defineTheme('custom', loadedTheme)
+ } catch (error) {
+ // invalid custom theme
+ setCustomTheme('')
+ if (_theme == 'custom') {setTheme('lightPlus')}
+ }
+ }
}, [])
/** Synchronize config and local store whenever there is a change to any of the config
@@ -55,10 +69,12 @@ const Settings: React.FC<{closeNav, theme, setTheme}> =
window.localStorage.setItem("abbreviationCharacter", abbreviationCharacter)
window.localStorage.setItem("verticalLayout", verticalLayout ? 'true' : 'false')
window.localStorage.setItem("theme", theme)
+ window.localStorage.setItem("customTheme", customTheme)
} else {
window.localStorage.removeItem("abbreviationCharacter")
window.localStorage.removeItem("verticalLayout")
window.localStorage.removeItem("theme")
+ window.localStorage.removeItem("customTheme")
}
}, [savingAllowed, abbreviationCharacter, verticalLayout, theme])
@@ -75,6 +91,26 @@ const Settings: React.FC<{closeNav, theme, setTheme}> =
// ev.stopPropagation()
}
+ /** Load a custom monaco theme, store it in local storage and activate it */
+ function uploadTheme(ev) {
+ const fileToLoad = ev.target.files[0]
+ var fileReader = new FileReader()
+ fileReader.onload = (fileLoadedEvent) => {
+ var loadedThemeRaw = fileLoadedEvent.target.result as string
+ window.localStorage.setItem("customTheme", loadedThemeRaw)
+ try {
+ var loadedTheme = JSON.parse(loadedThemeRaw)
+ } catch (error) {
+ return
+ }
+ setTheme('custom')
+ setCustomTheme(loadedThemeRaw)
+ monaco.editor.defineTheme('custom', loadedTheme)
+ monaco.editor.setTheme('custom')
+ }
+ fileReader.readAsText(fileToLoad, "UTF-8")
+ }
+
return <>
Settings
@@ -91,7 +127,7 @@ const Settings: React.FC<{closeNav, theme, setTheme}> =
{setAbbreviationCharacter(ev.target.value)}} value={abbreviationCharacter} />
-
+
+
+
+
+
+ {/* */}
diff --git a/client/src/config/config.ts b/client/src/config/config.ts
index 8b625223..fd9a3773 100644
--- a/client/src/config/config.ts
+++ b/client/src/config/config.ts
@@ -7,5 +7,6 @@ export const config = {
'inputModeCustomTranslations': {},
'eagerReplacementEnabled': true,
'verticalLayout': false, // value here irrelevant, will be overwritten with `width < 800` in Settings.tsx
- 'theme': 'light', // options: light, dark
+ 'theme': 'lightPlus',
+ 'customTheme': '',
}
diff --git a/client/src/css/Modal.css b/client/src/css/Modal.css
index b662bfa4..7fa86a46 100644
--- a/client/src/css/Modal.css
+++ b/client/src/css/Modal.css
@@ -52,10 +52,6 @@ input[type="file"] {
width: 100%;
}
-.modal select {
- float: right;
-}
-
.modal textarea {
height: 10em;
}
@@ -65,17 +61,30 @@ input[type="file"] {
font-weight: bold;
}
-.modal input[type="submit"] {
+.modal input[type="submit"], .modal .file-upload-button {
border: none;
color: var(--vscode-button-foreground);
background: var(--vscode-button-background);
cursor: pointer;
padding: .5rem 1rem;
border-radius: .2rem;
+}
+
+.modal input[type="submit"]{
display: block;
margin: 1rem auto;
}
+.modal .flex {
+ display: flex;
+ justify-content: space-between;
+}
+
+.modal .flex label {
+ margin-top: auto;
+ margin-bottom: auto;
+}
+
.modal-close {
float: right;
scale: 2;