From 4a2087a94e8290e32178953de4e5662adbd594fa Mon Sep 17 00:00:00 2001 From: Thomas Gideon Date: Sat, 17 Oct 2020 14:04:26 -0400 Subject: [PATCH] Add agent driven component. --- Cargo.toml | 2 +- src/alert/bus.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ src/alert/mod.rs | 4 ++++ src/alert/sub.rs | 52 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/alert/bus.rs create mode 100644 src/alert/sub.rs diff --git a/Cargo.toml b/Cargo.toml index 70e1b5a..04695dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bootstrap-rs" -version = "0.2.12" +version = "0.2.13" authors = ["Thomas Gideon "] edition = "2018" diff --git a/src/alert/bus.rs b/src/alert/bus.rs new file mode 100644 index 0000000..da80067 --- /dev/null +++ b/src/alert/bus.rs @@ -0,0 +1,61 @@ +use crate::prelude::*; +use std::collections::HashSet; +use yew::worker::{Agent, AgentLink, Context, HandlerId}; + +pub struct Bus { + link: AgentLink, + subscribers: HashSet, +} + +pub enum Request { + Primary(String), + Secondary(String), + Success(String), + Danger(String), + Warning(String), + Info(String), + Clear, +} + +impl Into> for &Request { + fn into(self) -> Option<(Color, String)> { + use Request::*; + match self { + Primary(alert) => Some((Color::Primary, alert.clone())), + Secondary(alert) => Some((Color::Secondary, alert.clone())), + Success(alert) => Some((Color::Success, alert.clone())), + Danger(alert) => Some((Color::Danger, alert.clone())), + Warning(alert) => Some((Color::Warning, alert.clone())), + Info(alert) => Some((Color::Info, alert.clone())), + Clear => None, + } + } +} + +impl Agent for Bus { + type Reach = Context; + type Message = (); + type Input = Request; + type Output = Option<(Color, String)>; + + fn create(link: AgentLink) -> Self { + let subscribers = HashSet::new(); + Self { link, subscribers } + } + + fn update(&mut self, _: Self::Message) {} + + fn handle_input(&mut self, input: Self::Input, _id: HandlerId) { + for sub in self.subscribers.iter() { + self.link.respond(*sub, (&input).into()); + } + } + + fn connected(&mut self, id: HandlerId) { + self.subscribers.insert(id); + } + + fn disconnected(&mut self, id: HandlerId) { + self.subscribers.remove(&id); + } +} diff --git a/src/alert/mod.rs b/src/alert/mod.rs index 11aafd8..5d4f3ef 100644 --- a/src/alert/mod.rs +++ b/src/alert/mod.rs @@ -1,7 +1,11 @@ +mod bus; mod props; +mod sub; use self::props::Props; use crate::{prelude::*, render}; +pub use bus::{Bus, Request}; +pub use sub::AlertSubscriber; use yew::prelude::*; pub struct Alert { diff --git a/src/alert/sub.rs b/src/alert/sub.rs new file mode 100644 index 0000000..5034f62 --- /dev/null +++ b/src/alert/sub.rs @@ -0,0 +1,52 @@ +use super::{Alert, Bus}; +use crate::prelude::*; +use yew::prelude::*; + +pub struct AlertSubscriber { + link: ComponentLink, + alert: Option<(Color, String)>, + _producer: Box>, +} + +impl Component for AlertSubscriber { + type Message = Option<(Color, String)>; + type Properties = (); + + fn create(_: Self::Properties, link: ComponentLink) -> Self { + let _producer = Bus::bridge(link.callback(|msg| msg)); + let alert = None; + Self { + link, + alert, + _producer, + } + } + + fn update(&mut self, msg: Self::Message) -> ShouldRender { + if self.alert == msg { + false + } else { + self.alert = msg; + true + } + } + + fn change(&mut self, _: Self::Properties) -> ShouldRender { + false + } + + fn view(&self) -> Html { + if let Some((color, message)) = self.alert.as_ref() { + html! { + + { message } + + } + } else { + html! {} + } + } +}