import * as React from 'react' ; import { SnapshotSubscriber , SnapshotUnsubscriber } from "polar-shared/src/util/Snapshots" ; import { useComponentDidMount , useComponentWillUnmount } from "../hooks/ReactLifecycleHooks" ; import { ISnapshot } from "./CachedSnapshotSubscriberContext" ; export interface CachedSnapshotSubscriberOpts < V > { /**
     * The cache key used to cache this entry.
     */ readonly id : string ; readonly subscriber : SnapshotSubscriber < ISnapshot < V > > ; readonly onNext : ( value : ISnapshot < V > | undefined ) => void ; readonly onError : ( err : Error ) => void ; } export namespace LocalCache { export function read < V > ( cacheKey ) { const cacheValue = localStorage . getItem ( cacheKey ) ; if ( cacheValue === null || cacheValue === undefined ) { return undefined ; } try { const value = cacheValue === 'undefined' ? undefined : JSON . parse ( cacheValue ) ; return { exists : true , value , source : 'cache' } ; } catch ( e ) { console . error ( `Unable to parse JSON for cached subscriber ${ cacheKey }: '${ cacheValue }'` , e ) ; return undefined ; } } export function write < V > ( cacheKey , snapshot ) { if ( snapshot === undefined ) { localStorage . removeItem ( cacheKey ) ; } else { localStorage . setItem ( cacheKey , JSON . stringify ( snapshot . value ) ) ; } } export function createKey ( id ) { return 'cache:' + id ; } } /**
 * Cached snapshot provider that uses write through and then reads future cached
 * values from cache.
 */ export function createLocalCachedSnapshotSubscriber < V > ( opts ) { const cacheKey = LocalCache . createKey ( opts . id ) ; const initialValue = LocalCache . read < V > ( cacheKey ) ; if ( initialValue ) { opts . onNext ( initialValue ) ; } const onNext = ( snapshot ) => { opts . onNext ( snapshot ) ; LocalCache . write ( cacheKey , snapshot ) ; } ; return opts . subscriber ( onNext , opts . onError ) ; } export function useLocalCachedSnapshotSubscriber < V > ( opts ) { const cacheKey = React . useMemo ( ( ) => LocalCache . createKey ( opts . id ) , [ opts . id ] ) ; const readCacheData = React . useCallback ( ( ) : ISnapshot < V > | undefined => { return LocalCache . read ( cacheKey ) ; } , [ cacheKey ] ) ; const writeCacheData = React . useCallback ( ( snapshot ) => { LocalCache . write ( cacheKey , snapshot ) ; } , [ cacheKey ] ) ; const initialValue = React . useMemo ( readCacheData , [ readCacheData ] ) ; const unsubscriberRef = React . useRef < SnapshotUnsubscriber > ( ) ; const onNext = React . useCallback ( ( snapshot ) => { writeCacheData ( snapshot ) ; opts . onNext ( snapshot ) ; } , [ opts , writeCacheData ] ) ; useComponentDidMount ( ( ) => { opts . onNext ( initialValue ) ; unsubscriberRef . current = opts . subscriber ( onNext , opts . onError ) ; } ) ; useComponentWillUnmount ( ( ) => { if ( unsubscriberRef . current ) { unsubscriberRef . current ( ) ; } } ) ; }