diff options
Diffstat (limited to 'examples/server_demo/src/demo/socket.gleam')
-rw-r--r-- | examples/server_demo/src/demo/socket.gleam | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/examples/server_demo/src/demo/socket.gleam b/examples/server_demo/src/demo/socket.gleam new file mode 100644 index 0000000..bc43962 --- /dev/null +++ b/examples/server_demo/src/demo/socket.gleam @@ -0,0 +1,78 @@ +// IMPORTS --------------------------------------------------------------------- + +import demo/app +import gleam/bit_array +import gleam/erlang/process.{type Subject} +import gleam/function.{identity} +import gleam/http/request.{type Request as HttpRequest} +import gleam/http/response.{type Response as HttpResponse} +import gleam/json +import gleam/option.{Some} +import gleam/otp/actor +import gleam/result +import lustre.{type Action, type ServerComponent} +import lustre/element.{type Patch} +import lustre/server +import mist.{ + type Connection, type ResponseData, type WebsocketConnection, + type WebsocketMessage, +} + +// + +pub fn handle(req: HttpRequest(Connection)) -> HttpResponse(ResponseData) { + mist.websocket(req, update, init, function.constant(Nil)) +} + +type Model(flags, model, msg) { + Model(self: Subject(Patch(msg)), app: Subject(Action(ServerComponent, msg))) +} + +fn init(_) { + let assert Ok(app) = + lustre.component(app.init, app.update, app.view, app.on_attribute_change()) + |> lustre.start_actor(0) + let self = process.new_subject() + let model = Model(self, app) + let selector = process.selecting(process.new_selector(), self, identity) + + actor.send(app, lustre.add_renderer(process.self(), process.send(self, _))) + #(model, Some(selector)) +} + +fn update( + model: Model(flags, model, msg), + conn: WebsocketConnection, + msg: WebsocketMessage(Patch(a)), +) { + case msg { + mist.Text(bits) -> { + let _ = { + use dyn <- json.decode_bits(bits) + use action <- result.try(server.decode_action(dyn)) + + actor.send(model.app, action) + Ok(Nil) + } + + actor.continue(model) + } + mist.Binary(_) -> actor.continue(model) + mist.Closed -> { + actor.send(model.app, lustre.remove_renderer(process.self())) + actor.continue(model) + } + mist.Shutdown -> { + actor.send(model.app, lustre.shutdown()) + actor.Stop(process.Normal) + } + mist.Custom(patch) -> { + element.encode_patch(patch) + |> json.to_string + |> bit_array.from_string + |> mist.send_text_frame(conn, _) + + actor.continue(model) + } + } +} |