gloomberb 0.11.0 → 0.11.2
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/README.md +38 -15
- package/README.zh-CN.md +12 -12
- package/package.json +10 -3
- package/src/api-client/auth.ts +14 -10
- package/src/api-client/data.ts +54 -0
- package/src/api-client/index.test.ts +124 -0
- package/src/api-client/index.ts +139 -4
- package/src/api-client/paths.ts +89 -0
- package/src/api-client/request.ts +15 -2
- package/src/api-client/socket-health.test.ts +1 -0
- package/src/api-client/socket.ts +2 -1
- package/src/api-client/types.ts +163 -0
- package/src/app/pane-runtime/index.tsx +4 -1
- package/src/app/pane-runtime/plugin-bindings.test.ts +117 -0
- package/src/app/pane-runtime/plugin-bindings.ts +25 -4
- package/src/app/pane-runtime/ticker-inspector-runtime.ts +25 -14
- package/src/app/runtime/desktop-deeplink.test.ts +16 -0
- package/src/app/runtime/desktop-deeplink.ts +66 -2
- package/src/app/runtime/desktop-menu.ts +3 -0
- package/src/app/runtime/plugin-bindings.ts +30 -28
- package/src/app/runtime/update.ts +8 -6
- package/src/app.tsx +21 -7
- package/src/architecture/import-boundaries.test.ts +5 -1
- package/src/capabilities/factories.ts +4 -0
- package/src/cli/commands/automation.test.ts +9 -0
- package/src/cli/commands/automation.ts +22 -73
- package/src/cli/index.ts +10 -6
- package/src/cli/registry.ts +1 -1
- package/src/components/chart/composite/composite-chart.test.tsx +45 -2
- package/src/components/chart/composite/composite-chart.tsx +16 -12
- package/src/components/chart/composite/format.test.ts +34 -0
- package/src/components/chart/composite/format.ts +33 -10
- package/src/components/chart/composite/scene.ts +0 -21
- package/src/components/chart/composite/tools.ts +49 -0
- package/src/components/chart/core/axis-format.ts +13 -3
- package/src/components/chart/core/index.test.ts +7 -0
- package/src/components/chart/core/renderer.ts +3 -4
- package/src/components/command-bar/commands/direct/index.ts +4 -0
- package/src/components/command-bar/commands/registry.ts +8 -1
- package/src/components/command-bar/layout-items/current-layout.ts +1 -1
- package/src/components/command-bar/pane-templates/workflow.ts +4 -0
- package/src/components/command-bar/routes/root/shortcut-feedback.ts +3 -0
- package/src/components/command-bar/routes/root/shortcuts.test.ts +19 -0
- package/src/components/command-bar/routes/root/shortcuts.ts +3 -1
- package/src/components/command-bar/surface/index.test.tsx +6 -6
- package/src/components/command-bar/surface/index.tsx +4 -1
- package/src/components/command-bar/surface/pane.test.tsx +66 -2
- package/src/components/command-bar/view-model.test.ts +2 -1
- package/src/components/command-bar/workflow/ops.test.ts +54 -0
- package/src/components/command-bar/workflow/ops.ts +1 -1
- package/src/components/company-logo.test.ts +19 -0
- package/src/components/company-logo.tsx +60 -0
- package/src/components/feed-data-table/stack-view.tsx +7 -1
- package/src/components/index.ts +1 -0
- package/src/components/layout/detached-pane-shell.tsx +85 -15
- package/src/components/layout/header.tsx +5 -5
- package/src/components/layout/pane/title.ts +31 -3
- package/src/components/layout/shell/active-drag.ts +4 -11
- package/src/components/layout/shell/drag/index.ts +4 -20
- package/src/components/layout/shell/drag/runtime.ts +3 -4
- package/src/components/layout/shell/index.test.tsx +17 -3
- package/src/components/layout/shell/index.tsx +89 -31
- package/src/components/layout/shell/menu.test.ts +37 -1
- package/src/components/layout/shell/menu.ts +14 -0
- package/src/components/layout/shell/native/pointer-runtime.ts +22 -8
- package/src/components/layout/shell/pane/actions.ts +0 -5
- package/src/components/layout/shell/pane/management-shortcuts.ts +9 -4
- package/src/components/layout/shell/shortcuts.ts +6 -3
- package/src/components/layout/shell/ticker-link-menu.test.ts +82 -0
- package/src/components/layout/shell/ticker-link-menu.ts +78 -0
- package/src/components/layout/status-bar.test.tsx +62 -61
- package/src/components/layout/status-bar.tsx +53 -75
- package/src/components/onboarding/account-step/form-panel.tsx +4 -2
- package/src/components/onboarding/account-step/index.tsx +1 -1
- package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
- package/src/components/onboarding/onboarding-wizard.test.tsx +44 -1
- package/src/components/onboarding/onboarding-wizard.tsx +13 -5
- package/src/components/onboarding/wizard-account.ts +4 -23
- package/src/components/table-view-shared.test.ts +11 -0
- package/src/components/table-view-shared.tsx +26 -0
- package/src/components/ui/data-table/index.tsx +19 -1
- package/src/components/ui/fields.tsx +5 -1
- package/src/core/state/app/layout-reducer.ts +36 -0
- package/src/core/state/app/layout.ts +10 -5
- package/src/core/state/app/state.ts +0 -13
- package/src/core/state/app/types.ts +6 -4
- package/src/data/config/chart-settings.ts +1 -1
- package/src/data/config/layout.ts +2 -0
- package/src/data/config/store/index.test.ts +27 -6
- package/src/data/config/store/normalize.ts +3 -5
- package/src/data/plugin-state-store.ts +11 -0
- package/src/data/sqlite/cache.test.ts +10 -0
- package/src/i18n/es.ts +13 -5
- package/src/i18n/ja.ts +13 -5
- package/src/i18n/ko.ts +13 -5
- package/src/i18n/zh-cn.ts +13 -5
- package/src/i18n/zh-tw.ts +13 -5
- package/src/layout-marketplace/api.test.ts +54 -0
- package/src/layout-marketplace/api.ts +65 -0
- package/src/layout-marketplace/gallery-desktop.test.tsx +262 -0
- package/src/layout-marketplace/gallery-desktop.tsx +375 -0
- package/src/layout-marketplace/gallery-terminal.tsx +376 -0
- package/src/layout-marketplace/gallery.test.tsx +84 -0
- package/src/layout-marketplace/gallery.tsx +323 -0
- package/src/layout-marketplace/geometry.test.ts +47 -0
- package/src/layout-marketplace/geometry.ts +80 -0
- package/src/layout-marketplace/mini-workspace.test.tsx +122 -0
- package/src/layout-marketplace/mini-workspace.tsx +428 -0
- package/src/layout-marketplace/model.test.ts +118 -0
- package/src/layout-marketplace/model.ts +171 -0
- package/src/layout-marketplace/name-dialog.tsx +60 -0
- package/src/layout-marketplace/pane-imagery.ts +85 -0
- package/src/layout-marketplace/pane.tsx +20 -0
- package/src/layout-marketplace/payload.test.ts +246 -0
- package/src/layout-marketplace/payload.ts +624 -0
- package/src/layout-marketplace/use-marketplace.ts +63 -0
- package/src/market-data/coordinator/index.test.ts +2 -2
- package/src/market-data/coordinator/index.ts +1 -1
- package/src/market-data/hooks.tsx +0 -41
- package/src/market-data/market/format.test.ts +7 -0
- package/src/market-data/market/freshness.ts +5 -2
- package/src/market-data/quotes/freshness.test.ts +16 -0
- package/src/news/aggregator.test.ts +92 -3
- package/src/news/aggregator.ts +98 -18
- package/src/news/hooks.test.tsx +2 -0
- package/src/news/hooks.ts +27 -1
- package/src/news/news-model.ts +5 -2
- package/src/news/types.ts +7 -0
- package/src/plugins/broker-sync/broker-sync.test.ts +58 -0
- package/src/plugins/broker-sync/normalize.ts +42 -5
- package/src/plugins/builtin/account-management/pane.tsx +5 -5
- package/src/plugins/builtin/ai/index.tsx +18 -2
- package/src/plugins/builtin/ai/screener/pane.test.tsx +47 -4
- package/src/plugins/builtin/ai/screener/pane.tsx +35 -12
- package/src/plugins/builtin/alerts/alert-engine.test.ts +53 -1
- package/src/plugins/builtin/alerts/alert-engine.ts +34 -1
- package/src/plugins/builtin/alerts/index.test.tsx +49 -6
- package/src/plugins/builtin/alerts/index.tsx +11 -6
- package/src/plugins/builtin/alerts/pane.tsx +51 -9
- package/src/plugins/builtin/alerts/quotes.ts +11 -3
- package/src/plugins/builtin/alerts/types.ts +1 -0
- package/src/plugins/builtin/analytics/index.tsx +11 -1
- package/src/plugins/builtin/analytics/pane-model.ts +6 -4
- package/src/plugins/builtin/broker-manager/index.tsx +3 -0
- package/src/plugins/builtin/buildout/model/index.ts +1 -1
- package/src/plugins/builtin/buildout/pane/index.tsx +17 -18
- package/src/plugins/builtin/cds/client.test.ts +83 -0
- package/src/plugins/builtin/cds/client.ts +67 -0
- package/src/plugins/builtin/cds/index.tsx +41 -0
- package/src/plugins/builtin/cds/model.test.ts +232 -0
- package/src/plugins/builtin/cds/model.ts +401 -0
- package/src/plugins/builtin/cds/pane.test.tsx +132 -0
- package/src/plugins/builtin/cds/pane.tsx +358 -0
- package/src/plugins/builtin/chart-composer/chart-spec.ts +31 -0
- package/src/plugins/builtin/chart-composer/index.tsx +88 -2
- package/src/plugins/builtin/chart-composer/pane-share.test.ts +71 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +103 -15
- package/src/plugins/builtin/chat/content/index.tsx +4 -1
- package/src/plugins/builtin/chat/controller/channels.ts +7 -1
- package/src/plugins/builtin/chat/controller/index.ts +14 -9
- package/src/plugins/builtin/chat/controller/notifications.ts +13 -3
- package/src/plugins/builtin/chat/controller/persistence.ts +0 -3
- package/src/plugins/builtin/chat/controller/realtime.ts +3 -3
- package/src/plugins/builtin/chat/controller/send.ts +1 -3
- package/src/plugins/builtin/chat/controller/session-runtime.ts +18 -11
- package/src/plugins/builtin/chat/controller/state.ts +1 -3
- package/src/plugins/builtin/chat/controller/storage.ts +0 -2
- package/src/plugins/builtin/chat/controller/utils.ts +4 -6
- package/src/plugins/builtin/chat/controller/view.ts +2 -2
- package/src/plugins/builtin/chat/controller.test.ts +142 -14
- package/src/plugins/builtin/chat/message/desktop.test.tsx +88 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +3 -1
- package/src/plugins/builtin/chat/message/profile-popover.test.tsx +1 -29
- package/src/plugins/builtin/chat/profile-popover.ts +53 -22
- package/src/plugins/builtin/chat/sidebar.test.tsx +81 -0
- package/src/plugins/builtin/chat/sidebar.tsx +63 -0
- package/src/plugins/builtin/chat/test-harness.tsx +29 -1
- package/src/plugins/builtin/cloud/auth-actions.tsx +14 -7
- package/src/plugins/builtin/cloud/auth-commands.ts +21 -51
- package/src/plugins/builtin/cloud/auth-dialog.tsx +296 -0
- package/src/{components/onboarding/account-step/model.test.ts → plugins/builtin/cloud/auth-model.test.ts} +1 -1
- package/src/{components/onboarding/account-step/model.ts → plugins/builtin/cloud/auth-model.ts} +37 -3
- package/src/plugins/builtin/cloud/browser.tsx +9 -0
- package/src/plugins/builtin/cloud/buildout-module.tsx +23 -0
- package/src/plugins/builtin/cloud/device-signin.ts +2 -8
- package/src/plugins/builtin/cloud/index.tsx +2 -0
- package/src/plugins/builtin/cloud/plugin.tsx +14 -24
- package/src/plugins/builtin/cloud/upgrade-command.ts +13 -6
- package/src/plugins/builtin/cloud-tweets/pane-share.test.ts +56 -0
- package/src/plugins/builtin/cloud-tweets/pane.tsx +20 -5
- package/src/plugins/builtin/cloud-tweets/registration.ts +50 -6
- package/src/plugins/builtin/composite-plugins.ts +3 -1
- package/src/plugins/builtin/congress-trades/detail.tsx +43 -1
- package/src/plugins/builtin/congress-trades/model.test.ts +85 -0
- package/src/plugins/builtin/congress-trades/model.ts +69 -1
- package/src/plugins/builtin/congress-trades/pane.tsx +51 -2
- package/src/plugins/builtin/connections/index.ts +3 -0
- package/src/plugins/builtin/dividend-yield/client.ts +18 -0
- package/src/plugins/builtin/dividend-yield/pane.tsx +7 -6
- package/src/plugins/builtin/earnings/index.tsx +5 -3
- package/src/plugins/builtin/earnings/model.test.ts +19 -1
- package/src/plugins/builtin/earnings/model.ts +17 -15
- package/src/plugins/builtin/econ/calendar-model.ts +0 -5
- package/src/plugins/builtin/econ/index.test.tsx +6 -1
- package/src/plugins/builtin/fear-greed/charts.tsx +12 -8
- package/src/plugins/builtin/help/index.tsx +2 -2
- package/src/plugins/builtin/holders/thirteenf-match.ts +1 -2
- package/src/plugins/builtin/insider/index.tsx +27 -11
- package/src/plugins/builtin/kelly-sizer/index.tsx +4 -1
- package/src/plugins/builtin/layout-manager/index.tsx +17 -4
- package/src/plugins/builtin/news/index.tsx +11 -6
- package/src/plugins/builtin/news/wire/breaking/notifications.test.ts +2 -0
- package/src/plugins/builtin/news/wire/breaking/pane.test.tsx +2 -0
- package/src/plugins/builtin/news/wire/breaking/pane.tsx +4 -1
- package/src/plugins/builtin/news/wire/feed-config.test.ts +15 -1
- package/src/plugins/builtin/news/wire/feed-config.ts +25 -5
- package/src/plugins/builtin/news/wire/index.tsx +3 -3
- package/src/plugins/builtin/news/wire/industry-pane.tsx +7 -2
- package/src/plugins/builtin/news/wire/news/footer.ts +34 -1
- package/src/plugins/builtin/news/wire/news/preset-pane.tsx +4 -1
- package/src/plugins/builtin/news/wire/news/table.tsx +8 -2
- package/src/plugins/builtin/news/wire/rss/source.test.ts +12 -0
- package/src/plugins/builtin/news/wire/rss/source.ts +1 -1
- package/src/plugins/builtin/notes/files.ts +80 -0
- package/src/plugins/builtin/notes/index.tsx +3 -0
- package/src/plugins/builtin/notes/sync.test.ts +49 -0
- package/src/plugins/builtin/notes/sync.ts +98 -0
- package/src/plugins/builtin/options/index.tsx +1 -0
- package/src/plugins/builtin/options/view.test.tsx +25 -3
- package/src/plugins/builtin/options/view.tsx +1 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.test.ts +22 -0
- package/src/plugins/builtin/portfolio-list/account-metrics.ts +12 -7
- package/src/plugins/builtin/portfolio-list/cli/render.ts +5 -3
- package/src/plugins/builtin/portfolio-list/column-values.ts +15 -4
- package/src/plugins/builtin/portfolio-list/header.tsx +13 -3
- package/src/plugins/builtin/portfolio-list/index.tsx +8 -0
- package/src/plugins/builtin/portfolio-list/metrics.test.ts +31 -1
- package/src/plugins/builtin/portfolio-list/pane/index.test.tsx +1 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +10 -7
- package/src/plugins/builtin/portfolio-list/pane/streaming.ts +6 -1
- package/src/plugins/builtin/portfolio-list/position-metrics.ts +25 -6
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +35 -21
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +20 -6
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +5 -12
- package/src/plugins/builtin/research/equity-diagnostic-pane.test.tsx +329 -0
- package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +582 -0
- package/src/plugins/builtin/research/index.test.ts +14 -0
- package/src/plugins/builtin/research/index.tsx +29 -0
- package/src/plugins/builtin/sec/index.tsx +24 -9
- package/src/plugins/builtin/sectors/index.tsx +14 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +18 -11
- package/src/plugins/builtin/shared/public-pane.test.ts +12 -0
- package/src/plugins/builtin/shared/public-pane.ts +9 -0
- package/src/plugins/builtin/shared/public-share.ts +23 -0
- package/src/plugins/builtin/shared/ticker-source.ts +32 -0
- package/src/plugins/builtin/shared/ticker-surface.test.ts +27 -0
- package/src/plugins/builtin/shared/ticker-surface.ts +17 -0
- package/src/plugins/builtin/substack/api/cache.ts +7 -3
- package/src/plugins/builtin/substack/api/loaders.ts +36 -12
- package/src/plugins/builtin/substack/api/types.ts +2 -0
- package/src/plugins/builtin/substack/pane-state.ts +1 -1
- package/src/plugins/builtin/substack/pane.tsx +55 -12
- package/src/plugins/builtin/thirteenf/api.test.ts +1 -1
- package/src/plugins/builtin/thirteenf/api.ts +40 -18
- package/src/plugins/builtin/thirteenf/data.ts +15 -7
- package/src/plugins/builtin/thirteenf/pane.tsx +45 -10
- package/src/plugins/builtin/ticker-detail/index.tsx +10 -0
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +12 -4
- package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +8 -2
- package/src/plugins/builtin/ticker-detail/settings.ts +12 -0
- package/src/plugins/builtin/treasury-auctions/index.tsx +2 -0
- package/src/plugins/builtin/world-indices/index.tsx +2 -0
- package/src/plugins/catalog-browser.test.ts +78 -0
- package/src/plugins/catalog-browser.ts +136 -0
- package/src/plugins/gridlock-notification.ts +2 -1
- package/src/plugins/ibkr/flex/index.test.ts +19 -0
- package/src/plugins/ibkr/flex/index.ts +1 -1
- package/src/plugins/pane-manager/gridlock.ts +87 -3
- package/src/plugins/pane-manager.test.ts +30 -0
- package/src/plugins/pane-manager.ts +6 -1
- package/src/plugins/prediction-markets/chart.tsx +2 -2
- package/src/plugins/prediction-markets/controller/catalog.ts +77 -2
- package/src/plugins/prediction-markets/controller/data.ts +7 -1
- package/src/plugins/prediction-markets/controller/index.ts +9 -2
- package/src/plugins/prediction-markets/controller/keyboard.ts +10 -14
- package/src/plugins/prediction-markets/detail/overview.tsx +21 -0
- package/src/plugins/prediction-markets/detail/pane.tsx +43 -34
- package/src/plugins/prediction-markets/detail/trades.tsx +34 -9
- package/src/plugins/prediction-markets/detail.test.tsx +29 -2
- package/src/plugins/prediction-markets/index.tsx +8 -4
- package/src/plugins/prediction-markets/navigation.ts +0 -1
- package/src/plugins/prediction-markets/pane.test.tsx +77 -0
- package/src/plugins/prediction-markets/pane.tsx +12 -0
- package/src/plugins/prediction-markets/plugin.test.tsx +36 -0
- package/src/plugins/prediction-markets/services/kalshi/adapter.ts +49 -9
- package/src/plugins/prediction-markets/services/polymarket/adapter.ts +31 -0
- package/src/plugins/prediction-markets/test-helpers.tsx +9 -0
- package/src/plugins/registry/index.ts +2 -0
- package/src/plugins/ticker-navigation.test.ts +24 -0
- package/src/plugins/ticker-navigation.ts +40 -0
- package/src/remote/schema.ts +1 -1
- package/src/renderers/browser/app-services.ts +61 -0
- package/src/renderers/browser/cloud-transport.test.ts +68 -0
- package/src/renderers/browser/cloud-transport.ts +48 -0
- package/src/renderers/browser/config-host.ts +58 -0
- package/src/renderers/browser/deeplink-bridge.test.ts +41 -0
- package/src/renderers/browser/deeplink-bridge.ts +22 -0
- package/src/renderers/browser/error-boundary.tsx +23 -0
- package/src/renderers/browser/main.tsx +64 -0
- package/src/renderers/browser/persistence.ts +74 -0
- package/src/renderers/browser/storage.test.ts +66 -0
- package/src/renderers/browser/storage.ts +50 -0
- package/src/renderers/browser/ticker-repository.ts +59 -0
- package/src/renderers/browser/ui-host.tsx +40 -0
- package/src/renderers/cloudflare/worker.test.ts +136 -0
- package/src/renderers/cloudflare/worker.ts +116 -0
- package/src/renderers/electrobun/bun/application-menu/index.ts +3 -2
- package/src/renderers/electrobun/bun/desktop/initialization.ts +1 -0
- package/src/renderers/electrobun/bun/desktop/plugin-state.ts +7 -1
- package/src/renderers/electrobun/view/app-services.ts +14 -3
- package/src/renderers/electrobun/view/build-assets.ts +12 -10
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -1
- package/src/renderers/electrobun/view/data-table/index.tsx +10 -1
- package/src/renderers/electrobun/view/desktop/controls.tsx +2 -0
- package/src/renderers/electrobun/view/dom-ui-host.tsx +143 -0
- package/src/renderers/electrobun/view/host/box.test.tsx +33 -0
- package/src/renderers/electrobun/view/host/box.tsx +11 -6
- package/src/renderers/electrobun/view/host/chart-surface.tsx +7 -1
- package/src/renderers/electrobun/view/host/input.tsx +11 -7
- package/src/renderers/electrobun/view/host/native.ts +0 -5
- package/src/renderers/electrobun/view/main.tsx +2 -0
- package/src/renderers/electrobun/view/remote/persistence.ts +5 -0
- package/src/renderers/electrobun/view/styles.css +107 -7
- package/src/renderers/electrobun/view/toast-host.test.tsx +78 -0
- package/src/renderers/electrobun/view/toast-host.tsx +69 -43
- package/src/renderers/electrobun/view/ui-host.tsx +6 -137
- package/src/renderers/opentui/start.tsx +2 -0
- package/src/renderers/share/layout-view.test.tsx +58 -0
- package/src/renderers/share/layout-view.tsx +133 -0
- package/src/renderers/share/main.tsx +102 -0
- package/src/renderers/share/styles.css +54 -0
- package/src/renderers/share/view.test.tsx +100 -0
- package/src/renderers/share/view.tsx +150 -0
- package/src/shares/api.test.ts +105 -0
- package/src/shares/api.ts +127 -0
- package/src/shares/chart-snapshot.test.ts +34 -0
- package/src/shares/chart-snapshot.ts +28 -0
- package/src/shares/location.test.ts +19 -0
- package/src/shares/location.ts +11 -0
- package/src/shares/pane.test.ts +110 -0
- package/src/shares/pane.ts +54 -0
- package/src/shares/payload.ts +177 -0
- package/src/sources/gloomberb-cloud/index.test.ts +61 -1
- package/src/sources/gloomberb-cloud/index.ts +86 -14
- package/src/sources/gloomberb-cloud/normalizers.test.ts +34 -0
- package/src/sources/gloomberb-cloud/normalizers.ts +5 -5
- package/src/sources/provider-router/history.test.ts +2 -2
- package/src/sources/provider-router/news.test.ts +34 -0
- package/src/sources/provider-router/news.ts +15 -1
- package/src/sources/sec-edgar.test.ts +59 -0
- package/src/sources/sec-edgar.ts +63 -23
- package/src/sources/yahoo-finance/mappers.ts +3 -0
- package/src/sources/yahoo-finance/snapshots.ts +10 -2
- package/src/sources/yahoo-finance/symbols.test.ts +10 -0
- package/src/sources/yahoo-finance/symbols.ts +13 -8
- package/src/sources/yahoo-finance.test.ts +1 -1
- package/src/sources/yahoo-finance.ts +6 -2
- package/src/state/app/bootstrap.ts +6 -7
- package/src/state/app/context/index.test.ts +41 -1
- package/src/state/app/context/index.test.tsx +34 -16
- package/src/state/selectors-ui.ts +0 -8
- package/src/sync/baseline.ts +32 -0
- package/src/sync/controller.test.ts +124 -1
- package/src/sync/controller.ts +54 -12
- package/src/sync/core-contributors.test.ts +44 -0
- package/src/sync/core-contributors.ts +59 -10
- package/src/sync/react.ts +22 -2
- package/src/sync/types.ts +12 -0
- package/src/theme/font-scale.ts +0 -11
- package/src/tickers/search/index.test.ts +27 -0
- package/src/tickers/search/upsert.ts +10 -0
- package/src/types/capability-route-source.ts +2 -1
- package/src/types/config.ts +35 -5
- package/src/types/desktop-menu.ts +1 -0
- package/src/types/plugin.ts +36 -0
- package/src/ui/context-menu.tsx +1 -1
- package/src/ui/host.tsx +4 -0
- package/src/ui/toast.tsx +2 -0
- package/src/utils/back-navigation.ts +0 -4
- package/src/utils/price-history.ts +11 -10
- package/src/utils/sec.test.ts +6 -0
- package/src/utils/sec.ts +1 -1
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
syncConfigActiveLayoutState,
|
|
22
22
|
useAppDispatch,
|
|
23
23
|
useAppSelector,
|
|
24
|
+
useAppStateRef,
|
|
24
25
|
} from "../../../state/app/context";
|
|
25
26
|
import {
|
|
26
27
|
selectCommandBarOpen,
|
|
@@ -37,6 +38,7 @@ import {
|
|
|
37
38
|
menuForPane,
|
|
38
39
|
menuItemsForFallback,
|
|
39
40
|
} from "./menu";
|
|
41
|
+
import { tickerLinkMenuItems } from "./ticker-link-menu";
|
|
40
42
|
import {
|
|
41
43
|
makeSnapGuides,
|
|
42
44
|
resolveExternalDockPreview,
|
|
@@ -58,6 +60,7 @@ import {
|
|
|
58
60
|
useShellResolvedPanes,
|
|
59
61
|
useShellVisibleLayout,
|
|
60
62
|
} from "./layout-state";
|
|
63
|
+
import { AuthDialogHost } from "../../../plugins/builtin/cloud/auth-dialog";
|
|
61
64
|
import { DeviceSignInDialogHost } from "../../../plugins/builtin/cloud/device-signin-dialog";
|
|
62
65
|
import { useShellPaneActions } from "./pane/actions";
|
|
63
66
|
import { resolvePaneFocusSourceLayout } from "./fullscreen";
|
|
@@ -66,6 +69,9 @@ import {
|
|
|
66
69
|
resolveShellCursorOcclusionRects,
|
|
67
70
|
useShellCursorOcclusionGuard,
|
|
68
71
|
} from "./cursor-occlusion";
|
|
72
|
+
import { createShare, openLiveShareUrl } from "../../../shares/api";
|
|
73
|
+
import { buildPaneSharePayload } from "../../../shares/pane";
|
|
74
|
+
import type { SharePayload } from "../../../shares/payload";
|
|
69
75
|
|
|
70
76
|
export { resolveAppHeaderHeightCells } from "./chrome";
|
|
71
77
|
export { buildNativeWindowState } from "./native/window-state";
|
|
@@ -99,13 +105,14 @@ export function Shell({
|
|
|
99
105
|
const previousFocusedPaneId = useAppSelector((state) => state.previousFocusedPaneId);
|
|
100
106
|
const activePanel = useAppSelector((state) => state.activePanel);
|
|
101
107
|
const commandBarOpen = useAppSelector(selectCommandBarOpen);
|
|
108
|
+
const stateRef = useAppStateRef();
|
|
102
109
|
const inputCaptured = useAppSelector((state) => state.inputCaptured);
|
|
103
110
|
const statusBarVisible = useAppSelector(selectStatusBarVisible);
|
|
104
111
|
const rendererHost = useRendererHost();
|
|
105
112
|
const { setTransientLayout } = useTransientLayout();
|
|
106
113
|
const uiKind = useUiHost().kind;
|
|
107
114
|
const shortcutDisplayMode = getShortcutDisplayMode(uiKind);
|
|
108
|
-
const { nativePaneChrome = false, nativeContextMenu, precisePointer, titleBarOverlay, cellHeightPx } = useUiCapabilities();
|
|
115
|
+
const { nativePaneChrome = false, nativeContextMenu, precisePointer, publicSharing, titleBarOverlay, cellHeightPx } = useUiCapabilities();
|
|
109
116
|
const { showContextMenu } = useContextMenu();
|
|
110
117
|
const { width, height } = useViewport();
|
|
111
118
|
const shellRef = useRef<BoxRenderable | null>(null);
|
|
@@ -118,8 +125,9 @@ export function Shell({
|
|
|
118
125
|
const dialogOpen = useDialogState((dialog) => dialog.isOpen);
|
|
119
126
|
const [hoveredPaneId, setHoveredPaneId] = useState<string | null>(null);
|
|
120
127
|
const setHoveredPaneIfChanged = useCallback((paneId: string | null) => {
|
|
128
|
+
if (commandBarOpen) return;
|
|
121
129
|
setHoveredPaneId((current) => (current === paneId ? current : paneId));
|
|
122
|
-
}, []);
|
|
130
|
+
}, [commandBarOpen]);
|
|
123
131
|
const [menuState, setMenuState] = useState<ActionMenuState | null>(null);
|
|
124
132
|
const [transientFocusLayoutState, setTransientFocusLayoutState] = useState<TransientFocusLayoutState | null>(null);
|
|
125
133
|
const transientFocusLayoutStateRef = useRef<TransientFocusLayoutState | null>(null);
|
|
@@ -130,6 +138,9 @@ export function Shell({
|
|
|
130
138
|
setHoveredMenuItemId(null);
|
|
131
139
|
}, []);
|
|
132
140
|
const overlayOpen = commandBarOpen || dialogOpen || !!menuState;
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
if (commandBarOpen) setHoveredPaneId(null);
|
|
143
|
+
}, [commandBarOpen]);
|
|
133
144
|
|
|
134
145
|
const dragRuntime = useShellDragRuntimeState({
|
|
135
146
|
contentHeight,
|
|
@@ -164,13 +175,14 @@ export function Shell({
|
|
|
164
175
|
dispatch(hasFocusTarget
|
|
165
176
|
? { type: "UPDATE_LAYOUT", layout: nextLayout, focusedPaneId: options.focusedPaneId ?? null }
|
|
166
177
|
: { type: "UPDATE_LAYOUT", layout: nextLayout });
|
|
178
|
+
const currentState = stateRef.current;
|
|
167
179
|
scheduleConfigSave(syncConfigActiveLayoutState(
|
|
168
|
-
{ ...config, layout: nextLayout },
|
|
169
|
-
paneState,
|
|
170
|
-
hasFocusTarget ? (options.focusedPaneId ?? null) : focusedPaneId,
|
|
171
|
-
activePanel,
|
|
180
|
+
{ ...currentState.config, layout: nextLayout },
|
|
181
|
+
currentState.paneState,
|
|
182
|
+
hasFocusTarget ? (options.focusedPaneId ?? null) : currentState.focusedPaneId,
|
|
183
|
+
currentState.activePanel,
|
|
172
184
|
));
|
|
173
|
-
}, [
|
|
185
|
+
}, [dispatch, stateRef]);
|
|
174
186
|
|
|
175
187
|
const focusPane = useCallback((paneId: string) => {
|
|
176
188
|
dispatch({ type: "FOCUS_PANE", paneId });
|
|
@@ -252,7 +264,6 @@ export function Shell({
|
|
|
252
264
|
gridlockVisiblePanes,
|
|
253
265
|
handleFloatingClose,
|
|
254
266
|
openFocusedPaneSettings,
|
|
255
|
-
openLayoutMenu,
|
|
256
267
|
openPaneSettings,
|
|
257
268
|
popOutFocusedPane,
|
|
258
269
|
toggleFocusedPaneFloating,
|
|
@@ -271,6 +282,9 @@ export function Shell({
|
|
|
271
282
|
visibleLayout,
|
|
272
283
|
width,
|
|
273
284
|
});
|
|
285
|
+
const openLayoutGallery = useCallback(() => {
|
|
286
|
+
pluginRegistry.showPane("layout-marketplace");
|
|
287
|
+
}, [pluginRegistry]);
|
|
274
288
|
const setTransientFocusLayout = useCallback((next: TransientFocusLayoutState | null) => {
|
|
275
289
|
transientFocusLayoutStateRef.current = next;
|
|
276
290
|
setTransientFocusLayoutState(next);
|
|
@@ -368,24 +382,6 @@ export function Shell({
|
|
|
368
382
|
transientFocusLayoutState,
|
|
369
383
|
]);
|
|
370
384
|
|
|
371
|
-
useShellPaneManagementShortcuts({
|
|
372
|
-
cancelActiveDrag,
|
|
373
|
-
closeAllFloatingPanes,
|
|
374
|
-
closeFocusedPane,
|
|
375
|
-
copyFocusedPaneScreenshot,
|
|
376
|
-
focusedPaneId,
|
|
377
|
-
gridlockVisiblePanes,
|
|
378
|
-
hasActiveDrag,
|
|
379
|
-
inputCaptured,
|
|
380
|
-
openFocusedPaneSettings,
|
|
381
|
-
openLayoutMenu,
|
|
382
|
-
overlayOpen,
|
|
383
|
-
popOutFocusedPane,
|
|
384
|
-
startWindowMode,
|
|
385
|
-
toggleFocusedPaneFullscreen,
|
|
386
|
-
toggleFocusedPaneFloating,
|
|
387
|
-
});
|
|
388
|
-
|
|
389
385
|
const dockLeafLayouts = useMemo(() => getDockLeafLayouts(activeLayout, bounds, dockGeometryOptions), [activeLayout, bounds, dockGeometryOptions]);
|
|
390
386
|
const dockDividerLayouts = useMemo(() => getDockDividerLayouts(activeLayout, bounds, dockGeometryOptions), [activeLayout, bounds, dockGeometryOptions]);
|
|
391
387
|
const snapGuides = useMemo(() => makeSnapGuides(width, contentHeight), [contentHeight, width]);
|
|
@@ -422,8 +418,8 @@ export function Shell({
|
|
|
422
418
|
[config, paneState],
|
|
423
419
|
);
|
|
424
420
|
const getPaneTitle = useCallback(
|
|
425
|
-
(pane: ResolvedPane): string => getPaneDisplayTitle(titleState, pane.instance, pane.def),
|
|
426
|
-
[titleState],
|
|
421
|
+
(pane: ResolvedPane): string => getPaneDisplayTitle(titleState, pane.instance, pane.def, pluginRegistry.panes),
|
|
422
|
+
[pluginRegistry.panes, titleState],
|
|
427
423
|
);
|
|
428
424
|
const handlePaneQuickSetting = useCallback((paneId: string, key: string, event: any) => {
|
|
429
425
|
event?.preventDefault?.();
|
|
@@ -446,6 +442,51 @@ export function Shell({
|
|
|
446
442
|
onMouseDown: (event) => handlePaneQuickSetting(paneId, setting.key, event),
|
|
447
443
|
}))
|
|
448
444
|
), [config, handlePaneQuickSetting, pluginRegistry]);
|
|
445
|
+
const sharePane = useCallback(async (payload: Extract<SharePayload, { kind: "pane" }>) => {
|
|
446
|
+
try {
|
|
447
|
+
const { id } = await createShare(payload);
|
|
448
|
+
await rendererHost.copyText(openLiveShareUrl(id));
|
|
449
|
+
pluginRegistry.notify({ body: "Share link copied to clipboard", type: "success" });
|
|
450
|
+
} catch (error) {
|
|
451
|
+
pluginRegistry.notify({
|
|
452
|
+
body: error instanceof Error ? error.message : "Could not share this pane.",
|
|
453
|
+
type: "error",
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
}, [pluginRegistry, rendererHost]);
|
|
457
|
+
const shareFocusedPane = useCallback(() => {
|
|
458
|
+
if (!publicSharing || !focusedPaneId) return false;
|
|
459
|
+
const pane = paneMap.get(focusedPaneId);
|
|
460
|
+
if (!pane) return false;
|
|
461
|
+
const payload = buildPaneSharePayload(
|
|
462
|
+
pluginRegistry,
|
|
463
|
+
pane.instance,
|
|
464
|
+
paneState[focusedPaneId] ?? {},
|
|
465
|
+
resolveTickerForPane(titleState, focusedPaneId),
|
|
466
|
+
);
|
|
467
|
+
if (!payload) return false;
|
|
468
|
+
void sharePane(payload);
|
|
469
|
+
return true;
|
|
470
|
+
}, [focusedPaneId, paneMap, paneState, pluginRegistry, publicSharing, sharePane, titleState]);
|
|
471
|
+
|
|
472
|
+
useShellPaneManagementShortcuts({
|
|
473
|
+
cancelActiveDrag,
|
|
474
|
+
closeAllFloatingPanes,
|
|
475
|
+
closeFocusedPane,
|
|
476
|
+
copyFocusedPaneScreenshot,
|
|
477
|
+
focusedPaneId,
|
|
478
|
+
gridlockVisiblePanes,
|
|
479
|
+
hasActiveDrag,
|
|
480
|
+
inputCaptured,
|
|
481
|
+
openFocusedPaneSettings,
|
|
482
|
+
openLayoutGallery,
|
|
483
|
+
overlayOpen,
|
|
484
|
+
popOutFocusedPane,
|
|
485
|
+
shareFocusedPane,
|
|
486
|
+
startWindowMode,
|
|
487
|
+
toggleFocusedPaneFullscreen,
|
|
488
|
+
toggleFocusedPaneFloating,
|
|
489
|
+
});
|
|
449
490
|
|
|
450
491
|
const openPaneMenu = useCallback((paneId: string, rect: LayoutBounds, event?: { preventDefault?: () => void; stopPropagation?: () => void }) => {
|
|
451
492
|
const pane = paneMap.get(paneId);
|
|
@@ -458,6 +499,14 @@ export function Shell({
|
|
|
458
499
|
title: getPaneTitle(pane),
|
|
459
500
|
floating: !!pane.floating,
|
|
460
501
|
};
|
|
502
|
+
const sharePayload = publicSharing
|
|
503
|
+
? buildPaneSharePayload(
|
|
504
|
+
pluginRegistry,
|
|
505
|
+
pane.instance,
|
|
506
|
+
paneState[paneId] ?? {},
|
|
507
|
+
resolveTickerForPane(titleState, paneId),
|
|
508
|
+
)
|
|
509
|
+
: null;
|
|
461
510
|
const items = menuForPane(
|
|
462
511
|
pane,
|
|
463
512
|
visibleLayout,
|
|
@@ -469,6 +518,14 @@ export function Shell({
|
|
|
469
518
|
openPaneSettings,
|
|
470
519
|
desktopWindowBridge,
|
|
471
520
|
nativePaneChrome && rendererHost.copyPngImage ? copyPaneScreenshot : undefined,
|
|
521
|
+
sharePayload ? () => sharePane(sharePayload) : undefined,
|
|
522
|
+
tickerLinkMenuItems({
|
|
523
|
+
instance: pane.instance,
|
|
524
|
+
layout: visibleLayout,
|
|
525
|
+
panes: pluginRegistry.panes,
|
|
526
|
+
state: titleState,
|
|
527
|
+
persistLayout,
|
|
528
|
+
}),
|
|
472
529
|
);
|
|
473
530
|
void showContextMenu(context, items, event).then((shown) => {
|
|
474
531
|
if (shown) return;
|
|
@@ -492,7 +549,7 @@ export function Shell({
|
|
|
492
549
|
items: fallbackItems,
|
|
493
550
|
});
|
|
494
551
|
});
|
|
495
|
-
}, [contentHeight, copyPaneScreenshot, desktopWindowBridge, focusPane, getPaneTitle, nativePaneChrome, openPaneSettings, paneMap, persistLayout, pluginRegistry, rendererHost.copyPngImage, shortcutDisplayMode, showContextMenu, visibleLayout, width]);
|
|
552
|
+
}, [contentHeight, copyPaneScreenshot, desktopWindowBridge, focusPane, getPaneTitle, nativePaneChrome, openPaneSettings, paneMap, paneState, persistLayout, pluginRegistry, publicSharing, rendererHost.copyPngImage, sharePane, shortcutDisplayMode, showContextMenu, titleState, visibleLayout, width]);
|
|
496
553
|
|
|
497
554
|
const {
|
|
498
555
|
handleFloatingCloseMouseDown,
|
|
@@ -510,7 +567,6 @@ export function Shell({
|
|
|
510
567
|
bounds,
|
|
511
568
|
closePaneMenu,
|
|
512
569
|
contentHeight,
|
|
513
|
-
dispatch,
|
|
514
570
|
dockGeometryOptions,
|
|
515
571
|
dockDividerLayouts,
|
|
516
572
|
dockLeafLayouts,
|
|
@@ -534,6 +590,7 @@ export function Shell({
|
|
|
534
590
|
visibleLayout,
|
|
535
591
|
width,
|
|
536
592
|
windowMode,
|
|
593
|
+
commandBarOpen,
|
|
537
594
|
});
|
|
538
595
|
const windowModeDockResizePathKey = windowMode?.focus.kind === "dock-resize"
|
|
539
596
|
? windowMode.focus.pathKey
|
|
@@ -560,8 +617,9 @@ export function Shell({
|
|
|
560
617
|
}
|
|
561
618
|
: {})}
|
|
562
619
|
>
|
|
563
|
-
{/*
|
|
620
|
+
{/* Render nothing; give the auth commands always-mounted components with dialog access. */}
|
|
564
621
|
<DeviceSignInDialogHost />
|
|
622
|
+
<AuthDialogHost />
|
|
565
623
|
<Box
|
|
566
624
|
position="absolute"
|
|
567
625
|
left={0}
|
|
@@ -1,7 +1,43 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import { displayWidth } from "../../../utils/format";
|
|
3
3
|
import { getLanguage, setLanguage, t } from "../../../i18n";
|
|
4
|
-
import { actionMenuWidth } from "./menu";
|
|
4
|
+
import { actionMenuWidth, menuForPane } from "./menu";
|
|
5
|
+
|
|
6
|
+
describe("pane action menu", () => {
|
|
7
|
+
test("offers the global share action for a portable pane", async () => {
|
|
8
|
+
let shared = false;
|
|
9
|
+
const items = menuForPane(
|
|
10
|
+
{
|
|
11
|
+
instance: { instanceId: "chart-1", paneId: "chart-composer" },
|
|
12
|
+
def: { defaultPosition: "right" },
|
|
13
|
+
floating: false,
|
|
14
|
+
} as any,
|
|
15
|
+
{
|
|
16
|
+
dockRoot: { kind: "pane", instanceId: "chart-1" },
|
|
17
|
+
instances: [{ instanceId: "chart-1", paneId: "chart-composer" }],
|
|
18
|
+
floating: [],
|
|
19
|
+
detached: [],
|
|
20
|
+
},
|
|
21
|
+
120,
|
|
22
|
+
40,
|
|
23
|
+
{
|
|
24
|
+
hasPaneSettings: () => false,
|
|
25
|
+
openWindowMode: () => {},
|
|
26
|
+
} as any,
|
|
27
|
+
() => {},
|
|
28
|
+
() => {},
|
|
29
|
+
() => {},
|
|
30
|
+
undefined,
|
|
31
|
+
undefined,
|
|
32
|
+
() => { shared = true; },
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const share = items.find((item) => item.type !== "divider" && item.id === "share-pane");
|
|
36
|
+
await share?.onSelect?.();
|
|
37
|
+
expect(shared).toBe(true);
|
|
38
|
+
expect(share?.accelerator).toBe("CmdOrCtrl+Shift+S");
|
|
39
|
+
});
|
|
40
|
+
});
|
|
5
41
|
|
|
6
42
|
describe("action menu sizing", () => {
|
|
7
43
|
test("uses translated terminal display width", () => {
|
|
@@ -32,6 +32,8 @@ export function menuForPane(
|
|
|
32
32
|
openPaneSettings: (paneId: string) => void,
|
|
33
33
|
desktopWindowBridge?: DesktopWindowBridge,
|
|
34
34
|
copyPaneScreenshot?: (paneId: string) => void | Promise<void>,
|
|
35
|
+
sharePane?: () => void | Promise<void>,
|
|
36
|
+
linkItems: ContextMenuItem[] = [],
|
|
35
37
|
): ContextMenuItem[] {
|
|
36
38
|
const baseActions: ContextMenuItem[] = [];
|
|
37
39
|
if (pluginRegistry.hasPaneSettings(pane.instance.instanceId)) {
|
|
@@ -42,6 +44,14 @@ export function menuForPane(
|
|
|
42
44
|
onSelect: () => openPaneSettings(pane.instance.instanceId),
|
|
43
45
|
});
|
|
44
46
|
}
|
|
47
|
+
if (sharePane) {
|
|
48
|
+
baseActions.push({
|
|
49
|
+
id: "share-pane",
|
|
50
|
+
label: "Share Pane",
|
|
51
|
+
accelerator: PANE_MANAGEMENT_ACCELERATORS.share,
|
|
52
|
+
onSelect: sharePane,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
45
55
|
if (copyPaneScreenshot) {
|
|
46
56
|
baseActions.push({
|
|
47
57
|
id: "copy-screenshot",
|
|
@@ -91,6 +101,10 @@ export function menuForPane(
|
|
|
91
101
|
onSelect: () => persistLayout(removePane(layout, pane.instance.instanceId)),
|
|
92
102
|
});
|
|
93
103
|
|
|
104
|
+
if (linkItems.length > 0) {
|
|
105
|
+
baseActions.push(contextMenuDivider("pane:link-divider"), ...linkItems);
|
|
106
|
+
}
|
|
107
|
+
|
|
94
108
|
baseActions.push(
|
|
95
109
|
contextMenuDivider("pane:layout-divider"),
|
|
96
110
|
{
|
|
@@ -22,6 +22,7 @@ interface UseShellNativePointerRuntimeOptions {
|
|
|
22
22
|
setMenuState: Dispatch<SetStateAction<ActionMenuState | null>>;
|
|
23
23
|
transientFocusActive: boolean;
|
|
24
24
|
windowMode: WindowEditState | null;
|
|
25
|
+
commandBarOpen?: boolean;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export function useShellNativePointerRuntime({
|
|
@@ -38,6 +39,7 @@ export function useShellNativePointerRuntime({
|
|
|
38
39
|
setMenuState,
|
|
39
40
|
transientFocusActive,
|
|
40
41
|
windowMode,
|
|
42
|
+
commandBarOpen = false,
|
|
41
43
|
}: UseShellNativePointerRuntimeOptions) {
|
|
42
44
|
const {
|
|
43
45
|
dragRef,
|
|
@@ -59,6 +61,11 @@ export function useShellNativePointerRuntime({
|
|
|
59
61
|
}, [focusPane, menuState, setHoveredMenuItemId, setMenuState]);
|
|
60
62
|
|
|
61
63
|
const handleNativePaneMouseDown = useCallback((paneId: string, event: ShellMouseEvent) => {
|
|
64
|
+
if (commandBarOpen) {
|
|
65
|
+
event.stopPropagation();
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
62
69
|
if (windowMode) {
|
|
63
70
|
selectWindowModePane(paneId);
|
|
64
71
|
event.stopPropagation();
|
|
@@ -69,10 +76,11 @@ export function useShellNativePointerRuntime({
|
|
|
69
76
|
if (event.isDefaultPrevented?.()) return;
|
|
70
77
|
focusNativePane(paneId);
|
|
71
78
|
});
|
|
72
|
-
}, [focusNativePane, selectWindowModePane, windowMode]);
|
|
79
|
+
}, [commandBarOpen, focusNativePane, selectWindowModePane, windowMode]);
|
|
73
80
|
|
|
74
81
|
const startNativeFloatingDrag = useCallback((paneId: string, rect: FloatingRect, event: ShellMouseEvent) => {
|
|
75
82
|
if (!nativePaneChrome) return;
|
|
83
|
+
if (commandBarOpen) return;
|
|
76
84
|
if (windowMode) return;
|
|
77
85
|
if (transientFocusActive) return;
|
|
78
86
|
if (event.button === 2) return;
|
|
@@ -89,10 +97,11 @@ export function useShellNativePointerRuntime({
|
|
|
89
97
|
};
|
|
90
98
|
updateDragFloatingRect({ paneId, rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height } });
|
|
91
99
|
event.preventDefault();
|
|
92
|
-
}, [dragRef, focusNativePane, getShellPointer, nativePaneChrome, transientFocusActive, updateDragFloatingRect, windowMode]);
|
|
100
|
+
}, [commandBarOpen, dragRef, focusNativePane, getShellPointer, nativePaneChrome, transientFocusActive, updateDragFloatingRect, windowMode]);
|
|
93
101
|
|
|
94
102
|
const startNativeDockedDrag = useCallback((paneId: string, rect: LayoutBounds, event: ShellMouseEvent) => {
|
|
95
103
|
if (!nativePaneChrome) return;
|
|
104
|
+
if (commandBarOpen) return;
|
|
96
105
|
if (windowMode) return;
|
|
97
106
|
if (transientFocusActive) return;
|
|
98
107
|
if (event.button === 2) return;
|
|
@@ -108,10 +117,11 @@ export function useShellNativePointerRuntime({
|
|
|
108
117
|
origRect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },
|
|
109
118
|
};
|
|
110
119
|
event.preventDefault();
|
|
111
|
-
}, [dragRef, focusNativePane, getShellPointer, nativePaneChrome, transientFocusActive, windowMode]);
|
|
120
|
+
}, [commandBarOpen, dragRef, focusNativePane, getShellPointer, nativePaneChrome, transientFocusActive, windowMode]);
|
|
112
121
|
|
|
113
122
|
const startNativeFloatResize = useCallback((paneId: string, rect: FloatingRect, event: ShellMouseEvent) => {
|
|
114
123
|
if (!nativePaneChrome) return;
|
|
124
|
+
if (commandBarOpen) return;
|
|
115
125
|
if (transientFocusActive) return;
|
|
116
126
|
|
|
117
127
|
const pointer = getShellPointer(event);
|
|
@@ -130,10 +140,11 @@ export function useShellNativePointerRuntime({
|
|
|
130
140
|
updateDragFloatingRect({ paneId, rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height } });
|
|
131
141
|
event.stopPropagation();
|
|
132
142
|
event.preventDefault();
|
|
133
|
-
}, [dragRef, focusNativePane, getShellPointer, nativePaneChrome, selectWindowModePane, transientFocusActive, updateDragFloatingRect, windowMode]);
|
|
143
|
+
}, [commandBarOpen, dragRef, focusNativePane, getShellPointer, nativePaneChrome, selectWindowModePane, transientFocusActive, updateDragFloatingRect, windowMode]);
|
|
134
144
|
|
|
135
145
|
const startNativeDividerDrag = useCallback((divider: DockDividerLayout, event: ShellMouseEvent) => {
|
|
136
146
|
if (!nativePaneChrome) return;
|
|
147
|
+
if (commandBarOpen) return;
|
|
137
148
|
if (transientFocusActive) return;
|
|
138
149
|
|
|
139
150
|
const pointer = getShellPointer(event);
|
|
@@ -157,27 +168,30 @@ export function useShellNativePointerRuntime({
|
|
|
157
168
|
});
|
|
158
169
|
event.stopPropagation();
|
|
159
170
|
event.preventDefault();
|
|
160
|
-
}, [dragRef, getShellPointer, menuState, nativePaneChrome, setHoveredMenuItemId, setMenuState, transientFocusActive, updateDividerPreview]);
|
|
171
|
+
}, [commandBarOpen, dragRef, getShellPointer, menuState, nativePaneChrome, setHoveredMenuItemId, setMenuState, transientFocusActive, updateDividerPreview]);
|
|
161
172
|
|
|
162
173
|
const handlePaneAction = useCallback((paneId: string, rect: LayoutBounds, event: ShellMouseEvent) => {
|
|
174
|
+
if (commandBarOpen) return;
|
|
163
175
|
if (windowMode) return;
|
|
164
176
|
if (event.button === 2) return;
|
|
165
177
|
event.stopPropagation();
|
|
166
178
|
event.preventDefault();
|
|
167
179
|
openPaneMenu(paneId, rect, event);
|
|
168
|
-
}, [openPaneMenu, windowMode]);
|
|
180
|
+
}, [commandBarOpen, openPaneMenu, windowMode]);
|
|
169
181
|
|
|
170
182
|
const handleNativePaneContextMenu = useCallback((paneId: string, rect: LayoutBounds, event: ShellMouseEvent) => {
|
|
183
|
+
if (commandBarOpen) return;
|
|
171
184
|
if (windowMode) return;
|
|
172
185
|
openPaneMenu(paneId, rect, event);
|
|
173
|
-
}, [openPaneMenu, windowMode]);
|
|
186
|
+
}, [commandBarOpen, openPaneMenu, windowMode]);
|
|
174
187
|
|
|
175
188
|
const handleFloatingCloseMouseDown = useCallback((paneId: string, event: ShellMouseEvent) => {
|
|
189
|
+
if (commandBarOpen) return;
|
|
176
190
|
if (windowMode) return;
|
|
177
191
|
event.stopPropagation();
|
|
178
192
|
event.preventDefault();
|
|
179
193
|
handleFloatingClose(paneId);
|
|
180
|
-
}, [handleFloatingClose, windowMode]);
|
|
194
|
+
}, [commandBarOpen, handleFloatingClose, windowMode]);
|
|
181
195
|
|
|
182
196
|
return {
|
|
183
197
|
handleFloatingCloseMouseDown,
|
|
@@ -54,10 +54,6 @@ export function useShellPaneActions({
|
|
|
54
54
|
visibleLayout,
|
|
55
55
|
width,
|
|
56
56
|
}: UseShellPaneActionsOptions) {
|
|
57
|
-
const openLayoutMenu = useCallback(() => {
|
|
58
|
-
pluginRegistry.openCommandBar("LAY ");
|
|
59
|
-
}, [pluginRegistry]);
|
|
60
|
-
|
|
61
57
|
const openPaneSettings = useCallback((paneId: string) => {
|
|
62
58
|
pluginRegistry.openPaneSettingsFn(paneId);
|
|
63
59
|
closePaneMenu();
|
|
@@ -143,7 +139,6 @@ export function useShellPaneActions({
|
|
|
143
139
|
gridlockVisiblePanes,
|
|
144
140
|
handleFloatingClose,
|
|
145
141
|
openFocusedPaneSettings,
|
|
146
|
-
openLayoutMenu,
|
|
147
142
|
openPaneSettings,
|
|
148
143
|
popOutFocusedPane,
|
|
149
144
|
toggleFocusedPaneFloating,
|
|
@@ -21,9 +21,10 @@ interface ShellPaneManagementShortcutOptions {
|
|
|
21
21
|
hasActiveDrag(): boolean;
|
|
22
22
|
inputCaptured: boolean;
|
|
23
23
|
openFocusedPaneSettings(): boolean;
|
|
24
|
-
|
|
24
|
+
openLayoutGallery(): void;
|
|
25
25
|
overlayOpen: boolean;
|
|
26
26
|
popOutFocusedPane(): boolean;
|
|
27
|
+
shareFocusedPane(): boolean;
|
|
27
28
|
startWindowMode(paneId?: string, mode?: WindowEditMode): void;
|
|
28
29
|
toggleFocusedPaneFullscreen(): boolean;
|
|
29
30
|
toggleFocusedPaneFloating(): boolean;
|
|
@@ -39,9 +40,10 @@ export function useShellPaneManagementShortcuts({
|
|
|
39
40
|
hasActiveDrag,
|
|
40
41
|
inputCaptured,
|
|
41
42
|
openFocusedPaneSettings,
|
|
42
|
-
|
|
43
|
+
openLayoutGallery,
|
|
43
44
|
overlayOpen,
|
|
44
45
|
popOutFocusedPane,
|
|
46
|
+
shareFocusedPane,
|
|
45
47
|
startWindowMode,
|
|
46
48
|
toggleFocusedPaneFullscreen,
|
|
47
49
|
toggleFocusedPaneFloating,
|
|
@@ -119,8 +121,11 @@ export function useShellPaneManagementShortcuts({
|
|
|
119
121
|
case "copy-screenshot":
|
|
120
122
|
handled = copyFocusedPaneScreenshot();
|
|
121
123
|
break;
|
|
122
|
-
case "
|
|
123
|
-
|
|
124
|
+
case "share":
|
|
125
|
+
handled = shareFocusedPane();
|
|
126
|
+
break;
|
|
127
|
+
case "layout-gallery":
|
|
128
|
+
openLayoutGallery();
|
|
124
129
|
handled = true;
|
|
125
130
|
break;
|
|
126
131
|
case "gridlock-all":
|
|
@@ -6,9 +6,10 @@ export const PANE_MANAGEMENT_ACCELERATORS = {
|
|
|
6
6
|
toggleFloating: "CmdOrCtrl+Shift+D",
|
|
7
7
|
popOut: "CmdOrCtrl+Shift+O",
|
|
8
8
|
copyScreenshot: "CmdOrCtrl+Shift+C",
|
|
9
|
+
share: "CmdOrCtrl+Shift+S",
|
|
9
10
|
close: "CmdOrCtrl+W",
|
|
10
11
|
closeAllFloating: "CmdOrCtrl+Alt+W",
|
|
11
|
-
|
|
12
|
+
layoutGallery: "CmdOrCtrl+Shift+L",
|
|
12
13
|
gridlockAll: "CmdOrCtrl+Shift+G",
|
|
13
14
|
windowMode: "CmdOrCtrl+Shift+M",
|
|
14
15
|
windowResizeMode: "CmdOrCtrl+Shift+R",
|
|
@@ -20,9 +21,10 @@ export type PaneManagementShortcut =
|
|
|
20
21
|
| "toggle-floating"
|
|
21
22
|
| "pop-out"
|
|
22
23
|
| "copy-screenshot"
|
|
24
|
+
| "share"
|
|
23
25
|
| "close"
|
|
24
26
|
| "close-all-floating"
|
|
25
|
-
| "layout-
|
|
27
|
+
| "layout-gallery"
|
|
26
28
|
| "gridlock-all"
|
|
27
29
|
| "window-mode"
|
|
28
30
|
| "window-resize-mode";
|
|
@@ -39,10 +41,11 @@ export function resolvePaneManagementShortcut(
|
|
|
39
41
|
if (!shifted && name === ",") return "settings";
|
|
40
42
|
if (!shifted || event.alt) return null;
|
|
41
43
|
if (name === "c") return "copy-screenshot";
|
|
44
|
+
if (name === "s") return "share";
|
|
42
45
|
if (name === "d") return "toggle-floating";
|
|
43
46
|
if (name === "f") return "toggle-fullscreen";
|
|
44
47
|
if (name === "o") return "pop-out";
|
|
45
|
-
if (name === "l") return "layout-
|
|
48
|
+
if (name === "l") return "layout-gallery";
|
|
46
49
|
if (name === "g") return "gridlock-all";
|
|
47
50
|
if (name === "m") return "window-mode";
|
|
48
51
|
if (name === "r") return "window-resize-mode";
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { createInitialState } from "../../../state/app/context";
|
|
3
|
+
import {
|
|
4
|
+
createDefaultConfig,
|
|
5
|
+
createPaneInstance,
|
|
6
|
+
findPaneInstance,
|
|
7
|
+
TICKER_RESEARCH_PANE_ID,
|
|
8
|
+
type LayoutConfig,
|
|
9
|
+
} from "../../../types/config";
|
|
10
|
+
import type { PaneDef } from "../../../types/plugin";
|
|
11
|
+
import { getPaneDisplayTitle } from "../pane/title";
|
|
12
|
+
import { tickerLinkMenuItems } from "./ticker-link-menu";
|
|
13
|
+
|
|
14
|
+
const panes = new Map<string, PaneDef>([
|
|
15
|
+
["portfolio-list", {
|
|
16
|
+
id: "portfolio-list",
|
|
17
|
+
name: "Portfolio",
|
|
18
|
+
component: () => null,
|
|
19
|
+
defaultPosition: "left",
|
|
20
|
+
tickerSource: true,
|
|
21
|
+
}],
|
|
22
|
+
[TICKER_RESEARCH_PANE_ID, {
|
|
23
|
+
id: TICKER_RESEARCH_PANE_ID,
|
|
24
|
+
name: "Ticker Research",
|
|
25
|
+
component: () => null,
|
|
26
|
+
defaultPosition: "right",
|
|
27
|
+
}],
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
describe("tickerLinkMenuItems", () => {
|
|
31
|
+
test("pins the current ticker when unlinking and can link back to the source", () => {
|
|
32
|
+
const state = createInitialState(createDefaultConfig("/tmp/gloomberb-link-menu-test"));
|
|
33
|
+
state.paneState["portfolio-list:main"] = { collectionId: "main", cursorSymbol: "AAPL" };
|
|
34
|
+
const target = findPaneInstance(state.config.layout, "ticker-detail:main")!;
|
|
35
|
+
let layout: LayoutConfig = state.config.layout;
|
|
36
|
+
|
|
37
|
+
expect(getPaneDisplayTitle(state, target, panes.get(TICKER_RESEARCH_PANE_ID)!, panes)).toBe(
|
|
38
|
+
"AAPL ⧉ Linked to Main Portfolio",
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
tickerLinkMenuItems({
|
|
42
|
+
instance: target,
|
|
43
|
+
layout,
|
|
44
|
+
panes,
|
|
45
|
+
state,
|
|
46
|
+
persistLayout: (nextLayout) => { layout = nextLayout; },
|
|
47
|
+
}).find((item) => item.id === "unlink:portfolio-list:main")?.onSelect?.();
|
|
48
|
+
|
|
49
|
+
const pinned = findPaneInstance(layout, target.instanceId)!;
|
|
50
|
+
expect(pinned.binding).toEqual({ kind: "fixed", symbol: "AAPL" });
|
|
51
|
+
|
|
52
|
+
const previousFollower = createPaneInstance(TICKER_RESEARCH_PANE_ID, {
|
|
53
|
+
instanceId: "ticker-detail:previous",
|
|
54
|
+
binding: { kind: "follow", sourceInstanceId: "portfolio-list:main" },
|
|
55
|
+
});
|
|
56
|
+
layout = {
|
|
57
|
+
...layout,
|
|
58
|
+
instances: [...layout.instances, previousFollower],
|
|
59
|
+
floating: [
|
|
60
|
+
...layout.floating,
|
|
61
|
+
{ instanceId: previousFollower.instanceId, x: 1, y: 1, width: 40, height: 12 },
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
const pinnedState = { ...state, config: { ...state.config, layout } };
|
|
65
|
+
tickerLinkMenuItems({
|
|
66
|
+
instance: pinned,
|
|
67
|
+
layout,
|
|
68
|
+
panes,
|
|
69
|
+
state: pinnedState,
|
|
70
|
+
persistLayout: (nextLayout) => { layout = nextLayout; },
|
|
71
|
+
}).find((item) => item.id === "link:portfolio-list:main")?.onSelect?.();
|
|
72
|
+
|
|
73
|
+
expect(findPaneInstance(layout, target.instanceId)?.binding).toEqual({
|
|
74
|
+
kind: "follow",
|
|
75
|
+
sourceInstanceId: "portfolio-list:main",
|
|
76
|
+
});
|
|
77
|
+
expect(findPaneInstance(layout, previousFollower.instanceId)?.binding).toEqual({
|
|
78
|
+
kind: "fixed",
|
|
79
|
+
symbol: "AAPL",
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
});
|