summaryrefslogtreecommitdiff
path: root/editor/state/state.ml
blob: 49a1e23bdcdbd632505654f39936a5ee4c5924bc (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
93
94
95
open Brr
module PM = Prosemirror
module Js = Js_of_ocaml.Js
module Storage = Storage

(** This is the state for the application *)
type t =
  { editable : bool
  ; view : PM.View.editor_view Js.t
  ; last_backup : float
  ; page_id : Jstr.t option
  ; window : Brr.El.t list
  ; pm : PM.t
  }

(** Compare two states together.

    The prosemirror elemens are ignored *)
let eq s1 s2 =
  Stdlib.( == )
    (s1.editable, s1.last_backup, s1.page_id, s1.window)
    (s2.editable, s2.last_backup, s2.page_id, s2.window)


let set_title : Storage.content Js.t -> unit =
 fun content ->
  let title = Js.Opt.get content##.title (fun () -> Jstr.empty) in
  let title_element = Document.find_el_by_id G.document (Jstr.v "title") in
  Option.iter (fun el -> El.set_prop El.Prop.value title el) title_element


let state_of_storage :
       PM.t
    -> Storage.content Js.t
    -> PM.Model.schema Js.t
    -> PM.State.editor_state Js.t =
 fun pm content schema ->
  Js.Opt.case
    content##.content
    (fun () ->
      let obj = PM.State.creation_prop () in
      obj##.plugins := Plugins.default pm schema;
      obj##.schema := Js.some schema;
      PM.State.create pm obj )
    (fun page_content ->
      let obj = PM.State.configuration_prop () in
      obj##.plugins := Plugins.default pm schema;
      obj##.schema := Js.some schema;
      PM.State.fromJSON pm obj page_content )


let load_page : Jstr.t option -> t -> t =
 fun page_id state ->
  let json = Storage.load page_id in
  let editor_state =
    state_of_storage state.pm json state.view##.state##.schema
  in
  let () = state.view##updateState editor_state
  and () = set_title json in

  let last_backup =
    Js.Opt.case json##.date (fun () -> state.last_backup) (fun v -> v)
  in

  { state with page_id; last_backup }


let new_page : Jstr.t option -> title:Jstr.t -> t -> t =
 fun page_id ~title state ->
  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
  let editor_state =
    state_of_storage state.pm content_obj state.view##.state##.schema
  in
  let () = state.view##updateState editor_state
  and () = set_title content_obj in

  let last_backup =
    Js.Opt.case content_obj##.date (fun () -> state.last_backup) (fun v -> v)
  in

  { state with page_id; last_backup }


let init : PM.t -> PM.View.editor_view Js.t -> float -> Jstr.t option -> t =
 fun pm view last_backup page_id ->
  { editable = true; view; last_backup; page_id; window = []; pm }