@@ -21,19 +21,23 @@ use crate::{
21
21
websys_bridge,
22
22
} ;
23
23
24
+ mod alias;
25
+ mod builder;
26
+
27
+ pub use alias:: * ;
28
+ pub use builder:: { Builder as AppBuilder , Init , Initializer , UrlHandling } ;
29
+
24
30
pub enum Effect < Ms , GMs > {
25
31
Msg ( Ms ) ,
26
32
Cmd ( Box < dyn Future < Item = Ms , Error = Ms > + ' static > ) ,
27
33
GMsg ( GMs ) ,
28
34
GCmd ( Box < dyn Future < Item = GMs , Error = GMs > + ' static > ) ,
29
35
}
30
-
31
36
impl < Ms , GMs > From < Ms > for Effect < Ms , GMs > {
32
37
fn from ( message : Ms ) -> Self {
33
38
Effect :: Msg ( message)
34
39
}
35
40
}
36
-
37
41
impl < Ms : ' static , OtherMs : ' static , GMs > MessageMapper < Ms , OtherMs > for Effect < Ms , GMs > {
38
42
type SelfWithOtherMs = Effect < OtherMs , GMs > ;
39
43
fn map_message ( self , f : impl FnOnce ( Ms ) -> OtherMs + ' static + Clone ) -> Effect < OtherMs , GMs > {
@@ -53,47 +57,6 @@ pub enum ShouldRender {
53
57
Skip ,
54
58
}
55
59
56
- //type InitFn<Ms, Mdl, ElC, GMs> =
57
- // Box<dyn FnOnce(routing::Url, &mut OrdersContainer<Ms, Mdl, ElC, GMs>) -> Mdl>;
58
- type InitFn < Ms , Mdl , ElC , GMs > =
59
- Box < dyn FnOnce ( routing:: Url , & mut OrdersContainer < Ms , Mdl , ElC , GMs > ) -> Init < Mdl > > ;
60
- type UpdateFn < Ms , Mdl , ElC , GMs > = fn ( Ms , & mut Mdl , & mut OrdersContainer < Ms , Mdl , ElC , GMs > ) ;
61
- type SinkFn < Ms , Mdl , ElC , GMs > = fn ( GMs , & mut Mdl , & mut OrdersContainer < Ms , Mdl , ElC , GMs > ) ;
62
- type ViewFn < Mdl , ElC > = fn ( & Mdl ) -> ElC ;
63
- type RoutesFn < Ms > = fn ( routing:: Url ) -> Option < Ms > ;
64
- type WindowEvents < Ms , Mdl > = fn ( & Mdl ) -> Vec < events:: Listener < Ms > > ;
65
- type MsgListeners < Ms > = Vec < Box < dyn Fn ( & Ms ) > > ;
66
-
67
- /// Used for handling initial routing.
68
- pub enum UrlHandling {
69
- PassToRoutes ,
70
- None ,
71
- // todo: Expand later, as-required
72
- }
73
-
74
- /// Used as a flexible wrapper for the init function.
75
- pub struct Init < Mdl > {
76
- // init: InitFn<Ms, Mdl, ElC, GMs>,
77
- model : Mdl ,
78
- url_handling : UrlHandling ,
79
- }
80
-
81
- impl < Mdl > Init < Mdl > {
82
- pub const fn new ( model : Mdl ) -> Self {
83
- Self {
84
- model,
85
- url_handling : UrlHandling :: PassToRoutes ,
86
- }
87
- }
88
-
89
- pub const fn new_with_url_handling ( model : Mdl , url_handling : UrlHandling ) -> Self {
90
- Self {
91
- model,
92
- url_handling,
93
- }
94
- }
95
- }
96
-
97
60
pub struct Mailbox < Message : ' static > {
98
61
func : Rc < dyn Fn ( Message ) > ,
99
62
}
@@ -170,169 +133,18 @@ impl<Ms: 'static + Clone, Mdl: 'static, ElC: View<Ms>, GMs> ::std::fmt::Debug
170
133
}
171
134
}
172
135
173
- pub trait MountPoint {
174
- fn element ( self ) -> Element ;
175
- }
176
-
177
- impl MountPoint for & str {
178
- fn element ( self ) -> Element {
179
- util:: document ( ) . get_element_by_id ( self ) . unwrap_or_else ( || {
180
- panic ! (
181
- "Can't find element with id={:?} - app cannot be mounted!\n \
182
- (Id defaults to \" app\" , or can be set with the .mount() method)",
183
- self
184
- )
185
- } )
186
- }
187
- }
188
-
189
- impl MountPoint for Element {
190
- fn element ( self ) -> Element {
191
- self
192
- }
193
- }
194
-
195
- impl MountPoint for web_sys:: HtmlElement {
196
- fn element ( self ) -> Element {
197
- self . into ( )
198
- }
199
- }
200
-
201
- /// Used to create and store initial app configuration, ie items passed by the app creator
202
- pub struct AppBuilder < Ms : ' static + Clone , Mdl : ' static , ElC : View < Ms > , GMs > {
203
- init : InitFn < Ms , Mdl , ElC , GMs > ,
204
- update : UpdateFn < Ms , Mdl , ElC , GMs > ,
205
- sink : Option < SinkFn < Ms , Mdl , ElC , GMs > > ,
206
- view : ViewFn < Mdl , ElC > ,
207
- mount_point : Option < Element > ,
208
- takeover_mount : bool ,
209
- routes : Option < RoutesFn < Ms > > ,
210
- window_events : Option < WindowEvents < Ms , Mdl > > ,
211
- }
212
-
213
- impl < Ms : Clone , Mdl , ElC : View < Ms > + ' static , GMs : ' static > AppBuilder < Ms , Mdl , ElC , GMs > {
214
- /// Choose the element where the application will be mounted.
215
- /// The default one is the element with `id` = "app".
216
- ///
217
- /// # Examples
218
- ///
219
- /// ```rust,no_run
220
- /// // argument is `&str`
221
- /// mount("another_id")
222
- ///
223
- /// // argument is `HTMLElement`
224
- /// // NOTE: Be careful with mounting into body,
225
- /// // it can cause hard-to-debug bugs when there are other scripts in the body.
226
- /// mount(seed::body())
227
- ///
228
- /// // argument is `Element`
229
- /// mount(seed::body().querySelector("section").unwrap().unwrap())
230
- /// ```
231
- pub fn mount ( mut self , mount_point : impl MountPoint ) -> Self {
232
- self . mount_point = Some ( mount_point. element ( ) ) ;
233
- self
234
- }
235
-
236
- #[ deprecated( since = "0.3.3" , note = "please use `mount` instead" ) ]
237
- pub fn mount_el ( mut self , el : Element ) -> Self {
238
- self . mount_point = Some ( el) ;
239
- self
240
- }
241
-
242
- /// Allows for the [`App`] to takeover all the children of the mount point. The default
243
- /// behavior is that the [`App`] ignores the children and leaves them in place. The new
244
- /// behavior can be useful if SSR is implemented.
245
- ///
246
- /// As of right now, nodes found in the root will be destroyed and recreated once. This can
247
- /// cause duplicated scripts, css, and other tags that should not otherwise be duplicated.
248
- /// Unrecognized tags are also converted into spans, so take note.
249
- pub fn takeover_mount ( mut self , should_takeover : bool ) -> Self {
250
- self . takeover_mount = should_takeover;
251
- self
252
- }
253
-
254
- /// Registers a function which maps URLs to messages.
255
- pub fn routes ( mut self , routes : RoutesFn < Ms > ) -> Self {
256
- self . routes = Some ( routes) ;
257
- self
258
- }
259
-
260
- /// Registers a function which decides how window events will be handled.
261
- pub fn window_events ( mut self , evts : WindowEvents < Ms , Mdl > ) -> Self {
262
- self . window_events = Some ( evts) ;
263
- self
264
- }
265
-
266
- /// Registers a sink function.
267
- ///
268
- /// The sink function is a function which can update the model based
269
- /// on global messages. Consider to use a sink function when a
270
- /// submodule needs to trigger changes in other modules.
271
- pub fn sink ( mut self , sink : SinkFn < Ms , Mdl , ElC , GMs > ) -> Self {
272
- self . sink = Some ( sink) ;
273
- self
274
- }
275
-
276
- /// Turn this [`AppBuilder`] into an [`App`] which is ready to run.
277
- ///
278
- /// [`AppBuilder`]: struct.AppBuilder.html
279
- /// [`App`]: struct.App.html
280
- pub fn finish ( mut self ) -> App < Ms , Mdl , ElC , GMs > {
281
- if self . mount_point . is_none ( ) {
282
- self = self . mount ( "app" )
283
- }
284
-
285
- let app = App :: new (
286
- self . update ,
287
- self . sink ,
288
- self . view ,
289
- self . mount_point . unwrap ( ) ,
290
- self . takeover_mount ,
291
- self . routes ,
292
- self . window_events ,
293
- ) ;
294
-
295
- let mut initial_orders = OrdersContainer :: new ( app. clone ( ) ) ;
296
- let mut init = ( self . init ) ( routing:: initial_url ( ) , & mut initial_orders) ;
297
-
298
- match init. url_handling {
299
- UrlHandling :: PassToRoutes => {
300
- let url = routing:: initial_url ( ) ;
301
- if let Some ( r) = self . routes {
302
- ( self . update ) ( r ( url) . unwrap ( ) , & mut init. model , & mut initial_orders) ;
303
- }
304
- }
305
- UrlHandling :: None => ( ) ,
306
- } ;
307
-
308
- app. cfg . initial_orders . replace ( Some ( initial_orders) ) ;
309
- app. data . model . replace ( Some ( init. model ) ) ;
310
-
311
- app
312
- }
313
- }
314
-
315
136
/// We use a struct instead of series of functions, in order to avoid passing
316
137
/// repetitive sequences of parameters.
317
138
impl < Ms : Clone , Mdl , ElC : View < Ms > + ' static , GMs : ' static > App < Ms , Mdl , ElC , GMs > {
318
- pub fn build (
319
- init : impl FnOnce ( routing :: Url , & mut OrdersContainer < Ms , Mdl , ElC , GMs > ) -> Init < Mdl > + ' static ,
139
+ pub fn build < I : FnOnce ( routing :: Url , & mut OrdersContainer < Ms , Mdl , ElC , GMs > ) -> Init < Mdl > > (
140
+ init : I ,
320
141
update : UpdateFn < Ms , Mdl , ElC , GMs > ,
321
142
view : ViewFn < Mdl , ElC > ,
322
- ) -> AppBuilder < Ms , Mdl , ElC , GMs > {
143
+ ) -> AppBuilder < Ms , Mdl , ElC , GMs , I > {
323
144
// Allows panic messages to output to the browser console.error.
324
145
console_error_panic_hook:: set_once ( ) ;
325
146
326
- AppBuilder {
327
- init : Box :: new ( init) ,
328
- update,
329
- view,
330
- sink : None ,
331
- mount_point : None ,
332
- takeover_mount : false ,
333
- routes : None ,
334
- window_events : None ,
335
- }
147
+ AppBuilder :: new ( init, update, view)
336
148
}
337
149
338
150
#[ allow( clippy:: too_many_arguments) ]
0 commit comments