aboutsummaryrefslogtreecommitdiff
path: root/editor/editor.ml
diff options
context:
space:
mode:
Diffstat (limited to 'editor/editor.ml')
-rwxr-xr-xeditor/editor.ml197
1 files changed, 26 insertions, 171 deletions
diff --git a/editor/editor.ml b/editor/editor.ml
index d3a9624..1a34dfc 100755
--- a/editor/editor.ml
+++ b/editor/editor.ml
@@ -2,56 +2,6 @@ open Brr
module PM = Prosemirror
module Js = Js_of_ocaml.Js
-(** This is the state for the application *)
-type state =
- { editable : bool
- ; view : PM.View.editor_view Js.t
- ; last_backup: float
- ; page_id: Jstr.t option
-
- ; window : El.t list
- }
-
-type events =
- | DeleteEvent
- | StoreEvent
- | LoadEvent of Jstr.t option
- | AddEvent
- | CloseEvent of Forms.Events.kind option
-
-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 key_of_title
- : Jstr.t -> Jstr.t
- = fun title ->
- title
-
-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)
-
(** Create a new editor view
[build_view element state] will create the editor and attach it to [element].
@@ -68,7 +18,7 @@ let build_view
This could be improved, instead of creating a new schema, just fetch
the node and marks from the plungin *)
let custom_schema =
- Footnotes.footnote_schema
+ Plugins.Footnotes.footnote_schema
pm
(PM.SchemaBasic.schema pm) in
@@ -83,7 +33,7 @@ let build_view
(Some custom_schema##.spec##.marks)
None in
let full_schema = PM.Model.schema pm specs in
- let stored_content = Storage.load page_id in
+ let stored_content = State.Storage.load page_id in
(* This variable contains the last update time, either because it is
stored, or because it is the date where we create the first page. *)
@@ -92,11 +42,11 @@ let build_view
(fun () -> (new%js Js.date_now)##getTime) in
let props = PM.View.direct_editor_props () in
- props##.state := state_of_storage pm stored_content full_schema;
+ props##.state := State.state_of_storage pm stored_content full_schema;
(* Add the custom nodes *)
props##.nodeViews := PM.O.init
- [| ( "footnote", (Footnotes.footnote_view pm))
+ [| ( "footnote", (Plugins.Footnotes.footnote_view pm))
|];
let view = PM.View.editor_view
@@ -105,114 +55,21 @@ let build_view
props in
view, last_backup
-let load_page
- : PM.t -> Jstr.t option -> state -> Storage.content Js.t -> state
- = fun pm page_id state json ->
- let editor_state = state_of_storage pm json state.view##.state##.schema in
- let () = state.view##updateState editor_state
- and () = set_title json in
- { state with page_id }
(** [update] is the event loop.
The function take a new event, and apply it to the current state. *)
let update
- : PM.t -> 'a option Note.E.send -> (events, state) Application.t
- = fun pm close_sender event state ->
- match event with
-
- | 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) ->
- Storage.delete (fun () -> Some id);
- let json = Storage.load None in
- load_page pm None state json
- (* Add a new page *)
- | Some (Forms.Add_page.AddPage {title}) ->
- let page_id = key_of_title title in
- Console.(log [title]);
- 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
- load_page pm (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 = 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 }
- | _ ->
- (* TODO In case of error, notify the user *)
- state
- end
-
- | LoadEvent page_id ->
- let json = Storage.load page_id in
- load_page pm page_id state json
-
+ : 'a option Note.E.send -> (App.events, State.t) Application.t
+ = App.update
let app id content =
+ (* This event is used in the pop process. The sender is given to the
+ subroutine in order to track the window closing *)
+ let event, sender = Note.E.create () in
+
(* Check the pre-requisite *)
let events_opt = Actions.populate_menu () in
match (Jv.is_none id), (Jv.is_none content), events_opt with
@@ -221,34 +78,32 @@ let app id content =
let pm = PM.v () in
let editor:El.t = Jv.Id.of_jv id in
(* Load the cache for the given page *)
- let page_id = Storage.page_id () in
+ let page_id = State.Storage.page_id () in
let view, last_backup = build_view pm page_id editor in
- (* This event is used in the pop process. The sender is given to the
- subroutine in order to track the window closing *)
- let event, sender = Note.E.create () in
- let _ = sender in
let init_state =
- { editable = true
- ; view
- ; last_backup
- ; page_id
-
- ; window = []
- }
+ State.{ editable = true
+ ; view
+ ; last_backup
+ ; page_id
+
+ ; window = []
+ ; pm
+ }
in
let app_state = Application.run
- (update pm sender)
+ ~eq:State.eq
+ (App.update sender)
init_state
(Note.E.select
- [ Note.E.map (fun () -> DeleteEvent) btn_events.Actions.delete
- ; Brr_note.Evr.on_el Ev.focusout (fun _ -> StoreEvent) editor
- ; Note.E.map (fun v -> LoadEvent v) btn_events.Actions.redirect
- ; Note.E.map (fun () -> AddEvent) btn_events.Actions.add
- ; Note.E.map (fun v -> CloseEvent v) event
+ [ Brr_note.Evr.on_el Ev.focusout (fun _ -> App.StoreEvent) editor
+ ; Note.E.map (fun () -> App.DeleteEvent) btn_events.Actions.delete
+ ; Note.E.map (fun () -> App.AddEvent) btn_events.Actions.add
+ ; Note.E.map (fun v -> App.LoadEvent v) btn_events.Actions.redirect
+ ; Note.E.map (fun v -> App.CloseEvent v) event
]) in
let () =