use crate::service::RouteService;
use yew_agent::{Agent, AgentLink, Context, HandlerId};
use std::collections::HashSet;
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Error as FmtError, Formatter};
use crate::route::{Route, RouteState};
use log::trace;
mod bridge;
pub use bridge::RouteAgentBridge;
mod dispatcher;
pub use dispatcher::RouteAgentDispatcher;
#[derive(Debug)]
pub enum Msg<STATE> {
BrowserNavigationRouteChanged(Route<STATE>), }
#[derive(Serialize, Deserialize, Debug)]
pub enum RouteRequest<T = ()> {
ReplaceRoute(Route<T>),
ReplaceRouteNoBroadcast(Route<T>),
ChangeRoute(Route<T>),
ChangeRouteNoBroadcast(Route<T>),
GetCurrentRoute,
}
pub struct RouteAgent<STATE = ()>
where
STATE: RouteState,
{
link: AgentLink<RouteAgent<STATE>>,
route_service: RouteService<STATE>,
subscribers: HashSet<HandlerId>,
}
impl<STATE: RouteState> Debug for RouteAgent<STATE> {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
f.debug_struct("RouteAgent")
.field("link", &"-")
.field("route_service", &self.route_service)
.field("subscribers", &self.subscribers.len())
.finish()
}
}
impl<STATE> Agent for RouteAgent<STATE>
where
STATE: RouteState,
{
type Input = RouteRequest<STATE>;
type Message = Msg<STATE>;
type Output = Route<STATE>;
type Reach = Context<Self>;
fn create(link: AgentLink<RouteAgent<STATE>>) -> Self {
let callback = link.callback(Msg::BrowserNavigationRouteChanged);
let mut route_service = RouteService::new();
route_service.register_callback(callback);
RouteAgent {
link,
route_service,
subscribers: HashSet::new(),
}
}
fn update(&mut self, msg: Self::Message) {
match msg {
Msg::BrowserNavigationRouteChanged(route) => {
trace!("Browser navigated");
for sub in &self.subscribers {
self.link.respond(*sub, route.clone());
}
}
}
}
fn connected(&mut self, id: HandlerId) {
if id.is_respondable() {
self.subscribers.insert(id);
}
}
fn handle_input(&mut self, msg: Self::Input, who: HandlerId) {
match msg {
RouteRequest::ReplaceRoute(route) => {
let route_string: String = route.to_string();
self.route_service.replace_route(&route_string, route.state);
let route = self.route_service.get_route();
for sub in &self.subscribers {
self.link.respond(*sub, route.clone());
}
}
RouteRequest::ReplaceRouteNoBroadcast(route) => {
let route_string: String = route.to_string();
self.route_service.replace_route(&route_string, route.state);
}
RouteRequest::ChangeRoute(route) => {
let route_string: String = route.to_string();
self.route_service.set_route(&route_string, route.state);
let route = self.route_service.get_route();
for sub in &self.subscribers {
self.link.respond(*sub, route.clone());
}
}
RouteRequest::ChangeRouteNoBroadcast(route) => {
let route_string: String = route.to_string();
self.route_service.set_route(&route_string, route.state);
}
RouteRequest::GetCurrentRoute => {
let route = self.route_service.get_route();
self.link.respond(who, route);
}
}
}
fn disconnected(&mut self, id: HandlerId) {
if id.is_respondable() {
self.subscribers.remove(&id);
}
}
}