Skip to content

Commit 7be80db

Browse files
committed
Convert takeover_mount to an enum BootstrapBehavior
1 parent 0e9c4e1 commit 7be80db

File tree

2 files changed

+43
-39
lines changed

2 files changed

+43
-39
lines changed

src/vdom.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ mod alias;
2525
mod builder;
2626

2727
pub use alias::*;
28-
pub use builder::{Builder as AppBuilder, Init, Initializer, UrlHandling};
28+
pub use builder::{BootstrapBehavior, Builder as AppBuilder, Init, Initializer, UrlHandling};
2929

3030
pub enum Effect<Ms, GMs> {
3131
Msg(Ms),
@@ -105,12 +105,12 @@ where
105105
{
106106
document: web_sys::Document,
107107
mount_point: web_sys::Element,
108-
takeover_mount: bool,
109108
pub update: UpdateFn<Ms, Mdl, ElC, GMs>,
110109
pub sink: Option<SinkFn<Ms, Mdl, ElC, GMs>>,
111110
view: ViewFn<Mdl, ElC>,
112111
window_events: Option<WindowEvents<Ms, Mdl>>,
113112
initial_orders: RefCell<Option<OrdersContainer<Ms, Mdl, ElC, GMs>>>,
113+
bootstrap_behavior: RefCell<Option<BootstrapBehavior>>,
114114
}
115115

116116
pub struct App<Ms: Clone, Mdl, ElC, GMs = ()>
@@ -153,7 +153,6 @@ impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static> App<Ms, Mdl, ElC, GM
153153
sink: Option<SinkFn<Ms, Mdl, ElC, GMs>>,
154154
view: ViewFn<Mdl, ElC>,
155155
mount_point: Element,
156-
takeover_mount: bool,
157156
routes: Option<RoutesFn<Ms>>,
158157
window_events: Option<WindowEvents<Ms, Mdl>>,
159158
) -> Self {
@@ -164,12 +163,12 @@ impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static> App<Ms, Mdl, ElC, GM
164163
cfg: Rc::new(AppCfg {
165164
document,
166165
mount_point,
167-
takeover_mount,
168166
update,
169167
sink,
170168
view,
171169
window_events,
172170
initial_orders: RefCell::new(None),
171+
bootstrap_behavior: RefCell::new(None),
173172
}),
174173
data: Rc::new(AppData {
175174
model: RefCell::new(None),
@@ -201,10 +200,11 @@ impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static> App<Ms, Mdl, ElC, GM
201200
/// replacing them with the vdom if requested. Will otherwise ignore the original children of
202201
/// the mount point.
203202
fn bootstrap_vdom(&self) -> El<Ms> {
203+
let bootstrap_behavior = *self.cfg.bootstrap_behavior.borrow();
204204
let mut new = El::empty(dom_types::Tag::Placeholder);
205205

206206
// Map the DOM's elements onto the virtual DOM if requested to takeover.
207-
if self.cfg.takeover_mount {
207+
if bootstrap_behavior == Some(BootstrapBehavior::Takeover) {
208208
// Construct a vdom from the root element. Subsequently strip the workspace so that we
209209
// can recreate it later - this is a kind of simple way to avoid missing nodes (but
210210
// not entirely correct).
@@ -227,7 +227,7 @@ impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static> App<Ms, Mdl, ElC, GM
227227
patch::attach_listeners(&mut new, &self.mailbox());
228228

229229
// Recreate the needed nodes. Only do this if requested to takeover the mount point.
230-
let mut new = if self.cfg.takeover_mount {
230+
let mut new = if bootstrap_behavior == Some(BootstrapBehavior::Takeover) {
231231
// TODO: Refer the TODO at the beginning of the function.
232232
let mut new_node = Node::Element(new);
233233
websys_bridge::assign_ws_nodes(&util::document(), &mut new_node);
@@ -269,6 +269,17 @@ impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static> App<Ms, Mdl, ElC, GM
269269
new
270270
}
271271

272+
fn initial_update(&self) {
273+
let queue = self
274+
.cfg
275+
.initial_orders
276+
.replace(None)
277+
.expect("initial_orders should be set in AppBuilder::finish")
278+
.effects;
279+
self.process_cmd_and_msg_queue(queue);
280+
self.rerender_vdom();
281+
}
282+
272283
/// App initialization: Collect its fundamental components, setup, and perform
273284
/// an initial render.
274285
pub fn run(self) -> Self {
@@ -296,13 +307,7 @@ impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static> App<Ms, Mdl, ElC, GM
296307
// render as per normal for seed behavior. -- Executed here to ensure that all state has
297308
// been initialized with a bootstrap version. The bootstrap will be replaced after first
298309
// render.
299-
self.process_cmd_and_msg_queue_with_forced_render(
300-
self.cfg
301-
.initial_orders
302-
.replace(None)
303-
.expect("initial_orders should be set in AppBuilder::finish")
304-
.effects,
305-
);
310+
self.initial_update();
306311

307312
self
308313
}
@@ -330,10 +335,6 @@ impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static> App<Ms, Mdl, ElC, GM
330335
self.process_cmd_and_msg_queue(queue);
331336
}
332337

333-
pub fn process_cmd_and_msg_queue_with_forced_render(&self, queue: VecDeque<Effect<Ms, GMs>>) {
334-
self.process_cmd_and_msg_queue(queue);
335-
self.rerender_vdom();
336-
}
337338
pub fn process_cmd_and_msg_queue(&self, mut queue: VecDeque<Effect<Ms, GMs>>) {
338339
while let Some(effect) = queue.pop_front() {
339340
match effect {

src/vdom/builder.rs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,60 @@ use crate::{
1010
pub trait Initializer<Ms: Clone + 'static, Mdl, ElC: View<Ms>, GMs> {
1111
fn into_init(
1212
self,
13-
routing_method: routing::Url,
13+
url: routing::Url,
1414
orders: &mut OrdersContainer<Ms, Mdl, ElC, GMs>,
1515
) -> Init<Mdl>;
1616
}
1717
impl<Ms: Clone + 'static, Mdl, ElC: View<Ms>, GMs, F> Initializer<Ms, Mdl, ElC, GMs> for F
1818
where
19-
F: FnOnce(routing::Url, &mut OrdersContainer<Ms, Mdl, ElC, GMs>) -> Init<Mdl>,
19+
F: for<'r, 'a> FnOnce(routing::Url, &'a mut OrdersContainer<Ms, Mdl, ElC, GMs>) -> Init<Mdl>,
2020
{
2121
fn into_init(
2222
self,
23-
routing_method: routing::Url,
23+
url: routing::Url,
2424
orders: &mut OrdersContainer<Ms, Mdl, ElC, GMs>,
2525
) -> Init<Mdl> {
26-
self(routing_method, orders)
26+
self(url, orders)
2727
}
2828
}
2929

3030
/// Used for handling initial routing.
31+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3132
pub enum UrlHandling {
3233
PassToRoutes,
3334
None,
3435
// todo: Expand later, as-required
3536
}
3637

38+
/// Used for determining behavior at startup.
39+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
40+
pub enum BootstrapBehavior {
41+
Takeover,
42+
Append,
43+
}
44+
3745
/// Used as a flexible wrapper for the init function.
3846
pub struct Init<Mdl> {
3947
// init: InitFn<Ms, Mdl, ElC, GMs>,
40-
model: Mdl,
41-
url_handling: UrlHandling,
48+
pub model: Mdl,
49+
pub url_handling: UrlHandling,
50+
pub bootstrap_behavior: BootstrapBehavior,
4251
}
4352

4453
impl<Mdl> Init<Mdl> {
4554
pub const fn new(model: Mdl) -> Self {
4655
Self {
4756
model,
4857
url_handling: UrlHandling::PassToRoutes,
58+
bootstrap_behavior: BootstrapBehavior::Append,
4959
}
5060
}
5161

5262
pub const fn new_with_url_handling(model: Mdl, url_handling: UrlHandling) -> Self {
5363
Self {
5464
model,
5565
url_handling,
66+
bootstrap_behavior: BootstrapBehavior::Append,
5667
}
5768
}
5869
}
@@ -104,22 +115,24 @@ pub struct Builder<
104115
sink: Option<SinkFn<Ms, Mdl, ElC, GMs>>,
105116
view: ViewFn<Mdl, ElC>,
106117
mount_point: Option<Element>,
107-
takeover_mount: bool,
108118
routes: Option<RoutesFn<Ms>>,
109119
window_events: Option<WindowEvents<Ms, Mdl>>,
110120
}
111121

112122
impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static, I: Initializer<Ms, Mdl, ElC, GMs>>
113123
Builder<Ms, Mdl, ElC, GMs, I>
114124
{
115-
pub fn new(init: I, update: UpdateFn<Ms, Mdl, ElC, GMs>, view: ViewFn<Mdl, ElC>) -> Self {
125+
pub(super) fn new(
126+
init: I,
127+
update: UpdateFn<Ms, Mdl, ElC, GMs>,
128+
view: ViewFn<Mdl, ElC>,
129+
) -> Self {
116130
Self {
117131
init,
118132
update,
119133
view,
120134
sink: None,
121135
mount_point: None,
122-
takeover_mount: false,
123136
routes: None,
124137
window_events: None,
125138
}
@@ -153,18 +166,6 @@ impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static, I: Initializer<Ms, M
153166
self
154167
}
155168

156-
/// Allows for the [`App`] to takeover all the children of the mount point. The default
157-
/// behavior is that the [`App`] ignores the children and leaves them in place. The new
158-
/// behavior can be useful if SSR is implemented.
159-
///
160-
/// As of right now, nodes found in the root will be destroyed and recreated once. This can
161-
/// cause duplicated scripts, css, and other tags that should not otherwise be duplicated.
162-
/// Unrecognized tags are also converted into spans, so take note.
163-
pub fn takeover_mount(mut self, should_takeover: bool) -> Self {
164-
self.takeover_mount = should_takeover;
165-
self
166-
}
167-
168169
/// Registers a function which maps URLs to messages.
169170
pub fn routes(mut self, routes: RoutesFn<Ms>) -> Self {
170171
self.routes = Some(routes);
@@ -201,7 +202,6 @@ impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static, I: Initializer<Ms, M
201202
self.sink,
202203
self.view,
203204
self.mount_point.unwrap(),
204-
self.takeover_mount,
205205
self.routes,
206206
self.window_events,
207207
);
@@ -222,6 +222,9 @@ impl<Ms: Clone, Mdl, ElC: View<Ms> + 'static, GMs: 'static, I: Initializer<Ms, M
222222
};
223223

224224
app.cfg.initial_orders.replace(Some(initial_orders));
225+
app.cfg
226+
.bootstrap_behavior
227+
.replace(Some(init.bootstrap_behavior));
225228
app.data.model.replace(Some(init.model));
226229

227230
app

0 commit comments

Comments
 (0)