orbit/component/
lifecycle.rs1use std::sync::{Arc, Mutex};
4
5use crate::component::{
6 ComponentError, ComponentInstance, Context, LifecyclePhase, UnmountContext, UnmountReason,
7};
8
9pub struct LifecycleManager {
11 phase: LifecyclePhase,
13
14 component: Arc<Mutex<ComponentInstance>>,
16
17 context: Context,
19}
20
21impl LifecycleManager {
22 pub fn new(component: ComponentInstance, context: Context) -> Self {
24 Self {
25 phase: LifecyclePhase::Created,
26 component: Arc::new(Mutex::new(component)),
27 context: context.clone(),
28 }
29 }
30
31 pub fn current_phase(&self) -> LifecyclePhase {
33 self.phase
34 }
35
36 pub fn get_component(&self) -> &Arc<Mutex<ComponentInstance>> {
38 &self.component
39 }
40 pub fn initialize(&mut self) -> Result<(), ComponentError> {
42 if self.phase != LifecyclePhase::Created {
43 return Err(ComponentError::InvalidLifecycleTransition(
44 self.phase,
45 "initialize".to_string(),
46 ));
47 }
48 let result = if let Ok(component_instance) = self.component.lock() {
49 if let Ok(mut inner_component) = component_instance.instance.lock() {
50 inner_component.any_initialize()
52 } else {
53 Err(ComponentError::LockError(
54 "Failed to lock inner component for initialization".to_string(),
55 ))
56 }
57 } else {
58 Err(ComponentError::LockError(
59 "Failed to lock component instance for initialization".to_string(),
60 ))
61 };
62
63 if result.is_ok() {
64 self.context.set_lifecycle_phase(LifecyclePhase::Created);
66 }
67
68 result
69 }
70 pub fn mount(&mut self) -> Result<(), ComponentError> {
72 if self.phase != LifecyclePhase::Created {
73 return Err(ComponentError::InvalidLifecycleTransition(
74 self.phase,
75 "mount".to_string(),
76 ));
77 }
78
79 let mount_context = crate::component::MountContext::new(
81 self.component
82 .lock()
83 .map_err(|_| {
84 ComponentError::LockError(
85 "Failed to lock component for mount context".to_string(),
86 )
87 })?
88 .instance
89 .lock()
90 .map_err(|_| {
91 ComponentError::LockError(
92 "Failed to lock inner component for mount context".to_string(),
93 )
94 })?
95 .component_id(),
96 );
97
98 let before_mount_result = {
100 let component_instance = self.component.lock().map_err(|_| {
101 ComponentError::LockError("Failed to lock component for before_mount".to_string())
102 })?;
103
104 let mut inner_component = component_instance.instance.lock().map_err(|_| {
105 ComponentError::LockError(
106 "Failed to lock inner component for before_mount".to_string(),
107 )
108 })?;
109
110 inner_component.any_before_mount()
111 };
112
113 before_mount_result?;
114
115 self.phase = LifecyclePhase::Mounting;
117 self.context.set_lifecycle_phase(LifecyclePhase::Mounting);
118
119 let result = {
121 let component_instance = self.component.lock().map_err(|_| {
122 ComponentError::LockError("Failed to lock component for mount".to_string())
123 })?;
124
125 let mut inner_component = component_instance.instance.lock().map_err(|_| {
127 ComponentError::LockError("Failed to lock inner component for mount".to_string())
128 })?;
129
130 self.context
132 .execute_lifecycle_hooks(LifecyclePhase::Mounting, &mut **inner_component);
133
134 inner_component.any_on_mount(&mount_context)?;
136
137 inner_component.any_mount()
139 };
140
141 if result.is_ok() {
143 self.phase = LifecyclePhase::Mounted;
144 self.context.set_lifecycle_phase(LifecyclePhase::Mounted);
145
146 let after_mount_result = {
148 let component_instance = self.component.lock().map_err(|_| {
149 ComponentError::LockError(
150 "Failed to lock component for after_mount".to_string(),
151 )
152 })?;
153
154 let mut inner_component = component_instance.instance.lock().map_err(|_| {
155 ComponentError::LockError(
156 "Failed to lock inner component for after_mount".to_string(),
157 )
158 })?;
159
160 inner_component.any_after_mount()
161 };
162
163 if let Err(e) = after_mount_result {
164 eprintln!("Warning: after_mount failed for component: {e}");
166 }
167 }
168
169 if result.is_err() {
170 self.phase = LifecyclePhase::Created;
172 self.context.set_lifecycle_phase(LifecyclePhase::Created);
173 }
174
175 result
176 }
177
178 pub fn update(
180 &mut self,
181 props: Box<dyn crate::component::Props>,
182 ) -> Result<(), ComponentError> {
183 if self.phase != LifecyclePhase::Mounted {
184 return Err(ComponentError::InvalidLifecycleTransition(
185 self.phase,
186 "update".to_string(),
187 ));
188 }
189
190 self.phase = LifecyclePhase::BeforeUpdate;
192 self.context
193 .set_lifecycle_phase(LifecyclePhase::BeforeUpdate);
194
195 let result = {
197 let mut component = self.component.lock().map_err(|_| {
198 ComponentError::LockError("Failed to lock component for update".to_string())
199 })?;
200
201 {
203 let mut instance = component.instance.lock().map_err(|_| {
204 ComponentError::LockError(
205 "Failed to lock component instance for update".to_string(),
206 )
207 })?;
208
209 self.context
210 .execute_lifecycle_hooks(LifecyclePhase::BeforeUpdate, &mut **instance);
211
212 let props_for_before_update = props.box_clone();
214 instance.any_before_update(props_for_before_update)?;
215 }
216
217 {
219 let mut instance = component.instance.lock().map_err(|_| {
220 ComponentError::LockError(
221 "Failed to lock component instance for update".to_string(),
222 )
223 })?;
224
225 let props_for_update = props.box_clone();
227 instance.any_update(props_for_update)?;
229 }
230
231 component.props = props;
233
234 {
236 let mut instance = component.instance.lock().map_err(|_| {
237 ComponentError::LockError(
238 "Failed to lock component instance for after_update".to_string(),
239 )
240 })?;
241
242 instance.any_after_update()
243 }
244 };
245
246 if result.is_ok() {
247 self.phase = LifecyclePhase::Mounted;
249 self.context.set_lifecycle_phase(LifecyclePhase::Mounted);
250 }
251
252 result
253 }
254
255 pub fn unmount(&mut self) -> Result<(), ComponentError> {
257 if self.phase != LifecyclePhase::Mounted {
258 return Err(ComponentError::InvalidLifecycleTransition(
259 self.phase,
260 "unmount".to_string(),
261 ));
262 }
263
264 self.phase = LifecyclePhase::BeforeUnmount;
266 self.context
267 .set_lifecycle_phase(LifecyclePhase::BeforeUnmount);
268
269 if let Ok(component_instance) = self.component.lock() {
271 let mut inner_component = component_instance.instance.lock().map_err(|_| {
272 ComponentError::LockError(
273 "Failed to lock inner component for before_unmount".to_string(),
274 )
275 })?;
276
277 self.context
278 .execute_lifecycle_hooks(LifecyclePhase::BeforeUnmount, &mut **inner_component);
279
280 inner_component.any_before_unmount()?;
282 } else {
283 return Err(ComponentError::LockError(
284 "Failed to lock component instance for before_unmount".to_string(),
285 ));
286 }
287
288 self.phase = LifecyclePhase::Unmounting;
290 self.context.set_lifecycle_phase(LifecyclePhase::Unmounting);
291
292 let unmount_context = UnmountContext::new(
294 self.component
295 .lock()
296 .map_err(|_| {
297 ComponentError::LockError(
298 "Failed to lock component for unmount context".to_string(),
299 )
300 })?
301 .instance
302 .lock()
303 .map_err(|_| {
304 ComponentError::LockError(
305 "Failed to lock inner component for unmount context".to_string(),
306 )
307 })?
308 .component_id(),
309 UnmountReason::Removed,
310 );
311
312 let unmount_result = if let Ok(component_instance) = self.component.lock() {
313 let mut inner_component = component_instance.instance.lock().map_err(|_| {
314 ComponentError::LockError("Failed to lock inner component for unmount".to_string())
315 })?;
316
317 self.context
319 .execute_lifecycle_hooks(LifecyclePhase::Unmounting, &mut **inner_component);
320
321 inner_component.any_on_unmount(&unmount_context)?;
323
324 inner_component.any_unmount()
326 } else {
327 Err(ComponentError::LockError(
328 "Failed to lock component instance during unmounting".to_string(),
329 ))
330 };
331
332 if unmount_result.is_ok() {
333 self.phase = LifecyclePhase::Unmounted;
335 self.context.set_lifecycle_phase(LifecyclePhase::Unmounted);
336
337 let after_unmount_result = if let Ok(component_instance) = self.component.lock() {
339 let mut inner_component = component_instance.instance.lock().map_err(|_| {
340 ComponentError::LockError(
341 "Failed to lock inner component for after_unmount".to_string(),
342 )
343 })?;
344
345 inner_component.any_after_unmount()
346 } else {
347 Err(ComponentError::LockError(
348 "Failed to lock component instance for after_unmount".to_string(),
349 ))
350 };
351
352 if let Err(e) = after_unmount_result {
353 eprintln!("Warning: after_unmount failed for component: {e}");
355 }
356 }
357
358 unmount_result
359 }
360
361 pub fn handle_updates(&mut self) -> Result<(), ComponentError> {
363 if self.phase != LifecyclePhase::Mounted {
364 return Err(ComponentError::InvalidLifecycleTransition(
365 self.phase,
366 "handle_updates".to_string(),
367 ));
368 }
369
370 Ok(())
373 }
374
375 pub fn render(&self) -> Result<Vec<crate::component::Node>, ComponentError> {
377 if self.phase != LifecyclePhase::Mounted {
378 return Err(ComponentError::InvalidLifecycleTransition(
379 self.phase,
380 "render".to_string(),
381 ));
382 }
383
384 if let Ok(component_instance) = self.component.lock() {
385 let _inner_component = component_instance.instance.lock().map_err(|_| {
386 ComponentError::LockError("Failed to lock inner component for render".to_string())
387 })?;
388
389 Ok(vec![])
392 } else {
393 Err(ComponentError::LockError(
394 "Failed to lock component instance for rendering".to_string(),
395 ))
396 }
397 }
398
399 pub fn get_context(&self) -> &Context {
401 &self.context
402 }
403}