diff --git a/src/counter.rs b/src/counter.rs new file mode 100644 index 0000000..7db94a8 --- /dev/null +++ b/src/counter.rs @@ -0,0 +1,50 @@ +use std::collections::HashSet; + +use lunatic::{abstract_process, ap::Config, Process}; + +pub struct Counter { + counter: i64, + subscribers: HashSet>, +} + +#[abstract_process(visibility = pub)] +impl Counter { + #[init] + pub fn init(_: Config, start: i64) -> Result { + Ok(Self { + counter: start, + subscribers: HashSet::new(), + }) + } + + #[handle_message] + pub fn subscribe(&mut self, m: Process) { + // monitor the process so we can remove it from this list when it dies + // let p = Process::spawn_link(self.counter, |capture, m: Mailbox<()>| { + // }); + + // add it to our list of subscribers + self.subscribers.insert(m); + } + + fn notify(&self) { + for s in self.subscribers.iter() { + s.send(self.counter) + } + } + + #[handle_message] + pub fn increment(&mut self) { + self.counter += 1; + } + + #[handle_message] + pub fn decrement(&mut self) { + self.counter -= 1; + } + + #[handle_request] + pub fn count(&self) -> i64 { + self.counter + } +} diff --git a/src/counter_view.rs b/src/counter_view.rs new file mode 100644 index 0000000..6f0324b --- /dev/null +++ b/src/counter_view.rs @@ -0,0 +1,63 @@ +use crate::counter::*; +use lunatic::{ap::ProcessRef, spawn}; +use serde::{Deserialize, Serialize}; +use submillisecond_live_view::prelude::*; + +#[derive(Clone, Serialize, Deserialize)] +pub struct CounterView { + global_counter: ProcessRef, + current_value: i64, +} + +impl LiveView for CounterView { + type Events = (Increment, Decrement); + + fn mount(_uri: Uri, socket: Option) -> Self { + println!("{:?}", socket.is_some()); + let global_counter = ProcessRef::::lookup(&"global_counter").unwrap(); + let current_count = global_counter.count(); + let mut result = Self { + global_counter, + current_value: current_count, + }; + spawn!(|m: Mailbox| { + loop { + result.current_value = m.receive(); + } + }); + result + } + + fn render(&self) -> Rendered { + html! { + button @click=(Increment) { "Increment" } + button @click=(Decrement) { "Decrement" } + p { "Count is " (self.current_value) } + } + } +} + +#[derive(Deserialize)] +pub struct Increment {} +impl LiveViewEvent for CounterView { + fn handle(state: &mut Self, _event: Increment) { + state.current_value += 1; + state.global_counter.increment() + } +} + +#[derive(Deserialize)] +pub struct Decrement {} +impl LiveViewEvent for CounterView { + fn handle(state: &mut Self, _event: Decrement) { + state.current_value -= 1; + state.global_counter.decrement() + } +} + +pub type Notified = i64; +impl LiveViewEvent for CounterView { + fn handle(state: &mut Self, event: Notified) { + state.current_value = event; + } +} diff --git a/src/main.rs b/src/main.rs index bd864d4..da365d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,38 +1,13 @@ -use lunatic::supervisor::{Supervisor, SupervisorConfig, SupervisorStrategy}; -use serde::{Deserialize, Serialize}; +mod counter; +mod counter_view; + +use counter::Counter; +use counter_view::CounterView; +use lunatic::supervisor::*; use submillisecond::{router, static_router, Application}; use submillisecond_live_view::prelude::*; -use lunatic::abstract_process; -use lunatic::ap::{Config, ProcessRef}; - -pub struct Counter(i64); - -#[abstract_process(visibility = pub)] -impl Counter { - #[init] - fn init(_: Config, start: i64) -> Result { - Ok(Self(start)) - } - - #[handle_message] - fn increment(&mut self) { - self.0 += 1; - } - - #[handle_message] - fn decrement(&mut self) { - self.0 -= 1; - } - - #[handle_request] - fn count(&self) -> i64 { - self.0 - } -} - struct Sup; - impl Supervisor for Sup { type Arg = (); // Start 1 child and monitor it for failures. @@ -49,48 +24,8 @@ fn main() -> std::io::Result<()> { Sup::init(&mut supconf, ()); Application::new(router! { - "/" => CounterView::handler("index.html", "#app") + "/" => CounterView::handler("./static/index.html", "#app") "/static" => static_router!("./static") }) .serve("127.0.0.1:3000") } - -#[derive(Clone, Serialize, Deserialize)] -struct CounterView { - global_counter: ProcessRef, -} - -impl LiveView for CounterView { - type Events = (Increment, Decrement); - - fn mount(_uri: Uri, _socket: Option) -> Self { - let global_counter = ProcessRef::::lookup(&"global_counter").unwrap(); - Self { global_counter } - } - - fn render(&self) -> Rendered { - html! { - button @click=(Increment) { "Increment" } - button @click=(Decrement) { "Decrement" } - p { "Count is " (self.global_counter.count()) } - } - } -} - -#[derive(Deserialize)] -struct Increment {} - -impl LiveViewEvent for CounterView { - fn handle(state: &mut Self, _event: Increment) { - state.global_counter.increment() - } -} - -#[derive(Deserialize)] -struct Decrement {} - -impl LiveViewEvent for CounterView { - fn handle(state: &mut Self, _event: Decrement) { - state.global_counter.decrement() - } -} diff --git a/index.html b/static/index.html similarity index 100% rename from index.html rename to static/index.html