yew_agent/worker/
hooks.rs1use std::any::type_name;
2use std::fmt;
3use std::ops::Deref;
4use std::rc::Rc;
5
6use wasm_bindgen::prelude::*;
7use yew::prelude::*;
8
9use crate::utils::{BridgeIdState, OutputsAction, OutputsState};
10use crate::worker::provider::WorkerProviderState;
11use crate::worker::{Worker, WorkerBridge};
12
13pub struct UseWorkerBridgeHandle<T>
15where
16 T: Worker,
17{
18 inner: Rc<WorkerBridge<T>>,
19 ctr: UseReducerDispatcher<BridgeIdState>,
20}
21
22impl<T> UseWorkerBridgeHandle<T>
23where
24 T: Worker,
25{
26 pub fn send(&self, msg: T::Input) {
28 self.inner.send(msg);
29 }
30
31 pub fn reset(&self) {
35 self.ctr.dispatch(());
36 }
37}
38
39impl<T> Clone for UseWorkerBridgeHandle<T>
40where
41 T: Worker,
42{
43 fn clone(&self) -> Self {
44 Self {
45 inner: self.inner.clone(),
46 ctr: self.ctr.clone(),
47 }
48 }
49}
50
51impl<T> fmt::Debug for UseWorkerBridgeHandle<T>
52where
53 T: Worker,
54{
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 f.debug_struct(type_name::<Self>())
57 .field("inner", &self.inner)
58 .finish()
59 }
60}
61
62impl<T> PartialEq for UseWorkerBridgeHandle<T>
63where
64 T: Worker,
65{
66 fn eq(&self, rhs: &Self) -> bool {
67 self.inner == rhs.inner
68 }
69}
70
71#[hook]
80pub fn use_worker_bridge<T, F>(on_output: F) -> UseWorkerBridgeHandle<T>
81where
82 T: Worker + 'static,
83 F: Fn(T::Output) + 'static,
84{
85 let ctr = use_reducer(BridgeIdState::default);
86
87 let worker_state = use_context::<Rc<WorkerProviderState<T>>>()
88 .expect_throw("cannot find a provider for current agent.");
89
90 let on_output = Rc::new(on_output);
91
92 let on_output_clone = on_output.clone();
93 let on_output_ref = use_mut_ref(move || on_output_clone);
94
95 {
97 let mut on_output_ref = on_output_ref.borrow_mut();
98 *on_output_ref = on_output;
99 }
100
101 let bridge = use_memo((worker_state, ctr.inner), |(state, _ctr)| {
102 state.create_bridge(Callback::from(move |output| {
103 let on_output = on_output_ref.borrow().clone();
104 on_output(output);
105 }))
106 });
107
108 UseWorkerBridgeHandle {
109 inner: bridge,
110 ctr: ctr.dispatcher(),
111 }
112}
113
114pub struct UseWorkerSubscriptionHandle<T>
116where
117 T: Worker,
118{
119 bridge: UseWorkerBridgeHandle<T>,
120 outputs: Vec<Rc<T::Output>>,
121 ctr: usize,
122}
123
124impl<T> UseWorkerSubscriptionHandle<T>
125where
126 T: Worker,
127{
128 pub fn send(&self, msg: T::Input) {
130 self.bridge.send(msg);
131 }
132
133 pub fn reset(&self) {
138 self.bridge.reset();
139 }
140}
141
142impl<T> Clone for UseWorkerSubscriptionHandle<T>
143where
144 T: Worker,
145{
146 fn clone(&self) -> Self {
147 Self {
148 bridge: self.bridge.clone(),
149 outputs: self.outputs.clone(),
150 ctr: self.ctr,
151 }
152 }
153}
154
155impl<T> fmt::Debug for UseWorkerSubscriptionHandle<T>
156where
157 T: Worker,
158 T::Output: fmt::Debug,
159{
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 f.debug_struct(type_name::<Self>())
162 .field("bridge", &self.bridge)
163 .field("outputs", &self.outputs)
164 .finish()
165 }
166}
167
168impl<T> Deref for UseWorkerSubscriptionHandle<T>
169where
170 T: Worker,
171{
172 type Target = [Rc<T::Output>];
173
174 fn deref(&self) -> &[Rc<T::Output>] {
175 &self.outputs
176 }
177}
178
179impl<T> PartialEq for UseWorkerSubscriptionHandle<T>
180where
181 T: Worker,
182{
183 fn eq(&self, rhs: &Self) -> bool {
184 self.bridge == rhs.bridge && self.ctr == rhs.ctr
185 }
186}
187
188#[hook]
192pub fn use_worker_subscription<T>() -> UseWorkerSubscriptionHandle<T>
193where
194 T: Worker + 'static,
195{
196 let outputs = use_reducer(OutputsState::default);
197
198 let bridge = {
199 let outputs = outputs.clone();
200 use_worker_bridge::<T, _>(move |output| {
201 outputs.dispatch(OutputsAction::Push(Rc::new(output)))
202 })
203 };
204
205 {
206 let outputs_dispatcher = outputs.dispatcher();
207 use_effect_with(bridge.clone(), move |_| {
208 outputs_dispatcher.dispatch(OutputsAction::Reset);
209
210 || {}
211 });
212 }
213
214 UseWorkerSubscriptionHandle {
215 bridge,
216 outputs: outputs.inner.clone(),
217 ctr: outputs.ctr,
218 }
219}