@@ -10,9 +10,8 @@ import * as path from 'path'
1010
1111// Local imports
1212import LeanLogo from './assets/logo.svg'
13- import defaultSettings , { IPreferencesContext , lightThemes , preferenceParams } from './config /settings'
13+ import { lightThemes } from './settings /settings-types '
1414import { Menu } from './Navigation'
15- import { PreferencesContext } from './Popups/Settings'
1615import { Entries } from './utils/Entries'
1716import { save } from './utils/SaveToFile'
1817import { fixedEncodeURIComponent , formatArgs , lookupUrl , parseArgs } from './utils/UrlParsing'
@@ -21,6 +20,9 @@ import { useWindowDimensions } from './utils/WindowWidth'
2120// CSS
2221import './css/App.css'
2322import './css/Editor.css'
23+ import { mobileAtom , settingsAtom } from './settings/settings-atoms'
24+ import { useAtom } from 'jotai/react'
25+ import { screenWidthAtom } from './store/window-atoms'
2426
2527/** Returns true if the browser wants dark mode */
2628function isBrowserDefaultDark ( ) {
@@ -33,8 +35,9 @@ function App() {
3335 const [ dragging , setDragging ] = useState < boolean | null > ( false )
3436 const [ editor , setEditor ] = useState < monaco . editor . IStandaloneCodeEditor > ( )
3537 const [ leanMonaco , setLeanMonaco ] = useState < LeanMonaco > ( )
36- const [ loaded , setLoaded ] = useState < boolean > ( false )
37- const [ preferences , setPreferences ] = useState < IPreferencesContext > ( defaultSettings )
38+ const [ settings ] = useAtom ( settingsAtom )
39+ const [ mobile ] = useAtom ( mobileAtom )
40+ const [ , setScreenWidth ] = useAtom ( screenWidthAtom )
3841 const { width } = useWindowDimensions ( )
3942
4043 // Lean4monaco options
@@ -83,67 +86,13 @@ function App() {
8386 setProject ( project )
8487 } , [ ] )
8588
86- // Load preferences from store in the beginning
89+ // save the screen width in jotai
8790 useEffect ( ( ) => {
88- // only load them once
89- if ( loaded ) { return }
90- console . debug ( '[Lean4web] Loading preferences' )
91-
92- let saveInLocalStore = false ;
93- let newPreferences : { [ K in keyof IPreferencesContext ] : IPreferencesContext [ K ] } = { ...preferences }
94- for ( const [ key , value ] of ( Object . entries ( preferences ) as Entries < IPreferencesContext > ) ) {
95- // prefer URL params over stored
96- const searchParams = new URLSearchParams ( window . location . search ) ;
97- let storedValue = (
98- preferenceParams . includes ( key ) && // only for keys we explictly check for
99- searchParams . has ( key ) && searchParams . get ( key ) )
100- ?? window . localStorage . getItem ( key )
101- if ( storedValue ) {
102- saveInLocalStore = window . localStorage . getItem ( key ) === storedValue
103- console . debug ( `[Lean4web] Found value for ${ key } : ${ storedValue } ` )
104- if ( typeof value === 'string' ) {
105- if ( key == 'theme' ) {
106- const theme = storedValue . toLowerCase ( ) . includes ( 'dark' ) ? "Visual Studio Dark" : "Visual Studio Light"
107- newPreferences [ key ] = theme
108- }
109- else {
110- newPreferences [ key ] = storedValue
111- }
112- } else if ( typeof value === 'boolean' ) {
113- newPreferences [ key ] = ( storedValue === "true" )
114- } else {
115- // other values aren't implemented yet.
116- console . error ( `[Lean4web] Preferences (key: ${ key } ) contain a value of unsupported type: ${ typeof value } ` )
117- }
118- } else {
119- // no stored preferences, set a default value
120- if ( key == 'theme' ) {
121- if ( isBrowserDefaultDark ( ) ) {
122- console . debug ( "[Lean4web] Preferences: Set dark theme." )
123- newPreferences [ 'theme' ] = 'Visual Studio Dark'
124- } else {
125- console . debug ( "[Lean4web] Preferences: Set light theme." )
126- newPreferences [ 'theme' ] = 'Visual Studio Light'
127- }
128- }
129- }
130- }
131- newPreferences [ 'saveInLocalStore' ] = saveInLocalStore
132- setPreferences ( newPreferences )
133- setLoaded ( true )
134- } , [ ] )
135-
136- // Use the window width to switch between mobile/desktop layout
137- useEffect ( ( ) => {
138- // Wait for preferences to be loaded
139- if ( ! loaded ) { return }
91+ const handleResize = ( ) => setScreenWidth ( window . innerWidth )
92+ window . addEventListener ( 'resize' , handleResize )
93+ return ( ) => window . removeEventListener ( 'resize' , handleResize )
94+ } , [ setScreenWidth ] )
14095
141- const _mobile = width < 800
142- const searchParams = new URLSearchParams ( window . location . search ) ;
143- if ( ! ( searchParams . has ( "mobile" ) || preferences . saveInLocalStore ) && _mobile !== preferences . mobile ) {
144- setPreferences ( { ...preferences , mobile : _mobile } )
145- }
146- } , [ width , loaded ] )
14796
14897 // Update LeanMonaco options when preferences are loaded or change
14998 useEffect ( ( ) => {
@@ -162,37 +111,36 @@ function App() {
162111 * for the desired setting, select "Copy Setting as JSON" from the "More Actions"
163112 * menu next to the selected setting, and paste the copied string here.
164113 */
165- "workbench.colorTheme" : preferences . theme ,
114+ "workbench.colorTheme" : settings . theme ,
166115 "editor.tabSize" : 2 ,
167116 // "editor.rulers": [100],
168117 "editor.lightbulb.enabled" : "on" ,
169- "editor.wordWrap" : preferences . wordWrap ? "on" : "off" ,
118+ "editor.wordWrap" : settings . wordWrap ? "on" : "off" ,
170119 "editor.wrappingStrategy" : "advanced" ,
171120 "editor.semanticHighlighting.enabled" : true ,
172- "editor.acceptSuggestionOnEnter" : preferences . acceptSuggestionOnEnter ? "on" : "off" ,
121+ "editor.acceptSuggestionOnEnter" : settings . acceptSuggestionOnEnter ? "on" : "off" ,
173122 "lean4.input.eagerReplacementEnabled" : true ,
174- "lean4.infoview.showGoalNames" : preferences . showGoalNames ,
123+ "lean4.infoview.showGoalNames" : settings . showGoalNames ,
175124 "lean4.infoview.emphasizeFirstGoal" : true ,
176125 "lean4.infoview.showExpectedType" : false ,
177126 "lean4.infoview.showTooltipOnHover" : false ,
178- "lean4.input.leader" : preferences . abbreviationCharacter
127+ "lean4.input.leader" : settings . abbreviationCharacter
179128 }
180129 }
181130 setOptions ( _options )
182- } , [ editorRef , project , preferences ] )
131+ } , [ editorRef , project , settings ] )
183132
184133 // Setting up the editor and infoview
185134 useEffect ( ( ) => {
186- // Wait for preferences to be loaded
187- if ( ! loaded ) { return }
135+ // if (project === undefined) return
188136 console . debug ( '[Lean4web] Restarting editor' )
189137 var _leanMonaco = new LeanMonaco ( )
190138 var leanMonacoEditor = new LeanMonacoEditor ( )
191139
192140 _leanMonaco . setInfoviewElement ( infoviewRef . current ! )
193141 ; ( async ( ) => {
194142 await _leanMonaco . start ( options )
195- await leanMonacoEditor . start ( editorRef . current ! , path . join ( project , `${ project } .lean` ) , code )
143+ await leanMonacoEditor . start ( editorRef . current ! , path . join ( project , `${ project } .lean` ) , code ?? '' )
196144
197145 setEditor ( leanMonacoEditor . editor )
198146 setLeanMonaco ( _leanMonaco )
@@ -201,7 +149,7 @@ function App() {
201149 // Monaco does not support clipboard pasting as all browsers block it
202150 // due to security reasons. Therefore we use a codeMirror editor overlay
203151 // which features good mobile support (but no Lean support yet)
204- if ( preferences . mobile ) {
152+ if ( mobile ) {
205153 leanMonacoEditor . editor ?. addAction ( {
206154 id : "myPaste" ,
207155 label : "Paste: open 'Plain Editor' for editing on mobile" ,
@@ -274,7 +222,7 @@ function App() {
274222 leanMonacoEditor . dispose ( )
275223 _leanMonaco . dispose ( )
276224 }
277- } , [ loaded , project , preferences , options , infoviewRef , editorRef ] )
225+ } , [ project , settings , options , infoviewRef , editorRef ] )
278226
279227 // Load content from source URL.
280228 // Once the editor is loaded, this reads the content of any provided `url=` in the URL and
@@ -330,7 +278,7 @@ function App() {
330278 code : null ,
331279 codez : null
332280 }
333- } else if ( preferences . compress ) {
281+ } else if ( settings . compress ) {
334282 // LZ padds the string with trailing `=`, which mess up the argument parsing
335283 // and aren't needed for LZ encoding, so we remove them.
336284 const compressed = LZString . compressToBase64 ( code ) . replace ( / = * $ / , '' )
@@ -402,7 +350,7 @@ function App() {
402350 }
403351 } , [ handleKeyDown , handleKeyUp ] )
404352
405- return < PreferencesContext . Provider value = { { preferences , setPreferences } } >
353+ return (
406354 < div className = "app monaco-editor" >
407355 < nav >
408356 < LeanLogo />
@@ -426,34 +374,34 @@ function App() {
426374 } }
427375 gutterStyle = { ( _dimension , gutterSize , _index ) => {
428376 return {
429- 'width' : preferences . mobile ? '100%' : `${ gutterSize } px` ,
430- 'height' : preferences . mobile ? `${ gutterSize } px` : '100%' ,
431- 'cursor' : preferences . mobile ? 'row-resize' : 'col-resize' ,
432- 'margin-left' : preferences . mobile ? 0 : `-${ gutterSize } px` ,
433- 'margin-top' : preferences . mobile ? `-${ gutterSize } px` : 0 ,
377+ 'width' : mobile ? '100%' : `${ gutterSize } px` ,
378+ 'height' : mobile ? `${ gutterSize } px` : '100%' ,
379+ 'cursor' : mobile ? 'row-resize' : 'col-resize' ,
380+ 'margin-left' : mobile ? 0 : `-${ gutterSize } px` ,
381+ 'margin-top' : mobile ? `-${ gutterSize } px` : 0 ,
434382 'z-index' : 0 ,
435383 } } }
436384 gutterSize = { 5 }
437385 onDragStart = { ( ) => setDragging ( true ) } onDragEnd = { ( ) => setDragging ( false ) }
438- sizes = { preferences . mobile ? [ 50 , 50 ] : [ 70 , 30 ] }
439- direction = { preferences . mobile ? "vertical" : "horizontal" }
440- style = { { flexDirection : preferences . mobile ? "column" : "row" } } >
386+ sizes = { mobile ? [ 50 , 50 ] : [ 70 , 30 ] }
387+ direction = { mobile ? "vertical" : "horizontal" }
388+ style = { { flexDirection : mobile ? "column" : "row" } } >
441389 < div className = 'codeview-wrapper'
442- style = { preferences . mobile ? { width : '100%' } : { height : '100%' } } >
390+ style = { mobile ? { width : '100%' } : { height : '100%' } } >
443391 { codeMirror &&
444392 < CodeMirror
445393 className = "codeview plain"
446394 value = { code }
447395 extensions = { [ EditorView . lineWrapping ] }
448396 height = '100%'
449397 maxHeight = '100%'
450- theme = { lightThemes . includes ( preferences . theme ) ? 'light' : 'dark' }
398+ theme = { lightThemes . includes ( settings . theme ) ? 'light' : 'dark' }
451399 onChange = { setContent } />
452400 }
453401 < div ref = { editorRef } className = { `codeview${ codeMirror ? ' hidden' : '' } ` } />
454402 </ div >
455403 < div ref = { infoviewRef } className = "vscode-light infoview"
456- style = { preferences . mobile ? { width : '100%' } : { height : '100%' } } >
404+ style = { mobile ? { width : '100%' } : { height : '100%' } } >
457405 < p className = { `editor-support-warning${ codeMirror ? '' : ' hidden' } ` } >
458406 You are in the plain text editor< br /> < br />
459407 Go back to the Monaco Editor (click < FontAwesomeIcon icon = { faCode } /> )
@@ -462,8 +410,7 @@ function App() {
462410 </ div >
463411 </ Split >
464412 </ div >
465- </ PreferencesContext . Provider >
466-
413+ )
467414}
468415
469416export default App
0 commit comments