yew_state/component/
wrapper.rs1use std::rc::Rc;
3
4use yew::{
5 agent::{Bridge, Bridged},
6 prelude::*,
7};
8
9use crate::handle::{Handle, SharedState, WrapperHandle};
10use crate::handler::{HandlerLink, Reduction, ReductionOnce, StateHandler};
11use crate::service::*;
12
13type PropHandle<SHARED> = <SHARED as SharedState>::Handle;
14type PropHandler<SHARED> = <PropHandle<SHARED> as Handle>::Handler;
15type Model<T> = <PropHandler<T> as StateHandler>::Model;
16
17#[doc(hidden)]
18pub enum SharedStateComponentMsg<SHARED>
19where
20 SHARED: SharedState,
21 <SHARED as SharedState>::Handle: WrapperHandle,
22 PropHandler<SHARED>: 'static,
23{
24 SetLocal(Rc<Model<SHARED>>),
27 SetLink(HandlerLink<PropHandler<SHARED>>),
28 Apply(Reduction<Model<SHARED>>),
30 ApplyOnce(ReductionOnce<Model<SHARED>>),
31 Ignore,
33}
34
35pub struct SharedStateComponent<C, SCOPE = PropHandler<<C as Component>::Properties>>
53where
54 C: Component,
55 C::Properties: SharedState + Clone,
56 PropHandle<C::Properties>: WrapperHandle,
57 SCOPE: 'static,
58{
59 props: C::Properties,
60 bridge: Box<dyn Bridge<StateService<PropHandler<C::Properties>, SCOPE>>>,
61 link_set: bool,
62 state_set: bool,
63}
64
65impl<C, SCOPE> Component for SharedStateComponent<C, SCOPE>
66where
67 C: Component,
68 C::Properties: SharedState + Clone,
69 <C::Properties as SharedState>::Handle: Clone + WrapperHandle,
70{
71 type Message = SharedStateComponentMsg<C::Properties>;
72 type Properties = C::Properties;
73
74 fn create(mut props: Self::Properties, link: ComponentLink<Self>) -> Self {
75 use SharedStateComponentMsg::*;
76 let callback = link.callback(|msg| match msg {
78 ServiceOutput::Service(ServiceResponse::State(state)) => SetLocal(state),
79 ServiceOutput::Service(ServiceResponse::Link(link)) => SetLink(link),
80 ServiceOutput::Handler(_) => Ignore,
81 });
82 let mut bridge = StateService::bridge(callback);
83 bridge.send(ServiceInput::Service(ServiceRequest::Subscribe));
85 props
87 .handle()
88 .set_callbacks(link.callback(Apply), link.callback(ApplyOnce));
89
90 Self {
91 props,
92 bridge,
93 state_set: Default::default(),
94 link_set: Default::default(),
95 }
96 }
97
98 fn update(&mut self, msg: Self::Message) -> ShouldRender {
99 use SharedStateComponentMsg::*;
100 match msg {
101 Apply(reduce) => {
102 self.bridge
103 .send(ServiceInput::Service(ServiceRequest::Apply(reduce)));
104 false
105 }
106 ApplyOnce(reduce) => {
107 self.bridge
108 .send(ServiceInput::Service(ServiceRequest::ApplyOnce(reduce)));
109 false
110 }
111 SetLocal(state) => {
112 self.props.handle().set_state(state);
113 self.state_set = true;
114 true
115 }
116 SetLink(link) => {
117 self.props.handle().set_link(link);
118 self.link_set = true;
119 true
120 }
121 Ignore => false,
122 }
123 }
124
125 fn change(&mut self, mut props: Self::Properties) -> ShouldRender {
126 *props.handle() = self.props.handle().clone();
127 self.props = props;
128 true
129 }
130
131 fn view(&self) -> Html {
132 if self.link_set && self.state_set {
133 let props = self.props.clone();
134 html! {
135 <C with props />
136 }
137 } else {
138 html! {}
139 }
140 }
141}