@@ -21,14 +21,9 @@ import {
2121} from './utils' ;
2222import { SideDrawer } from './SideDrawer' ;
2323import {
24- INIT_COLUMN_NUMBER ,
25- INIT_SWAP_TIME ,
26- INIT_COMPARE_TIME ,
27- DEFAULT_ALGORITHM_OPTIONS ,
28- DEFAULT_COLUMN_COLOR ,
29- DEFAULT_BACKGROUND_COLOR ,
30- DEFAULT_HIGHLIGHT_COLOR ,
3124 RAINBOW_BACKGROUND_COLOR ,
25+ INIT_STATE ,
26+ INIT_SETTINGS ,
3227} from './constants' ;
3328import { SortAppBar } from './AppBar' ;
3429import { CanvasController } from './canvas-controller' ;
@@ -48,74 +43,89 @@ class App extends React.Component<Props> {
4843 state : {
4944 isSorting : boolean ;
5045 areSettingsOpen : boolean ;
51- chosenSortAlg : SortName ;
52- columnNbr : number ;
53- compareTime : number ;
54- swapTime : number ;
5546 canDraw : boolean ;
47+ shouldPlaySound : boolean ;
5648 nbrOfSwaps : number ;
5749 nbrOfComparisons : number ;
58- resetPreset : ResetPreset ;
59- shouldHighlightSwaps : boolean ;
60- shouldHighlightComparisons : boolean ;
61- shouldPlaySound : boolean ;
62- algorithmOptions : AlgorithmOptions ;
63- colorPreset : ColorPreset ;
64- columnColor : string ;
65- backgroundColor : string ;
66- highlightColor : string ;
50+ settings : {
51+ chosenSortAlg : SortName ;
52+ columnNbr : number ;
53+ swapTime : number ;
54+ compareTime : number ;
55+ resetPreset : ResetPreset ;
56+ algorithmOptions : AlgorithmOptions ;
57+ colorPreset : ColorPreset ;
58+ columnColor : string ;
59+ backgroundColor : string ;
60+ highlightColor : string ;
61+ } ;
6762 } ;
6863 canvasController : CanvasController ;
6964
7065 constructor ( public props : Props ) {
7166 super ( props ) ;
7267
68+ const storedSettings = localStorage . getItem ( 'settings' ) ;
69+ this . state = {
70+ ...INIT_STATE ,
71+ settings : {
72+ ...INIT_SETTINGS ,
73+ ...( storedSettings ? JSON . parse ( storedSettings ) : { } ) ,
74+ } ,
75+ } ;
76+
7377 this . sortingAlgorithms = new SortingAlgorithms (
74- INIT_COLUMN_NUMBER ,
78+ this . state . settings . columnNbr ,
7579 this . compare ,
7680 this . drawAndSwap ,
7781 ) ;
7882
79- this . arr = createArr ( INIT_COLUMN_NUMBER ) ;
80- shuffleArray ( this . arr ) ;
81- this . state = {
82- isSorting : false ,
83- areSettingsOpen : false ,
84- chosenSortAlg : SortName . InsertionSort ,
85- columnNbr : INIT_COLUMN_NUMBER ,
86- swapTime : INIT_SWAP_TIME ,
87- compareTime : INIT_COMPARE_TIME ,
88- canDraw : false ,
89- nbrOfSwaps : 0 ,
90- nbrOfComparisons : 0 ,
91- resetPreset : ResetPreset . Shuffle ,
92- shouldHighlightSwaps : true ,
93- shouldHighlightComparisons : false ,
94- shouldPlaySound : false ,
95- algorithmOptions : DEFAULT_ALGORITHM_OPTIONS ,
96- colorPreset : ColorPreset . Rainbow ,
97- columnColor : DEFAULT_COLUMN_COLOR ,
98- backgroundColor : DEFAULT_BACKGROUND_COLOR ,
99- highlightColor : DEFAULT_HIGHLIGHT_COLOR ,
100- } ;
101-
10283 this . resetPresets = {
10384 [ ResetPreset . Shuffle ] : ( ) => shuffleArray ( this . arr ) ,
10485 [ ResetPreset . Sorted ] : ( ) => this . arr . sort ( ( a , b ) => a . value - b . value ) ,
10586 [ ResetPreset . ReverseSorted ] : ( ) =>
10687 this . arr . sort ( ( a , b ) => b . value - a . value ) ,
10788 } ;
10889
90+ this . arr = createArr ( this . state . settings . columnNbr ) ;
91+ this . resetPresets [ this . state . settings . resetPreset ] ( ) ;
92+
10993 const ref = React . createRef < HTMLCanvasElement > ( ) ;
11094 this . canvasController = new CanvasController (
11195 ref as React . RefObject < HTMLCanvasElement > ,
112- INIT_COLUMN_NUMBER ,
113- this . state . colorPreset ,
114- this . state . columnColor ,
115- this . state . highlightColor ,
96+ this . state . settings . columnNbr ,
97+ this . state . settings . colorPreset ,
98+ this . state . settings . columnColor ,
99+ this . state . settings . highlightColor ,
116100 ) ;
117101 }
118102
103+ setSettings = (
104+ settings :
105+ | Partial < typeof this . state . settings >
106+ | ( (
107+ prevSettings : typeof this . state . settings ,
108+ ) => Partial < typeof this . state . settings > ) ,
109+ callback ?: ( ) => Promise < void > | void ,
110+ ) => {
111+ this . setState (
112+ ( prevState : typeof this . state ) => {
113+ const newSettings =
114+ settings instanceof Function
115+ ? settings ( prevState . settings )
116+ : settings ;
117+ return {
118+ ...prevState ,
119+ settings : { ...prevState . settings , ...newSettings } ,
120+ } ;
121+ } ,
122+ async ( ) => {
123+ await callback ?.( ) ;
124+ localStorage . setItem ( 'settings' , JSON . stringify ( this . state . settings ) ) ;
125+ } ,
126+ ) ;
127+ } ;
128+
119129 resizeCanvas = ( ) => {
120130 this . canvasController . resizeCanvas ( this . arr ) ;
121131 } ;
@@ -161,8 +171,8 @@ class App extends React.Component<Props> {
161171 async ( ) => {
162172 try {
163173 await this . sortingAlgorithms . getSortingAlgorithm (
164- this . state . chosenSortAlg ,
165- ) ( arr , this . state . algorithmOptions ) ;
174+ this . state . settings . chosenSortAlg ,
175+ ) ( arr , this . state . settings . algorithmOptions ) ;
166176 } catch ( e ) {
167177 console . error ( 'Sorting interrupted! Reason: ' , e ) ;
168178 }
@@ -190,14 +200,14 @@ class App extends React.Component<Props> {
190200 this . swap ( arr , i1 , i2 ) ;
191201 this . canvasController . redrawColumns ( arr , [ i1 , i2 ] ) ;
192202 this . nbrOfSwaps ++ ;
193- if ( this . state . swapTime ) {
203+ if ( this . state . settings . swapTime ) {
194204 // With a zero swapTime, maximum update depth will be exceeded
195205 // when updating state too often
196206 this . setState ( ( prevState : typeof this . state ) => ( {
197207 nbrOfSwaps : prevState . nbrOfSwaps + 1 ,
198208 } ) ) ;
199209 this . canvasController . highlightColumns ( arr , [ i1 , i2 ] ) ;
200- await sleep ( this . state . swapTime ) ;
210+ await sleep ( this . state . settings . swapTime ) ;
201211 }
202212 } ;
203213
@@ -209,17 +219,20 @@ class App extends React.Component<Props> {
209219 ) : Promise < boolean > => {
210220 if ( ! this . state . isSorting ) throw Error ( 'isSorting is false!' ) ;
211221 this . nbrOfComparisons ++ ;
212- if ( this . state . compareTime ) {
222+ if ( this . state . settings . compareTime ) {
213223 // With a zero compareTime, maximum update depth will be exceeded
214224 // when updating state too often
215225 this . setState ( ( prevState : typeof this . state ) => ( {
216226 nbrOfComparisons : prevState . nbrOfComparisons + 1 ,
217227 } ) ) ;
218228 this . canvasController . highlightColumns ( arr , [ i1 , i2 ] ) ;
219- await sleep ( this . state . compareTime ) ;
229+ await sleep ( this . state . settings . compareTime ) ;
220230 }
221231
222- if ( sortNameToSortType [ this . state . chosenSortAlg ] === SortType . Comparison ) {
232+ if (
233+ sortNameToSortType [ this . state . settings . chosenSortAlg ] ===
234+ SortType . Comparison
235+ ) {
223236 this . playSoundForColumn ( arr , i1 ) ;
224237 }
225238
@@ -239,7 +252,8 @@ class App extends React.Component<Props> {
239252 if ( ! this . state . isSorting ) throw Error ( 'isSorting is false!' ) ;
240253
241254 if (
242- sortNameToSortType [ this . state . chosenSortAlg ] === SortType . Distribution
255+ sortNameToSortType [ this . state . settings . chosenSortAlg ] ===
256+ SortType . Distribution
243257 ) {
244258 this . playSoundForColumn ( arr , i1 ) ;
245259 }
@@ -250,7 +264,9 @@ class App extends React.Component<Props> {
250264 playSoundForColumn = ( arr : SortValue [ ] , i : number ) => {
251265 if ( ! this . state . shouldPlaySound ) return ;
252266
253- this . props . setSoundPitch ( ( arr [ i ] . value * 7 ) / this . state . columnNbr + 3 ) ;
267+ this . props . setSoundPitch (
268+ ( arr [ i ] . value * 7 ) / this . state . settings . columnNbr + 3 ,
269+ ) ;
254270 this . props . playSound ( ) ;
255271 } ;
256272
@@ -265,37 +281,37 @@ class App extends React.Component<Props> {
265281 chooseSortAlg = ( event : SelectChangeEvent < SortName > ) => {
266282 this . stopSorting ( ) ;
267283
268- this . setState ( { chosenSortAlg : event . target . value } ) ;
284+ this . setSettings ( { chosenSortAlg : event . target . value as SortName } ) ;
269285 } ;
270286
271287 chooseResetPreset = ( event : SelectChangeEvent < ResetPreset > ) => {
272- this . setState ( { resetPreset : event . target . value } ) ;
288+ this . setSettings ( { resetPreset : event . target . value as ResetPreset } ) ;
273289 } ;
274290
275291 changeColumnNbr = ( _ : unknown , value : number | number [ ] ) => {
276292 const columnNbr = value instanceof Array ? value [ 0 ] : value ;
277293 this . sortingAlgorithms . columnNbr = columnNbr ;
278294 this . canvasController . columnNbr = columnNbr ;
279- this . setState ( { columnNbr } , ( ) => this . resetAndDraw ( ) ) ;
295+ this . setSettings ( { columnNbr } , ( ) => this . resetAndDraw ( ) ) ;
280296 } ;
281297
282298 changeSwapTime = ( _ : unknown , value : number | number [ ] ) => {
283- this . setState ( {
299+ this . setSettings ( {
284300 swapTime : timeScale ( value instanceof Array ? value [ 0 ] : value ) ,
285301 } ) ;
286302 } ;
287303
288304 changeCompareTime = ( _ : unknown , value : number | number [ ] ) => {
289- this . setState ( {
305+ this . setSettings ( {
290306 compareTime : timeScale ( value instanceof Array ? value [ 0 ] : value ) ,
291307 } ) ;
292308 } ;
293309
294310 resetAndDraw = ( ) => {
295311 this . stopSorting ( ) ;
296312 this . resetCounters ( ) ;
297- this . arr = createArr ( this . state . columnNbr ) ;
298- this . resetPresets [ this . state . resetPreset ] ( ) ;
313+ this . arr = createArr ( this . state . settings . columnNbr ) ;
314+ this . resetPresets [ this . state . settings . resetPreset ] ( ) ;
299315 this . canvasController . redraw ( this . arr ) ;
300316 } ;
301317
@@ -337,42 +353,42 @@ class App extends React.Component<Props> {
337353 key : keyof AlgorithmOptions ,
338354 value : AlgorithmOptions [ typeof key ] ,
339355 ) => {
340- this . setState ( ( prevState : typeof this . state ) => ( {
341- algorithmOptions : { ...prevState . algorithmOptions , [ key ] : value } ,
356+ this . setSettings ( ( prevSettings ) => ( {
357+ algorithmOptions : { ...prevSettings . algorithmOptions , [ key ] : value } ,
342358 } ) ) ;
343359 } ;
344360
345361 setColorPreset = ( colorPreset : ColorPreset ) => {
346- this . setState ( { colorPreset } ) ;
362+ this . setSettings ( { colorPreset } ) ;
347363 this . canvasController . colorPreset = colorPreset ;
348364 this . stopSorting ( ) ;
349365 this . canvasController . redraw ( this . arr ) ;
350366 } ;
351367
352368 setColumnColor = ( columnColor : string ) => {
353- this . setState ( { columnColor } ) ;
369+ this . setSettings ( { columnColor } ) ;
354370 this . canvasController . columnColor = columnColor ;
355371 this . stopSorting ( ) ;
356372 this . canvasController . redraw ( this . arr ) ;
357373 } ;
358374
359375 setBackgroundColor = ( backgroundColor : string ) => {
360- this . setState ( { backgroundColor } ) ;
376+ this . setSettings ( { backgroundColor } ) ;
361377 } ;
362378
363379 setHighlightColor = ( highlightColor : string ) => {
364- this . setState ( { highlightColor } ) ;
380+ this . setSettings ( { highlightColor } ) ;
365381 this . canvasController . highlightColor = highlightColor ;
366382 this . stopSorting ( ) ;
367383 this . canvasController . redraw ( this . arr ) ;
368384 } ;
369385
370386 getBackgroundColor = ( ) => {
371- switch ( this . state . colorPreset ) {
387+ switch ( this . state . settings . colorPreset ) {
372388 case ColorPreset . Rainbow :
373389 return RAINBOW_BACKGROUND_COLOR ;
374390 case ColorPreset . Custom :
375- return this . state . backgroundColor ;
391+ return this . state . settings . backgroundColor ;
376392 }
377393 } ;
378394
@@ -385,8 +401,8 @@ class App extends React.Component<Props> {
385401 < div className = "App-header" >
386402 < SortAppBar
387403 arr = { this . arr }
388- swapTime = { this . state . swapTime }
389- compareTime = { this . state . compareTime }
404+ swapTime = { this . state . settings . swapTime }
405+ compareTime = { this . state . settings . compareTime }
390406 canDraw = { this . state . canDraw }
391407 isSorting = { this . state . isSorting }
392408 nbrOfSwaps = { this . state . nbrOfSwaps }
@@ -415,21 +431,23 @@ class App extends React.Component<Props> {
415431 </ div >
416432 < SideDrawer
417433 areSettingsOpen = { this . state . areSettingsOpen }
418- resetPreset = { this . state . resetPreset }
419- chosenSortAlg = { this . state . chosenSortAlg }
434+ resetPreset = { this . state . settings . resetPreset }
435+ chosenSortAlg = { this . state . settings . chosenSortAlg }
420436 toggleDisplaySettings = { this . toggleDisplaySettings }
421437 chooseSortAlg = { this . chooseSortAlg }
422438 chooseResetPreset = { this . chooseResetPreset }
423439 changeColumnNbr = { this . changeColumnNbr }
424440 changeSwapTime = { this . changeSwapTime }
425441 changeCompareTime = { this . changeCompareTime }
426- columnNbr = { this . state . columnNbr }
427- algorithmOptions = { this . state . algorithmOptions }
442+ columnNbr = { this . state . settings . columnNbr }
443+ swapTime = { this . state . settings . swapTime }
444+ compareTime = { this . state . settings . compareTime }
445+ algorithmOptions = { this . state . settings . algorithmOptions }
428446 setAlgorithmOption = { this . setAlgorithmOption }
429- colorPreset = { this . state . colorPreset }
430- columnColor = { this . state . columnColor }
431- backgroundColor = { this . state . backgroundColor }
432- highlightColor = { this . state . highlightColor }
447+ colorPreset = { this . state . settings . colorPreset }
448+ columnColor = { this . state . settings . columnColor }
449+ backgroundColor = { this . state . settings . backgroundColor }
450+ highlightColor = { this . state . settings . highlightColor }
433451 setColorPreset = { this . setColorPreset }
434452 setColumnColor = { this . setColumnColor }
435453 setBackgroundColor = { this . setBackgroundColor }
0 commit comments