From 30192b92e9c2588c73623196785f02b2695d6ecf Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Sun, 23 Jul 2023 11:48:10 -0400 Subject: [PATCH] Fix double-view creation when `restore()` called after `load()` within a microtask --- rust/perspective-viewer/src/rust/session.rs | 62 ++++++++++++--------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/rust/perspective-viewer/src/rust/session.rs b/rust/perspective-viewer/src/rust/session.rs index 5279ad5d7f..60f226a31c 100644 --- a/rust/perspective-viewer/src/rust/session.rs +++ b/rust/perspective-viewer/src/rust/session.rs @@ -66,6 +66,7 @@ pub struct SessionData { config: ViewConfig, view_sub: Option, stats: Option, + is_clean: bool, } impl Deref for Session { @@ -107,6 +108,7 @@ impl Session { /// # Arguments /// - `keep_expressions` Whether to reset the `expressions` property. pub fn reset(&self, reset_expressions: bool) { + self.borrow_mut().is_clean = false; self.borrow_mut().view_sub = None; self.borrow_mut().config.reset(reset_expressions); } @@ -306,8 +308,9 @@ impl Session { /// Update the config, setting the `columns` property to the plugin defaults /// if provided. pub fn update_view_config(&self, config_update: ViewConfigUpdate) { - self.borrow_mut().view_sub = None; if self.borrow_mut().config.apply_update(config_update) { + self.borrow_mut().view_sub = None; + self.0.borrow_mut().is_clean = false; self.view_config_changed.emit_all(()); } } @@ -452,6 +455,12 @@ impl Session { self.borrow_mut().config = config; Ok(()) } + + fn reset_clean(&self) -> bool { + let mut is_clean = true; + std::mem::swap(&mut is_clean, &mut self.0.borrow_mut().is_clean); + is_clean + } } /// A newtype wrapper which only provides `create_view()` @@ -463,31 +472,34 @@ impl<'a> ValidSession<'a> { /// the original `&Session`. pub async fn create_view(&self) -> Result<&'a Session, ApiError> { let js_config = self.0.borrow().config.as_jsvalue()?; - let table = self - .0 - .borrow() - .table - .clone() - .ok_or("`restore()` called before `load()`")?; - - let view = table.view(&js_config).await?; - let view_schema = view.schema().await?; - self.0.metadata_mut().update_view_schema(&view_schema)?; - - let on_stats = Callback::from({ - let this = self.0.clone(); - move |stats| this.update_stats(stats) - }); - - let sub = { - let config = self.0.borrow().config.clone(); - let on_update = self.0.table_updated.callback(); - ViewSubscription::new(view, config, on_stats, on_update) - }; + if !self.0.reset_clean() { + let table = self + .0 + .borrow() + .table + .clone() + .ok_or("`restore()` called before `load()`")?; + + let view = table.view(&js_config).await?; + let view_schema = view.schema().await?; + self.0.metadata_mut().update_view_schema(&view_schema)?; + + let on_stats = Callback::from({ + let this = self.0.clone(); + move |stats| this.update_stats(stats) + }); + + let sub = { + let config = self.0.borrow().config.clone(); + let on_update = self.0.table_updated.callback(); + ViewSubscription::new(view, config, on_stats, on_update) + }; + + // self.0.borrow_mut().metadata.as_mut().unwrap().view_schema = + // Some(view_schema); + self.0.borrow_mut().view_sub = Some(sub); + } - // self.0.borrow_mut().metadata.as_mut().unwrap().view_schema = - // Some(view_schema); - self.0.borrow_mut().view_sub = Some(sub); Ok(self.0) } }