Add agent driven component.

This commit is contained in:
Thomas Gideon 2020-10-17 14:04:26 -04:00
parent d19f9051c2
commit 4a2087a94e
4 changed files with 118 additions and 1 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "bootstrap-rs"
version = "0.2.12"
version = "0.2.13"
authors = ["Thomas Gideon <cmdln@thecommandline.net>"]
edition = "2018"

61
src/alert/bus.rs Normal file
View File

@ -0,0 +1,61 @@
use crate::prelude::*;
use std::collections::HashSet;
use yew::worker::{Agent, AgentLink, Context, HandlerId};
pub struct Bus {
link: AgentLink<Bus>,
subscribers: HashSet<HandlerId>,
}
pub enum Request {
Primary(String),
Secondary(String),
Success(String),
Danger(String),
Warning(String),
Info(String),
Clear,
}
impl Into<Option<(Color, String)>> 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<Self>;
type Message = ();
type Input = Request;
type Output = Option<(Color, String)>;
fn create(link: AgentLink<Self>) -> 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);
}
}

View File

@ -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 {

52
src/alert/sub.rs Normal file
View File

@ -0,0 +1,52 @@
use super::{Alert, Bus};
use crate::prelude::*;
use yew::prelude::*;
pub struct AlertSubscriber {
link: ComponentLink<Self>,
alert: Option<(Color, String)>,
_producer: Box<dyn Bridge<Bus>>,
}
impl Component for AlertSubscriber {
type Message = Option<(Color, String)>;
type Properties = ();
fn create(_: Self::Properties, link: ComponentLink<Self>) -> 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! {
<Alert
on_close=self.link.callback(|_| None)
color=color
>
{ message }
</Alert>
}
} else {
html! {}
}
}
}