From 50e3669a45a39bddabd62787441de1cf92f08191 Mon Sep 17 00:00:00 2001 From: Patrick Ferris Date: Fri, 13 Jan 2023 11:56:30 +0000 Subject: [PATCH] Add next_event and more real-world example --- lib_eio_js/browser/eio_browser.ml | 9 ++++++++ lib_eio_js/browser/eio_browser.mli | 4 ++++ lib_eio_js/browser/test/index.html | 3 +++ lib_eio_js/browser/test/index.ml | 35 +++++++++++++++++++++--------- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/lib_eio_js/browser/eio_browser.ml b/lib_eio_js/browser/eio_browser.ml index f0e1bb14b..a6a09262c 100644 --- a/lib_eio_js/browser/eio_browser.ml +++ b/lib_eio_js/browser/eio_browser.ml @@ -66,12 +66,14 @@ let rec schedule t : unit = | None -> if t.pending_io = 0 then begin Option.iter G.stop_timer t.timeout; + (* Option.iter G.cancel_animation_frame t.timeout; *) t.timeout <- None end else begin match t.timeout with | None -> let id = G.set_timeout ~ms:0 (fun () -> t.timeout <- None; schedule t) in + (* let id = G.request_animation_frame (fun _ -> t.timeout <- None; schedule t) in *) t.timeout <- Some id; schedule t | Some _id -> () @@ -87,6 +89,13 @@ end let await fut = enter_io @@ Fut.await fut +let next_event : 'a Brr.Ev.type' -> Brr.Ev.target -> 'a Brr.Ev.t = fun typ target -> + let opts = Brr.Ev.listen_opts ~once:true () in + let listen fn = + ignore (Brr.Ev.listen ~opts typ fn target : Brr.Ev.listener) + in + enter_io listen + (* Largely based on the Eio_mock.Backend event loop. *) let run main = let run_q = Lf_queue.create () in diff --git a/lib_eio_js/browser/eio_browser.mli b/lib_eio_js/browser/eio_browser.mli index a9cd9dc7d..af4179b3b 100644 --- a/lib_eio_js/browser/eio_browser.mli +++ b/lib_eio_js/browser/eio_browser.mli @@ -6,6 +6,10 @@ end val await : 'a Fut.t -> 'a (** [await fut] blocks on the promise [fut] and allows other fibers to do work. *) +val next_event : 'a Brr.Ev.type' -> Brr.Ev.target -> 'a Brr.Ev.t +(** [next_event typ target] blocks until an event of type [typ] arrives + on the [target]. *) + (** {1 Main loop} *) val run : (unit -> 'a) -> 'a Fut.t diff --git a/lib_eio_js/browser/test/index.html b/lib_eio_js/browser/test/index.html index b1f3b4f5f..0c35cf098 100644 --- a/lib_eio_js/browser/test/index.html +++ b/lib_eio_js/browser/test/index.html @@ -7,6 +7,9 @@ Eio in the Browser +
+ +
\ No newline at end of file diff --git a/lib_eio_js/browser/test/index.ml b/lib_eio_js/browser/test/index.ml index 0cf3e6d35..badf6ef43 100644 --- a/lib_eio_js/browser/test/index.ml +++ b/lib_eio_js/browser/test/index.ml @@ -1,16 +1,31 @@ open Eio +open Brr let () = + let counter = Brr.Document.find_el_by_id G.document Jstr.(v "counter") |> Option.get in + let text = Brr.Document.find_el_by_id G.document Jstr.(v "text") |> Option.get in + let output = Brr.Document.find_el_by_id G.document Jstr.(v "output") |> Option.get in let main = Eio_browser.run @@ fun () -> - Fiber.both - (fun () -> Eio_browser.Timeout.sleep ~ms:1000; traceln "World") - (fun () -> traceln "Hello, "); - let p1, r1 = Fut.create () in - let p2, r2 = Fut.create () in - Fiber.both - (fun () -> Eio_browser.await p1; traceln "Waited for p1"; r2 ()) - (fun () -> r1 (); Eio_browser.await p2; traceln "Waited for p2"); - "Done" + Eio.Switch.run @@ fun sw -> + Fiber.both (fun () -> + (* A little text editor *) + while true do + let ev = Eio_browser.next_event Ev.keyup (El.as_target text) in + let target = Jv.get (Ev.to_jv ev) "target" in + let text = Jv.get target "value" |> Jv.to_jstr in + Brr.El.set_children output [ El.txt text ] + done + ) + (fun () -> + (* A little timer counting up *) + let i = ref 0 in + while true do + Eio_browser.Timeout.sleep ~ms:1000; + incr i; + Brr.El.set_children counter [ El.txt' (string_of_int !i ^ "s")] + done + ) + in - Fut.await main (fun v -> Brr.Console.log [ Jstr.v v ]) \ No newline at end of file + Fut.await main (fun v -> Brr.Console.log [ Jstr.v "Done" ]) \ No newline at end of file