@perspective-dev/viewer 5.3.1 → 5.5.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 +6 -6
- package/dist/cdn/perspective-viewer.js.map +2 -2
- package/dist/css/blueprint.css +1 -1
- package/dist/css/botanical.css +1 -1
- package/dist/css/dracula.css +1 -1
- package/dist/css/eggplant.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/ar.css +1 -0
- 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/ledger.css +1 -1
- package/dist/css/monokai.css +1 -1
- package/dist/css/nord.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/css/velvet.css +1 -1
- package/dist/docs/perspective-docs.json +1 -1
- package/dist/esm/extensions.d.ts +0 -5
- package/dist/esm/perspective-viewer.d.ts +2 -0
- package/dist/esm/perspective-viewer.inline.js +8 -8
- package/dist/esm/perspective-viewer.inline.js.map +2 -2
- package/dist/esm/perspective-viewer.js +5 -5
- package/dist/esm/perspective-viewer.js.map +2 -2
- package/dist/esm/plugin.d.ts +9 -0
- package/dist/esm/ts-rs/AddPanelOptions.d.ts +9 -0
- package/dist/esm/ts-rs/GetViewMode.d.ts +4 -0
- package/dist/esm/ts-rs/GetViewOptions.d.ts +8 -0
- package/dist/esm/ts-rs/RestoreOptions.d.ts +6 -0
- package/dist/esm/ts-rs/RestoreWorkspaceOptions.d.ts +9 -0
- package/dist/esm/ts-rs/ViewOnUpdateResp.d.ts +1 -1
- package/dist/esm/ts-rs/WorkspaceConfigUpdate.d.ts +30 -22
- package/dist/wasm/perspective-viewer.d.ts +137 -104
- package/dist/wasm/perspective-viewer.js +337 -269
- package/dist/wasm/perspective-viewer.wasm +0 -0
- package/dist/wasm/perspective-viewer.wasm.d.ts +20 -30
- package/package.json +7 -7
- package/src/css/_context_menu.css +1 -1
- package/src/css/_dropdown_menu.css +1 -1
- package/src/css/_viewer_bundle.css +7 -8
- package/src/css/column-dropdown.css +0 -3
- package/src/css/column-selector.css +18 -7
- package/src/css/column-settings-panel.css +0 -225
- package/src/css/column-style.css +175 -0
- package/src/css/config-selector.css +19 -11
- package/src/css/filter-dropdown.css +5 -5
- package/src/css/form/debug.css +37 -4
- package/src/css/function-dropdown.css +5 -5
- package/src/css/panel-tab.css +23 -0
- package/src/css/plugin-selector.css +5 -5
- package/src/css/render-warning.css +1 -1
- package/src/css/status-bar.css +63 -21
- package/src/css/type-icon.css +1 -3
- package/src/css/{containers → ui/containers}/context-menu.css +22 -16
- package/src/css/ui/containers/dropdown-menu-items.css +66 -0
- package/src/css/{containers → ui/containers}/dropdown-menu.css +8 -53
- package/src/css/{containers → ui/containers}/tabs.css +2 -1
- package/src/css/viewer.css +32 -26
- package/src/rust/agent/tools.rs +80 -7
- package/src/rust/components/chat_panel.rs +1 -1
- package/src/rust/components/{form/code_editor.rs → code_editor.rs} +4 -2
- package/src/rust/components/column_dropdown.rs +2 -2
- package/src/rust/components/column_selector/active_column.rs +24 -9
- package/src/rust/components/column_selector/aggregate_selector.rs +1 -1
- package/src/rust/components/column_selector/config_selector.rs +2 -2
- package/src/rust/components/column_selector/filter_column.rs +8 -5
- package/src/rust/components/column_selector/inactive_column.rs +4 -2
- package/src/rust/components/column_selector/pivot_column.rs +4 -3
- package/src/rust/components/column_selector/sort_column.rs +7 -4
- package/src/rust/components/column_selector.rs +14 -3
- package/src/rust/components/column_settings_sidebar/style_tab/agg_depth_selector.rs +1 -1
- package/src/rust/components/column_settings_sidebar/style_tab/alignment_field.rs +90 -0
- package/src/rust/components/column_settings_sidebar/style_tab/font_field.rs +267 -0
- package/src/rust/components/column_settings_sidebar/style_tab/primitive_field.rs +16 -18
- package/src/rust/components/column_settings_sidebar/style_tab/symbol/symbol_selector.rs +1 -1
- package/src/rust/components/column_settings_sidebar/style_tab.rs +70 -12
- package/src/rust/components/column_settings_sidebar.rs +3 -4
- package/src/rust/components/copy_dropdown.rs +1 -1
- package/src/rust/components/datetime_column_style/custom.rs +1 -3
- package/src/rust/components/datetime_column_style/simple.rs +1 -2
- package/src/rust/components/datetime_column_style.rs +1 -2
- package/src/rust/components/{form/debug.rs → debug_panel.rs} +112 -55
- package/src/rust/components/{containers/dragdrop_list.rs → dragdrop_list.rs} +2 -10
- package/src/rust/components/export_dropdown.rs +1 -1
- package/src/rust/components/expression_editor.rs +1 -1
- package/src/rust/components/filter_dropdown.rs +2 -2
- package/src/rust/components/function_dropdown.rs +2 -2
- package/src/rust/components/main_panel/frame_theme.rs +3 -59
- package/src/rust/components/main_panel/msg.rs +4 -0
- package/src/rust/components/main_panel/reconcile.rs +9 -4
- package/src/rust/components/main_panel/render.rs +62 -11
- package/src/rust/components/main_panel/update.rs +39 -10
- package/src/rust/components/main_panel.rs +40 -2
- package/src/rust/components/mod.rs +5 -8
- package/src/rust/components/new_panel_menu.rs +97 -0
- package/src/rust/components/number_series_style.rs +2 -3
- package/src/rust/components/panel_menu.rs +61 -87
- package/src/rust/components/panel_tab.rs +100 -43
- package/src/rust/components/plugin_tab.rs +58 -4
- package/src/rust/components/render_warning.rs +2 -2
- package/src/rust/components/{status_bar_counter.rs → rows_counter.rs} +10 -10
- package/src/rust/components/settings_panel.rs +8 -2
- package/src/rust/components/status_bar.rs +113 -19
- package/src/rust/components/status_indicator.rs +9 -14
- package/src/rust/components/{style/mod.rs → style.rs} +32 -15
- package/src/rust/components/style_controls/number_string_format/digits_section.rs +3 -5
- package/src/rust/components/style_controls/number_string_format/misc_section.rs +1 -1
- package/src/rust/components/style_controls/number_string_format/style_section.rs +1 -1
- package/src/rust/components/viewer/msg.rs +43 -30
- package/src/rust/components/viewer/panels.rs +53 -19
- package/src/rust/components/viewer/render.rs +16 -13
- package/src/rust/components/viewer/settings.rs +137 -68
- package/src/rust/components/viewer/snapshots.rs +5 -10
- package/src/rust/components/viewer/wiring.rs +11 -22
- package/src/rust/components/viewer.rs +15 -10
- package/src/rust/components/window_editor.rs +8 -9
- package/src/rust/config/column_config_schema.rs +312 -33
- package/src/rust/config/datetime_column_style.rs +0 -11
- package/src/rust/config/mod.rs +0 -4
- package/src/rust/config/options.rs +50 -0
- package/src/rust/config/workspace_config.rs +70 -24
- package/src/rust/custom_elements/debug_plugin.rs +1 -10
- package/src/rust/custom_elements/mod.rs +0 -3
- package/src/rust/custom_elements/viewer.rs +194 -115
- package/src/rust/js/plugin.rs +3 -87
- package/src/rust/lib.rs +19 -18
- package/src/rust/presentation/column_locator.rs +3 -7
- package/src/rust/presentation.rs +68 -38
- package/src/rust/queries/hosted_tables.rs +38 -0
- package/src/rust/queries/mod.rs +2 -0
- package/src/rust/queries/palette_set.rs +1 -1
- package/src/rust/queries/plugin_column_styles.rs +6 -5
- package/src/rust/renderer/activate.rs +1 -3
- package/src/rust/renderer/dispatch.rs +83 -22
- package/src/rust/renderer/limits.rs +24 -5
- package/src/rust/renderer/plugin_config.rs +201 -41
- package/src/rust/renderer/plugin_store.rs +2 -1
- package/src/rust/renderer/props.rs +7 -1
- package/src/rust/renderer.rs +23 -27
- package/src/rust/session/props.rs +8 -3
- package/src/rust/session/view_subscription.rs +19 -6
- package/src/rust/session.rs +189 -150
- package/src/rust/tasks/create_panel.rs +5 -2
- package/src/rust/tasks/dismiss_render_warning.rs +1 -1
- package/src/rust/tasks/eject.rs +1 -0
- package/src/rust/tasks/pipeline.rs +18 -67
- package/src/rust/tasks/presize_panels.rs +24 -1
- package/src/rust/tasks/restore_and_render.rs +0 -17
- package/src/rust/tasks/restore_panel.rs +129 -30
- package/src/rust/tasks/send_column_config.rs +4 -1
- package/src/rust/tasks/send_plugin_config.rs +1 -1
- package/src/rust/tasks/set_edit_mode.rs +1 -1
- package/src/rust/tasks/sync_update_panels.rs +147 -67
- package/src/rust/tasks/table_lifecycle.rs +7 -1
- package/src/rust/{components → ui}/containers/control_group.rs +25 -3
- package/src/rust/{components → ui}/containers/dropdown_menu.rs +5 -2
- package/src/rust/{components → ui}/containers/mod.rs +0 -4
- package/src/rust/{components → ui}/containers/scroll_panel.rs +0 -22
- package/src/rust/{components → ui}/containers/scroll_panel_item.rs +0 -13
- package/src/rust/{components → ui}/containers/select.rs +0 -6
- package/src/rust/{components → ui}/containers/sidebar.rs +5 -32
- package/src/rust/{components → ui}/containers/split_panel.rs +8 -80
- package/src/rust/{components → ui}/containers/tab_list.rs +15 -9
- package/src/rust/{components → ui}/context_menu.rs +8 -13
- package/src/rust/{presentation/drag_helpers.rs → ui/dragdrop.rs} +26 -31
- package/src/rust/{components → ui}/font_loader.rs +0 -26
- package/src/rust/{components → ui}/form/color_selector.rs +4 -2
- package/src/rust/{config/datetime_column_style/color_mode.rs → ui/form/intl_label.rs} +42 -42
- package/src/rust/{components → ui}/form/mirrored_textarea.rs +0 -53
- package/src/rust/{components → ui}/form/mod.rs +1 -10
- package/src/rust/{components → ui}/form/multi_stop_gradient_selector.rs +4 -5
- package/src/rust/{components → ui}/form/named_value_picker.rs +1 -6
- package/src/rust/{components → ui}/form/number_field.rs +1 -1
- package/src/rust/{components → ui}/form/number_range_field.rs +1 -1
- package/src/rust/{components → ui}/form/optional_field.rs +3 -1
- package/src/rust/{components → ui}/form/palette_selector.rs +4 -5
- package/src/rust/{components → ui}/form/select_enum_field.rs +2 -2
- package/src/rust/{components → ui}/form/select_value_field.rs +2 -2
- package/src/rust/ui/mod.rs +56 -0
- package/src/rust/ui/modal.rs +61 -0
- package/src/rust/{components → ui}/portal.rs +175 -79
- package/src/rust/{components/style/style_provider.rs → ui/style.rs} +4 -34
- package/src/rust/utils/completion.rs +0 -6
- package/src/rust/{config/css_scale.rs → utils/css.rs} +38 -35
- package/src/rust/utils/css_vars.rs +13 -0
- package/src/rust/utils/local_fonts.rs +395 -0
- package/src/rust/utils/mod.rs +4 -0
- package/src/rust/workspace.rs +47 -0
- package/src/svg/boolean-type.svg +3 -2
- package/src/svg/checkbox-checked-icon.svg +4 -7
- package/src/svg/checkbox-hover.svg +3 -3
- package/src/svg/checkbox-off.svg +2 -3
- package/src/svg/checkbox-on.svg +3 -3
- package/src/svg/checkbox-unchecked-icon.svg +3 -3
- package/src/svg/datagrid-select-column.svg +8 -15
- package/src/svg/datagrid-select-region.svg +8 -15
- package/src/svg/datagrid-select-row-tree.svg +7 -12
- package/src/svg/datagrid-select-row.svg +8 -13
- package/src/svg/date-type.svg +4 -23
- package/src/svg/drawer-tab-hover.svg +4 -6
- package/src/svg/drawer-tab-invert-hover.svg +5 -5
- package/src/svg/drawer-tab-invert.svg +3 -5
- package/src/svg/drawer-tab.svg +5 -5
- package/src/svg/mega-menu-icons-candlestick.svg +5 -37
- package/src/svg/mega-menu-icons-ohlc.svg +4 -39
- package/src/svg/mega-menu-icons-sunburst.svg +4 -38
- package/src/svg/mega-menu-icons-treemap.svg +3 -43
- package/src/svg/mega-menu-icons-y-scatter.svg +12 -72
- package/src/svg/new-panel-icon.svg +4 -0
- package/src/svg/number-type.svg +3 -3
- package/src/svg/radio-hover.svg +3 -3
- package/src/svg/radio-off.svg +3 -3
- package/src/svg/radio-on.svg +3 -3
- package/src/svg/status_ok.svg +3 -26
- package/src/svg/status_pending.svg +3 -0
- package/src/svg/string-type.svg +4 -8
- package/src/svg/theme-icon.svg +5 -5
- package/src/themes/blueprint.css +0 -57
- package/src/themes/botanical.css +0 -36
- package/src/themes/defaults.css +1 -24
- package/src/themes/dracula.css +0 -58
- package/src/themes/eggplant.css +0 -58
- package/src/themes/gruvbox-dark.css +0 -65
- package/src/themes/gruvbox.css +1 -39
- package/src/themes/icons.css +2 -8
- package/src/themes/intl/ar.css +198 -0
- package/src/themes/intl/de.css +63 -40
- package/src/themes/intl/es.css +58 -35
- package/src/themes/intl/fr.css +57 -34
- package/src/themes/intl/ja.css +59 -36
- package/src/themes/intl/pt.css +54 -31
- package/src/themes/intl/zh.css +65 -42
- package/src/themes/intl.css +34 -8
- package/src/themes/ledger.css +1 -59
- package/src/themes/monokai.css +0 -51
- package/src/themes/nord.css +0 -55
- package/src/themes/phosphor.css +0 -48
- package/src/themes/pro-dark.css +0 -37
- package/src/themes/pro.css +3 -23
- package/src/themes/solarized-dark.css +0 -31
- package/src/themes/solarized.css +1 -24
- package/src/themes/vaporwave.css +0 -44
- package/src/themes/velvet.css +0 -60
- package/src/ts/extensions.ts +0 -13
- package/src/ts/perspective-viewer.ts +2 -0
- package/src/ts/plugin.ts +9 -0
- package/src/ts/ts-rs/AddPanelOptions.ts +10 -0
- package/src/ts/ts-rs/{DatetimeColorMode.ts → GetViewMode.ts} +4 -1
- package/src/ts/ts-rs/GetViewOptions.ts +7 -0
- package/src/ts/ts-rs/RestoreOptions.ts +7 -1
- package/src/ts/ts-rs/RestoreWorkspaceOptions.ts +10 -0
- package/src/ts/ts-rs/ViewOnUpdateResp.ts +1 -1
- package/src/ts/ts-rs/WorkspaceConfigUpdate.ts +31 -20
- package/dist/esm/ts-rs/DatetimeColorMode.d.ts +0 -1
- package/dist/esm/ts-rs/FormatMode.d.ts +0 -1
- package/dist/esm/ts-rs/StringColorMode.d.ts +0 -1
- package/src/css/plugin-settings-panel.css +0 -171
- package/src/rust/components/modal.rs +0 -177
- package/src/rust/components/string_column_style.rs +0 -121
- package/src/rust/config/string_column_style.rs +0 -135
- package/src/rust/custom_elements/copy_dropdown.rs +0 -219
- package/src/rust/custom_elements/export_dropdown.rs +0 -216
- package/src/rust/custom_elements/modal.rs +0 -299
- package/src/ts/ts-rs/FormatMode.ts +0 -3
- package/src/ts/ts-rs/StringColorMode.ts +0 -3
- /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-ea71a3990cad35d7}/inline0.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-ea71a3990cad35d7}/inline1.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-ea71a3990cad35d7}/inline2.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-ea71a3990cad35d7}/inline3.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-ea71a3990cad35d7}/inline4.js +0 -0
- /package/dist/wasm/snippets/{perspective-viewer-87bd21b215d0631a → perspective-viewer-ea71a3990cad35d7}/inline5.js +0 -0
- /package/src/css/{containers → ui/containers}/scroll-panel.css +0 -0
- /package/src/css/{containers → ui/containers}/split-panel.css +0 -0
- /package/src/css/{dom → ui/dom}/checkbox.css +0 -0
- /package/src/css/{dom → ui/dom}/scrollbar.css +0 -0
- /package/src/css/{dom → ui/dom}/select.css +0 -0
- /package/src/css/{form → ui/form}/mirrored-textarea.css +0 -0
- /package/src/rust/components/{form → code_editor}/highlight.rs +0 -0
- /package/src/rust/{components → ui}/containers/sidebar_close_button.rs +0 -0
- /package/src/rust/{components → ui}/form/number_input.rs +0 -0
package/src/rust/session.rs
CHANGED
|
@@ -24,6 +24,7 @@ use std::ops::Deref;
|
|
|
24
24
|
use std::rc::Rc;
|
|
25
25
|
|
|
26
26
|
use perspective_client::config::*;
|
|
27
|
+
use perspective_client::proto::ViewDimensionsResp;
|
|
27
28
|
use perspective_client::{Client, ClientError, ReconnectCallback, View};
|
|
28
29
|
use perspective_js::apierror;
|
|
29
30
|
use perspective_js::utils::*;
|
|
@@ -56,11 +57,7 @@ pub struct SessionHandle {
|
|
|
56
57
|
pub table_loaded: PubSub<()>,
|
|
57
58
|
pub table_unloaded: PubSub<bool>,
|
|
58
59
|
|
|
59
|
-
/// Fires when a `View` was CREATED — literally
|
|
60
|
-
/// path constructed and bound a new engine `View`. Nothing else may
|
|
61
|
-
/// emit this (a SKIP/REUSE/paused reconcile is [`Self::commit_reconciled`],
|
|
62
|
-
/// which REBUILD also emits) — overloading it broke consumers that
|
|
63
|
-
/// relied on the name's meaning (see `UPDATE_COUNT_REGRESSION_PLAN.md`).
|
|
60
|
+
/// Fires when a `View` was CREATED — literally.
|
|
64
61
|
pub view_created: PubSub<()>,
|
|
65
62
|
|
|
66
63
|
/// Fires exactly once per locked run that RECONCILED the committed
|
|
@@ -74,43 +71,23 @@ pub struct SessionHandle {
|
|
|
74
71
|
pub view_config_changed: PubSub<()>,
|
|
75
72
|
pub title_changed: PubSub<Option<String>>,
|
|
76
73
|
|
|
77
|
-
/// Count of in-flight CONFIG-DRIVEN pipeline runs
|
|
78
|
-
/// settled), incremented by [`Session::begin_config_run`] and
|
|
79
|
-
/// decremented when the returned [`ConfigRunToken`] drops. Drives the
|
|
80
|
-
/// `StatusIndicator` "updating" spinner via [`Self::run_state_changed`].
|
|
81
|
-
/// Pure redraws (resize, activation nudges, `just_render`) do NOT
|
|
82
|
-
/// count — the spinner means "a config requery is in flight".
|
|
74
|
+
/// Count of in-flight CONFIG-DRIVEN pipeline runs.
|
|
83
75
|
in_flight_config_runs: Cell<u32>,
|
|
84
76
|
|
|
85
77
|
/// Fires with the ABSOLUTE [`Self::in_flight_config_runs`] count after
|
|
86
|
-
/// every change.
|
|
87
|
-
/// payload rather than accumulate deltas, so a dropped or reordered
|
|
88
|
-
/// notification is corrected by the next one — the delta-counting
|
|
89
|
-
/// (`view_config_changed`+1 / `view_created`−1) design this replaces
|
|
90
|
-
/// drifted whenever those streams weren't perfectly paired (see
|
|
91
|
-
/// `UPDATE_COUNT_REGRESSION_PLAN.md`).
|
|
78
|
+
/// every change.
|
|
92
79
|
pub run_state_changed: PubSub<u32>,
|
|
93
80
|
|
|
94
81
|
/// Fires when the user clicks the status indicator while in
|
|
95
|
-
/// [`StatusIconState::Normal`].
|
|
96
|
-
/// listener and fans this out as the `perspective-status-indicator-click`
|
|
97
|
-
/// `CustomEvent`.
|
|
82
|
+
/// [`StatusIconState::Normal`].
|
|
98
83
|
pub status_indicator_clicked: PubSub<()>,
|
|
99
84
|
|
|
100
|
-
/// Per-column numeric stats cache.
|
|
101
|
-
/// `fetch_column_abs_max` task and consumed by the schema-query
|
|
102
|
-
/// path so plugins emit gradient defaults without
|
|
103
|
-
/// per-render `View::get_min_max` round trips. Cleared
|
|
104
|
-
/// synchronously inside [`Session::commit_view_config`].
|
|
85
|
+
/// Per-column numeric stats cache.
|
|
105
86
|
column_stats: RefCell<HashMap<String, ColumnStats>>,
|
|
106
87
|
|
|
107
88
|
/// Memoized snapshots used by [`Session::to_props`] to keep
|
|
108
89
|
/// `PtrEqRc` identity stable across repeated `to_props()` calls
|
|
109
|
-
/// when the underlying value hasn't changed.
|
|
110
|
-
/// `PubSub` fire (including `column_stats_changed`) produces a
|
|
111
|
-
/// fresh `Rc` for `config` / `metadata`, triggering downstream
|
|
112
|
-
/// `use_effect_with(view_config, ...)` effects to spuriously
|
|
113
|
-
/// refire — closing a loop with the stats fetch path.
|
|
90
|
+
/// when the underlying value hasn't changed.
|
|
114
91
|
cached_config: RefCell<Option<PtrEqRc<ViewConfig>>>,
|
|
115
92
|
cached_metadata: RefCell<Option<SessionMetadataRc>>,
|
|
116
93
|
|
|
@@ -131,18 +108,7 @@ pub struct SessionHandle {
|
|
|
131
108
|
load_generation: Cell<u32>,
|
|
132
109
|
|
|
133
110
|
/// Open between a `load()` call and its payload's classification as
|
|
134
|
-
/// `Table`/`Client` ([`PendingLoad`]).
|
|
135
|
-
/// unknown, so its RESET/no-RESET disposition cannot be decided yet — but
|
|
136
|
-
/// the window's POSITION on the config-commit stream is fixed at the
|
|
137
|
-
/// `load()` call site. During the window, config commits still apply live
|
|
138
|
-
/// (so `save()` stays coherent — I1) but ALSO append their raw delta to
|
|
139
|
-
/// the journal, and config-driven binds DEFER ([`Session::snapshot`]'s
|
|
140
|
-
/// caller [`crate::tasks::bind_snapshot`]) — the incoming config must
|
|
141
|
-
/// never draw against the still-bound outgoing table (hold the last
|
|
142
|
-
/// frame). Classified as `Table` the journal replays over a reset base
|
|
143
|
-
/// (`reset ∘ Δ₁ ∘ Δ₂ …`, the program-order result the old synchronous
|
|
144
|
-
/// reset guaranteed); as `Client` it is dropped (no reset — live already
|
|
145
|
-
/// carries every Δ). See `SESSION_CONFIG_COHERENCE_PLAN.md`.
|
|
111
|
+
/// `Table`/`Client` ([`PendingLoad`]).
|
|
146
112
|
pending_load: RefCell<Option<PendingLoad>>,
|
|
147
113
|
|
|
148
114
|
/// Coalesces `view_config_changed`: multiple synchronous commits in one
|
|
@@ -165,8 +131,11 @@ pub struct SessionHandle {
|
|
|
165
131
|
/// new value.
|
|
166
132
|
pub column_stats_changed: PubSub<()>,
|
|
167
133
|
|
|
168
|
-
///
|
|
169
|
-
|
|
134
|
+
/// Fires when view stats are updated.
|
|
135
|
+
pub stats_changed: PubSub<()>,
|
|
136
|
+
|
|
137
|
+
/// Injected callback from the root component, driving
|
|
138
|
+
/// `session_props.has_table_cells` for the active panel.
|
|
170
139
|
pub on_stats_changed: RefCell<Option<Callback<()>>>,
|
|
171
140
|
|
|
172
141
|
/// Injected callback from the root component, replacing the former
|
|
@@ -183,6 +152,51 @@ impl Deref for SessionHandle {
|
|
|
183
152
|
}
|
|
184
153
|
}
|
|
185
154
|
|
|
155
|
+
/// What an un-hosted `table` name means to a bind, per the `wait_for_table`
|
|
156
|
+
/// option.
|
|
157
|
+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
158
|
+
pub enum MissingTable {
|
|
159
|
+
/// A hard error that leaves the panel as it was.
|
|
160
|
+
Error,
|
|
161
|
+
|
|
162
|
+
/// The panel waits unbound and binds when the name is hosted.
|
|
163
|
+
Pend,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
impl MissingTable {
|
|
167
|
+
/// Decode the `wait_for_table` option (absent = `false` = `Error`).
|
|
168
|
+
pub fn from_wait(wait_for_table: Option<bool>) -> Self {
|
|
169
|
+
if wait_for_table.unwrap_or_default() {
|
|
170
|
+
Self::Pend
|
|
171
|
+
} else {
|
|
172
|
+
Self::Error
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/// Open `name` on `client`, returning `Ok(None)` when the name is not hosted
|
|
178
|
+
/// and `missing` is [`MissingTable::Pend`].
|
|
179
|
+
pub(crate) async fn probe_table(
|
|
180
|
+
client: &Client,
|
|
181
|
+
name: &str,
|
|
182
|
+
missing: MissingTable,
|
|
183
|
+
) -> ApiResult<Option<perspective_client::Table>> {
|
|
184
|
+
match client.open_table(name.to_owned()).await {
|
|
185
|
+
Ok(table) => Ok(Some(table)),
|
|
186
|
+
Err(e) => {
|
|
187
|
+
let hosted = client.get_hosted_table_names().await.unwrap_or_default();
|
|
188
|
+
if hosted.iter().any(|n| n == name) {
|
|
189
|
+
return Err(e.into());
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
match missing {
|
|
193
|
+
MissingTable::Pend => Ok(None),
|
|
194
|
+
MissingTable::Error => Err(ApiError::new(format!("Unknown table \"{name}\""))),
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
186
200
|
/// Mutable state for `Session`.
|
|
187
201
|
#[derive(Default)]
|
|
188
202
|
pub struct SessionData {
|
|
@@ -279,13 +293,7 @@ pub struct ResetOptions {
|
|
|
279
293
|
#[derive(Clone)]
|
|
280
294
|
pub struct Session(Rc<SessionHandle>);
|
|
281
295
|
|
|
282
|
-
/// RAII spinner accounting for one config-driven pipeline run
|
|
283
|
-
/// [`Session::begin_config_run`] and `UPDATE_COUNT_REGRESSION_PLAN.md`):
|
|
284
|
-
/// created when the run is scheduled — immediately after its commit — and
|
|
285
|
-
/// moved INTO the run future, so `Drop` settles the count on every exit
|
|
286
|
-
/// path: completion, error, cancellation, and runs that never reach
|
|
287
|
-
/// `bind_view` (the deferred-draw restore). A stranded count is
|
|
288
|
-
/// unrepresentable; there is no other writer.
|
|
296
|
+
/// RAII spinner accounting for one config-driven pipeline run.
|
|
289
297
|
pub struct ConfigRunToken(Session);
|
|
290
298
|
|
|
291
299
|
impl Drop for ConfigRunToken {
|
|
@@ -346,6 +354,7 @@ impl Session {
|
|
|
346
354
|
/// `Session`.
|
|
347
355
|
pub fn reset(&self, options: ResetOptions) -> impl Future<Output = ApiResult<()>> + use<> {
|
|
348
356
|
let view = self.0.borrow_mut().view_sub.take();
|
|
357
|
+
let had_table = self.borrow().table.is_some();
|
|
349
358
|
let err = self.get_error();
|
|
350
359
|
self.borrow_mut().error = None;
|
|
351
360
|
if options.stats {
|
|
@@ -365,11 +374,13 @@ impl Session {
|
|
|
365
374
|
self.borrow_mut().is_loading = false;
|
|
366
375
|
self.borrow_mut().table = None;
|
|
367
376
|
self.borrow_mut().pending_table = None;
|
|
377
|
+
self.borrow_mut().metadata = SessionMetadata::default();
|
|
368
378
|
},
|
|
369
379
|
Some(TableIntermediateState::Reloaded) => {
|
|
370
380
|
self.borrow_mut().is_loading = true;
|
|
371
381
|
self.borrow_mut().table = None;
|
|
372
382
|
self.borrow_mut().pending_table = None;
|
|
383
|
+
self.borrow_mut().metadata = SessionMetadata::default();
|
|
373
384
|
},
|
|
374
385
|
_ => {
|
|
375
386
|
self.borrow_mut().is_loading = false;
|
|
@@ -390,7 +401,7 @@ impl Session {
|
|
|
390
401
|
let session = self.clone();
|
|
391
402
|
async move {
|
|
392
403
|
let res = view.delete().await;
|
|
393
|
-
if options.table.is_some() {
|
|
404
|
+
if options.table.is_some() && had_table {
|
|
394
405
|
session.table_unloaded.emit(true)
|
|
395
406
|
}
|
|
396
407
|
|
|
@@ -447,6 +458,8 @@ impl Session {
|
|
|
447
458
|
Some(TableLoadState::Loaded)
|
|
448
459
|
} else if data.is_loading {
|
|
449
460
|
Some(TableLoadState::Loading)
|
|
461
|
+
} else if data.pending_table.is_some() {
|
|
462
|
+
Some(TableLoadState::Pending)
|
|
450
463
|
} else {
|
|
451
464
|
None
|
|
452
465
|
}
|
|
@@ -507,10 +520,8 @@ impl Session {
|
|
|
507
520
|
/// `table_name` is unique per `Client`, so if this value has not changed,
|
|
508
521
|
/// `Session::set_table` does nothing and returns `Ok(false)`.
|
|
509
522
|
///
|
|
510
|
-
/// A name
|
|
511
|
-
///
|
|
512
|
-
/// `Ok(false)`; the element's hosted-tables subscription
|
|
513
|
-
/// (`tasks::table_lifecycle`) re-runs the bind when the table is created.
|
|
523
|
+
/// A name no loaded client hosts pends ([`MissingTable::Pend`]) and
|
|
524
|
+
/// returns `Ok(false)` until the table lifecycle re-runs the bind.
|
|
514
525
|
pub async fn set_table(&self, table_name: String) -> ApiResult<bool> {
|
|
515
526
|
if Some(table_name.as_str()) == self.0.borrow().table.as_ref().map(|x| x.get_name()) {
|
|
516
527
|
self.0.borrow_mut().pending_table = None;
|
|
@@ -518,60 +529,68 @@ impl Session {
|
|
|
518
529
|
}
|
|
519
530
|
|
|
520
531
|
let client = self.0.borrow().client.clone().into_apierror()?;
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
// open failure by the hosted set, not the error's text.
|
|
526
|
-
let hosted = client.get_hosted_table_names().await.unwrap_or_default();
|
|
527
|
-
if hosted.iter().any(|n| n == &table_name) {
|
|
528
|
-
return Err(e.into());
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
self.0.borrow_mut().pending_table = Some(table_name);
|
|
532
|
-
return Ok(false);
|
|
532
|
+
match probe_table(&client, &table_name, MissingTable::Pend).await? {
|
|
533
|
+
Some(table) => match self.bind_table(table).await {
|
|
534
|
+
Ok(()) => Ok(true),
|
|
535
|
+
Err(err) => self.set_error(false, err).await.map(|_| false),
|
|
533
536
|
},
|
|
534
|
-
|
|
537
|
+
None => {
|
|
538
|
+
self.pend_table(table_name).await?;
|
|
539
|
+
Ok(false)
|
|
540
|
+
},
|
|
541
|
+
}
|
|
542
|
+
}
|
|
535
543
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
544
|
+
/// Bind an opened `Table`, replacing any previous binding and announcing
|
|
545
|
+
/// `table_loaded`.
|
|
546
|
+
pub(crate) async fn bind_table(&self, table: perspective_client::Table) -> ApiResult<()> {
|
|
547
|
+
let metadata = SessionMetadata::from_table(&table).await?;
|
|
548
|
+
let client = table.get_client();
|
|
549
|
+
let on_error = self.on_table_errored.borrow().clone();
|
|
550
|
+
let session = self.clone();
|
|
551
|
+
let poll_loop = LocalPollLoop::new(move |(message, reconnect): (ApiError, _)| {
|
|
552
|
+
session.borrow_mut().error = Some(TableErrorState(message, reconnect));
|
|
553
|
+
if let Some(cb) = &on_error {
|
|
554
|
+
cb.emit(());
|
|
555
|
+
}
|
|
556
|
+
if let Some(sub) = session.borrow_mut().view_sub.take() {
|
|
557
|
+
sub.dismiss();
|
|
558
|
+
}
|
|
549
559
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
let _callback_id = client
|
|
554
|
-
.on_error(Box::new(move |message: ClientError, reconnect| {
|
|
555
|
-
let poll_loop = poll_loop.clone();
|
|
556
|
-
async move {
|
|
557
|
-
poll_loop.poll((message.into(), reconnect)).await;
|
|
558
|
-
Ok(())
|
|
559
|
-
}
|
|
560
|
-
}))
|
|
561
|
-
.await?;
|
|
560
|
+
Ok(JsValue::UNDEFINED)
|
|
561
|
+
});
|
|
562
562
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
563
|
+
let _callback_id = client
|
|
564
|
+
.on_error(Box::new(move |message: ClientError, reconnect| {
|
|
565
|
+
let poll_loop = poll_loop.clone();
|
|
566
|
+
async move {
|
|
567
|
+
poll_loop.poll((message.into(), reconnect)).await;
|
|
568
|
+
Ok(())
|
|
569
|
+
}
|
|
570
|
+
}))
|
|
571
|
+
.await?;
|
|
572
|
+
|
|
573
|
+
let sub = self.borrow_mut().view_sub.take();
|
|
574
|
+
self.borrow_mut().metadata = metadata;
|
|
575
|
+
self.borrow_mut().table = Some(table);
|
|
576
|
+
self.borrow_mut().pending_table = None;
|
|
577
|
+
self.borrow_mut().is_loading = false;
|
|
578
|
+
self.borrow_mut().last_validated_expressions = None;
|
|
579
|
+
sub.delete().await?;
|
|
580
|
+
self.table_loaded.emit(());
|
|
581
|
+
Ok(())
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/// Record `name` as pending, dropping any bound `Table` so nothing binds
|
|
585
|
+
/// against the outgoing table while the name waits for a host.
|
|
586
|
+
pub(crate) async fn pend_table(&self, name: String) -> ApiResult<()> {
|
|
587
|
+
let sub = self.borrow_mut().view_sub.take();
|
|
588
|
+
self.borrow_mut().table = None;
|
|
589
|
+
self.borrow_mut().metadata = SessionMetadata::default();
|
|
590
|
+
self.borrow_mut().pending_table = Some(name);
|
|
591
|
+
self.borrow_mut().is_loading = false;
|
|
592
|
+
self.borrow_mut().last_validated_expressions = None;
|
|
593
|
+
sub.delete().await
|
|
575
594
|
}
|
|
576
595
|
|
|
577
596
|
pub async fn set_error(&self, reset_table: bool, err: ApiError) -> ApiResult<()> {
|
|
@@ -664,10 +683,27 @@ impl Session {
|
|
|
664
683
|
.map(|sub| sub.get_view().clone())
|
|
665
684
|
}
|
|
666
685
|
|
|
686
|
+
/// The bound `View` together with its latest known dimensions, read under
|
|
687
|
+
/// one borrow so they always belong together.
|
|
688
|
+
pub fn get_view_with_dimensions(&self) -> Option<(View, Option<ViewDimensionsResp>)> {
|
|
689
|
+
self.borrow()
|
|
690
|
+
.view_sub
|
|
691
|
+
.as_ref()
|
|
692
|
+
.map(|sub| (sub.get_view().clone(), sub.dimensions()))
|
|
693
|
+
}
|
|
694
|
+
|
|
667
695
|
pub(crate) fn get_table_stats(&self) -> Option<ViewStats> {
|
|
668
696
|
self.borrow().stats.clone()
|
|
669
697
|
}
|
|
670
698
|
|
|
699
|
+
/// Whether the stats snapshot carries table dimensions.
|
|
700
|
+
pub(crate) fn has_table_cells(&self) -> bool {
|
|
701
|
+
self.borrow()
|
|
702
|
+
.stats
|
|
703
|
+
.as_ref()
|
|
704
|
+
.is_some_and(|s| s.num_table_cells.is_some())
|
|
705
|
+
}
|
|
706
|
+
|
|
671
707
|
pub fn get_view_config(&'_ self) -> Ref<'_, ViewConfig> {
|
|
672
708
|
Ref::map(self.borrow(), |x| &x.config)
|
|
673
709
|
}
|
|
@@ -924,15 +960,6 @@ impl Session {
|
|
|
924
960
|
/// Emit `view_config_changed` coalesced to one event per microtask batch.
|
|
925
961
|
/// Stats are cleared synchronously per commit (idempotent — an
|
|
926
962
|
/// already-empty cache no-ops, so rapid commit sequences fetch once).
|
|
927
|
-
///
|
|
928
|
-
/// CONTRACT: this channel is COALESCED and DEFERRED — N same-batch
|
|
929
|
-
/// commits produce ONE emission, on a microtask AFTER the mutation.
|
|
930
|
-
/// Subscribers must be batch-tolerant snapshot refreshers (they re-read
|
|
931
|
-
/// live state; today: the root `SessionProps` snapshot and the debug
|
|
932
|
-
/// panel). It is NOT suitable for per-commit accounting — pairing its
|
|
933
|
-
/// edges against any other event stream WILL drift (the stuck-spinner
|
|
934
|
-
/// regression, `UPDATE_COUNT_REGRESSION_PLAN.md`); run accounting is
|
|
935
|
-
/// [`Self::begin_config_run`]'s RAII token instead.
|
|
936
963
|
fn notify_view_config_changed(&self) {
|
|
937
964
|
self.clear_column_stats();
|
|
938
965
|
if !self.0.config_event_scheduled.replace(true) {
|
|
@@ -1123,31 +1150,7 @@ impl Session {
|
|
|
1123
1150
|
.clone()
|
|
1124
1151
|
.ok_or("`restore()` called before `load()`")?;
|
|
1125
1152
|
|
|
1126
|
-
|
|
1127
|
-
// virtual server api. Snapshot-local — never written back.
|
|
1128
|
-
let mut view_config = (*effective).clone();
|
|
1129
|
-
for col in view_config
|
|
1130
|
-
.columns
|
|
1131
|
-
.iter()
|
|
1132
|
-
.flatten()
|
|
1133
|
-
.chain(view_config.sort.iter().map(|x| &x.0))
|
|
1134
|
-
{
|
|
1135
|
-
if !view_config.aggregates.contains_key(col.as_str()) {
|
|
1136
|
-
let agg = self
|
|
1137
|
-
.metadata()
|
|
1138
|
-
.get_column_aggregates(col.as_str())
|
|
1139
|
-
.and_then(|mut aggs| aggs.next())
|
|
1140
|
-
.into_apierror();
|
|
1141
|
-
|
|
1142
|
-
match agg {
|
|
1143
|
-
Err(_) => {
|
|
1144
|
-
tracing::warn!("No default aggregate for column '{}' found, skipping", col)
|
|
1145
|
-
},
|
|
1146
|
-
Ok(agg) => _ = view_config.aggregates.insert(col.to_string(), agg),
|
|
1147
|
-
};
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
|
|
1153
|
+
let view_config = self.with_default_aggregates(&effective);
|
|
1151
1154
|
let view = table.view(Some(view_config.into())).await?;
|
|
1152
1155
|
let view_schema = view.schema().await?;
|
|
1153
1156
|
self.metadata_mut().update_view_schema(&view_schema)?;
|
|
@@ -1179,6 +1182,43 @@ impl Session {
|
|
|
1179
1182
|
}
|
|
1180
1183
|
}
|
|
1181
1184
|
|
|
1185
|
+
/// The engine config for a `View` built from `effective`, per-column
|
|
1186
|
+
/// default aggregates filled in as a courtesy to the virtual server API.
|
|
1187
|
+
fn with_default_aggregates(&self, effective: &ViewConfig) -> ViewConfig {
|
|
1188
|
+
let mut view_config = effective.clone();
|
|
1189
|
+
for col in view_config
|
|
1190
|
+
.columns
|
|
1191
|
+
.iter()
|
|
1192
|
+
.flatten()
|
|
1193
|
+
.chain(view_config.sort.iter().map(|x| &x.0))
|
|
1194
|
+
{
|
|
1195
|
+
if !view_config.aggregates.contains_key(col.as_str()) {
|
|
1196
|
+
let agg = self
|
|
1197
|
+
.metadata()
|
|
1198
|
+
.get_column_aggregates(col.as_str())
|
|
1199
|
+
.and_then(|mut aggs| aggs.next())
|
|
1200
|
+
.into_apierror();
|
|
1201
|
+
|
|
1202
|
+
match agg {
|
|
1203
|
+
Err(_) => {
|
|
1204
|
+
tracing::warn!("No default aggregate for column '{}' found, skipping", col)
|
|
1205
|
+
},
|
|
1206
|
+
Ok(agg) => _ = view_config.aggregates.insert(col.to_string(), agg),
|
|
1207
|
+
};
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
view_config
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
/// Build a caller-owned `View` from the effective config outside the
|
|
1215
|
+
/// render pipeline, with no subscription and no interaction with pause.
|
|
1216
|
+
pub async fn create_detached_view(&self) -> ApiResult<View> {
|
|
1217
|
+
let table = self.borrow().table.clone().ok_or("No `Table` set")?;
|
|
1218
|
+
let view_config = self.with_default_aggregates(&self.effective_view_config());
|
|
1219
|
+
Ok(table.view(Some(view_config.into())).await?)
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1182
1222
|
/// Record a failed pipeline run: error state plus a reconnect affordance
|
|
1183
1223
|
/// that resets the config (the error screen's reset button). Replaces
|
|
1184
1224
|
/// the old `validate()` error path — the committed config is NOT rolled
|
|
@@ -1218,6 +1258,8 @@ impl Session {
|
|
|
1218
1258
|
if let Some(cb) = self.on_stats_changed.borrow().as_ref() {
|
|
1219
1259
|
cb.emit(());
|
|
1220
1260
|
}
|
|
1261
|
+
|
|
1262
|
+
self.stats_changed.emit(());
|
|
1221
1263
|
}
|
|
1222
1264
|
|
|
1223
1265
|
fn all_columns(&self) -> Vec<String> {
|
|
@@ -1258,11 +1300,16 @@ impl Session {
|
|
|
1258
1300
|
|
|
1259
1301
|
SessionProps {
|
|
1260
1302
|
config,
|
|
1261
|
-
|
|
1303
|
+
has_table_cells: data
|
|
1304
|
+
.stats
|
|
1305
|
+
.as_ref()
|
|
1306
|
+
.is_some_and(|s| s.num_table_cells.is_some()),
|
|
1262
1307
|
has_table: if data.table.is_some() {
|
|
1263
1308
|
Some(TableLoadState::Loaded)
|
|
1264
1309
|
} else if data.is_loading {
|
|
1265
1310
|
Some(TableLoadState::Loading)
|
|
1311
|
+
} else if data.pending_table.is_some() {
|
|
1312
|
+
Some(TableLoadState::Pending)
|
|
1266
1313
|
} else {
|
|
1267
1314
|
None
|
|
1268
1315
|
},
|
|
@@ -1290,15 +1337,7 @@ pub struct ConfigSnapshot {
|
|
|
1290
1337
|
pub struct ValidatedSnapshot(ConfigSnapshot);
|
|
1291
1338
|
|
|
1292
1339
|
/// Type-state witness that a `View` is NEW for the plugin about to render
|
|
1293
|
-
/// it
|
|
1294
|
-
/// `draw` fires iff there is a new `View`, never otherwise). Minted in
|
|
1295
|
-
/// exactly two places: [`Session::bind_view`]'s REBUILD arm (a new engine
|
|
1296
|
-
/// `View` was constructed) and
|
|
1297
|
-
/// [`crate::renderer::Renderer::promote_first_paint`] (a freshly-selected
|
|
1298
|
-
/// plugin owes its first paint of the bound `View`). Do NOT construct it
|
|
1299
|
-
/// anywhere else — `Renderer::draw_fresh` is the only consumer, and this
|
|
1300
|
-
/// witness is what makes "full draw without a new `View`" (the stacked-chart
|
|
1301
|
-
/// activation regression) uncompilable.
|
|
1340
|
+
/// it.
|
|
1302
1341
|
pub struct FreshView(View);
|
|
1303
1342
|
|
|
1304
1343
|
impl FreshView {
|
|
@@ -17,7 +17,7 @@ use crate::config::*;
|
|
|
17
17
|
use crate::custom_events::wire_panel_events;
|
|
18
18
|
use crate::presentation::*;
|
|
19
19
|
use crate::renderer::*;
|
|
20
|
-
use crate::session::{ResetOptions, Session};
|
|
20
|
+
use crate::session::{MissingTable, ResetOptions, Session};
|
|
21
21
|
use crate::tasks::*;
|
|
22
22
|
use crate::utils::*;
|
|
23
23
|
use crate::workspace::{Panel, PanelId, PanelPhase, Workspace};
|
|
@@ -60,7 +60,7 @@ fn wire_panel_render_sub(session: &Session, renderer: &Renderer) -> Subscription
|
|
|
60
60
|
clone!(renderer, session);
|
|
61
61
|
ApiFuture::spawn(async move {
|
|
62
62
|
renderer
|
|
63
|
-
.update_lazy(async move { Ok(session.
|
|
63
|
+
.update_lazy(async move { Ok(session.get_view_with_dimensions()) })
|
|
64
64
|
.await
|
|
65
65
|
.ignore_view_delete()
|
|
66
66
|
.map(|_| ())
|
|
@@ -76,6 +76,7 @@ fn wire_panel_render_sub(session: &Session, renderer: &Renderer) -> Subscription
|
|
|
76
76
|
/// one. `theme` is stripped (element-level, not per-panel) and `client` —
|
|
77
77
|
/// or the element's default client when `None` — is bound so the config's
|
|
78
78
|
/// `table` resolves against it.
|
|
79
|
+
#[allow(clippy::too_many_arguments)]
|
|
79
80
|
pub(crate) async fn create_panel(
|
|
80
81
|
elem: &HtmlElement,
|
|
81
82
|
presentation: &Presentation,
|
|
@@ -84,6 +85,7 @@ pub(crate) async fn create_panel(
|
|
|
84
85
|
id: Option<PanelId>,
|
|
85
86
|
config: ViewerConfigInitial,
|
|
86
87
|
client: Option<perspective_client::Client>,
|
|
88
|
+
missing: MissingTable,
|
|
87
89
|
) -> ApiResult<PanelId> {
|
|
88
90
|
let (id, session, renderer, update) = create_panel_model(
|
|
89
91
|
elem,
|
|
@@ -120,6 +122,7 @@ pub(crate) async fn create_panel(
|
|
|
120
122
|
RestoreMode::Fresh,
|
|
121
123
|
update,
|
|
122
124
|
crate::tasks::RestoreErrors::Publish,
|
|
125
|
+
missing,
|
|
123
126
|
)
|
|
124
127
|
.await;
|
|
125
128
|
|
|
@@ -28,7 +28,7 @@ pub fn dismiss_render_warning_callback(session: &Session, renderer: &Renderer) -
|
|
|
28
28
|
ApiFuture::spawn(async move {
|
|
29
29
|
renderer.disable_active_plugin_render_warning();
|
|
30
30
|
renderer
|
|
31
|
-
.update_lazy(async move { Ok(session.
|
|
31
|
+
.update_lazy(async move { Ok(session.get_view_with_dimensions()) })
|
|
32
32
|
.await
|
|
33
33
|
});
|
|
34
34
|
})
|
package/src/rust/tasks/eject.rs
CHANGED