aboutsummaryrefslogtreecommitdiff
path: root/editor/app.ml
diff options
context:
space:
mode:
Diffstat (limited to 'editor/app.ml')
-rwxr-xr-xeditor/app.ml118
1 files changed, 118 insertions, 0 deletions
diff --git a/editor/app.ml b/editor/app.ml
new file mode 100755
index 0000000..aee396a
--- /dev/null
+++ b/editor/app.ml
@@ -0,0 +1,118 @@
+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
+
+