import { Newtype , _iso } from './newtype' ; import { defaultStorage , isStorageSupported , dump , parse } from './storage' ; export type Point = { readonly x : number ; readonly y : number ; } ; type S = { lines : Array < Point [ ] > ; drawing : Point [ ] ; dirty : boolean ; down : boolean ; } ; export interface State extends Newtype < { readonly State : unique symbol ; } , S > { } const iso = _iso < State > ( ) ; const db = defaultStorage ( ) ; function save ( x ) { if ( ! isStorageSupported ( db ) ) { return ; } db . setItem ( 'state' , dump ( x ) ) ; } export function load ( ) { if ( ! isStorageSupported ( db ) ) { return empty ( ) ; } const item = db . getItem ( 'state' ) ; if ( item === null || item === undefined ) { return empty ( ) ; } return iso . wrap ( { ... parse ( item ) , dirty : true } ) ; } export function empty ( ) { const result = { lines : [ ] , drawing : [ ] , dirty : true , down : false , } ; save ( result ) ; return iso . wrap ( result ) ; } export function map ( s , cb ) { const state = iso . unwrap ( s ) ; const dup = parse ( dump ( state ) ) ; dup . lines = dup . lines . map ( l => l . map ( cb ) ) ; return iso . wrap ( dup ) ; } export function undo ( s ) { const state = iso . unwrap ( s ) ; state . lines . splice ( - 1 , 1 ) ; state . dirty = true ; save ( state ) ; } export function clear ( s ) { const state = iso . unwrap ( s ) ; state . lines . splice ( 0 , state . lines . length ) ; state . dirty = true ; save ( state ) ; } export type Action = ( state : State , p : Point ) => void ; export function addDrawingPoint ( s , p ) { const state = iso . unwrap ( s ) ; if ( ! state . down ) { return ; } state . drawing . push ( p ) ; state . dirty = true ; save ( state ) ; } export function addFirstDrawingPoint ( s , p ) { const state = iso . unwrap ( s ) ; state . down = true ; addDrawingPoint ( s , p ) ; } export function addLastDrawingPoing ( s , p ) { const state = iso . unwrap ( s ) ; state . drawing . push ( p ) ; state . lines . push ( state . drawing ) ; state . drawing = [ ] ; state . dirty = true ; state . down = false ; save ( state ) ; } export function willdisplay ( s , cb ) { const state = iso . unwrap ( s ) ; if ( state . dirty ) { const successful = cb ( [ ... state . lines , state . drawing ] . filter ( x => x . length > 0 ) ) ; state . dirty = ! successful ; } }