summaryrefslogtreecommitdiff
path: root/editor/app.ml
blob: 455904424bf7f56f3cea000e15bf80d4e4e555b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
open Brr
module Js = Js_of_ocaml.Js

type events =
  | StoreEvent
  | LoadEvent of Jstr.t option
  | ClosePopup of Forms.Events.event option
  | Generic of Actions.Event.t

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
  : (events, State.t) Application.t
  = fun event state ->
    match event with

    | Generic (E (t, (module EventHandler))) ->
      EventHandler.apply t state


    | ClosePopup result ->
      (* First close the last popin. *)
      let state = match state.window with
        | []     -> { state with window = [] }
        | el::tl -> El.remove el
                  ; { state with window = tl } in
      (* Call the handler associated with the event *)
      begin match result with
        | None -> state
        | Some (Event (t, (module Handler))) ->
          Handler.on_close t 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. *)
                   let is_ok = date <= state.last_backup in
                   if (not is_ok) then (
                     let open Console in
                     log
                       [ Jstr.v "Last backup date is "
                       ; new%js Js.date_fromTimeValue state.last_backup
                       ; Jstr.v " but date is "
                       ; new%js Js.date_fromTimeValue date] );
                   is_ok)) in
      begin match save with
        | Ok true -> { state with last_backup = new_date }
        | Ok false ->
          Console.(log [Jstr.v "Didn't save"]);
          state
        | Error other ->
          (* TODO In case of error, notify the user *)
          Console.(log [Jstr.v "Couldn't save" ; other]);
          state
      end

    | LoadEvent page_id ->
      let json = State.Storage.load page_id in
      State.load_page page_id state json