gloomberb 0.15.5 → 0.15.7
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 +2 -2
- package/README.zh-CN.md +1 -1
- package/package.json +1 -1
- package/src/api-client/auth.ts +28 -0
- package/src/api-client/data.ts +37 -10
- package/src/api-client/estimate-revisions.ts +1 -1
- package/src/api-client/futures-curve.ts +1 -1
- package/src/api-client/index.ts +10 -1
- package/src/api-client/market-discovery.ts +84 -0
- package/src/api-client/paths.ts +14 -11
- package/src/api-client/request.ts +12 -2
- package/src/api-client/research-activity.ts +4 -1
- package/src/api-client/tape.ts +2 -2
- package/src/api-client/types.ts +10 -0
- package/src/app/dialog-bridge.tsx +33 -0
- package/src/app/pane-runtime/index.tsx +9 -2
- package/src/app/pane-runtime/pane-settings-runtime.tsx +2 -1
- package/src/app/pane-runtime/pane-template-runtime.ts +8 -28
- package/src/app/pane-runtime/plugin-bindings.ts +34 -12
- package/src/app/pane-runtime/ticker-open-runtime.ts +5 -3
- package/src/app/runtime/broker-import.ts +5 -3
- package/src/app/runtime/desktop-menu.ts +9 -6
- package/src/app/runtime/plugin-bindings.ts +7 -1
- package/src/app/runtime/ticker-refresh.ts +1 -1
- package/src/app.tsx +12 -0
- package/src/brokers/directory.ts +11 -2
- package/src/brokers/profile-form.ts +2 -1
- package/src/brokers/remove-profile.ts +61 -0
- package/src/brokers/signed-in/connect.ts +20 -7
- package/src/brokers/signed-in/sign-in-dialog.tsx +68 -30
- package/src/cli/desktop-pane-shot.ts +2 -2
- package/src/cli/history-rows.ts +1 -1
- package/src/cli/pane-functions/function-help.ts +10 -3
- package/src/cli/ticker-resolution.ts +2 -2
- package/src/components/chart/composite/composite-chart.tsx +4 -2
- package/src/components/chart/composite/rasterizer.ts +69 -9
- package/src/components/command-bar/action-runtime.ts +7 -67
- package/src/components/command-bar/commands/direct/index.ts +9 -5
- package/src/components/command-bar/commands/direct/runtime.ts +12 -11
- package/src/components/command-bar/commands/plugin/actions.ts +6 -35
- package/src/components/command-bar/helpers.ts +3 -31
- package/src/components/command-bar/keyboard-handlers.ts +7 -219
- package/src/components/command-bar/keyboard-shortcuts.ts +25 -99
- package/src/components/command-bar/layout-items/current-layout.ts +12 -1
- package/src/components/command-bar/layout-items/focused-pane.ts +2 -1
- package/src/components/command-bar/layout-items/types.ts +2 -0
- package/src/components/command-bar/layout-items.ts +3 -0
- package/src/components/command-bar/list/model.ts +1 -1
- package/src/components/command-bar/list/navigation.ts +5 -12
- package/src/components/command-bar/pane-actions.ts +17 -14
- package/src/components/command-bar/pane-settings.ts +7 -250
- package/src/components/command-bar/pane-templates/workflow.ts +6 -13
- package/src/components/command-bar/panel/index.tsx +4 -110
- package/src/components/command-bar/panel/layout.ts +4 -16
- package/src/components/command-bar/panel/runtime.ts +1 -87
- package/src/components/command-bar/panel/state.ts +12 -29
- package/src/components/command-bar/panel/types.ts +2 -26
- package/src/components/command-bar/picker-activation.ts +7 -56
- package/src/components/command-bar/routes/root/plugin-install.ts +3 -3
- package/src/components/command-bar/routes/root/search-report.ts +2 -1
- package/src/components/command-bar/routing/actions.ts +21 -59
- package/src/components/command-bar/routing/confirm.ts +15 -88
- package/src/components/command-bar/routing/effects.ts +1 -20
- package/src/components/command-bar/routing/launch-request.ts +1 -36
- package/src/components/command-bar/routing/list-state.ts +5 -36
- package/src/components/command-bar/selection-runtime.ts +6 -35
- package/src/components/command-bar/surface/environment.ts +10 -6
- package/src/components/command-bar/surface/index.tsx +4 -37
- package/src/components/command-bar/workflow/alert.ts +23 -17
- package/src/components/command-bar/workflow/broker.ts +30 -40
- package/src/components/command-bar/workflow/builtin.ts +33 -38
- package/src/components/command-bar/workflow/collection-actions.ts +26 -21
- package/src/components/command-bar/workflow/collection-ticker.ts +4 -4
- package/src/components/command-bar/workflow/coordinator.ts +27 -156
- package/src/components/command-bar/workflow/fields.ts +6 -22
- package/src/components/command-bar/workflow/ops.ts +46 -3
- package/src/components/command-bar/workflow/submit.ts +28 -43
- package/src/components/command-bar/workflow/ticker-listing-picker.ts +12 -9
- package/src/components/command-bar/workflow/tickers.ts +2 -2
- package/src/components/command-bar/workflow/types.ts +10 -35
- package/src/components/feedback-dialog.tsx +1 -13
- package/src/components/form-modal/broker-step.tsx +119 -0
- package/src/components/form-modal/confirm.tsx +145 -0
- package/src/components/form-modal/content.tsx +698 -0
- package/src/components/form-modal/deps.ts +77 -0
- package/src/components/form-modal/field-row.tsx +318 -0
- package/src/components/form-modal/host.tsx +169 -0
- package/src/components/form-modal/index.ts +2 -0
- package/src/components/form-modal/model.ts +131 -0
- package/src/components/form-modal/request.ts +67 -0
- package/src/components/form-modal/routes.ts +139 -0
- package/src/components/layout/pane/frame.tsx +2 -1
- package/src/components/layout/pane/surface.ts +26 -0
- package/src/components/layout/pane/title.ts +21 -5
- package/src/components/layout/shell/index.tsx +12 -1
- package/src/components/layout/shell/ticker-link-menu.ts +46 -23
- package/src/components/layout/status-bar.tsx +7 -1
- package/src/components/onboarding/desks-step.tsx +43 -0
- package/src/components/onboarding/first-run-workspace.ts +1 -1
- package/src/components/onboarding/onboarding-frame.tsx +4 -1
- package/src/components/onboarding/onboarding-wizard.tsx +151 -26
- package/src/components/onboarding/wizard-positions.ts +19 -6
- package/src/components/pane-settings-dialog.tsx +7 -1
- package/src/components/pane-template-wizard.tsx +4 -149
- package/src/components/sign-in-code-panel.tsx +22 -9
- package/src/components/textarea-keys.ts +13 -0
- package/src/components/toggle-list.tsx +18 -10
- package/src/components/ui/button.tsx +3 -2
- package/src/components/ui/confirm-dialog.tsx +62 -10
- package/src/components/ui/frame.tsx +7 -2
- package/src/components/ui/list-view.tsx +16 -9
- package/src/core/app-runtime.ts +1 -1
- package/src/core/state/app/layout.ts +2 -0
- package/src/core/state/app/types.ts +1 -15
- package/src/data/config/home.ts +82 -11
- package/src/data/config/store/node.ts +29 -16
- package/src/data/config/store/normalize.ts +3 -0
- package/src/i18n/es.ts +79 -7
- package/src/i18n/ja.ts +79 -7
- package/src/i18n/ko.ts +79 -7
- package/src/i18n/zh-cn.ts +79 -7
- package/src/i18n/zh-tw.ts +79 -7
- package/src/layout/desks.ts +335 -0
- package/src/layout/pane-follow.ts +47 -0
- package/src/layout/ticker-navigation.ts +13 -0
- package/src/layout-marketplace/gallery.tsx +11 -3
- package/src/market-data/coordinator/fx-legs.ts +1 -1
- package/src/market-data/history-session.ts +3 -5
- package/src/market-data/market/format.ts +15 -9
- package/src/market-data/market/freshness.ts +1 -1
- package/src/market-data/market/status.ts +1 -1
- package/src/market-data/quotes/metadata.ts +3 -3
- package/src/market-data/quotes/resolution.ts +3 -3
- package/src/news/types.ts +1 -1
- package/src/plugins/builtin/account-management/calendar-tab.tsx +196 -0
- package/src/plugins/builtin/account-management/footer.ts +5 -2
- package/src/plugins/builtin/account-management/index.tsx +2 -2
- package/src/plugins/builtin/account-management/navigation.ts +1 -1
- package/src/plugins/builtin/account-management/pane.tsx +11 -1
- package/src/plugins/builtin/alerts/alert-engine.ts +2 -0
- package/src/plugins/builtin/alerts/cli.ts +2 -2
- package/src/plugins/builtin/alerts/types.ts +2 -0
- package/src/plugins/builtin/analytics/index.tsx +16 -9
- package/src/plugins/builtin/analytics/pane-model.ts +20 -11
- package/src/plugins/builtin/backtest/index.tsx +1 -1
- package/src/plugins/builtin/broker-manager/add-flow.tsx +625 -0
- package/src/plugins/builtin/broker-manager/add-request.ts +34 -0
- package/src/plugins/builtin/broker-manager/detail.tsx +128 -50
- package/src/plugins/builtin/broker-manager/footer.ts +6 -5
- package/src/plugins/builtin/broker-manager/index.tsx +62 -21
- package/src/plugins/builtin/broker-manager/model.ts +7 -0
- package/src/plugins/builtin/broker-manager/pane-actions.tsx +47 -44
- package/src/plugins/builtin/chart-composer/index.tsx +20 -0
- package/src/plugins/builtin/chart-composer/pane.tsx +35 -7
- package/src/plugins/builtin/cloud/company-picker.tsx +658 -0
- package/src/plugins/builtin/credit-boards/model.ts +1 -1
- package/src/plugins/builtin/debt-maturities/index.tsx +1 -0
- package/src/plugins/builtin/dividend-yield/browser.tsx +2 -25
- package/src/plugins/builtin/dividend-yield/client.ts +34 -122
- package/src/plugins/builtin/dividend-yield/index.tsx +10 -9
- package/src/plugins/builtin/dividend-yield/provider-client.ts +1 -1
- package/src/plugins/builtin/estimate-revisions/client.ts +3 -3
- package/src/plugins/builtin/estimate-revisions/index.tsx +1 -0
- package/src/plugins/builtin/estimate-revisions/pane.tsx +2 -2
- package/src/plugins/builtin/executives/index.tsx +1 -0
- package/src/plugins/builtin/executives/pane.tsx +13 -4
- package/src/plugins/builtin/filing-events/index.tsx +1 -0
- package/src/plugins/builtin/filing-events/pane.tsx +23 -6
- package/src/plugins/builtin/futures/contracts.ts +3 -3
- package/src/plugins/builtin/futures/returns.ts +1 -1
- package/src/plugins/builtin/futures-curve/client.ts +1 -1
- package/src/plugins/builtin/futures-curve/model.ts +1 -1
- package/src/plugins/builtin/help/index.tsx +8 -3
- package/src/plugins/builtin/holders/index.tsx +1 -0
- package/src/plugins/builtin/insider/index.tsx +1 -0
- package/src/plugins/builtin/iv-history/index.tsx +1 -1
- package/src/plugins/builtin/layout-manager/index.tsx +75 -1
- package/src/plugins/builtin/market-heatmap/data.ts +13 -256
- package/src/plugins/builtin/market-heatmap/index.tsx +5 -15
- package/src/plugins/builtin/market-movers/client.ts +1 -1
- package/src/plugins/builtin/market-movers/screener.ts +60 -142
- package/src/plugins/builtin/market-valuation/defs.ts +1 -2
- package/src/plugins/builtin/market-valuation/sources.ts +1 -3
- package/src/plugins/builtin/news/index.tsx +1 -0
- package/src/plugins/builtin/news/wire/default-feeds.ts +2 -8
- package/src/plugins/builtin/news/wire/feed-config.ts +5 -1
- package/src/plugins/builtin/news/wire/persisted-articles.ts +9 -5
- package/src/plugins/builtin/news/wire/rss/cli.ts +1 -1
- package/src/plugins/builtin/news/wire/rss/managed-feed.ts +19 -0
- package/src/plugins/builtin/news/wire/rss/parser.ts +18 -9
- package/src/plugins/builtin/news/wire/rss/source.ts +1 -1
- package/src/plugins/builtin/options/index.tsx +1 -0
- package/src/plugins/builtin/options-positioning/client.ts +5 -0
- package/src/plugins/builtin/options-positioning/headless.ts +2 -1
- package/src/plugins/builtin/options-positioning/index.tsx +1 -0
- package/src/plugins/builtin/options-positioning/pane.tsx +24 -9
- package/src/plugins/builtin/options-scenario/client.ts +78 -21
- package/src/plugins/builtin/options-scenario/headless.ts +14 -2
- package/src/plugins/builtin/options-scenario/model.ts +2 -0
- package/src/plugins/builtin/options-scenario/pane.tsx +14 -5
- package/src/plugins/builtin/plugin-marketplace/model.ts +5 -0
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +4 -2
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +7 -1
- package/src/plugins/builtin/portfolio-list/cli/render.ts +13 -13
- package/src/plugins/builtin/portfolio-list/column-values.ts +1 -0
- package/src/plugins/builtin/portfolio-list/metrics.ts +1 -1
- package/src/plugins/builtin/portfolio-list/mutations.ts +71 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +26 -14
- package/src/plugins/builtin/portfolio-list/summary/index.tsx +18 -9
- package/src/plugins/builtin/portfolio-list/summary/totals.ts +48 -7
- package/src/plugins/builtin/realized-vol/index.tsx +1 -1
- package/src/plugins/builtin/relative-rotation/client.ts +1 -1
- package/src/plugins/builtin/research/analyst-model.ts +1 -1
- package/src/plugins/builtin/research/event-model.ts +1 -1
- package/src/plugins/builtin/research/index.tsx +4 -0
- package/src/plugins/builtin/revenue-breakdown/index.tsx +1 -0
- package/src/plugins/builtin/risk-factors/index.tsx +1 -0
- package/src/plugins/builtin/risk-factors/pane.tsx +25 -10
- package/src/plugins/builtin/seasonality/index.tsx +1 -1
- package/src/plugins/builtin/sec/index.tsx +1 -0
- package/src/plugins/builtin/shared/pro-feature-wall.tsx +47 -0
- package/src/plugins/builtin/short-interest/client.ts +14 -106
- package/src/plugins/builtin/short-interest/headless.ts +2 -2
- package/src/plugins/builtin/short-interest/index.tsx +7 -6
- package/src/plugins/builtin/short-interest/pane.tsx +4 -4
- package/src/plugins/builtin/short-volume/index.tsx +6 -1
- package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
- package/src/plugins/builtin/ticker-detail/pane.tsx +2 -2
- package/src/plugins/builtin/time-sales/client.ts +3 -3
- package/src/plugins/builtin/time-sales/index.tsx +1 -1
- package/src/plugins/builtin/vol-surface/model.ts +1 -1
- package/src/plugins/builtin/volatility/model.ts +1 -1
- package/src/plugins/bundle.ts +2 -2
- package/src/plugins/catalog-manifest.ts +0 -1
- package/src/plugins/catalog-ui.ts +1 -1
- package/src/plugins/catalog.ts +0 -2
- package/src/plugins/host-link.ts +1 -1
- package/src/plugins/host-resolver.ts +1 -1
- package/src/plugins/loader.ts +6 -5
- package/src/plugins/registry/host-actions.ts +6 -1
- package/src/plugins/registry/index.ts +1 -0
- package/src/plugins/runtime/context.tsx +2 -0
- package/src/plugins/runtime/index.tsx +2 -0
- package/src/public/__snapshots__/public-api.test.ts.snap +0 -1
- package/src/public/market-data.ts +0 -7
- package/src/remote/controller-utils.ts +1 -1
- package/src/remote/controller.ts +27 -3
- package/src/remote/form.ts +20 -0
- package/src/remote/resources.ts +7 -0
- package/src/remote/schema.ts +25 -3
- package/src/remote/semantic-tree.tsx +15 -0
- package/src/remote/types.ts +2 -0
- package/src/renderers/browser/research-entry.ts +2 -2
- package/src/renderers/cloudflare/http-proxy.ts +157 -33
- package/src/renderers/cloudflare/proxy-session.ts +270 -0
- package/src/renderers/cloudflare/worker.ts +4 -1
- package/src/renderers/dom/desktop/controls.tsx +2 -1
- package/src/renderers/dom/dialog-host.tsx +17 -8
- package/src/renderers/dom/styles.css +4 -0
- package/src/renderers/electrobun/bun/application-menu/index.ts +5 -4
- package/src/renderers/electrobun/bun/desktop/backend.ts +7 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -2
- package/src/renderers/electrobun/bun/external-plugins.ts +1 -1
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +3 -6
- package/src/renderers/electrobun/view/cli-pane-shot-health.ts +3 -3
- package/src/renderers/opentui/dialog-host.tsx +14 -2
- package/src/renderers/opentui/start.tsx +2 -2
- package/src/renderers/opentui/terminal-media.ts +2 -2
- package/src/renderers/opentui/test-utils.tsx +9 -2
- package/src/renderers/opentui/toast-host.tsx +1 -1
- package/src/shares/portable-layout.ts +4 -6
- package/src/sources/gloomberb-cloud/index.ts +23 -24
- package/src/sources/gloomberb-cloud/news.ts +3 -3
- package/src/sources/history-retention.ts +6 -6
- package/src/sources/{yahoo-finance/symbols.ts → listing-symbols.ts} +16 -41
- package/src/sources/listing-target.ts +4 -4
- package/src/sources/provider-router/cache.ts +16 -6
- package/src/sources/provider-router/financials.ts +1 -1
- package/src/sources/provider-router/history.ts +3 -2
- package/src/state/app/bootstrap.ts +1 -1
- package/src/state/app/context/index.tsx +13 -0
- package/src/sync/core-contributors.ts +163 -16
- package/src/test-support/plugin-runtime.ts +1 -0
- package/src/tickers/instrument-kind.ts +1 -1
- package/src/tickers/open-target.ts +4 -4
- package/src/tickers/search/index.ts +3 -3
- package/src/tickers/search/ranking.ts +4 -4
- package/src/time-series/resolution.ts +1 -1
- package/src/time-series/resolve.ts +1 -1
- package/src/types/config.ts +19 -12
- package/src/types/financials.ts +5 -5
- package/src/types/instrument.ts +1 -1
- package/src/types/plugin.ts +10 -3
- package/src/types/price-history.ts +1 -1
- package/src/ui/dialog-bridge.tsx +50 -0
- package/src/ui/dialog-context.ts +24 -0
- package/src/ui/dialog-stack.ts +47 -1
- package/src/ui/dialog.tsx +2 -10
- package/src/ui/host.tsx +6 -1
- package/src/ui/index.tsx +7 -2
- package/src/utils/latest-financial-period.ts +1 -1
- package/src/utils/plugin-proxy-hosts.json +1 -5
- package/src/utils/sec.ts +1 -1
- package/src/app/pane-template-dialog-wizard.tsx +0 -67
- package/src/components/command-bar/multi-select-picker.tsx +0 -225
- package/src/components/command-bar/multi-select-runtime.ts +0 -91
- package/src/components/command-bar/workflow/body.tsx +0 -164
- package/src/components/command-bar/workflow/field-row.tsx +0 -231
- package/src/components/command-bar/workflow/route-actions.ts +0 -235
- package/src/components/command-bar/workflow/runtime.ts +0 -247
- package/src/plugins/builtin/yahoo/index.ts +0 -38
- package/src/sources/yahoo-finance/chart-period.ts +0 -138
- package/src/sources/yahoo-finance/financials.ts +0 -370
- package/src/sources/yahoo-finance/history.ts +0 -150
- package/src/sources/yahoo-finance/http.ts +0 -119
- package/src/sources/yahoo-finance/mappers.ts +0 -549
- package/src/sources/yahoo-finance/names.ts +0 -28
- package/src/sources/yahoo-finance/options.ts +0 -190
- package/src/sources/yahoo-finance/quote-summary.ts +0 -176
- package/src/sources/yahoo-finance/requests.ts +0 -245
- package/src/sources/yahoo-finance/snapshots.ts +0 -336
- package/src/sources/yahoo-finance/types.ts +0 -198
- package/src/sources/yahoo-finance/yahoo-chart-interval.ts +0 -18
- package/src/sources/yahoo-finance.ts +0 -339
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ The desktop app and TUI share the command language and plugin system. The [brows
|
|
|
38
38
|
On **macOS (Apple Silicon)**:
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
brew install --cask
|
|
41
|
+
brew install --cask gloomberb
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
On **Windows 11**, [download the installer](https://github.com/gloom-sh/gloomberb/releases/latest/download/stable-win-x64-GloomberbSetup.exe). It supports x64, and ARM64 through x64 emulation.
|
|
@@ -117,7 +117,7 @@ When the app hits an uncaught error, a render crash, or a plugin that fails to l
|
|
|
117
117
|
|
|
118
118
|
The app also counts how often you open each function, from the command bar, a menu or a link in another pane, and which functions are on screen when a workspace is restored at launch. It sends each function's mnemonic (such as `DES` or `GP`) with those two counts, the surface, the app version and the operating system, a minute after the first count, then every 15 minutes, and when you quit. Functions from plugins other than the official gloom-sh ones are sent as `plugin`, so their names never leave your machine. The server adds your plan (signed out, Free or Pro); the counts are never tied to your account.
|
|
119
119
|
|
|
120
|
-
Neither contains anything from your workspace: no tickers, arguments, portfolios, watchlists, layouts, settings or queries. Both carry a random install id stored in
|
|
120
|
+
Neither contains anything from your workspace: no tickers, arguments, portfolios, watchlists, layouts, settings or queries. Both carry a random install id stored in `install-id` in the data folder, `~/.gloomberb` by default (in the browser, in local storage).
|
|
121
121
|
|
|
122
122
|
The usage setting also covers command bar searches. When you are signed in, a search you finish in the command bar (you pause typing or run something, never each keystroke) is stored with your account to improve search: its text, the AI suggestions it got and the result you picked. Searches are deleted with your account.
|
|
123
123
|
|
package/README.zh-CN.md
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
在 **macOS(Apple Silicon)** 上:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
brew install --cask
|
|
43
|
+
brew install --cask gloomberb
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
在 **Windows 11** 上,[下载安装程序](https://github.com/gloom-sh/gloomberb/releases/latest/download/stable-win-x64-GloomberbSetup.exe)。支持 x64,也可通过 x64 仿真在 ARM64 上运行。
|
package/package.json
CHANGED
package/src/api-client/auth.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
AuthUser,
|
|
7
7
|
BuildoutAccountResponse,
|
|
8
8
|
BuildoutTokenResponse,
|
|
9
|
+
CalendarFeed,
|
|
9
10
|
CloudAccountPlan,
|
|
10
11
|
CloudBrowserHandoffResponse,
|
|
11
12
|
CloudPricing,
|
|
@@ -250,6 +251,33 @@ export class CloudAuthApi {
|
|
|
250
251
|
);
|
|
251
252
|
}
|
|
252
253
|
|
|
254
|
+
/** The private calendar feed link, or null until it is first created. */
|
|
255
|
+
async getCalendarFeed(): Promise<CalendarFeed | null> {
|
|
256
|
+
const result = await this.options.request<{ feed: CalendarFeed | null }>(
|
|
257
|
+
"/account/calendar-feed",
|
|
258
|
+
{ method: "GET" },
|
|
259
|
+
);
|
|
260
|
+
return result.feed;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** The calendar feed link, created on first use. */
|
|
264
|
+
async ensureCalendarFeed(): Promise<CalendarFeed> {
|
|
265
|
+
const result = await this.options.request<{ feed: CalendarFeed }>(
|
|
266
|
+
"/account/calendar-feed",
|
|
267
|
+
{ method: "POST", body: JSON.stringify({}) },
|
|
268
|
+
);
|
|
269
|
+
return result.feed;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/** A new calendar feed link; the old one stops working. */
|
|
273
|
+
async rotateCalendarFeed(): Promise<CalendarFeed> {
|
|
274
|
+
const result = await this.options.request<{ feed: CalendarFeed }>(
|
|
275
|
+
"/account/calendar-feed/rotate",
|
|
276
|
+
{ method: "POST", body: JSON.stringify({}) },
|
|
277
|
+
);
|
|
278
|
+
return result.feed;
|
|
279
|
+
}
|
|
280
|
+
|
|
253
281
|
async updateAccountProfile(
|
|
254
282
|
update: AccountProfileUpdate,
|
|
255
283
|
): Promise<AccountProfile> {
|
package/src/api-client/data.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { EarningsEvent } from "../types/data-provider";
|
|
2
|
+
import type { MarketDividendsPayload, MarketHeatmapResult, MarketHeatmapUniverseId, MarketMoversPayload } from "./market-discovery";
|
|
1
3
|
import type { DebtMaturitiesPayload } from "./debt-maturities";
|
|
2
4
|
import type { RevenueBreakdownPayload, RevenueBreakdownView } from "./revenue-breakdown";
|
|
3
5
|
import type { MnaDealPayload, MnaDealsParams, MnaDealsPayload } from "./mna";
|
|
@@ -39,11 +41,11 @@ import {
|
|
|
39
41
|
cloudJobsPath,
|
|
40
42
|
cloudJobsPostingsPath,
|
|
41
43
|
type CloudJobsPostingsParams,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
cloudProxyStatementPath,
|
|
45
|
+
cloudFilingEventsPath,
|
|
46
|
+
cloudRiskReportPath,
|
|
47
|
+
cloudRiskReportsPath,
|
|
48
|
+
cloudProxyStatementsPath,
|
|
47
49
|
cloudExchangeRatePath,
|
|
48
50
|
cloudSec13FPath,
|
|
49
51
|
cloudSecFilingContentPath,
|
|
@@ -213,6 +215,31 @@ export class CloudDataApi {
|
|
|
213
215
|
);
|
|
214
216
|
}
|
|
215
217
|
|
|
218
|
+
getMarketEarningsCalendar(symbols: string[]): Promise<CloudMarketResponse<Array<Omit<EarningsEvent, "earningsDate" | "earningsCallDate"> & { earningsDate: string; earningsCallDate?: string | null }>>> {
|
|
219
|
+
return this.request(`/market/earnings-calendar?${new URLSearchParams({ symbols: symbols.join(",") })}`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
getCloudArticleSummary(url: string): Promise<{ summary: string | null }> {
|
|
223
|
+
return this.request(`/news/article-summary?${new URLSearchParams({ url })}`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
getMarketMovers(category: "day_gainers" | "day_losers" | "most_actives", count = 25, refresh = false): Promise<CloudMarketResponse<MarketMoversPayload>> {
|
|
227
|
+
const params = new URLSearchParams({ category, count: String(count), mode: refresh ? "refresh" : "cache-first" });
|
|
228
|
+
return this.request(`/market/movers?${params}`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
getMarketTrending(count = 25): Promise<CloudMarketResponse<Array<{ symbol: string }>>> {
|
|
232
|
+
return this.request(`/market/trending?count=${encodeURIComponent(count)}`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
getMarketHeatmap(universe: MarketHeatmapUniverseId, count = 80): Promise<CloudMarketResponse<MarketHeatmapResult>> {
|
|
236
|
+
return this.request(`/market/heatmap?${new URLSearchParams({ universe, count: String(count) })}`);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
getMarketDividends(symbol: string, exchange = ""): Promise<CloudMarketResponse<MarketDividendsPayload>> {
|
|
240
|
+
return this.requestMarketSymbol("/market/dividends", symbol, exchange);
|
|
241
|
+
}
|
|
242
|
+
|
|
216
243
|
/** Gainers, losers and most active, or the pre-market, after-hours and gap lists with a `side`. */
|
|
217
244
|
async getCloudMarketScreener<Category extends CloudMarketScreenerCategory | CloudSessionMoversCategory>(
|
|
218
245
|
category: Category,
|
|
@@ -521,7 +548,7 @@ export class CloudDataApi {
|
|
|
521
548
|
ticker: string,
|
|
522
549
|
): Promise<CloudProxyStatementListPayload> {
|
|
523
550
|
return this.request<CloudProxyStatementListPayload>(
|
|
524
|
-
|
|
551
|
+
cloudProxyStatementsPath(ticker),
|
|
525
552
|
);
|
|
526
553
|
}
|
|
527
554
|
|
|
@@ -530,7 +557,7 @@ export class CloudDataApi {
|
|
|
530
557
|
year: number,
|
|
531
558
|
): Promise<CloudProxyStatementPayload> {
|
|
532
559
|
return this.request<CloudProxyStatementPayload>(
|
|
533
|
-
|
|
560
|
+
cloudProxyStatementPath(ticker, year),
|
|
534
561
|
);
|
|
535
562
|
}
|
|
536
563
|
|
|
@@ -539,13 +566,13 @@ export class CloudDataApi {
|
|
|
539
566
|
limit?: number,
|
|
540
567
|
): Promise<{ ticker: string; events: CloudFilingEventPayload[] }> {
|
|
541
568
|
return this.request<{ ticker: string; events: CloudFilingEventPayload[] }>(
|
|
542
|
-
|
|
569
|
+
cloudFilingEventsPath(ticker, limit),
|
|
543
570
|
);
|
|
544
571
|
}
|
|
545
572
|
|
|
546
573
|
async getRiskReports(ticker: string): Promise<CloudRiskReportListPayload> {
|
|
547
574
|
return this.request<CloudRiskReportListPayload>(
|
|
548
|
-
|
|
575
|
+
cloudRiskReportsPath(ticker),
|
|
549
576
|
);
|
|
550
577
|
}
|
|
551
578
|
|
|
@@ -554,7 +581,7 @@ export class CloudDataApi {
|
|
|
554
581
|
year: number,
|
|
555
582
|
): Promise<CloudRiskReportPayload> {
|
|
556
583
|
return this.request<CloudRiskReportPayload>(
|
|
557
|
-
|
|
584
|
+
cloudRiskReportPath(ticker, year),
|
|
558
585
|
);
|
|
559
586
|
}
|
|
560
587
|
|
package/src/api-client/index.ts
CHANGED
|
@@ -360,7 +360,7 @@ class GloomApiClient {
|
|
|
360
360
|
event: import("./research-activity").ResearchActivity; eventId: string;
|
|
361
361
|
surface: "web" | "desktop" | "tui" | "cli"; anonymousId?: string;
|
|
362
362
|
attribution?: Record<string, string>; feature?: import("./research-activity").ResearchFeature;
|
|
363
|
-
tab?: string;
|
|
363
|
+
tab?: string; desks?: readonly string[];
|
|
364
364
|
}): Promise<void> {
|
|
365
365
|
await this.request("/activity/research", { method: "POST", body: JSON.stringify(payload) });
|
|
366
366
|
}
|
|
@@ -405,6 +405,9 @@ class GloomApiClient {
|
|
|
405
405
|
getBuildoutAccount = this.auth.getBuildoutAccount.bind(this.auth);
|
|
406
406
|
getBuildoutToken = this.auth.getBuildoutToken.bind(this.auth);
|
|
407
407
|
updateAccountProfile = this.auth.updateAccountProfile.bind(this.auth);
|
|
408
|
+
getCalendarFeed = this.auth.getCalendarFeed.bind(this.auth);
|
|
409
|
+
ensureCalendarFeed = this.auth.ensureCalendarFeed.bind(this.auth);
|
|
410
|
+
rotateCalendarFeed = this.auth.rotateCalendarFeed.bind(this.auth);
|
|
408
411
|
|
|
409
412
|
async getSyncSnapshot(): Promise<CloudSyncSnapshotResponse> {
|
|
410
413
|
return this.request<CloudSyncSnapshotResponse>("/sync/snapshot", { method: "GET" });
|
|
@@ -674,6 +677,12 @@ class GloomApiClient {
|
|
|
674
677
|
getCloudQuote = this.data.getCloudQuote.bind(this.data);
|
|
675
678
|
getCloudQuotesBatch = this.data.getCloudQuotesBatch.bind(this.data);
|
|
676
679
|
getCloudWorldVenues = this.data.getCloudWorldVenues.bind(this.data);
|
|
680
|
+
getMarketEarningsCalendar = this.data.getMarketEarningsCalendar.bind(this.data);
|
|
681
|
+
getCloudArticleSummary = this.data.getCloudArticleSummary.bind(this.data);
|
|
682
|
+
getMarketMovers = this.data.getMarketMovers.bind(this.data);
|
|
683
|
+
getMarketTrending = this.data.getMarketTrending.bind(this.data);
|
|
684
|
+
getMarketHeatmap = this.data.getMarketHeatmap.bind(this.data);
|
|
685
|
+
getMarketDividends = this.data.getMarketDividends.bind(this.data);
|
|
677
686
|
getCloudMarketScreener = this.data.getCloudMarketScreener.bind(this.data);
|
|
678
687
|
getCloudOptionsChain = this.data.getCloudOptionsChain.bind(this.data);
|
|
679
688
|
getCloudFinancials = this.data.getCloudFinancials.bind(this.data);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { CloudCorporateActionsPayload, CloudQuotePayload } from "./types";
|
|
2
|
+
|
|
3
|
+
export interface ScreenerQuote {
|
|
4
|
+
symbol: string;
|
|
5
|
+
name: string;
|
|
6
|
+
price: number | null;
|
|
7
|
+
change: number | null;
|
|
8
|
+
changePercent: number | null;
|
|
9
|
+
volume: number | null;
|
|
10
|
+
avgVolume: number | null;
|
|
11
|
+
volumeRatio: number | null; // volume / avgVolume
|
|
12
|
+
marketCap: number | undefined;
|
|
13
|
+
currency: string;
|
|
14
|
+
fiftyTwoWeekHigh: number | undefined;
|
|
15
|
+
fiftyTwoWeekLow: number | undefined;
|
|
16
|
+
dayHigh: number | undefined;
|
|
17
|
+
dayLow: number | undefined;
|
|
18
|
+
exchange: string;
|
|
19
|
+
lastUpdated?: number;
|
|
20
|
+
/** Session-fixed, so the price column reads its decimals from it rather than from each tick. */
|
|
21
|
+
previousClose?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export type MarketHeatmapUniverseId = "us-equity" | "us-etf";
|
|
26
|
+
type MarketHeatmapSource = "gloom";
|
|
27
|
+
type MarketHeatmapSizeKind = "market-cap" | "net-assets";
|
|
28
|
+
export interface MarketHeatmapAsset {
|
|
29
|
+
symbol: string;
|
|
30
|
+
name: string;
|
|
31
|
+
price: number;
|
|
32
|
+
change: number;
|
|
33
|
+
changePercent: number;
|
|
34
|
+
/**
|
|
35
|
+
* Whether the source actually carried a session change. `changePercent` keeps
|
|
36
|
+
* a numeric 0 for the shared screener row shape, so tiles must read this
|
|
37
|
+
* before showing a flat session that was really missing data.
|
|
38
|
+
*/
|
|
39
|
+
hasChange: boolean;
|
|
40
|
+
size: number | null;
|
|
41
|
+
sizeKind: MarketHeatmapSizeKind;
|
|
42
|
+
volume: number | null;
|
|
43
|
+
currency: string;
|
|
44
|
+
exchange: string;
|
|
45
|
+
sector: string | null;
|
|
46
|
+
industry: string | null;
|
|
47
|
+
marketState: string | null;
|
|
48
|
+
source: MarketHeatmapSource;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface MarketHeatmapResult {
|
|
52
|
+
stale?: boolean;
|
|
53
|
+
universe: MarketHeatmapUniverseId;
|
|
54
|
+
source: MarketHeatmapSource;
|
|
55
|
+
fetchedAt: number;
|
|
56
|
+
assets: MarketHeatmapAsset[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
export interface MarketMoversPayload {
|
|
61
|
+
quotes: ScreenerQuote[];
|
|
62
|
+
source: "gloom";
|
|
63
|
+
stale: boolean;
|
|
64
|
+
asOf: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface DividendSummary {
|
|
68
|
+
trailingAnnualDividendRate: number | null;
|
|
69
|
+
trailingAnnualDividendYield: number | null;
|
|
70
|
+
forwardAnnualDividendRate: number | null;
|
|
71
|
+
payoutRatio: number | null;
|
|
72
|
+
exDividendDate: number | null;
|
|
73
|
+
dividendDate: number | null;
|
|
74
|
+
currency: string | null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface MarketDividendsPayload {
|
|
78
|
+
stale?: boolean;
|
|
79
|
+
actions: CloudCorporateActionsPayload | null;
|
|
80
|
+
quote: CloudQuotePayload | null;
|
|
81
|
+
summary: DividendSummary | null;
|
|
82
|
+
historyError?: string;
|
|
83
|
+
summaryError?: string;
|
|
84
|
+
}
|
package/src/api-client/paths.ts
CHANGED
|
@@ -311,30 +311,33 @@ export function cloudEarningsTranscriptPath(id: string): string {
|
|
|
311
311
|
return `/cloud/transcripts/${encodeURIComponent(id)}`;
|
|
312
312
|
}
|
|
313
313
|
|
|
314
|
-
/**
|
|
315
|
-
|
|
316
|
-
|
|
314
|
+
/**
|
|
315
|
+
* RISK, EXEC and EK are Pro: these reads need a verified Pro account. The same
|
|
316
|
+
* risk factors and pay are open under /public for the gloom.sh pages.
|
|
317
|
+
*/
|
|
318
|
+
export function cloudProxyStatementsPath(ticker: string): string {
|
|
319
|
+
return `/cloud/proxies/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}`;
|
|
317
320
|
}
|
|
318
321
|
|
|
319
|
-
export function
|
|
322
|
+
export function cloudFilingEventsPath(ticker: string, limit?: number): string {
|
|
320
323
|
const search = new URLSearchParams();
|
|
321
324
|
if (limit != null) search.set("limit", String(limit));
|
|
322
325
|
return appendQuery(
|
|
323
|
-
`/
|
|
326
|
+
`/cloud/events/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}`,
|
|
324
327
|
search,
|
|
325
328
|
);
|
|
326
329
|
}
|
|
327
330
|
|
|
328
|
-
export function
|
|
329
|
-
return `/
|
|
331
|
+
export function cloudRiskReportsPath(ticker: string): string {
|
|
332
|
+
return `/cloud/risks/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}`;
|
|
330
333
|
}
|
|
331
334
|
|
|
332
|
-
export function
|
|
333
|
-
return `/
|
|
335
|
+
export function cloudRiskReportPath(ticker: string, year: number): string {
|
|
336
|
+
return `/cloud/risks/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}/${year}`;
|
|
334
337
|
}
|
|
335
338
|
|
|
336
|
-
export function
|
|
337
|
-
return `/
|
|
339
|
+
export function cloudProxyStatementPath(ticker: string, year: number): string {
|
|
340
|
+
return `/cloud/proxies/${encodeURIComponent(normalizeIssuerResearchTicker(ticker))}/${year}`;
|
|
338
341
|
}
|
|
339
342
|
|
|
340
343
|
export function cloudSecFilingsPath(params: CloudSecFilingsParams): string {
|
|
@@ -17,6 +17,12 @@ import { SESSION_COOKIE_NAMES } from "./session-cookie";
|
|
|
17
17
|
|
|
18
18
|
const DEFAULT_API_URL = "https://api.gloom.sh";
|
|
19
19
|
const DEFAULT_MARKET_REQUEST_TIMEOUT_MS = 10_000;
|
|
20
|
+
const DEFAULT_RESEARCH_REQUEST_TIMEOUT_MS = 45_000;
|
|
21
|
+
// Research may fill missing sections after a primary read; quote/history reads remain latency bounded.
|
|
22
|
+
const RESEARCH_MARKET_PATHS = new Set([
|
|
23
|
+
"/market/dividends", "/market/short-interest", "/market/movers", "/market/trending",
|
|
24
|
+
"/market/heatmap", "/market/earnings-calendar",
|
|
25
|
+
]);
|
|
20
26
|
/** Local status for "this runtime cannot stream", never returned by the server. */
|
|
21
27
|
export const STREAMING_UNSUPPORTED_STATUS = 0;
|
|
22
28
|
|
|
@@ -140,6 +146,7 @@ export class CloudApiRequestTransport {
|
|
|
140
146
|
private cookieSessionMode = false;
|
|
141
147
|
private readonly fetchTransport: CloudApiFetchTransport | null;
|
|
142
148
|
private readonly marketRequestTimeoutMs: number;
|
|
149
|
+
private readonly researchRequestTimeoutMs: number;
|
|
143
150
|
private readonly connectionHealth: ConnectionHealthRegistry;
|
|
144
151
|
|
|
145
152
|
readonly baseUrl = getCloudApiBaseUrl();
|
|
@@ -154,6 +161,7 @@ export class CloudApiRequestTransport {
|
|
|
154
161
|
this.fetchTransport = options.fetchTransport ?? null;
|
|
155
162
|
this.marketRequestTimeoutMs =
|
|
156
163
|
options.marketRequestTimeoutMs ?? DEFAULT_MARKET_REQUEST_TIMEOUT_MS;
|
|
164
|
+
this.researchRequestTimeoutMs = options.marketRequestTimeoutMs ?? DEFAULT_RESEARCH_REQUEST_TIMEOUT_MS;
|
|
157
165
|
this.connectionHealth = options.connectionHealth ?? connectionHealth;
|
|
158
166
|
}
|
|
159
167
|
|
|
@@ -257,6 +265,8 @@ export class CloudApiRequestTransport {
|
|
|
257
265
|
return this.performRequest<T>(path, options, canApplySession);
|
|
258
266
|
}
|
|
259
267
|
|
|
268
|
+
const timeoutMs = RESEARCH_MARKET_PATHS.has(path.split("?")[0]!)
|
|
269
|
+
? this.researchRequestTimeoutMs : this.marketRequestTimeoutMs;
|
|
260
270
|
const controller = new AbortController();
|
|
261
271
|
const callerSignal = options?.signal;
|
|
262
272
|
const abortFromCaller = () => controller.abort(callerSignal?.reason);
|
|
@@ -273,8 +283,8 @@ export class CloudApiRequestTransport {
|
|
|
273
283
|
}, canApplySession);
|
|
274
284
|
return await withDeadline(
|
|
275
285
|
request,
|
|
276
|
-
|
|
277
|
-
`Cloud market request timed out after ${
|
|
286
|
+
timeoutMs,
|
|
287
|
+
`Cloud market request timed out after ${timeoutMs}ms: ${path}`,
|
|
278
288
|
(error) => controller.abort(error),
|
|
279
289
|
);
|
|
280
290
|
} finally {
|
|
@@ -318,12 +318,14 @@ function attributionPayload(): Record<string, string> | undefined {
|
|
|
318
318
|
/**
|
|
319
319
|
* Counts milestones once per feature/session/account, never their content.
|
|
320
320
|
* Native surfaces report anonymously only with an identifier the website
|
|
321
|
-
* handed over; they still never mint one of their own.
|
|
321
|
+
* handed over; they still never mint one of their own. `desks` rides on the
|
|
322
|
+
* end of the first-run funnel: the desks picked at "What do you trade?".
|
|
322
323
|
*/
|
|
323
324
|
export function recordResearchActivity(
|
|
324
325
|
event: ResearchActivity,
|
|
325
326
|
feature?: ResearchFeature,
|
|
326
327
|
tab?: string,
|
|
328
|
+
desks?: readonly string[],
|
|
327
329
|
): void {
|
|
328
330
|
const target = getCurrentPluginTarget();
|
|
329
331
|
const user = apiClient.getCurrentUser();
|
|
@@ -342,6 +344,7 @@ export function recordResearchActivity(
|
|
|
342
344
|
attribution: attributionPayload(),
|
|
343
345
|
feature,
|
|
344
346
|
tab,
|
|
347
|
+
desks,
|
|
345
348
|
})
|
|
346
349
|
.catch(() => {
|
|
347
350
|
sent.delete(key);
|
package/src/api-client/tape.ts
CHANGED
|
@@ -11,7 +11,7 @@ export interface TapeQuote {
|
|
|
11
11
|
timestamp: string;
|
|
12
12
|
bid: number | null;
|
|
13
13
|
ask: number | null;
|
|
14
|
-
/**
|
|
14
|
+
/** Quote sizes are round lots. */
|
|
15
15
|
bidSize: number;
|
|
16
16
|
askSize: number;
|
|
17
17
|
bidExchange: string;
|
|
@@ -20,7 +20,7 @@ export interface TapeQuote {
|
|
|
20
20
|
tape: string;
|
|
21
21
|
}
|
|
22
22
|
export interface TapeSnapshot {
|
|
23
|
-
source: "
|
|
23
|
+
source: "Gloom Cloud";
|
|
24
24
|
symbol: string;
|
|
25
25
|
exchange: string;
|
|
26
26
|
access: "realtime" | "delayed";
|
package/src/api-client/types.ts
CHANGED
|
@@ -193,6 +193,14 @@ export interface CloudPricing {
|
|
|
193
193
|
yearly: CloudPricingTier;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
/** The account's private calendar feed link (`/account/calendar-feed`). */
|
|
197
|
+
export interface CalendarFeed {
|
|
198
|
+
url: string;
|
|
199
|
+
createdAt: string;
|
|
200
|
+
/** The last time a calendar app read it, to the hour. */
|
|
201
|
+
lastFetchedAt: string | null;
|
|
202
|
+
}
|
|
203
|
+
|
|
196
204
|
/** One command-bar prefix described for `/assist/command`. */
|
|
197
205
|
export interface AssistCommandDescriptor {
|
|
198
206
|
prefix: string;
|
|
@@ -446,6 +454,7 @@ export interface CloudCdsHistoryResponse {
|
|
|
446
454
|
|
|
447
455
|
interface CloudShortInterestPointPayload {
|
|
448
456
|
settlementDate: string;
|
|
457
|
+
shortPercentFloat?: number | null;
|
|
449
458
|
sharesShort: number;
|
|
450
459
|
previousSharesShort: number | null;
|
|
451
460
|
averageDailyVolume: number | null;
|
|
@@ -455,6 +464,7 @@ interface CloudShortInterestPointPayload {
|
|
|
455
464
|
}
|
|
456
465
|
|
|
457
466
|
export interface CloudShortInterestPayload {
|
|
467
|
+
source?: "finra" | "gloom";
|
|
458
468
|
symbol: string;
|
|
459
469
|
issueName: string | null;
|
|
460
470
|
points: CloudShortInterestPointPayload[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useCallback, useContext, type ReactNode } from "react";
|
|
2
|
+
import { RemoteUiRegistryProvider, useRemoteUiRegistry } from "../remote/semantic-tree";
|
|
3
|
+
import { AppContext, getEffectiveThemeId, useAppSelector } from "../state/app/context";
|
|
4
|
+
import { ThemeProvider } from "../theme/theme-context";
|
|
5
|
+
import { useRegisterDialogBridge } from "../ui/dialog-bridge";
|
|
6
|
+
import { KeybindingsProvider, useKeybindings } from "./keybindings";
|
|
7
|
+
|
|
8
|
+
function DialogTheme({ children }: { children: ReactNode }) {
|
|
9
|
+
const themeId = useAppSelector(getEffectiveThemeId);
|
|
10
|
+
return <ThemeProvider themeId={themeId}>{children}</ThemeProvider>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Gives every dialog what the app gives its panes: the store, the theme, the
|
|
15
|
+
* keybindings and the remote registry, so a form in a dialog reads state and
|
|
16
|
+
* registers nodes like one in the app. Renders nothing.
|
|
17
|
+
*/
|
|
18
|
+
export function AppDialogBridge() {
|
|
19
|
+
const store = useContext(AppContext);
|
|
20
|
+
const registry = useRemoteUiRegistry();
|
|
21
|
+
const keybindings = useKeybindings();
|
|
22
|
+
const bridge = useCallback((content: ReactNode) => {
|
|
23
|
+
const withKeybindings = <KeybindingsProvider value={keybindings}>{content}</KeybindingsProvider>;
|
|
24
|
+
const withRegistry = registry
|
|
25
|
+
? <RemoteUiRegistryProvider registry={registry}>{withKeybindings}</RemoteUiRegistryProvider>
|
|
26
|
+
: withKeybindings;
|
|
27
|
+
return store
|
|
28
|
+
? <AppContext value={store}><DialogTheme>{withRegistry}</DialogTheme></AppContext>
|
|
29
|
+
: withRegistry;
|
|
30
|
+
}, [keybindings, registry, store]);
|
|
31
|
+
useRegisterDialogBridge(bridge);
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
bringToFront,
|
|
7
7
|
findDockLeaf,
|
|
8
8
|
getDockedPaneIds,
|
|
9
|
+
isPaneDetached,
|
|
9
10
|
isPaneInLayout,
|
|
10
11
|
} from "../../layout/pane-manager";
|
|
11
12
|
import type { PluginRegistry } from "../../plugins/registry";
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
type AppState,
|
|
19
20
|
} from "../../state/app/context";
|
|
20
21
|
import { scheduleConfigSave } from "../../state/config-save-scheduler";
|
|
22
|
+
import { pinFollowingPane } from "../../layout/pane-follow";
|
|
21
23
|
import {
|
|
22
24
|
createPaneInstance,
|
|
23
25
|
isTickerPaneId,
|
|
@@ -51,6 +53,8 @@ interface AppPaneRuntimeArgs {
|
|
|
51
53
|
dialog: DialogApi;
|
|
52
54
|
dispatch: Dispatch<AppAction>;
|
|
53
55
|
externalPlugins: readonly LoadedExternalPlugin[];
|
|
56
|
+
/** Desktop main window: raises a detached pane's own window. */
|
|
57
|
+
focusDetachedPane?: (paneId: string) => void;
|
|
54
58
|
isDetachedWindow: boolean;
|
|
55
59
|
notify: (body: string, options?: { type?: "info" | "success" | "error" }) => void;
|
|
56
60
|
persistConfig: (nextConfig: AppState["config"]) => void;
|
|
@@ -66,6 +70,7 @@ export function useAppPaneRuntime({
|
|
|
66
70
|
dialog,
|
|
67
71
|
dispatch,
|
|
68
72
|
externalPlugins,
|
|
73
|
+
focusDetachedPane,
|
|
69
74
|
isDetachedWindow,
|
|
70
75
|
notify,
|
|
71
76
|
persistConfig,
|
|
@@ -82,6 +87,7 @@ export function useAppPaneRuntime({
|
|
|
82
87
|
const currentState = stateRef.current;
|
|
83
88
|
const normalizedLayout = normalizePaneLayout(layout, {
|
|
84
89
|
resolveOrphanSymbol: (instanceId) => resolveTickerForPane(currentState, instanceId),
|
|
90
|
+
pinOrphan: pinFollowingPane,
|
|
85
91
|
});
|
|
86
92
|
if (options?.pushHistory !== false) {
|
|
87
93
|
dispatch({ type: "PUSH_LAYOUT_HISTORY" });
|
|
@@ -157,7 +163,9 @@ export function useAppPaneRuntime({
|
|
|
157
163
|
persistLayout(nextLayout, { pushHistory: false });
|
|
158
164
|
}
|
|
159
165
|
activatePane(paneId);
|
|
160
|
-
|
|
166
|
+
// Focus in this window's state alone would leave the pane's window behind this one.
|
|
167
|
+
if (isPaneDetached(nextLayout, paneId)) focusDetachedPane?.(paneId);
|
|
168
|
+
}, [activatePane, focusDetachedPane, persistLayout, state.config.layout]);
|
|
161
169
|
|
|
162
170
|
const placePaneInstance = useCallback((
|
|
163
171
|
instance: PaneInstanceConfig,
|
|
@@ -238,7 +246,6 @@ export function useAppPaneRuntime({
|
|
|
238
246
|
const { createPaneFromTemplate } = useAppPaneTemplateRuntime({
|
|
239
247
|
buildPaneInstance,
|
|
240
248
|
dataProvider,
|
|
241
|
-
dialog,
|
|
242
249
|
dispatch,
|
|
243
250
|
notify,
|
|
244
251
|
placePaneInstance,
|
|
@@ -32,7 +32,7 @@ export function useAppPaneSettingsRuntime({
|
|
|
32
32
|
stateRef,
|
|
33
33
|
tickerRepository,
|
|
34
34
|
}: UseAppPaneSettingsRuntimeOptions) {
|
|
35
|
-
const openPaneSettings = useCallback(async (paneId?: string) => {
|
|
35
|
+
const openPaneSettings = useCallback(async (paneId?: string, options?: { fieldKey?: string }) => {
|
|
36
36
|
const targetPaneId = paneId
|
|
37
37
|
? resolvePaneTarget(paneId)
|
|
38
38
|
: stateRef.current.focusedPaneId;
|
|
@@ -59,6 +59,7 @@ export function useAppPaneSettingsRuntime({
|
|
|
59
59
|
paneId={targetPaneId}
|
|
60
60
|
pluginRegistry={pluginRegistry}
|
|
61
61
|
applyFieldValue={applyFieldValue}
|
|
62
|
+
initialFieldKey={options?.fieldKey}
|
|
62
63
|
/>
|
|
63
64
|
),
|
|
64
65
|
});
|