yew_router_nested/agent/
mod.rs1use crate::service::RouteService;
6
7use yew_agent::{Agent, AgentLink, Context, HandlerId};
8
9use std::collections::HashSet;
10
11use serde::{Deserialize, Serialize};
12use std::fmt::{Debug, Error as FmtError, Formatter};
13
14use crate::route::{Route, RouteState};
15use log::trace;
16
17mod bridge;
18pub use bridge::RouteAgentBridge;
19
20mod dispatcher;
21pub use dispatcher::RouteAgentDispatcher;
22
23#[derive(Debug)]
25pub enum Msg<STATE> {
26 BrowserNavigationRouteChanged(Route<STATE>), }
29
30#[derive(Serialize, Deserialize, Debug)]
32pub enum RouteRequest<T = ()> {
33 ReplaceRoute(Route<T>),
36 ReplaceRouteNoBroadcast(Route<T>),
39 ChangeRoute(Route<T>),
41 ChangeRouteNoBroadcast(Route<T>),
44 GetCurrentRoute,
46}
47
48pub struct RouteAgent<STATE = ()>
59where
60 STATE: RouteState,
61{
62 link: AgentLink<RouteAgent<STATE>>,
65 route_service: RouteService<STATE>,
67 subscribers: HashSet<HandlerId>,
71}
72
73impl<STATE: RouteState> Debug for RouteAgent<STATE> {
74 fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
75 f.debug_struct("RouteAgent")
76 .field("link", &"-")
77 .field("route_service", &self.route_service)
78 .field("subscribers", &self.subscribers.len())
79 .finish()
80 }
81}
82
83impl<STATE> Agent for RouteAgent<STATE>
84where
85 STATE: RouteState,
86{
87 type Input = RouteRequest<STATE>;
88 type Message = Msg<STATE>;
89 type Output = Route<STATE>;
90 type Reach = Context<Self>;
91
92 fn create(link: AgentLink<RouteAgent<STATE>>) -> Self {
93 let callback = link.callback(Msg::BrowserNavigationRouteChanged);
94 let mut route_service = RouteService::new();
95 route_service.register_callback(callback);
96
97 RouteAgent {
98 link,
99 route_service,
100 subscribers: HashSet::new(),
101 }
102 }
103
104 fn update(&mut self, msg: Self::Message) {
105 match msg {
106 Msg::BrowserNavigationRouteChanged(route) => {
107 trace!("Browser navigated");
108 for sub in &self.subscribers {
109 self.link.respond(*sub, route.clone());
110 }
111 }
112 }
113 }
114
115 fn connected(&mut self, id: HandlerId) {
116 if id.is_respondable() {
117 self.subscribers.insert(id);
118 }
119 }
120
121 fn handle_input(&mut self, msg: Self::Input, who: HandlerId) {
122 match msg {
123 RouteRequest::ReplaceRoute(route) => {
124 let route_string: String = route.to_string();
125 self.route_service.replace_route(&route_string, route.state);
126 let route = self.route_service.get_route();
127 for sub in &self.subscribers {
128 self.link.respond(*sub, route.clone());
129 }
130 }
131 RouteRequest::ReplaceRouteNoBroadcast(route) => {
132 let route_string: String = route.to_string();
133 self.route_service.replace_route(&route_string, route.state);
134 }
135 RouteRequest::ChangeRoute(route) => {
136 let route_string: String = route.to_string();
137 self.route_service.set_route(&route_string, route.state);
139 let route = self.route_service.get_route();
141 for sub in &self.subscribers {
143 self.link.respond(*sub, route.clone());
144 }
145 }
146 RouteRequest::ChangeRouteNoBroadcast(route) => {
147 let route_string: String = route.to_string();
148 self.route_service.set_route(&route_string, route.state);
149 }
150 RouteRequest::GetCurrentRoute => {
151 let route = self.route_service.get_route();
152 self.link.respond(who, route);
153 }
154 }
155 }
156
157 fn disconnected(&mut self, id: HandlerId) {
158 if id.is_respondable() {
159 self.subscribers.remove(&id);
160 }
161 }
162}