Last active
August 29, 2015 14:27
-
-
Save ThomasBrittain/bb147e0a6bf3c9d7fcf3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* 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