@@ -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,168 +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
- // @TODO: Remove as soon as Webkit is fixed and older browsers are no longer in use.
233
- // https://github.com/David-OConnor/seed/issues/241
234
- // https://bugs.webkit.org/show_bug.cgi?id=202881
235
- let _ = util:: document ( ) . query_selector ( "html" ) ;
236
-
237
- self . mount_point = Some ( mount_point. element ( ) ) ;
238
- self
239
- }
240
-
241
- /// Allows for the [`App`] to takeover all the children of the mount point. The default
242
- /// behavior is that the [`App`] ignores the children and leaves them in place. The new
243
- /// behavior can be useful if SSR is implemented.
244
- ///
245
- /// As of right now, nodes found in the root will be destroyed and recreated once. This can
246
- /// cause duplicated scripts, css, and other tags that should not otherwise be duplicated.
247
- /// Unrecognized tags are also converted into spans, so take note.
248
- pub fn takeover_mount ( mut self , should_takeover : bool ) -> Self {
249
- self . takeover_mount = should_takeover;
250
- self
251
- }
252
-
253
- /// Registers a function which maps URLs to messages.
254
- pub fn routes ( mut self , routes : RoutesFn < Ms > ) -> Self {
255
- self . routes = Some ( routes) ;
256
- self
257
- }
258
-
259
- /// Registers a function which decides how window events will be handled.
260
- pub fn window_events ( mut self , evts : WindowEvents < Ms , Mdl > ) -> Self {
261
- self . window_events = Some ( evts) ;
262
- self
263
- }
264
-
265
- /// Registers a sink function.
266
- ///
267
- /// The sink function is a function which can update the model based
268
- /// on global messages. Consider to use a sink function when a
269
- /// submodule needs to trigger changes in other modules.
270
- pub fn sink ( mut self , sink : SinkFn < Ms , Mdl , ElC , GMs > ) -> Self {
271
- self . sink = Some ( sink) ;
272
- self
273
- }
274
-
275
- /// Turn this [`AppBuilder`] into an [`App`] which is ready to run.
276
- ///
277
- /// [`AppBuilder`]: struct.AppBuilder.html
278
- /// [`App`]: struct.App.html
279
- pub fn finish ( mut self ) -> App < Ms , Mdl , ElC , GMs > {
280
- if self . mount_point . is_none ( ) {
281
- self = self . mount ( "app" )
282
- }
283
-
284
- let app = App :: new (
285
- self . update ,
286
- self . sink ,
287
- self . view ,
288
- self . mount_point . unwrap ( ) ,
289
- self . takeover_mount ,
290
- self . routes ,
291
- self . window_events ,
292
- ) ;
293
-
294
- let mut initial_orders = OrdersContainer :: new ( app. clone ( ) ) ;
295
- let mut init = ( self . init ) ( routing:: initial_url ( ) , & mut initial_orders) ;
296
-
297
- match init. url_handling {
298
- UrlHandling :: PassToRoutes => {
299
- let url = routing:: initial_url ( ) ;
300
- if let Some ( r) = self . routes {
301
- ( self . update ) ( r ( url) . unwrap ( ) , & mut init. model , & mut initial_orders) ;
302
- }
303
- }
304
- UrlHandling :: None => ( ) ,
305
- } ;
306
-
307
- app. cfg . initial_orders . replace ( Some ( initial_orders) ) ;
308
- app. data . model . replace ( Some ( init. model ) ) ;
309
-
310
- app
311
- }
312
- }
313
-
314
136
/// We use a struct instead of series of functions, in order to avoid passing
315
137
/// repetitive sequences of parameters.
316
138
impl < Ms : Clone , Mdl , ElC : View < Ms > + ' static , GMs : ' static > App < Ms , Mdl , ElC , GMs > {
317
- pub fn build (
318
- 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 ,
319
141
update : UpdateFn < Ms , Mdl , ElC , GMs > ,
320
142
view : ViewFn < Mdl , ElC > ,
321
- ) -> AppBuilder < Ms , Mdl , ElC , GMs > {
143
+ ) -> AppBuilder < Ms , Mdl , ElC , GMs , I > {
322
144
// Allows panic messages to output to the browser console.error.
323
145
console_error_panic_hook:: set_once ( ) ;
324
146
325
- AppBuilder {
326
- init : Box :: new ( init) ,
327
- update,
328
- view,
329
- sink : None ,
330
- mount_point : None ,
331
- takeover_mount : false ,
332
- routes : None ,
333
- window_events : None ,
334
- }
147
+ AppBuilder :: new ( init, update, view)
335
148
}
336
149
337
150
#[ allow( clippy:: too_many_arguments) ]
0 commit comments