Skip to content

Instantly share code, notes, and snippets.

@ThomasBrittain
Last active August 29, 2015 14:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ThomasBrittain/bb147e0a6bf3c9d7fcf3 to your computer and use it in GitHub Desktop.
Save ThomasBrittain/bb147e0a6bf3c9d7fcf3 to your computer and use it in GitHub Desktop.
(* Example website login: localhost:8080/?user_num=1 *)
{shared{
open Eliom_lib
open Eliom_content
open Eliom_content.Html5
open Html5.D
open Eliom_registration
open Eliom_parameter
}}
module Channel_example_app =
Eliom_registration.App (
struct
let application_name = "channel_example"
end)
let main_service =
Eliom_service.App.service ~path:[] ~get_params:(string "user_num") ()
(* Create a channel eref *)
let channel_ref =
Eliom_reference.Volatile.eref_from_fun
~scope:Eliom_common.default_process_scope
(fun () ->
let (s, notify) = Lwt_stream.create () in
let c = Eliom_comet.Channel.create s in
(c, notify)
)
(* Send a message from one client to another *)
let notify from_user_id to_user_id s =
let () = Lwt.async (fun () -> Lwt_io.print "\nnotify called") in
(* Get the session group state for the user *)
let state =
Eliom_state.Ext.volatile_data_group_state ~scope:Eliom_common.default_group_scope to_user_id in
(* Iterate on all sessions from the group *)
Eliom_state.Ext.iter_volatile_sub_states ~state
(fun state ->
(* Iterate on all client process states in the session *)
Eliom_state.Ext.iter_volatile_sub_states ~state
(fun state ->
let (_, notify) = Eliom_reference.Volatile.Ext.get state channel_ref in
notify (Some ("Hello from " ^ from_user_id ^ "! You are user " ^ to_user_id ^ "\n\n" ^ s))
)
)
(* Reactive client string *)
{client{ let client_string, set_client_string = React.E.create () }}
(* Action for a client to send a message *)
let new_message_action =
Eliom_registration.Action.register_post_coservice'
~options:`NoReload
~post_params:(string "from_user_id" ** string "to_user_id" ** string "msg")
(fun () (from_user_id, (to_user_id, msg)) ->
let () = Lwt.async (fun () -> Lwt_io.print "\nnew_message_action called") in
Lwt.return @@ notify from_user_id to_user_id msg
)
(* Post form for one user to send a message to another user *)
let client_message_form =
let open Eliom_content in
Html5.F.post_form ~service:new_message_action ~port:8080
(
fun (from_user_id, (to_user_id, msg)) ->
[p [pcdata "To:"];
Html5.F.string_input ~input_type:`Text ~name:to_user_id ();
p [pcdata "Send a message here:"];
Html5.F.string_input ~input_type:`Text ~name:msg ();
Html5.D.string_input ~input_type:`Submit ~value:"Send" ()
]
)
let () =
Channel_example_app.register
~service:main_service
(fun user_num () ->
(* Set the session group to which the erefs belong *)
Eliom_state.set_volatile_data_session_group
~set_max:1
~scope:Eliom_common.default_session_scope
~secure:true
user_num;
let (channel, _) = Eliom_reference.Volatile.get channel_ref in
(* When a message is received on the channel, push it as a reactive event *)
let _ =
{unit{
Lwt.async
(fun () -> Lwt_stream.iter (fun (s : string) -> set_client_string s) %channel)
}}
in
Lwt.return
(Eliom_tools.F.html
~title:"channel_example"
~css:[["css";"channel_example.css"]]
Eliom_content.Html5.F.(body [
h2 [pcdata ("Your are logged in as user " ^ user_num)];
client_message_form ();
p [pcdata "Your message is:"];
C.node {{ R.pcdata (React.S.hold "No Message Yet" client_string)}}
])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment