@perspective-dev/viewer 4.5.2 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdn/perspective-viewer.js +20 -1
- package/dist/cdn/perspective-viewer.js.map +4 -4
- package/dist/css/botanical.css +1 -1
- package/dist/css/dracula.css +1 -1
- package/dist/css/gruvbox-dark.css +1 -1
- package/dist/css/gruvbox.css +1 -1
- package/dist/css/icons.css +1 -1
- package/dist/css/intl/de.css +1 -1
- package/dist/css/intl/es.css +1 -1
- package/dist/css/intl/fr.css +1 -1
- package/dist/css/intl/ja.css +1 -1
- package/dist/css/intl/pt.css +1 -1
- package/dist/css/intl/zh.css +1 -1
- package/dist/css/intl.css +1 -1
- package/dist/css/monokai.css +1 -1
- package/dist/css/phosphor.css +1 -1
- package/dist/css/pro-dark.css +1 -1
- package/dist/css/pro.css +1 -1
- package/dist/css/solarized-dark.css +1 -1
- package/dist/css/solarized.css +1 -1
- package/dist/css/themes.css +1 -1
- package/dist/css/vaporwave.css +1 -1
- package/dist/esm/extensions.d.ts +22 -3
- package/dist/esm/perspective-viewer.d.ts +9 -0
- package/dist/esm/perspective-viewer.inline.js +20 -1
- package/dist/esm/perspective-viewer.inline.js.map +4 -4
- package/dist/esm/perspective-viewer.js +20 -1
- package/dist/esm/perspective-viewer.js.map +4 -4
- package/dist/esm/plugin.d.ts +71 -5
- package/dist/esm/ts-rs/ClientOptions.d.ts +7 -0
- package/dist/esm/ts-rs/ExportMethod.d.ts +1 -0
- package/dist/esm/ts-rs/ExportOptions.d.ts +9 -0
- package/dist/esm/ts-rs/GetClientOptions.d.ts +8 -0
- package/dist/esm/ts-rs/GetTableOptions.d.ts +8 -0
- package/dist/esm/ts-rs/Layout.d.ts +11 -0
- package/dist/esm/ts-rs/Orientation.d.ts +4 -0
- package/dist/esm/ts-rs/PanelOptions.d.ts +7 -0
- package/dist/esm/ts-rs/PanelViewerConfig.d.ts +41 -0
- package/dist/esm/ts-rs/SplitLayout.d.ts +7 -0
- package/dist/esm/ts-rs/TabLayout.d.ts +10 -0
- package/dist/esm/ts-rs/ViewerConfig.d.ts +8 -2
- package/dist/esm/ts-rs/ViewerConfigUpdate.d.ts +9 -0
- package/dist/esm/ts-rs/WindowAggregate.d.ts +1 -0
- package/dist/esm/ts-rs/WindowSort.d.ts +7 -0
- package/dist/esm/ts-rs/WindowSortDir.d.ts +6 -0
- package/dist/esm/ts-rs/WindowSpec.d.ts +46 -0
- package/dist/esm/ts-rs/Windows.d.ts +10 -0
- package/dist/esm/ts-rs/WorkspaceConfig.d.ts +40 -0
- package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +28 -0
- package/dist/wasm/perspective-viewer.d.ts +299 -78
- package/dist/wasm/perspective-viewer.js +544 -186
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +34 -26
- package/dist/wasm/snippets/perspective-viewer-8a8c7d5d696b43ae/inline0.js +6 -0
- package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline3.js → perspective-viewer-8a8c7d5d696b43ae/inline4.js} +5 -0
- package/package.json +3 -2
- package/src/css/_context_menu.css +14 -0
- package/src/css/column-selector.css +1 -0
- package/src/css/column-settings-panel.css +68 -3
- package/src/css/column-style.css +4 -3
- package/src/css/config-selector.css +22 -1
- package/src/css/containers/context-menu.css +107 -0
- package/src/css/containers/tabs.css +2 -2
- package/src/css/panel-tab.css +193 -0
- package/src/css/plugin-selector.css +7 -10
- package/src/css/status-bar.css +75 -81
- package/src/css/viewer.css +188 -70
- package/src/rust/components/column_dropdown.rs +40 -30
- package/src/rust/components/column_selector/active_column.rs +28 -45
- package/src/rust/components/column_selector/aggregate_selector.rs +4 -7
- package/src/rust/components/column_selector/column_selector_column_row.rs +73 -0
- package/src/rust/components/column_selector/config_selector.rs +40 -82
- package/src/rust/components/column_selector/expr_edit_button.rs +7 -1
- package/src/rust/components/column_selector/filter_column.rs +5 -15
- package/src/rust/components/column_selector/inactive_column.rs +11 -9
- package/src/rust/components/column_selector/sort_column.rs +3 -6
- package/src/rust/components/column_selector.rs +25 -14
- package/src/rust/components/column_settings_sidebar/style_tab.rs +2 -1
- package/src/rust/components/column_settings_sidebar/window_tab.rs +34 -0
- package/src/rust/components/column_settings_sidebar.rs +163 -16
- package/src/rust/components/containers/dragdrop_list.rs +73 -3
- package/src/rust/components/containers/sidebar.rs +99 -22
- package/src/rust/components/containers/split_panel.rs +181 -62
- package/src/rust/components/context_menu.rs +130 -0
- package/src/rust/components/editable_header.rs +2 -0
- package/src/rust/components/form/debug.rs +3 -0
- package/src/rust/components/global_filter_bar.rs +76 -0
- package/src/rust/components/main_panel/frame_theme.rs +186 -0
- package/src/rust/components/main_panel/msg.rs +62 -0
- package/src/rust/components/main_panel/presize.rs +220 -0
- package/src/rust/components/main_panel/reconcile.rs +224 -0
- package/src/rust/components/main_panel/render.rs +385 -0
- package/src/rust/components/main_panel/update.rs +184 -0
- package/src/rust/components/main_panel.rs +316 -71
- package/src/rust/components/mod.rs +5 -0
- package/src/rust/components/panel_menu.rs +493 -0
- package/src/rust/components/panel_tab.rs +510 -0
- package/src/rust/components/plugin_tab.rs +1 -1
- package/src/rust/components/portal.rs +7 -0
- package/src/rust/components/settings_panel.rs +13 -5
- package/src/rust/components/status_bar.rs +110 -178
- package/src/rust/components/status_indicator.rs +6 -9
- package/src/rust/components/style/mod.rs +5 -0
- package/src/rust/components/style/style_provider.rs +2 -0
- package/src/rust/components/viewer/filters.rs +133 -0
- package/src/rust/components/viewer/msg.rs +182 -0
- package/src/rust/components/viewer/panels.rs +326 -0
- package/src/rust/components/viewer/render.rs +255 -0
- package/src/rust/components/viewer/settings.rs +434 -0
- package/src/rust/components/viewer/snapshots.rs +134 -0
- package/src/rust/components/viewer/wiring.rs +505 -0
- package/src/rust/components/viewer.rs +245 -756
- package/src/rust/components/window_editor.rs +1013 -0
- package/src/rust/config/export_method.rs +1 -1
- package/src/rust/config/mod.rs +4 -0
- package/src/rust/config/options.rs +71 -0
- package/src/rust/config/viewer_config.rs +24 -2
- package/src/rust/config/workspace_config.rs +92 -0
- package/src/rust/custom_elements/copy_dropdown.rs +3 -1
- package/src/rust/custom_elements/debug_plugin.rs +20 -1
- package/src/rust/custom_elements/export_dropdown.rs +3 -1
- package/src/rust/custom_elements/viewer.rs +1015 -286
- package/src/rust/custom_events.rs +212 -61
- package/src/rust/js/mod.rs +2 -0
- package/src/rust/js/plugin.rs +297 -10
- package/src/rust/js/regular_layout.rs +258 -0
- package/src/rust/lib.rs +24 -2
- package/src/rust/presentation/column_locator.rs +16 -1
- package/src/rust/presentation.rs +66 -33
- package/src/rust/queries/columns_iter_set.rs +7 -1
- package/src/rust/queries/get_viewer_config.rs +29 -11
- package/src/rust/queries/plugin_column_styles.rs +2 -2
- package/src/rust/renderer/activate.rs +41 -14
- package/src/rust/renderer/dispatch.rs +463 -0
- package/src/rust/renderer/plugin_config.rs +495 -0
- package/src/rust/renderer/registry.rs +18 -6
- package/src/rust/renderer/render_timer.rs +29 -10
- package/src/rust/renderer.rs +384 -838
- package/src/rust/session/column_defaults_update.rs +26 -8
- package/src/rust/session/drag_drop_update.rs +18 -0
- package/src/rust/session/metadata.rs +66 -9
- package/src/rust/session/replace_expression_update.rs +1 -0
- package/src/rust/session/view_subscription.rs +30 -15
- package/src/rust/session.rs +755 -264
- package/src/rust/tasks/apply_global_filters.rs +89 -0
- package/src/rust/tasks/auto_pause.rs +171 -0
- package/src/rust/tasks/copy_export.rs +29 -19
- package/src/rust/tasks/create_panel.rs +243 -0
- package/src/rust/tasks/dismiss_render_warning.rs +3 -1
- package/src/rust/tasks/edit_expression.rs +4 -4
- package/src/rust/tasks/edit_window.rs +155 -0
- package/src/rust/tasks/eject.rs +64 -23
- package/src/rust/tasks/mod.rs +30 -4
- package/src/rust/tasks/pipeline.rs +411 -0
- package/src/rust/tasks/presize_panels.rs +324 -0
- package/src/rust/tasks/reset_all.rs +22 -12
- package/src/rust/tasks/resize_observer.rs +124 -87
- package/src/rust/tasks/restore_and_render.rs +80 -86
- package/src/rust/tasks/restore_panel.rs +145 -0
- package/src/rust/tasks/send_column_config.rs +5 -2
- package/src/rust/tasks/send_plugin_config.rs +5 -2
- package/src/rust/tasks/set_edit_mode.rs +59 -0
- package/src/rust/tasks/sync_update_panels.rs +152 -0
- package/src/rust/tasks/table_lifecycle.rs +158 -0
- package/src/rust/tasks/update_theme.rs +56 -12
- package/src/rust/utils/browser/dragdrop.rs +12 -0
- package/src/rust/utils/browser/tests/debounce.rs +49 -0
- package/src/rust/utils/completion.rs +56 -0
- package/src/rust/utils/custom_element.rs +5 -0
- package/src/rust/utils/debounce.rs +189 -17
- package/src/rust/utils/mod.rs +6 -0
- package/src/rust/utils/pending_effects.rs +62 -0
- package/src/rust/utils/spawn.rs +33 -0
- package/src/rust/utils/weak_scope.rs +0 -10
- package/src/rust/workspace.rs +846 -0
- package/src/svg/active-indicator.svg +3 -0
- package/src/svg/pin-icon.svg +5 -0
- package/src/themes/botanical.css +5 -2
- package/src/themes/defaults.css +54 -2
- package/src/themes/dracula.css +6 -3
- package/src/themes/gruvbox-dark.css +5 -2
- package/src/themes/gruvbox.css +5 -2
- package/src/themes/icons.css +5 -2
- package/src/themes/intl/de.css +7 -0
- package/src/themes/intl/es.css +7 -0
- package/src/themes/intl/fr.css +7 -0
- package/src/themes/intl/ja.css +7 -0
- package/src/themes/intl/pt.css +7 -0
- package/src/themes/intl/zh.css +7 -0
- package/src/themes/intl.css +10 -1
- package/src/themes/monokai.css +5 -2
- package/src/themes/phosphor.css +5 -2
- package/src/themes/pro-dark.css +5 -2
- package/src/themes/pro.css +2 -1
- package/src/themes/solarized-dark.css +5 -2
- package/src/themes/solarized.css +5 -2
- package/src/themes/vaporwave.css +5 -2
- package/src/ts/bootstrap.ts +8 -7
- package/src/ts/extensions.ts +30 -2
- package/src/ts/perspective-viewer.ts +10 -0
- package/src/ts/plugin.ts +72 -5
- package/src/ts/ts-rs/ClientOptions.ts +7 -0
- package/src/ts/ts-rs/ExportMethod.ts +3 -0
- package/src/ts/ts-rs/ExportOptions.ts +8 -0
- package/src/ts/ts-rs/GetClientOptions.ts +7 -0
- package/src/ts/ts-rs/GetTableOptions.ts +7 -0
- package/src/ts/ts-rs/Layout.ts +9 -0
- package/src/ts/ts-rs/Orientation.ts +6 -0
- package/src/ts/ts-rs/PanelOptions.ts +7 -0
- package/src/ts/ts-rs/PanelViewerConfig.ts +16 -0
- package/src/ts/ts-rs/SplitLayout.ts +5 -0
- package/src/ts/ts-rs/TabLayout.ts +11 -0
- package/src/ts/ts-rs/ViewerConfig.ts +7 -2
- package/src/ts/ts-rs/ViewerConfigUpdate.ts +9 -0
- package/src/ts/ts-rs/WindowAggregate.ts +3 -0
- package/src/ts/ts-rs/WindowSort.ts +9 -0
- package/src/ts/ts-rs/WindowSortDir.ts +8 -0
- package/src/ts/ts-rs/WindowSpec.ts +46 -0
- package/src/ts/ts-rs/Windows.ts +10 -0
- package/src/ts/ts-rs/WorkspaceConfig.ts +36 -0
- package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +24 -0
- package/src/rust/tasks/intersection_observer.rs +0 -98
- package/src/rust/tasks/update_and_render.rs +0 -110
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline0.js → perspective-viewer-8a8c7d5d696b43ae/inline1.js} +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline1.js → perspective-viewer-8a8c7d5d696b43ae/inline2.js} +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline2.js → perspective-viewer-8a8c7d5d696b43ae/inline3.js} +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-93064d0d79855d97/inline4.js → perspective-viewer-8a8c7d5d696b43ae/inline5.js} +0 -0
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
//! Settings-sidebar handlers: the open/close toggle (with its presize
|
|
14
|
+
//! choreography), the deferred divider's latest-wins presize pump
|
|
15
|
+
//! (`PRESIZE_EVERYWHERE_PLAN.md` P1/P2), and the column-settings drawer. The
|
|
16
|
+
//! presize sweeps themselves live in [`crate::tasks`] (`presize_panels`).
|
|
17
|
+
|
|
18
|
+
use futures::channel::oneshot::{Sender, channel};
|
|
19
|
+
use perspective_js::utils::*;
|
|
20
|
+
use wasm_bindgen::prelude::*;
|
|
21
|
+
use yew::prelude::*;
|
|
22
|
+
|
|
23
|
+
use super::PerspectiveViewer;
|
|
24
|
+
use super::msg::PerspectiveViewerMsg::*;
|
|
25
|
+
use crate::components::font_loader::FontLoaderStatus;
|
|
26
|
+
use crate::components::settings_panel::SelectedTab;
|
|
27
|
+
use crate::config::*;
|
|
28
|
+
use crate::presentation::{ColumnLocator, ColumnSettingsTab};
|
|
29
|
+
use crate::tasks::*;
|
|
30
|
+
|
|
31
|
+
/// The settings sidebar's geometry state, folded into one field on
|
|
32
|
+
/// [`PerspectiveViewer`]: the pane/drawer width overrides, the divider
|
|
33
|
+
/// presize pump, and the open-state deltas cache.
|
|
34
|
+
#[derive(Default)]
|
|
35
|
+
pub(super) struct SettingsGeometry {
|
|
36
|
+
/// User-dragged settings-pane width (the deferred `SplitPanel`'s
|
|
37
|
+
/// controlled `size`); `None` until first dragged / after a reset.
|
|
38
|
+
pub pane_width_override: Option<i32>,
|
|
39
|
+
|
|
40
|
+
/// The selected settings-panel tab.
|
|
41
|
+
pub selected_tab: SelectedTab,
|
|
42
|
+
|
|
43
|
+
/// High-water-mark auto width reported by the settings panel.
|
|
44
|
+
pub auto_width: f64,
|
|
45
|
+
|
|
46
|
+
/// Latest-wins presize pump for the (deferred) settings divider: the
|
|
47
|
+
/// newest proposed pane width not yet presized, and whether a pump
|
|
48
|
+
/// iteration is in flight. See `SettingsDividerMove`.
|
|
49
|
+
pub divider_target: Option<i32>,
|
|
50
|
+
pub divider_pumping: bool,
|
|
51
|
+
|
|
52
|
+
/// Open-state geometry deltas `(layout_area.w − mpc.w, main_column.h −
|
|
53
|
+
/// mpc.h)`, cached at settings *close* time — used to presize panels to
|
|
54
|
+
/// their shrunk boxes BEFORE the pane mounts on the next *open* (P2).
|
|
55
|
+
/// `None` until the first close (the first-ever open is reactive).
|
|
56
|
+
pub open_deltas: Option<(f64, f64)>,
|
|
57
|
+
|
|
58
|
+
/// User-dragged column-settings drawer width override.
|
|
59
|
+
pub column_settings_width_override: Option<i32>,
|
|
60
|
+
|
|
61
|
+
/// High-water-mark auto width reported by the column-settings drawer -
|
|
62
|
+
/// the trap-door shared across its Style/Attributes/Window tabs, lifted
|
|
63
|
+
/// here (like `auto_width`) so it survives drawer re-opens and clears
|
|
64
|
+
/// on divider reset.
|
|
65
|
+
pub column_settings_auto_width: f64,
|
|
66
|
+
|
|
67
|
+
/// Whether the column-settings drawer is PINNED - laid out as a static
|
|
68
|
+
/// flex sibling between the main panel and the settings panel - rather
|
|
69
|
+
/// than FLOATING over the main panel (the default absolute overlay).
|
|
70
|
+
/// Session UI state, not part of the saved config.
|
|
71
|
+
pub column_settings_pinned: bool,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
impl PerspectiveViewer {
|
|
75
|
+
pub(super) fn on_toggle_settings_init(
|
|
76
|
+
&mut self,
|
|
77
|
+
ctx: &Context<Self>,
|
|
78
|
+
update: Option<SettingsUpdate>,
|
|
79
|
+
resolve: Option<Sender<ApiResult<JsValue>>>,
|
|
80
|
+
) -> bool {
|
|
81
|
+
match (update, resolve) {
|
|
82
|
+
(Some(SettingsUpdate::Missing), None) => false,
|
|
83
|
+
(Some(SettingsUpdate::Missing), Some(resolve)) => {
|
|
84
|
+
resolve.send(Ok(JsValue::UNDEFINED)).unwrap();
|
|
85
|
+
false
|
|
86
|
+
},
|
|
87
|
+
(Some(SettingsUpdate::SetDefault), resolve) => {
|
|
88
|
+
self.init_toggle_settings_task(ctx, Some(false), resolve);
|
|
89
|
+
false
|
|
90
|
+
},
|
|
91
|
+
(Some(SettingsUpdate::Update(force)), resolve) => {
|
|
92
|
+
self.init_toggle_settings_task(ctx, Some(force), resolve);
|
|
93
|
+
false
|
|
94
|
+
},
|
|
95
|
+
(None, resolve) => {
|
|
96
|
+
self.init_toggle_settings_task(ctx, None, resolve);
|
|
97
|
+
false
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
pub(super) fn on_toggle_settings_complete(
|
|
103
|
+
&mut self,
|
|
104
|
+
ctx: &Context<Self>,
|
|
105
|
+
update: SettingsUpdate,
|
|
106
|
+
resolve: Sender<()>,
|
|
107
|
+
) -> bool {
|
|
108
|
+
match update {
|
|
109
|
+
SettingsUpdate::SetDefault if self.settings_open => {
|
|
110
|
+
ctx.props().presentation.set_open_column_settings(None);
|
|
111
|
+
self.settings_open = false;
|
|
112
|
+
self.on_rendered.push(resolve);
|
|
113
|
+
true
|
|
114
|
+
},
|
|
115
|
+
SettingsUpdate::Update(force) if force != self.settings_open => {
|
|
116
|
+
ctx.props().presentation.set_open_column_settings(None);
|
|
117
|
+
self.settings_open = force;
|
|
118
|
+
self.on_rendered.push(resolve);
|
|
119
|
+
true
|
|
120
|
+
},
|
|
121
|
+
_ if matches!(self.fonts.get_status(), FontLoaderStatus::Finished) => {
|
|
122
|
+
if let Err(e) = resolve.send(()) {
|
|
123
|
+
tracing::error!("toggle settings failed {:?}", e);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
false
|
|
127
|
+
},
|
|
128
|
+
_ => {
|
|
129
|
+
ctx.props().presentation.set_open_column_settings(None);
|
|
130
|
+
self.on_rendered.push(resolve);
|
|
131
|
+
true
|
|
132
|
+
},
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/// Toggle the settings, or force the settings panel either open (true) or
|
|
137
|
+
/// closed (false) explicitly. In order to reduce apparent
|
|
138
|
+
/// screen-shear, `toggle_settings()` uses a somewhat complex render
|
|
139
|
+
/// order: it first resize the plugin's `<div>` without moving it,
|
|
140
|
+
/// using `overflow: hidden` to hide the extra draw area; then,
|
|
141
|
+
/// after the _async_ drawing of the plugin is complete, it will send a
|
|
142
|
+
/// message to complete the toggle action and re-render the element with
|
|
143
|
+
/// the settings removed.
|
|
144
|
+
///
|
|
145
|
+
/// # Arguments
|
|
146
|
+
/// * `force` - Whether to explicitly set the settings panel state to
|
|
147
|
+
/// Open/Close (`Some(true)`/`Some(false)`), or to just toggle the current
|
|
148
|
+
/// state (`None`).
|
|
149
|
+
fn init_toggle_settings_task(
|
|
150
|
+
&mut self,
|
|
151
|
+
ctx: &Context<Self>,
|
|
152
|
+
force: Option<bool>,
|
|
153
|
+
sender: Option<Sender<ApiResult<JsValue>>>,
|
|
154
|
+
) {
|
|
155
|
+
let is_open = ctx.props().presentation.is_settings_open();
|
|
156
|
+
ctx.props().presentation.set_settings_before_open(!is_open);
|
|
157
|
+
match force {
|
|
158
|
+
Some(force) if is_open == force => {
|
|
159
|
+
if let Some(sender) = sender {
|
|
160
|
+
sender.send(Ok(JsValue::UNDEFINED)).unwrap();
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
Some(_) | None => {
|
|
164
|
+
let force = !is_open;
|
|
165
|
+
let callback = ctx.link().callback(move |resolve| {
|
|
166
|
+
let update = SettingsUpdate::Update(force);
|
|
167
|
+
ToggleSettingsComplete(update, resolve)
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// P2: at CLOSE time the open-state geometry is measurable —
|
|
171
|
+
// cache the deltas the next OPEN needs to presize with.
|
|
172
|
+
if is_open {
|
|
173
|
+
self.settings_geometry.open_deltas =
|
|
174
|
+
measure_settings_open_deltas(&ctx.props().elem);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
let open_deltas = self.settings_geometry.open_deltas;
|
|
178
|
+
let workspace = ctx.props().workspace.clone();
|
|
179
|
+
let presentation = ctx.props().presentation.clone();
|
|
180
|
+
let elem = ctx.props().elem.clone();
|
|
181
|
+
|
|
182
|
+
ApiFuture::spawn(async move {
|
|
183
|
+
// Resize every visible plugin (not just the active one) to its
|
|
184
|
+
// new cell as the settings pane toggles. The pane is the outer
|
|
185
|
+
// SplitPanel, which emits no `before-resize`, so this is driven
|
|
186
|
+
// explicitly here. CLOSING grows the cells, so pre-size each
|
|
187
|
+
// plugin to its grown box BEFORE collapsing the pane; OPENING
|
|
188
|
+
// shrinks them, so pre-size to the shrunk box (from the deltas
|
|
189
|
+
// cached at the last close; the first-ever open has none and
|
|
190
|
+
// stays reactive) BEFORE the pane mounts — either way, one
|
|
191
|
+
// clean resize with the reactive pass after as the exactness
|
|
192
|
+
// finalizer.
|
|
193
|
+
let result: ApiResult<JsValue> = async {
|
|
194
|
+
if is_open {
|
|
195
|
+
let presents = presize_visible_panels_grown(&workspace, &elem).await;
|
|
196
|
+
let (notify, rendered) = channel::<()>();
|
|
197
|
+
callback.emit(notify);
|
|
198
|
+
presentation.set_settings_open(false);
|
|
199
|
+
rendered.await?;
|
|
200
|
+
// `notify` fires in `rendered()` (same task as the
|
|
201
|
+
// Yew DOM patch) and this future resumes as one of
|
|
202
|
+
// its microtasks — so the staged reveal below and
|
|
203
|
+
// the pane's geometry change reach the screen in a
|
|
204
|
+
// single paint.
|
|
205
|
+
presents.reveal();
|
|
206
|
+
// I6: the exactness-finalizer resize is part of
|
|
207
|
+
// what this toggle caused — await it here rather
|
|
208
|
+
// than leaving it to the ResizeObserver (whose
|
|
209
|
+
// continuous pass remains as the reactive
|
|
210
|
+
// backstop).
|
|
211
|
+
resize_visible_panels(&workspace).await;
|
|
212
|
+
} else {
|
|
213
|
+
let presents = if let Some((delta_w, delta_h)) = open_deltas {
|
|
214
|
+
presize_visible_panels_open(&workspace, &elem, delta_w, delta_h)
|
|
215
|
+
.await
|
|
216
|
+
} else {
|
|
217
|
+
StagedPresents::default()
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
let (notify, rendered) = channel::<()>();
|
|
221
|
+
callback.emit(notify);
|
|
222
|
+
presentation.set_settings_open(true);
|
|
223
|
+
rendered.await?;
|
|
224
|
+
presents.reveal();
|
|
225
|
+
resize_visible_panels(&workspace).await;
|
|
226
|
+
}
|
|
227
|
+
Ok(JsValue::UNDEFINED)
|
|
228
|
+
}
|
|
229
|
+
.await;
|
|
230
|
+
|
|
231
|
+
if let Some(sender) = sender {
|
|
232
|
+
let msg = result.ignore_view_delete();
|
|
233
|
+
sender
|
|
234
|
+
.send(msg.map(|x| x.unwrap_or(JsValue::UNDEFINED)))
|
|
235
|
+
.into_apierror()?;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
Ok(JsValue::undefined())
|
|
239
|
+
});
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
pub(super) fn on_settings_panel_size_update(&mut self, x: Option<i32>) -> bool {
|
|
245
|
+
match x {
|
|
246
|
+
Some(x) => {
|
|
247
|
+
self.settings_geometry.pane_width_override = Some(x);
|
|
248
|
+
false
|
|
249
|
+
},
|
|
250
|
+
None => {
|
|
251
|
+
self.settings_geometry.pane_width_override = None;
|
|
252
|
+
self.settings_geometry.auto_width = 0.0;
|
|
253
|
+
self.on_settings_panel_dimensions_reset.emit(());
|
|
254
|
+
true
|
|
255
|
+
},
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
pub(super) fn on_settings_divider_move(
|
|
260
|
+
&mut self,
|
|
261
|
+
ctx: &Context<Self>,
|
|
262
|
+
pane_width: i32,
|
|
263
|
+
) -> bool {
|
|
264
|
+
// Latest-wins: overwrite the pending target; start the pump if
|
|
265
|
+
// idle. Intermediate targets that arrive while a presize is in
|
|
266
|
+
// flight are dropped (mirrors `PresizeQueue`'s single queued
|
|
267
|
+
// slot) — the pane tracks the pointer at content-render rate.
|
|
268
|
+
self.settings_geometry.divider_target = Some(pane_width);
|
|
269
|
+
if !self.settings_geometry.divider_pumping {
|
|
270
|
+
self.settings_geometry.divider_pumping = true;
|
|
271
|
+
ctx.link().send_message(SettingsDividerPump);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
false
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
pub(super) fn on_settings_divider_pump(&mut self, ctx: &Context<Self>) -> bool {
|
|
278
|
+
if let Some(pane_width) = self.settings_geometry.divider_target.take() {
|
|
279
|
+
let workspace = ctx.props().workspace.clone();
|
|
280
|
+
let elem = ctx.props().elem.clone();
|
|
281
|
+
let link = ctx.link().clone();
|
|
282
|
+
ApiFuture::spawn(async move {
|
|
283
|
+
let presents =
|
|
284
|
+
presize_visible_panels_pane_width(&workspace, &elem, pane_width as f64).await;
|
|
285
|
+
link.send_message(SettingsDividerCommit(pane_width));
|
|
286
|
+
// Same task as the commit's re-render (whether Yew drained it
|
|
287
|
+
// synchronously inside `send_message` or deferred it to a
|
|
288
|
+
// microtask): the staged reveal and the pane-width geometry
|
|
289
|
+
// land in one paint.
|
|
290
|
+
presents.reveal();
|
|
291
|
+
Ok(())
|
|
292
|
+
});
|
|
293
|
+
} else {
|
|
294
|
+
self.settings_geometry.divider_pumping = false;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
false
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
pub(super) fn on_settings_divider_commit(
|
|
301
|
+
&mut self,
|
|
302
|
+
ctx: &Context<Self>,
|
|
303
|
+
pane_width: i32,
|
|
304
|
+
) -> bool {
|
|
305
|
+
// Every visible panel has rendered at (approximately) its
|
|
306
|
+
// target box — NOW move the geometry: the re-render below
|
|
307
|
+
// applies this width to the deferred `SplitPanel`'s controlled
|
|
308
|
+
// `size`, in the same task as the presizes' inline clears.
|
|
309
|
+
self.settings_geometry.pane_width_override = Some(pane_width);
|
|
310
|
+
ctx.link().send_message(SettingsDividerPump);
|
|
311
|
+
true
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
pub(super) fn on_settings_divider_finish(&mut self, ctx: &Context<Self>) -> bool {
|
|
315
|
+
let workspace = ctx.props().workspace.clone();
|
|
316
|
+
ApiFuture::spawn(async move {
|
|
317
|
+
resize_visible_panels(&workspace).await;
|
|
318
|
+
Ok(())
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
false
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
pub(super) fn on_settings_panel_tab_changed(&mut self, tab: SelectedTab) -> bool {
|
|
325
|
+
let changed = tab != self.settings_geometry.selected_tab;
|
|
326
|
+
self.settings_geometry.selected_tab = tab;
|
|
327
|
+
changed
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
pub(super) fn on_settings_panel_auto_width(&mut self, w: f64) -> bool {
|
|
331
|
+
if w > self.settings_geometry.auto_width {
|
|
332
|
+
self.settings_geometry.auto_width = w;
|
|
333
|
+
true
|
|
334
|
+
} else {
|
|
335
|
+
false
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
pub(super) fn on_open_column_settings(
|
|
340
|
+
&mut self,
|
|
341
|
+
ctx: &Context<Self>,
|
|
342
|
+
locator: Option<ColumnLocator>,
|
|
343
|
+
sender: Option<Sender<()>>,
|
|
344
|
+
toggle: bool,
|
|
345
|
+
) -> bool {
|
|
346
|
+
let mut open_column_settings = ctx.props().presentation.get_open_column_settings();
|
|
347
|
+
if locator == open_column_settings.locator {
|
|
348
|
+
if toggle {
|
|
349
|
+
ctx.props().presentation.set_open_column_settings(None);
|
|
350
|
+
}
|
|
351
|
+
} else {
|
|
352
|
+
open_column_settings.locator.clone_from(&locator);
|
|
353
|
+
open_column_settings.tab = if matches!(locator, Some(ColumnLocator::NewExpression)) {
|
|
354
|
+
Some(ColumnSettingsTab::Attributes)
|
|
355
|
+
} else {
|
|
356
|
+
locator.as_ref().and_then(|x| {
|
|
357
|
+
x.name().map(|x| {
|
|
358
|
+
if self.session_props.is_column_active(x) {
|
|
359
|
+
ColumnSettingsTab::Style
|
|
360
|
+
} else {
|
|
361
|
+
ColumnSettingsTab::Attributes
|
|
362
|
+
}
|
|
363
|
+
})
|
|
364
|
+
})
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
ctx.props()
|
|
368
|
+
.presentation
|
|
369
|
+
.set_open_column_settings(Some(open_column_settings));
|
|
370
|
+
|
|
371
|
+
if locator.is_some() {
|
|
372
|
+
self.settings_geometry.selected_tab = SelectedTab::Query;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if let Some(sender) = sender {
|
|
377
|
+
// I6: resolve on the render commit that applies this change (the
|
|
378
|
+
// shared `on_rendered` queue, drained in `rendered()` once fonts
|
|
379
|
+
// settle), not at message-handling time.
|
|
380
|
+
self.on_rendered.push(sender);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
true
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
pub(super) fn on_column_settings_panel_size_update(&mut self, x: Option<i32>) -> bool {
|
|
387
|
+
self.settings_geometry.column_settings_width_override = x;
|
|
388
|
+
if x.is_none() {
|
|
389
|
+
self.settings_geometry.column_settings_auto_width = 0.0;
|
|
390
|
+
true
|
|
391
|
+
} else {
|
|
392
|
+
false
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
pub(super) fn on_column_settings_panel_auto_width(&mut self, w: f64) -> bool {
|
|
397
|
+
if w > self.settings_geometry.column_settings_auto_width {
|
|
398
|
+
self.settings_geometry.column_settings_auto_width = w;
|
|
399
|
+
true
|
|
400
|
+
} else {
|
|
401
|
+
false
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
pub(super) fn on_toggle_column_settings_pin(&mut self) -> bool {
|
|
406
|
+
self.settings_geometry.column_settings_pinned =
|
|
407
|
+
!self.settings_geometry.column_settings_pinned;
|
|
408
|
+
true
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
pub(super) fn on_column_settings_tab_changed(
|
|
412
|
+
&mut self,
|
|
413
|
+
ctx: &Context<Self>,
|
|
414
|
+
tab: ColumnSettingsTab,
|
|
415
|
+
) -> bool {
|
|
416
|
+
let mut open_column_settings = ctx.props().presentation.get_open_column_settings();
|
|
417
|
+
open_column_settings.tab.clone_from(&Some(tab));
|
|
418
|
+
ctx.props()
|
|
419
|
+
.presentation
|
|
420
|
+
.set_open_column_settings(Some(open_column_settings));
|
|
421
|
+
true
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/// Toggling the debug tab re-renders the settings panel only — the
|
|
425
|
+
/// `DebugPanel` populates itself (`get_viewer_config` on mount +
|
|
426
|
+
/// change subscriptions), so no plugin dispatch is owed. The old
|
|
427
|
+
/// `just_render` here relied on the pre-amendment unconditional
|
|
428
|
+
/// `Unchanged → update` arm and repainted the plugin as a side effect
|
|
429
|
+
/// (`PLUGIN_DRAW_INVARIANT_PLAN.md` amendment, migration 2).
|
|
430
|
+
pub(super) fn on_toggle_debug(&mut self, _ctx: &Context<Self>) -> bool {
|
|
431
|
+
self.debug_open = !self.debug_open;
|
|
432
|
+
true
|
|
433
|
+
}
|
|
434
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
2
|
+
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
|
3
|
+
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
|
4
|
+
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
|
5
|
+
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
|
6
|
+
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
|
7
|
+
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
|
8
|
+
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
|
9
|
+
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
|
10
|
+
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
|
11
|
+
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
|
12
|
+
|
|
13
|
+
//! Value-semantic snapshot plumbing: the mechanical `Update*` handlers that
|
|
14
|
+
//! copy fresh engine-state snapshots (dispatched by the [`super::wiring`]
|
|
15
|
+
//! subscriptions/callbacks) into the root's props fields, re-rendering only
|
|
16
|
+
//! on an actual change.
|
|
17
|
+
|
|
18
|
+
use yew::prelude::*;
|
|
19
|
+
|
|
20
|
+
use super::PerspectiveViewer;
|
|
21
|
+
use crate::presentation::{DragDropProps, OpenColumnSettings, PresentationProps};
|
|
22
|
+
use crate::renderer::RendererProps;
|
|
23
|
+
use crate::session::{SessionProps, TableLoadState, ViewStats};
|
|
24
|
+
|
|
25
|
+
impl PerspectiveViewer {
|
|
26
|
+
pub(super) fn on_update_session(&mut self, props: SessionProps) -> bool {
|
|
27
|
+
let changed = props != self.session_props;
|
|
28
|
+
self.session_props = props;
|
|
29
|
+
changed
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
pub(super) fn on_update_session_stats(
|
|
33
|
+
&mut self,
|
|
34
|
+
stats: Option<ViewStats>,
|
|
35
|
+
has_table: Option<TableLoadState>,
|
|
36
|
+
) -> bool {
|
|
37
|
+
let changed =
|
|
38
|
+
stats != self.session_props.stats || has_table != self.session_props.has_table;
|
|
39
|
+
self.session_props.stats = stats;
|
|
40
|
+
self.session_props.has_table = has_table;
|
|
41
|
+
changed
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
pub(super) fn on_update_renderer(&mut self, props: RendererProps) -> bool {
|
|
45
|
+
let changed = props != self.renderer_props;
|
|
46
|
+
self.renderer_props = props;
|
|
47
|
+
changed
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
pub(super) fn on_update_presentation(
|
|
51
|
+
&mut self,
|
|
52
|
+
ctx: &Context<Self>,
|
|
53
|
+
props: PresentationProps,
|
|
54
|
+
) -> bool {
|
|
55
|
+
// Default-theme fan-out: when the registry default (first available
|
|
56
|
+
// theme) changes — the async theme discovery resolving at boot, or a
|
|
57
|
+
// `resetThemes` — push the new default into every panel's renderer
|
|
58
|
+
// cache (locked draws stamp the effective theme from it), and
|
|
59
|
+
// restyle the panels whose captured `--psp-*` CSS is STALE against
|
|
60
|
+
// the new effective value (`Renderer::needs_restyle` — the plugin's
|
|
61
|
+
// captured theme is the baseline; plugins only re-read CSS at
|
|
62
|
+
// `restyle()`/first-draw, so a plain redraw would not repaint a
|
|
63
|
+
// panel that first drew before discovery resolved, while a panel
|
|
64
|
+
// that captured post-discovery — or owes its first paint — restyles
|
|
65
|
+
// nothing). The outer default-diff scopes the scan; the per-panel
|
|
66
|
+
// gate is state, never call history or DOM state.
|
|
67
|
+
let old_default = self.presentation_props.available_themes.first().cloned();
|
|
68
|
+
let new_default = props.available_themes.first().cloned();
|
|
69
|
+
if old_default != new_default {
|
|
70
|
+
for panel in ctx
|
|
71
|
+
.props()
|
|
72
|
+
.workspace
|
|
73
|
+
.panel_ids()
|
|
74
|
+
.into_iter()
|
|
75
|
+
.filter_map(|id| ctx.props().workspace.panel(&id))
|
|
76
|
+
{
|
|
77
|
+
panel.renderer.set_default_theme(new_default.clone());
|
|
78
|
+
if panel.renderer.needs_restyle() {
|
|
79
|
+
let renderer = panel.renderer.clone();
|
|
80
|
+
crate::utils::spawn_owned("default-theme-restyle", async move {
|
|
81
|
+
renderer.restyle_all().await?;
|
|
82
|
+
Ok(())
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let changed = props != self.presentation_props;
|
|
89
|
+
self.presentation_props = props;
|
|
90
|
+
changed
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
pub(super) fn on_update_settings_open(&mut self, open: bool) -> bool {
|
|
94
|
+
let changed = open != self.presentation_props.is_settings_open;
|
|
95
|
+
self.presentation_props.is_settings_open = open;
|
|
96
|
+
changed
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
pub(super) fn on_update_is_workspace(&mut self, is_workspace: bool) -> bool {
|
|
100
|
+
let changed = is_workspace != self.presentation_props.is_workspace;
|
|
101
|
+
self.presentation_props.is_workspace = is_workspace;
|
|
102
|
+
changed
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
pub(super) fn on_update_column_settings(&mut self, ocs: OpenColumnSettings) -> bool {
|
|
106
|
+
let changed = ocs != self.presentation_props.open_column_settings;
|
|
107
|
+
self.presentation_props.open_column_settings = ocs;
|
|
108
|
+
changed
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
pub(super) fn on_update_dragdrop(&mut self, props: DragDropProps) -> bool {
|
|
112
|
+
let changed = props != self.dragdrop_props;
|
|
113
|
+
self.dragdrop_props = props;
|
|
114
|
+
changed
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
pub(super) fn on_update_global_filters(&mut self, ctx: &Context<Self>) -> bool {
|
|
118
|
+
let filters = ctx.props().workspace.global_filters();
|
|
119
|
+
let changed = filters != self.global_filters;
|
|
120
|
+
self.global_filters = filters;
|
|
121
|
+
changed
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/// LEVEL-triggered spinner count: ASSIGN the absolute in-flight
|
|
125
|
+
/// config-run count from the session's RAII accounting — any missed or
|
|
126
|
+
/// reordered notification is corrected by the next one, unlike the
|
|
127
|
+
/// edge-counted increment/decrement pair this replaces (see
|
|
128
|
+
/// `UPDATE_COUNT_REGRESSION_PLAN.md`).
|
|
129
|
+
pub(super) fn on_update_in_flight(&mut self, count: u32) -> bool {
|
|
130
|
+
let changed = count != self.update_count;
|
|
131
|
+
self.update_count = count;
|
|
132
|
+
changed
|
|
133
|
+
}
|
|
134
|
+
}
|