open Brr module PM = Prosemirror module Js = Js_of_ocaml.Js type events = | DeleteEvent | StoreEvent | LoadEvent of Jstr.t option | AddEvent | CloseEvent of Forms.Events.kind option | GEvent of Forms.Events.event let key_of_title : Jstr.t -> Jstr.t = fun title -> title (** [update] is the event loop. The function take a new event, and apply it to the current state. *) let update : 'a option Note.E.send -> (events, State.t) Application.t = fun close_sender event state -> match event with | GEvent (Event (t, (module Handler))) -> Handler.on_close t state | AddEvent -> let title = Jstr.v "Nouvelle page" in let popup = Ui.popup ~title ~form:(Some (Forms.Add_page.create ())) close_sender in { state with window = popup::state.window} | DeleteEvent -> begin match state.page_id with | None -> state | Some page_id -> let title = Jstr.v "Confirmation" in let popup = Ui.popup ~title ~form:(Some (Forms.Delete_page.create page_id)) close_sender in { state with window = popup::state.window} end | CloseEvent res -> let state = match state.window with | [] -> { state with window = [] } | el::tl -> El.remove el ; { state with window = tl } in (* The actions is confirmed by the user. Handle the form result *) begin match res with (* Delete the current page, then load the home page *) | Some (Forms.Delete_page.DeletePage id) -> State.Storage.delete (fun () -> Some id); let json = State.Storage.load None in State.load_page None state json (* Add a new page *) | Some (Forms.Add_page.AddPage {title}) -> let page_id = key_of_title title in let new_date = (new%js Js.date_now)##getTime in let content_obj = object%js val content = Js.null val title = Js.some title val date = Js.some new_date end in State.load_page (Some page_id) state content_obj | _ -> state end | StoreEvent -> let title_element = Document.find_el_by_id G.document (Jstr.v "title") in let content = Option.map (fun el -> El.prop (El.Prop.value) el) title_element in let new_date = (new%js Js.date_now)##getTime in let content_obj = object%js val content = Js.some @@ Jv.Id.to_jv (state.view##.state##toJSON ()) val title = Js.Opt.option content val date = Js.some new_date end in let save = State.Storage.save content_obj state.page_id ~check:(fun previous_state -> Js.Opt.case previous_state##.date (fun () -> true) (fun date -> (* I do not figure how the previous date could be older than the last backup. It could be either : - equal (if we are the only one to update it) - more recent (if the content has been updated elsewhere) but older shoud be a bug. *) date <= state.last_backup)) in begin match save with | Ok true -> { state with last_backup = new_date } | other -> (* TODO In case of error, notify the user *) Console.(log [other]); state end | LoadEvent page_id -> let json = State.Storage.load page_id in State.load_page page_id state json