@@ -61,8 +61,8 @@ import {
61
61
forEach ,
62
62
keys ,
63
63
lensPath ,
64
+ mergeRight ,
64
65
set ,
65
- symmetricDifference ,
66
66
type ,
67
67
} from 'ramda' ;
68
68
import { createAction } from 'redux-actions' ;
@@ -276,9 +276,8 @@ const getTransform = (element, propName, propPart) =>
276
276
? element . persistenceTransforms [ propName ] [ propPart ]
277
277
: noopTransform ;
278
278
279
- const getNewValKey = ( id , persistedProp ) => id + '.' + persistedProp ;
280
- const getOriginalValKey = newValKey => newValKey + '.orig' ;
281
- const getPersistIdKey = newValKey => newValKey + '.id' ;
279
+ const getValsKey = ( id , persistedProp , persistence ) =>
280
+ `${ id } .${ persistedProp } .${ JSON . stringify ( persistence ) } ` ;
282
281
283
282
const getProps = layout => {
284
283
const { props} = layout ;
@@ -322,43 +321,27 @@ export function recordUiEdit(layout, newProps, dispatch) {
322
321
const storage = getStore ( persistence_type , dispatch ) ;
323
322
const { extract} = getTransform ( element , propName , propPart ) ;
324
323
325
- const newValKey = getNewValKey ( id , persistedProp ) ;
326
- const persistIdKey = getPersistIdKey ( newValKey ) ;
327
- const previousVal = extract ( props [ propName ] ) ;
324
+ const valsKey = getValsKey ( id , persistedProp , persistence ) ;
325
+ let originalVal = extract ( props [ propName ] ) ;
328
326
const newVal = extract ( newProps [ propName ] ) ;
329
327
330
328
// mainly for nested props with multiple persisted parts, it's
331
329
// possible to have the same value as before - should not store
332
330
// in this case.
333
- if ( previousVal !== newVal ) {
334
- if (
335
- ! storage . hasItem ( newValKey ) ||
336
- storage . getItem ( persistIdKey ) !== persistence
337
- ) {
338
- storage . setItem (
339
- getOriginalValKey ( newValKey ) ,
340
- previousVal ,
341
- dispatch
342
- ) ;
343
- storage . setItem ( persistIdKey , persistence , dispatch ) ;
331
+ if ( originalVal !== newVal ) {
332
+ if ( storage . hasItem ( valsKey ) ) {
333
+ originalVal = storage . getItem ( valsKey ) [ 1 ] ;
344
334
}
345
- storage . setItem ( newValKey , newVal , dispatch ) ;
335
+ const vals =
336
+ originalVal === undefined
337
+ ? [ newVal ]
338
+ : [ newVal , originalVal ] ;
339
+ storage . setItem ( valsKey , vals ) ;
346
340
}
347
341
}
348
342
} , persisted_props ) ;
349
343
}
350
344
351
- function clearUIEdit ( id , persistence_type , persistedProp , dispatch ) {
352
- const storage = getStore ( persistence_type , dispatch ) ;
353
- const newValKey = getNewValKey ( id , persistedProp ) ;
354
-
355
- if ( storage . hasItem ( newValKey ) ) {
356
- storage . removeItem ( newValKey ) ;
357
- storage . removeItem ( getOriginalValKey ( newValKey ) ) ;
358
- storage . removeItem ( getPersistIdKey ( newValKey ) ) ;
359
- }
360
- }
361
-
362
345
/*
363
346
* Used for entire layouts (on load) or partial layouts (from children
364
347
* callbacks) to apply previously-stored UI edits to components
@@ -371,6 +354,28 @@ export function applyPersistence(layout, dispatch) {
371
354
return persistenceMods ( layout , layout , [ ] , dispatch ) ;
372
355
}
373
356
357
+ const UNDO = true ;
358
+ function modProp ( key , storage , element , props , persistedProp , update , undo ) {
359
+ if ( storage . hasItem ( key ) ) {
360
+ const [ newVal , originalVal ] = storage . getItem ( key ) ;
361
+ const fromVal = undo ? newVal : originalVal ;
362
+ const toVal = undo ? originalVal : newVal ;
363
+ const [ propName , propPart ] = persistedProp . split ( '.' ) ;
364
+ const transform = getTransform ( element , propName , propPart ) ;
365
+
366
+ if ( equals ( fromVal , transform . extract ( props [ propName ] ) ) ) {
367
+ update [ propName ] = transform . apply (
368
+ toVal ,
369
+ propName in update ? update [ propName ] : props [ propName ]
370
+ ) ;
371
+ } else {
372
+ // clear this saved edit - we've started with the wrong
373
+ // value for this persistence ID
374
+ storage . removeItem ( key ) ;
375
+ }
376
+ }
377
+ }
378
+
374
379
function persistenceMods ( layout , component , path , dispatch ) {
375
380
const {
376
381
id,
@@ -385,31 +390,18 @@ function persistenceMods(layout, component, path, dispatch) {
385
390
if ( persistence ) {
386
391
const storage = getStore ( persistence_type , dispatch ) ;
387
392
const update = { } ;
388
- forEach ( persistedProp => {
389
- const [ propName , propPart ] = persistedProp . split ( '.' ) ;
390
- const newValKey = getNewValKey ( id , persistedProp ) ;
391
- const storedPersistID = storage . getItem ( getPersistIdKey ( newValKey ) ) ;
392
- const transform = getTransform ( element , propName , propPart ) ;
393
-
394
- if ( storedPersistID ) {
395
- if (
396
- storedPersistID === persistence &&
397
- equals (
398
- storage . getItem ( getOriginalValKey ( newValKey ) ) ,
399
- transform . extract ( props [ propName ] )
400
- )
401
- ) {
402
- // To handle multiple nested props, apply each stored value
403
- // in turn; then at the end we'll push these into the layout
404
- update [ propName ] = transform . apply (
405
- storage . getItem ( newValKey ) ,
406
- propName in update ? update [ propName ] : props [ propName ]
407
- ) ;
408
- } else {
409
- clearUIEdit ( id , persistence_type , persistedProp , dispatch ) ;
410
- }
411
- }
412
- } , persisted_props ) ;
393
+ forEach (
394
+ persistedProp =>
395
+ modProp (
396
+ getValsKey ( id , persistedProp , persistence ) ,
397
+ storage ,
398
+ element ,
399
+ props ,
400
+ persistedProp ,
401
+ update
402
+ ) ,
403
+ persisted_props
404
+ ) ;
413
405
414
406
for ( const propName in update ) {
415
407
layoutOut = set (
@@ -452,51 +444,85 @@ function persistenceMods(layout, component, path, dispatch) {
452
444
export function prunePersistence ( layout , newProps , dispatch ) {
453
445
const {
454
446
id,
447
+ props,
455
448
persistence,
456
449
persisted_props,
457
450
persistence_type,
458
451
element,
459
452
} = getProps ( layout ) ;
460
- if ( ! persistence ) {
461
- return ;
462
- }
463
453
464
- // first look for conditions that clear the persistence store entirely
465
- if (
466
- ( 'persistence' in newProps && newProps . persistence !== persistence ) ||
467
- ( 'persistence_type' in newProps &&
468
- newProps . persistence_type !== persistence_type )
469
- ) {
470
- getStore ( persistence_type , dispatch ) . clear ( id ) ;
471
- return ;
454
+ const getFinal = ( propName , prevVal ) =>
455
+ propName in newProps ? newProps [ propName ] : prevVal ;
456
+ const finalPersistence = getFinal ( 'persistence' , persistence ) ;
457
+
458
+ if ( ! persistence && ! finalPersistence ) {
459
+ return newProps ;
472
460
}
473
461
474
- // if the persisted props list itself changed, clear any props not
475
- // present in both the new and old
476
- if ( 'persisted_props' in newProps ) {
462
+ const finalPersistenceType = getFinal ( 'persistence_type' , persistence_type ) ;
463
+ const finalPersistedProps = getFinal ( 'persisted_props' , persisted_props ) ;
464
+ const persistenceChanged =
465
+ finalPersistence !== persistence ||
466
+ finalPersistenceType !== persistence_type ||
467
+ finalPersistedProps !== persisted_props ;
468
+
469
+ const notInNewProps = persistedProp =>
470
+ ! ( persistedProp . split ( '.' ) [ 0 ] in newProps ) ;
471
+
472
+ const update = { } ;
473
+
474
+ if ( persistenceChanged && persistence ) {
475
+ // clear previously-applied persistence
476
+ const storage = getStore ( persistence_type , dispatch ) ;
477
477
forEach (
478
478
persistedProp =>
479
- clearUIEdit ( id , persistence_type , persistedProp , dispatch ) ,
480
- symmetricDifference ( persisted_props , newProps . persisted_props )
479
+ modProp (
480
+ getValsKey ( id , persistedProp , persistence ) ,
481
+ storage ,
482
+ element ,
483
+ props ,
484
+ persistedProp ,
485
+ update ,
486
+ UNDO
487
+ ) ,
488
+ filter ( notInNewProps , persisted_props )
481
489
) ;
482
490
}
483
491
484
- // now the main point - clear any edit associated with a prop that changed
485
- // note that this is independent of the new prop value.
486
- const transforms = element . persistenceTransforms || { } ;
487
- for ( const propName in newProps ) {
488
- const propTransforms = transforms [ propName ] ;
489
- if ( propTransforms ) {
490
- for ( const propPart in propTransforms ) {
491
- clearUIEdit (
492
- id ,
493
- persistence_type ,
494
- `${ propName } .${ propPart } ` ,
495
- dispatch
496
- ) ;
492
+ if ( finalPersistence ) {
493
+ const finalStorage = getStore ( finalPersistenceType , dispatch ) ;
494
+
495
+ if ( persistenceChanged ) {
496
+ // apply new persistence
497
+ forEach (
498
+ persistedProp =>
499
+ modProp (
500
+ getValsKey ( id , persistedProp , persistence ) ,
501
+ finalStorage ,
502
+ element ,
503
+ props ,
504
+ persistedProp ,
505
+ update
506
+ ) ,
507
+ filter ( notInNewProps , finalPersistedProps )
508
+ ) ;
509
+ }
510
+
511
+ // now the main point - clear any edit of a prop that changed
512
+ // note that this is independent of the new prop value.
513
+ const transforms = element . persistenceTransforms || { } ;
514
+ for ( const propName in newProps ) {
515
+ const propTransforms = transforms [ propName ] ;
516
+ if ( propTransforms ) {
517
+ for ( const propPart in propTransforms ) {
518
+ finalStorage . removeItem (
519
+ getValsKey ( id , `${ propName } .${ propPart } ` , persistence )
520
+ ) ;
521
+ }
522
+ } else {
523
+ finalStorage . removeItem ( getValsKey ( id , propName , persistence ) ) ;
497
524
}
498
- } else {
499
- clearUIEdit ( id , persistence_type , propName , dispatch ) ;
500
525
}
501
526
}
527
+ return persistenceChanged ? mergeRight ( newProps , update ) : newProps ;
502
528
}
0 commit comments