use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use yew::prelude::*;
use super::view::*;
use crate::config::*;
use crate::js::perspective::*;
use crate::utils::*;
use crate::*;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct ViewStats {
pub is_group_by: bool,
pub is_split_by: bool,
pub is_filtered: bool,
pub num_table_cells: Option<(u32, u32)>,
pub num_view_cells: Option<(u32, u32)>,
}
#[derive(Clone)]
struct ViewSubscriptionData {
view: View,
config: ViewConfig,
on_stats: Callback<ViewStats>,
on_update: Callback<()>,
}
pub struct ViewSubscription {
data: ViewSubscriptionData,
closure: Closure<dyn Fn(JsValue) -> js_sys::Promise>,
}
impl ViewSubscriptionData {
async fn on_view_update(self) -> ApiResult<JsValue> {
self.on_update.emit(());
self.clone().update_view_stats().await?;
Ok(JsValue::UNDEFINED)
}
async fn update_view_stats(self) -> ApiResult<JsValue> {
let dimensions = self.view.dimensions().await?;
let num_rows = dimensions.num_table_rows() as u32;
let num_cols = dimensions.num_table_columns() as u32;
let virtual_rows = dimensions.num_view_rows() as u32;
let virtual_cols = dimensions.num_view_columns() as u32;
let stats = ViewStats {
num_table_cells: Some((num_rows, num_cols)),
num_view_cells: Some((virtual_rows, virtual_cols)),
is_filtered: virtual_rows != num_rows,
is_group_by: !self.config.group_by.is_empty(),
is_split_by: !self.config.split_by.is_empty(),
};
self.on_stats.emit(stats);
Ok(JsValue::UNDEFINED)
}
}
impl ViewSubscription {
pub fn new(
view: JsPerspectiveView,
config: ViewConfig,
on_stats: Callback<ViewStats>,
on_update: Callback<()>,
) -> Self {
let data = ViewSubscriptionData {
view: View::new(view),
config,
on_stats,
on_update,
};
let fun = {
clone!(data);
move |_| js_sys::Promise::from(ApiFuture::new(data.clone().on_view_update()))
};
let closure = fun.into_closure();
data.view.on_update(closure.as_ref().unchecked_ref());
ApiFuture::spawn(data.clone().update_view_stats());
Self { data, closure }
}
pub const fn get_view(&self) -> &View {
&self.data.view
}
}
impl Drop for ViewSubscription {
fn drop(&mut self) {
let update = self.closure.as_ref().unchecked_ref();
self.data.view.remove_update(update);
}
}