1- use std:: future:: Future ;
1+ use std:: { future:: Future , task :: Poll } ;
22
3- use frender_html:: { dom:: ProvideRenderContext , CsrElement as Element , RenderHtml , RenderState } ;
3+ use frender_html:: {
4+ dom:: { ui_handle:: UiHandle as _, ProvideRenderContext } ,
5+ experimental:: {
6+ PinMutRenderInitStates , PinnedRenderStateKind , PinnedRenderStateKindPollRender as _,
7+ RenderStates ,
8+ } ,
9+ CsrElement , RenderHtml , StateUnmount as _,
10+ } ;
11+
12+ enum ElementOrUiHandle < E , UH > {
13+ Taken ,
14+ Element ( E ) ,
15+ UiHandle ( UH ) ,
16+ }
17+
18+ impl < E , UH > ElementOrUiHandle < E , UH > {
19+ fn as_mut_ui_handle_or_insert ( & mut self , f : impl FnOnce ( E ) -> UH ) -> & mut UH {
20+ match self {
21+ ElementOrUiHandle :: Taken => unreachable ! ( ) ,
22+ ElementOrUiHandle :: Element ( _) => {
23+ let this = std:: mem:: replace ( self , Self :: Taken ) ;
24+ let Self :: Element ( element) = this else {
25+ unreachable ! ( )
26+ } ;
27+
28+ * self = Self :: UiHandle ( f ( element) ) ;
29+
30+ if let ElementOrUiHandle :: UiHandle ( this) = self {
31+ this
32+ } else {
33+ unreachable ! ( )
34+ }
35+ }
36+ ElementOrUiHandle :: UiHandle ( this) => this,
37+ }
38+ }
39+
40+ fn take_ui_handle ( & mut self ) -> UH {
41+ if let ElementOrUiHandle :: UiHandle ( this) = std:: mem:: replace ( self , Self :: Taken ) {
42+ this
43+ } else {
44+ unreachable ! ( )
45+ }
46+ }
47+ }
448
549pin_project_lite:: pin_project!(
6- pub struct RenderElement <P : ProvideRenderContext , E : Element , Stop = std:: future:: Pending <( ) >>
50+ pub struct RenderElement <
51+ P : ProvideRenderContext ,
52+ E : CsrElement ,
53+ Stop = std:: future:: Pending <( ) >,
54+ >
755 where
856 P :: Renderer : RenderHtml ,
957 {
1058 p: P ,
11- element: Option <E >,
59+ element: ElementOrUiHandle <
60+ E ,
61+ <E :: RenderStateKind as PinnedRenderStateKind >:: PinnedUiHandle <P :: Renderer >,
62+ >,
63+ #[ pin]
64+ non_reactive_state:
65+ <E :: RenderStateKind as PinnedRenderStateKind >:: PinnedNonReactiveState <P :: Renderer >,
1266 #[ pin]
13- state:
14- <E :: RenderStateKind as frender_html:: RenderStateKindPinned >:: RenderState <P :: Renderer >,
67+ reactive_state: <E :: RenderStateKind as PinnedRenderStateKind >:: PinnedReactiveState ,
1568 #[ pin]
1669 stop: Stop ,
1770 }
1871) ;
1972
20- impl < P : ProvideRenderContext , E : Element > RenderElement < P , E >
73+ impl < P : ProvideRenderContext , E : CsrElement > RenderElement < P , E >
2174where
2275 P :: Renderer : RenderHtml ,
2376{
@@ -26,49 +79,69 @@ where
2679 }
2780}
2881
29- impl < P : ProvideRenderContext , E : Element , Stop > RenderElement < P , E , Stop >
82+ impl < P : ProvideRenderContext , E : CsrElement , Stop > RenderElement < P , E , Stop >
3083where
3184 P :: Renderer : RenderHtml ,
3285{
3386 pub fn new_with_stop ( render_context : P , element : E , stop : Stop ) -> Self {
3487 Self {
3588 p : render_context,
36- element : Some ( element) ,
37- state : Default :: default ( ) ,
89+ element : ElementOrUiHandle :: Element ( element) ,
90+ non_reactive_state : Default :: default ( ) ,
91+ reactive_state : Default :: default ( ) ,
3892 stop,
3993 }
4094 }
4195}
4296
43- impl < P : ProvideRenderContext , E : Element , Stop : Future < Output = ( ) > > std:: future:: Future
97+ impl < P : ProvideRenderContext , E : CsrElement , Stop : Future < Output = ( ) > > std:: future:: Future
4498 for RenderElement < P , E , Stop >
4599where
46100 P :: Renderer : RenderHtml ,
47101{
48102 type Output = ( ) ;
49103
50- fn poll (
51- self : std:: pin:: Pin < & mut Self > ,
52- cx : & mut std:: task:: Context < ' _ > ,
53- ) -> std:: task:: Poll < Self :: Output > {
104+ fn poll ( self : std:: pin:: Pin < & mut Self > , cx : & mut std:: task:: Context < ' _ > ) -> Poll < Self :: Output > {
54105 let mut this = self . project ( ) ;
55106
56- if let Some ( element) = this. element . take ( ) {
57- this. p . provide_render_context ( |render_context| {
58- element. render_update ( render_context, this. state . as_mut ( ) )
59- } ) ;
107+ if let ElementOrUiHandle :: Taken = this. element {
108+ return Poll :: Ready ( ( ) ) ;
60109 }
61110
62- if let std:: task:: Poll :: Pending = this. state . as_mut ( ) . poll_render ( this. p . renderer_mut ( ) , cx)
63- {
64- return std:: task:: Poll :: Pending ;
111+ let ui_handle = this. element . as_mut_ui_handle_or_insert ( |element| {
112+ this. p . provide_render_context ( |render_context| {
113+ element. pinned_render_init (
114+ render_context,
115+ PinMutRenderInitStates {
116+ non_reactive_state : this. non_reactive_state . as_mut ( ) ,
117+ reactive_state : this. reactive_state . as_mut ( ) ,
118+ } ,
119+ )
120+ } )
121+ } ) ;
122+
123+ if let Poll :: Pending = <E :: RenderStateKind >:: pinned_poll_render (
124+ this. p . renderer_mut ( ) ,
125+ RenderStates {
126+ ui_handle,
127+ non_reactive_state : this. non_reactive_state . as_mut ( ) ,
128+ reactive_state : this. reactive_state . as_mut ( ) ,
129+ } ,
130+ cx,
131+ ) {
132+ return Poll :: Pending ;
65133 }
66134
67- if let std:: task:: Poll :: Ready ( ( ) ) = this. stop . poll ( cx) {
68- this. state . unmount ( this. p . renderer_mut ( ) ) ;
69- return std:: task:: Poll :: Ready ( ( ) ) ;
135+ if let Poll :: Ready ( ( ) ) = this. stop . poll ( cx) {
136+ // The unmount order is the same as EitherElement accidentally
137+ // (This is not considered as a feature and might change in the future)
138+ this. non_reactive_state . set ( Default :: default ( ) ) ;
139+ this. reactive_state . as_mut ( ) . state_unmount ( ) ;
140+ this. reactive_state . set ( Default :: default ( ) ) ;
141+ this. element . take_ui_handle ( ) . unmount ( this. p . renderer_mut ( ) ) ;
142+ return Poll :: Ready ( ( ) ) ;
70143 }
71144
72- std :: task :: Poll :: Pending
145+ Poll :: Pending
73146 }
74147}
0 commit comments