@gloom-sh/terminal 0.19.2 → 0.19.3
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 +7 -1
- package/package.json +1 -1
- package/patches/electrobun@1.18.1.patch +108 -1
- package/src/account/upgrade-dialog.tsx +4 -23
- package/src/api-client/coalesce.ts +118 -0
- package/src/api-client/credit-boards.ts +13 -0
- package/src/api-client/crypto-etf-flows.ts +6 -0
- package/src/api-client/crypto-markets.ts +40 -0
- package/src/api-client/data.ts +201 -14
- package/src/api-client/equity-screener.ts +10 -0
- package/src/api-client/errors.ts +20 -0
- package/src/api-client/gpu.ts +29 -0
- package/src/api-client/index.ts +5 -2
- package/src/api-client/plan-access.ts +10 -1
- package/src/api-client/plan-rules.ts +35 -0
- package/src/api-client/research-activity.ts +1 -32
- package/src/api-client/types.ts +21 -1
- package/src/app/attention-notice.tsx +94 -0
- package/src/app.tsx +23 -1
- package/src/architecture/core-builtin-allowlist.json +2 -1
- package/src/capabilities/factories.ts +1 -0
- package/src/cli/ascii-output.ts +42 -0
- package/src/cli/base-converter.ts +10 -2
- package/src/cli/command-options.ts +16 -1
- package/src/cli/commands/crypto-hints.ts +23 -4
- package/src/cli/commands/market.ts +92 -23
- package/src/cli/commands/news-search.ts +24 -5
- package/src/cli/commands/overview.ts +9 -4
- package/src/cli/commands/search.ts +71 -12
- package/src/cli/commands/system.ts +22 -30
- package/src/cli/commands/ticker.ts +49 -9
- package/src/cli/commands/version.ts +33 -0
- package/src/cli/context.ts +5 -9
- package/src/cli/data-dir.ts +7 -0
- package/src/cli/desktop-pane-shot-api-policy.ts +85 -0
- package/src/cli/desktop-pane-shot-browser.ts +320 -0
- package/src/cli/desktop-pane-shot-routes.ts +26 -1
- package/src/cli/desktop-pane-shot.ts +196 -256
- package/src/cli/early-command.ts +42 -0
- package/src/cli/earnings-calendar.ts +9 -0
- package/src/cli/entry.ts +19 -13
- package/src/cli/errors.ts +12 -2
- package/src/cli/help.ts +1 -1
- package/src/cli/history-export.ts +22 -2
- package/src/cli/history-rows.ts +154 -4
- package/src/cli/index.ts +18 -1
- package/src/cli/known-gaps.ts +40 -5
- package/src/cli/listing-arg.ts +46 -9
- package/src/cli/options.ts +1 -1
- package/src/cli/output-file.ts +60 -13
- package/src/cli/pane-functions/catalog.ts +14 -3
- package/src/cli/pane-functions/data.ts +1 -1
- package/src/cli/pane-functions/dom.ts +45 -0
- package/src/cli/pane-functions/freshness.ts +46 -9
- package/src/cli/pane-functions/function-help.ts +17 -9
- package/src/cli/pane-functions/headless.ts +22 -14
- package/src/cli/pane-functions/index.ts +6 -2
- package/src/cli/pane-functions/options.ts +6 -2
- package/src/cli/pane-functions/resolver.ts +27 -5
- package/src/cli/pane-functions/screenshot-assessment.ts +33 -0
- package/src/cli/pane-functions/screenshot-bridge.ts +94 -13
- package/src/cli/pane-functions/screenshot-http.ts +70 -0
- package/src/cli/pane-functions/screenshot-render.ts +19 -5
- package/src/cli/quote-answer.ts +20 -0
- package/src/cli/registry.ts +41 -13
- package/src/cli/result.ts +12 -6
- package/src/cli/ticker-resolution.ts +2 -1
- package/src/cli/types.ts +2 -0
- package/src/components/chart/composite/format.ts +3 -0
- package/src/components/chart-table/header.tsx +1 -1
- package/src/components/chart-table/layout.ts +28 -11
- package/src/components/command-bar/action-runtime.ts +4 -0
- package/src/components/command-bar/commands/direct/index.ts +18 -33
- package/src/components/command-bar/commands/direct/runtime.ts +5 -0
- package/src/components/command-bar/commands/registry.ts +10 -1
- package/src/components/command-bar/routes/root/command-items.ts +9 -4
- package/src/components/command-bar/routes/root/runtime.ts +24 -1
- package/src/components/command-bar/surface/index.tsx +9 -3
- package/src/components/company-logo.tsx +2 -1
- package/src/components/layout/header.tsx +8 -3
- package/src/components/layout/market-summary.ts +25 -7
- package/src/components/layout/pane/footer/index.tsx +7 -2
- package/src/components/layout/pane/footer/model.ts +40 -5
- package/src/components/market-board/index.tsx +3 -2
- package/src/components/onboarding/desks-step.tsx +12 -4
- package/src/components/onboarding/first-run-workspace.ts +81 -4
- package/src/components/onboarding/onboarding-frame.tsx +2 -1
- package/src/components/onboarding/onboarding-keyboard.ts +8 -5
- package/src/components/onboarding/onboarding-wizard.tsx +54 -23
- package/src/components/onboarding/portfolio-step/positions-panel.tsx +7 -2
- package/src/components/onboarding/run-setup-again.ts +24 -0
- package/src/components/onboarding/use-onboarding-progress.ts +33 -15
- package/src/components/onboarding/use-onboarding-upgrade.ts +2 -6
- package/src/components/onboarding/wizard-model.ts +57 -3
- package/src/components/onboarding/wizard-positions.ts +1 -1
- package/src/components/ui/delayed-mark.tsx +56 -0
- package/src/components/ui/external-link.tsx +3 -6
- package/src/components/ui/icon.tsx +8 -1
- package/src/components/ui/logo-mark.tsx +8 -5
- package/src/components/ui/stat-grid.tsx +263 -19
- package/src/data/config/store/node.ts +11 -5
- package/src/data/config/store/normalize.ts +16 -3
- package/src/data/profile-permissions.ts +47 -0
- package/src/data/resource-store.ts +34 -31
- package/src/data/sqlite/access.ts +19 -8
- package/src/data/sqlite/checkpointer.ts +95 -8
- package/src/data/sqlite/database.ts +40 -7
- package/src/docs/snapshot.json +191 -78
- package/src/i18n/es.ts +18 -2
- package/src/i18n/ja.ts +18 -2
- package/src/i18n/ko.ts +18 -2
- package/src/i18n/zh-cn.ts +18 -2
- package/src/i18n/zh-tw.ts +18 -2
- package/src/layout/desk-keys.ts +4 -1
- package/src/layout/desks.ts +38 -5
- package/src/layout-marketplace/gallery-desktop.tsx +45 -16
- package/src/market-data/batched-reads.ts +16 -0
- package/src/market-data/coordinator/auxiliary.ts +4 -2
- package/src/market-data/coordinator/index.ts +11 -2
- package/src/market-data/futures-board.ts +1 -1
- package/src/market-data/futures-contract.ts +3 -1
- package/src/market-data/market/index-level.ts +6 -4
- package/src/market-data/published-apac-sessions.ts +6 -0
- package/src/news/aggregator.ts +7 -4
- package/src/news/news-model.ts +11 -0
- package/src/news/story-id.ts +22 -0
- package/src/news/ticker-symbols.ts +17 -1
- package/src/notifications/app-notifier.ts +35 -14
- package/src/plugins/builtin/account-management/form-components.tsx +1 -1
- package/src/plugins/builtin/account-management/index.tsx +2 -3
- package/src/plugins/builtin/account-management/model.ts +1 -1
- package/src/plugins/builtin/alerts/cli-forms.ts +15 -1
- package/src/plugins/builtin/alerts/events-pane.tsx +7 -5
- package/src/plugins/builtin/alerts/events.ts +10 -2
- package/src/plugins/builtin/alerts/index.tsx +5 -5
- package/src/plugins/builtin/alerts/research-builder.ts +5 -1
- package/src/plugins/builtin/alerts/research-rules.ts +18 -0
- package/src/plugins/builtin/alerts/targets.ts +4 -1
- package/src/plugins/builtin/attention/headless.ts +1 -1
- package/src/plugins/builtin/attention/index.tsx +2 -4
- package/src/plugins/builtin/attention/listing.ts +1 -1
- package/src/plugins/builtin/attention/series.ts +1 -1
- package/src/plugins/builtin/awards/index.tsx +1 -2
- package/src/plugins/builtin/backtest/client.ts +1 -0
- package/src/plugins/builtin/backtest/index.tsx +1 -2
- package/src/plugins/builtin/backtest/rules.ts +3 -1
- package/src/plugins/builtin/backtest/window.ts +8 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +16 -3
- package/src/plugins/builtin/broker-manager/index.tsx +1 -1
- package/src/plugins/builtin/buildout/cells.tsx +5 -0
- package/src/plugins/builtin/buildout/company/flow.tsx +367 -0
- package/src/plugins/builtin/buildout/company/id.ts +2 -0
- package/src/plugins/builtin/buildout/company/model.ts +247 -0
- package/src/plugins/builtin/buildout/company/pane.tsx +317 -0
- package/src/plugins/builtin/buildout/data-runtime.ts +31 -10
- package/src/plugins/builtin/buildout/facilities.ts +309 -0
- package/src/plugins/builtin/buildout/format.ts +9 -0
- package/src/plugins/builtin/buildout/index.tsx +51 -5
- package/src/plugins/builtin/buildout/model/index.ts +62 -10
- package/src/plugins/builtin/buildout/model/normalizers.ts +5 -0
- package/src/plugins/builtin/buildout/model/types.ts +11 -2
- package/src/plugins/builtin/buildout/pane/index.tsx +91 -20
- package/src/plugins/builtin/buildout/pane/status.tsx +1 -1
- package/src/plugins/builtin/buildout/pane/themes.tsx +110 -0
- package/src/plugins/builtin/buildout/table-model.ts +26 -2
- package/src/plugins/builtin/builtin-plugin-meta.ts +16 -0
- package/src/plugins/builtin/cds/headless.ts +10 -2
- package/src/plugins/builtin/cds/model.ts +7 -3
- package/src/plugins/builtin/central-bank-rates/index.tsx +1 -2
- package/src/plugins/builtin/central-bank-rates/pane.tsx +2 -1
- package/src/plugins/builtin/changelog/index.tsx +3 -2
- package/src/plugins/builtin/chart-composer/headless-schema.ts +7 -2
- package/src/plugins/builtin/chart-composer/headless.ts +88 -21
- package/src/plugins/builtin/chart-composer/index.tsx +2 -3
- package/src/plugins/builtin/chart-composer/pane.tsx +26 -2
- package/src/plugins/builtin/chart-composer/series-expression.ts +3 -2
- package/src/plugins/builtin/chart-composer/studies.ts +1 -1
- package/src/plugins/builtin/chat/controller/index.ts +1 -1
- package/src/plugins/builtin/chat/controller/messages.ts +15 -4
- package/src/plugins/builtin/chat/ghost-user.ts +8 -0
- package/src/plugins/builtin/chat/index.tsx +5 -5
- package/src/plugins/builtin/clinical-trials/index.tsx +1 -2
- package/src/plugins/builtin/cloud/company-picker.tsx +1 -1
- package/src/plugins/builtin/cloud/index.tsx +1 -2
- package/src/plugins/builtin/cloud/plugin.tsx +6 -4
- package/src/plugins/builtin/cloud/team/module.tsx +1 -1
- package/src/plugins/builtin/cloud/thesis/module.tsx +1 -1
- package/src/plugins/builtin/cloud/trial-offer-status-widget.tsx +24 -1
- package/src/plugins/builtin/cloud/upgrade-status-widget.tsx +39 -15
- package/src/plugins/builtin/comment-letters/index.tsx +1 -2
- package/src/plugins/builtin/commodity-balances/index.tsx +3 -3
- package/src/plugins/builtin/commodity-balances/pane.tsx +2 -2
- package/src/plugins/builtin/congress-trades/aggregates.ts +13 -2
- package/src/plugins/builtin/congress-trades/detail.tsx +20 -4
- package/src/plugins/builtin/congress-trades/headless.ts +2 -0
- package/src/plugins/builtin/congress-trades/model.ts +92 -64
- package/src/plugins/builtin/congress-trades/table.tsx +14 -2
- package/src/plugins/builtin/connections/index.ts +2 -3
- package/src/plugins/builtin/cot/index.tsx +1 -2
- package/src/plugins/builtin/cpi/index.tsx +1 -2
- package/src/plugins/builtin/credit-boards/cdx-pane.tsx +2 -1
- package/src/plugins/builtin/credit-boards/client.ts +7 -2
- package/src/plugins/builtin/credit-boards/headless.ts +25 -12
- package/src/plugins/builtin/credit-boards/model.ts +29 -0
- package/src/plugins/builtin/credit-boards/sovr-pane.tsx +9 -4
- package/src/plugins/builtin/crypto-board/bitcoin-network.ts +143 -0
- package/src/plugins/builtin/crypto-board/headless.ts +4 -3
- package/src/plugins/builtin/crypto-board/index.tsx +4 -2
- package/src/plugins/builtin/crypto-board/series.ts +2 -0
- package/src/plugins/builtin/crypto-etf-flows/client.ts +9 -2
- package/src/plugins/builtin/crypto-etf-flows/headless.ts +61 -6
- package/src/plugins/builtin/crypto-etf-flows/index.tsx +1 -2
- package/src/plugins/builtin/crypto-etf-flows/model.ts +14 -1
- package/src/plugins/builtin/crypto-etf-flows/pane.tsx +8 -5
- package/src/plugins/builtin/debt-maturities/headless.ts +4 -3
- package/src/plugins/builtin/debt-maturities/model.ts +17 -1
- package/src/plugins/builtin/debt-maturities/pane.tsx +18 -4
- package/src/plugins/builtin/debug/index.tsx +1 -1
- package/src/plugins/builtin/dividend-yield/client.ts +32 -2
- package/src/plugins/builtin/dividend-yield/headless.ts +58 -33
- package/src/plugins/builtin/dividend-yield/index.tsx +37 -2
- package/src/plugins/builtin/dividend-yield/pane.tsx +32 -13
- package/src/plugins/builtin/dividend-yield/ranking-reads.ts +73 -0
- package/src/plugins/builtin/dividend-yield/ranking-view.tsx +163 -0
- package/src/plugins/builtin/dividend-yield/ranking.ts +1 -1
- package/src/plugins/builtin/dividend-yield/view.ts +21 -0
- package/src/plugins/builtin/docs/index.tsx +2 -3
- package/src/plugins/builtin/doe/headless.ts +16 -3
- package/src/plugins/builtin/doe/index.tsx +5 -4
- package/src/plugins/builtin/earnings/board.tsx +2 -1
- package/src/plugins/builtin/earnings/history.tsx +2 -1
- package/src/plugins/builtin/earnings-ripple/client.ts +32 -7
- package/src/plugins/builtin/earnings-ripple/index.tsx +1 -2
- package/src/plugins/builtin/econ/calendar-model.ts +29 -6
- package/src/plugins/builtin/econ-statistics/index.tsx +1 -2
- package/src/plugins/builtin/equity-screener/client.ts +1 -1
- package/src/plugins/builtin/equity-screener/headless.ts +1 -0
- package/src/plugins/builtin/equity-screener/ideas.ts +30 -1
- package/src/plugins/builtin/equity-screener/index.tsx +1 -2
- package/src/plugins/builtin/equity-screener/model.ts +28 -4
- package/src/plugins/builtin/equity-screener/pane.tsx +5 -0
- package/src/plugins/builtin/equity-screener/screen-check.ts +23 -1
- package/src/plugins/builtin/estimate-revisions/index.tsx +1 -2
- package/src/plugins/builtin/exposure/holdings.ts +35 -13
- package/src/plugins/builtin/exposure/index.tsx +1 -2
- package/src/plugins/builtin/fear-greed/cli.ts +44 -0
- package/src/plugins/builtin/fear-greed/index.tsx +5 -53
- package/src/plugins/builtin/fear-greed/pane.tsx +2 -1
- package/src/plugins/builtin/fixed-income/index.tsx +1 -2
- package/src/plugins/builtin/futures/board-reads.ts +25 -0
- package/src/plugins/builtin/futures/coalesced-bump.ts +44 -0
- package/src/plugins/builtin/futures/index.tsx +15 -0
- package/src/plugins/builtin/futures/model.ts +14 -0
- package/src/plugins/builtin/futures/use-board-terms.ts +22 -15
- package/src/plugins/builtin/futures/use-front-returns.ts +20 -14
- package/src/plugins/builtin/futures-curve/headless.ts +6 -1
- package/src/plugins/builtin/futures-curve/index.tsx +1 -2
- package/src/plugins/builtin/fx-matrix/index.tsx +2 -2
- package/src/plugins/builtin/gpu/board.tsx +51 -12
- package/src/plugins/builtin/gpu/client.ts +15 -2
- package/src/plugins/builtin/gpu/equities.tsx +5 -2
- package/src/plugins/builtin/gpu/headless.ts +14 -2
- package/src/plugins/builtin/gpu/index.tsx +1 -2
- package/src/plugins/builtin/gpu/model.ts +20 -2
- package/src/plugins/builtin/gpu/pane.tsx +1 -1
- package/src/plugins/builtin/help/index.tsx +1 -1
- package/src/plugins/builtin/holders/index-holders.ts +24 -12
- package/src/plugins/builtin/holders/index.tsx +2 -3
- package/src/plugins/builtin/ipo-calendar/index.tsx +1 -2
- package/src/plugins/builtin/iv-history/index.tsx +1 -2
- package/src/plugins/builtin/jodi/index.tsx +1 -2
- package/src/plugins/builtin/kelly-sizer/index.tsx +1 -2
- package/src/plugins/builtin/layout-manager/index.tsx +9 -8
- package/src/plugins/builtin/macro-day/pane.tsx +4 -2
- package/src/plugins/builtin/market-halts/index.tsx +1 -2
- package/src/plugins/builtin/market-heatmap/index.tsx +11 -2
- package/src/plugins/builtin/market-movers/index.tsx +7 -1
- package/src/plugins/builtin/market-movers/session-body.tsx +4 -1
- package/src/plugins/builtin/market-valuation/index.tsx +1 -2
- package/src/plugins/builtin/members/index.tsx +1 -2
- package/src/plugins/builtin/money-markets/index.tsx +1 -2
- package/src/plugins/builtin/money-markets/pane.tsx +2 -1
- package/src/plugins/builtin/news/headless.ts +7 -0
- package/src/plugins/builtin/news/wire/index.tsx +1 -1
- package/src/plugins/builtin/news/wire/news/pop-out.tsx +9 -3
- package/src/plugins/builtin/notes/index.tsx +3 -6
- package/src/plugins/builtin/openfda/index.tsx +1 -2
- package/src/plugins/builtin/options/view.tsx +6 -5
- package/src/plugins/builtin/options-calculator/index.tsx +1 -2
- package/src/plugins/builtin/options-positioning/index.tsx +1 -2
- package/src/plugins/builtin/options-scenario/index.tsx +2 -4
- package/src/plugins/builtin/perps/index.tsx +1 -2
- package/src/plugins/builtin/plugin-marketplace/index.tsx +2 -3
- package/src/plugins/builtin/plugin-marketplace/pane.tsx +2 -1
- package/src/plugins/builtin/plugin-module.ts +16 -2
- package/src/plugins/builtin/portfolio-list/cli/render.ts +53 -3
- package/src/plugins/builtin/portfolio-list/index.tsx +1 -2
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +11 -0
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +2 -2
- package/src/plugins/builtin/power/index.tsx +1 -2
- package/src/plugins/builtin/rate-path/index.tsx +1 -2
- package/src/plugins/builtin/realized-vol/headless.ts +2 -0
- package/src/plugins/builtin/realized-vol/index.tsx +1 -2
- package/src/plugins/builtin/realized-vol/model.ts +16 -2
- package/src/plugins/builtin/realized-vol/pane.tsx +3 -3
- package/src/plugins/builtin/relative-rotation/index.tsx +1 -2
- package/src/plugins/builtin/research/analyst-headless.ts +33 -6
- package/src/plugins/builtin/research/analyst-model.ts +37 -2
- package/src/plugins/builtin/research/analyst-pane.tsx +25 -5
- package/src/plugins/builtin/research/index.tsx +5 -8
- package/src/plugins/builtin/research-search/index.tsx +1 -2
- package/src/plugins/builtin/revenue-breakdown/headless.ts +22 -8
- package/src/plugins/builtin/revenue-breakdown/model.ts +23 -0
- package/src/plugins/builtin/reverse-dcf/pane.tsx +4 -2
- package/src/plugins/builtin/roadmap/index.tsx +2 -3
- package/src/plugins/builtin/roadmap/pane.tsx +49 -2
- package/src/plugins/builtin/scanner/hilo-model.ts +18 -1
- package/src/plugins/builtin/scanner/hilo-pane.tsx +12 -2
- package/src/plugins/builtin/scanner/live-pane.tsx +7 -4
- package/src/plugins/builtin/sec/filing-content.ts +38 -6
- package/src/plugins/builtin/sec/headless.ts +5 -1
- package/src/plugins/builtin/sec/index.tsx +4 -2
- package/src/plugins/builtin/sec/model.ts +2 -0
- package/src/plugins/builtin/sectors/index.tsx +11 -5
- package/src/plugins/builtin/series-inventory.ts +2 -0
- package/src/plugins/builtin/shared/cloud-resource.ts +60 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +24 -1
- package/src/plugins/builtin/shared/forming-bars.ts +29 -0
- package/src/plugins/builtin/shared/fx-rate-freshness.ts +17 -0
- package/src/plugins/builtin/shared/series-detail-chart.tsx +4 -2
- package/src/plugins/builtin/shared/use-quote-board.ts +5 -0
- package/src/plugins/builtin/short-interest/publications-pane.tsx +2 -1
- package/src/plugins/builtin/short-volume/pane.tsx +2 -1
- package/src/plugins/builtin/social-mentions/index.tsx +1 -2
- package/src/plugins/builtin/social-mentions/pane.tsx +2 -1
- package/src/plugins/builtin/supply-chain/client.ts +22 -1
- package/src/plugins/builtin/supply-chain/graph-client.ts +22 -1
- package/src/plugins/builtin/supply-chain/index.tsx +1 -2
- package/src/plugins/builtin/thirteenf/api.ts +116 -13
- package/src/plugins/builtin/thirteenf/data.ts +132 -30
- package/src/plugins/builtin/thirteenf/index.tsx +2 -4
- package/src/plugins/builtin/thirteenf/model.ts +2 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +20 -11
- package/src/plugins/builtin/thirteenf/types.ts +12 -0
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +17 -4
- package/src/plugins/builtin/ticker-detail/data-panes/returns-history.ts +81 -11
- package/src/plugins/builtin/ticker-detail/headless.ts +11 -3
- package/src/plugins/builtin/ticker-detail/index.tsx +5 -10
- package/src/plugins/builtin/ticker-detail/overview-tab.tsx +16 -6
- package/src/plugins/builtin/time-sales/index.tsx +1 -2
- package/src/plugins/builtin/time-sales/pane.tsx +3 -1
- package/src/plugins/builtin/trace-bonds/headless.ts +11 -2
- package/src/plugins/builtin/trace-bonds/model.ts +44 -10
- package/src/plugins/builtin/trace-bonds/pane.tsx +12 -7
- package/src/plugins/builtin/treasury-auctions/pane.tsx +2 -2
- package/src/plugins/builtin/vol-surface/client.ts +18 -3
- package/src/plugins/builtin/vol-surface/index.tsx +1 -2
- package/src/plugins/builtin/volatility/index.tsx +1 -2
- package/src/plugins/builtin/world-indices/footer.ts +6 -1
- package/src/plugins/builtin/world-venue-map/client.ts +10 -1
- package/src/plugins/builtin/world-venue-map/index.ts +6 -2
- package/src/plugins/builtin/world-venue-map/layered-pane.tsx +48 -7
- package/src/plugins/builtin/world-venue-map/layers.ts +17 -0
- package/src/plugins/builtin/world-venue-map/local-layers.ts +141 -0
- package/src/plugins/builtin/world-venue-map/map-symbols.ts +18 -0
- package/src/plugins/builtin/world-venue-map/map.tsx +4 -2
- package/src/plugins/builtin/world-venue-map/scope.ts +63 -0
- package/src/plugins/builtin/yield-curve/curves.ts +16 -2
- package/src/plugins/builtin/yield-curve/headless.ts +3 -3
- package/src/plugins/bundle.ts +52 -2
- package/src/plugins/catalog-browser.ts +2 -2
- package/src/plugins/catalog-cli.ts +20 -0
- package/src/plugins/host-link.ts +13 -1
- package/src/plugins/installer.ts +15 -4
- package/src/plugins/loader.ts +43 -11
- package/src/plugins/peer-imports.ts +201 -0
- package/src/plugins/peer-retry.ts +26 -29
- package/src/plugins/plugin-process.ts +128 -0
- package/src/plugins/redirection-guard.ts +45 -0
- package/src/remote/endpoint.ts +16 -3
- package/src/renderers/browser/main.tsx +3 -2
- package/src/renderers/cloudflare/http-proxy.ts +7 -123
- package/src/renderers/dom/desktop/icons.tsx +2 -0
- package/src/renderers/dom/host/image-surface.tsx +46 -21
- package/src/renderers/dom/styles.css +7 -0
- package/src/renderers/dom/toast-host.tsx +2 -0
- package/src/renderers/electrobun/bun/desktop/backend.ts +7 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +3 -2
- package/src/renderers/electrobun/bun/desktop/rpc-timing.ts +88 -0
- package/src/renderers/electrobun/bun/desktop/update.ts +20 -4
- package/src/renderers/electrobun/bun/desktop/view-ids.ts +8 -4
- package/src/renderers/electrobun/bun/external-plugins.ts +4 -0
- package/src/renderers/electrobun/bun/window/create.ts +4 -2
- package/src/renderers/electrobun/bun/window/native-timing.ts +48 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +82 -4
- package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +13 -5
- package/src/renderers/electrobun/view/desktop/window/snapshot.ts +3 -0
- package/src/renderers/electrobun/view/main.tsx +7 -2
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -0
- package/src/renderers/opentui/browser-open.ts +10 -4
- package/src/renderers/opentui/image/surface.tsx +1 -1
- package/src/renderers/opentui/start.tsx +12 -6
- package/src/renderers/opentui/toast-host.tsx +2 -1
- package/src/series/registry.ts +18 -0
- package/src/series/standalone.ts +10 -1
- package/src/series/types.ts +7 -0
- package/src/series/validate.ts +11 -2
- package/src/sources/gloomberb-cloud/index.ts +28 -5
- package/src/sources/gloomberb-cloud/news.ts +24 -3
- package/src/sources/gloomberb-cloud/normalizers.ts +17 -2
- package/src/sources/provider-errors.ts +26 -3
- package/src/sources/provider-router/history.ts +5 -0
- package/src/sources/provider-router/index.ts +13 -0
- package/src/sync/core-contributors.ts +32 -0
- package/src/telemetry/attention-counts.ts +64 -6
- package/src/telemetry/attention-setting.ts +33 -0
- package/src/telemetry/crash-reports-node.ts +3 -1
- package/src/telemetry/stall-clocks.ts +93 -0
- package/src/telemetry/stall-reports-node.ts +12 -7
- package/src/telemetry/stall-reports.ts +34 -5
- package/src/test-support/preload.ts +9 -0
- package/src/tickers/company-name.ts +19 -0
- package/src/tickers/listing-fate.ts +14 -3
- package/src/tickers/saved-instrument.ts +17 -0
- package/src/tickers/search/home-listing.ts +13 -2
- package/src/tickers/search/index.ts +4 -1
- package/src/tickers/search/types.ts +6 -1
- package/src/time-series/bar-aggregation.ts +7 -1
- package/src/time-series/base-series.ts +3 -3
- package/src/time-series/chart-bounds.ts +1 -1
- package/src/time-series/chart-data.ts +5 -2
- package/src/time-series/chart-seed.ts +1 -1
- package/src/time-series/coin-session-close.ts +211 -0
- package/src/time-series/live-bars.ts +13 -2
- package/src/time-series/live-quotes.ts +1 -1
- package/src/time-series/official-close.ts +159 -0
- package/src/time-series/price-comparison.ts +55 -6
- package/src/time-series/resolve.ts +12 -3
- package/src/time-series/series-presentation.ts +1 -1
- package/src/time-series/studies/formula.ts +205 -0
- package/src/time-series/studies/indicators.ts +299 -0
- package/src/time-series/studies/leverage.ts +75 -0
- package/src/time-series/studies/pair.ts +138 -0
- package/src/time-series/studies/resolve.ts +333 -0
- package/src/time-series/studies/shared.ts +141 -0
- package/src/time-series/studies/units.ts +243 -0
- package/src/time-series/studies/vwap.ts +274 -0
- package/src/types/config.ts +18 -2
- package/src/types/data-provider.ts +23 -0
- package/src/types/financials.ts +22 -0
- package/src/types/headless.ts +42 -3
- package/src/types/plugin.ts +32 -3
- package/src/ui/host.tsx +11 -0
- package/src/ui/toast.tsx +26 -1
- package/src/utils/ascii-text.ts +140 -0
- package/src/utils/cli-output.ts +91 -18
- package/src/utils/concurrency.ts +24 -0
- package/src/utils/exchanges.ts +6 -0
- package/src/utils/external-url.ts +20 -7
- package/src/utils/futures-generic.ts +4 -4
- package/src/utils/http-proxy-upstream.ts +124 -0
- package/src/utils/main-thread-stall.ts +75 -3
- package/src/utils/perf-marks.ts +36 -2
- package/src/utils/private-files.ts +141 -0
- package/src/utils/public-address.ts +99 -0
- package/src/account/upgrade-personalization.ts +0 -57
- package/src/account/upgrade-tickers.ts +0 -124
- package/src/api-client/upgrade-experiment.ts +0 -91
- package/src/plugins/builtin/cloud/browser.tsx +0 -3
- package/src/renderers/electrobun/launcher/preload.ts +0 -13
- package/src/renderers/electrobun/launcher/windows-emulation.ts +0 -50
- package/src/time-series/studies.ts +0 -1628
|
@@ -10,7 +10,13 @@ import type { PluginRegistry } from "../../plugins/registry";
|
|
|
10
10
|
import { resolvePlanAccess } from "../../api-client/plan-access";
|
|
11
11
|
import type { PortfolioSub } from "./onboarding-steps";
|
|
12
12
|
import type { useOnboardingPositions } from "./wizard-positions";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
applyFirstRunLayout,
|
|
15
|
+
buildFirstRunLayout,
|
|
16
|
+
onboardingDeskLayoutId,
|
|
17
|
+
planFirstRunWatchlist,
|
|
18
|
+
setupDeskPicks,
|
|
19
|
+
} from "./first-run-workspace";
|
|
14
20
|
import { buildDesk, getDesk, isDeskKey, isDeskStock, pickDeskCompany, type DeskKey } from "../../layout/desks";
|
|
15
21
|
import { debugLog } from "../../utils/debug-log";
|
|
16
22
|
import {
|
|
@@ -92,15 +98,18 @@ export function useOnboardingWorkspace({
|
|
|
92
98
|
selectedBrokerId: string | null;
|
|
93
99
|
setPortfolioSub: Dispatch<SetStateAction<PortfolioSub>>;
|
|
94
100
|
}) {
|
|
95
|
-
|
|
101
|
+
// Run again, it starts with the desks it made ticked.
|
|
102
|
+
const [chosenDesks, setChosenDesks] = useState<DeskKey[]>(() => setupDeskPicks(stateRef.current.config));
|
|
96
103
|
const [deskCursor, setDeskCursor] = useState(0);
|
|
97
104
|
const [buildingDesks, setBuildingDesks] = useState(false);
|
|
98
105
|
const buildingDesksRef = useRef(false);
|
|
99
106
|
|
|
100
107
|
/**
|
|
101
108
|
* Seeds the watchlist and swaps Home for the first-run workspace built
|
|
102
|
-
* around `symbol`, with the picked desks as tabs right after it.
|
|
103
|
-
*
|
|
109
|
+
* around `symbol`, with the picked desks as tabs right after it. Run again,
|
|
110
|
+
* it replaces the layouts it made before instead of adding copies, and
|
|
111
|
+
* from Settings it leaves an existing watchlist alone. The config comes
|
|
112
|
+
* back for the caller to persist with its own progress patch.
|
|
104
113
|
*/
|
|
105
114
|
const buildFirstRunWorkspace = useCallback(async (
|
|
106
115
|
baseConfig: AppConfig,
|
|
@@ -109,12 +118,17 @@ export function useOnboardingWorkspace({
|
|
|
109
118
|
desks: readonly DeskKey[],
|
|
110
119
|
): Promise<AppConfig> => {
|
|
111
120
|
let config = baseConfig;
|
|
121
|
+
const rerun = getOnboardingProgress(baseConfig).rerun === true;
|
|
112
122
|
let watchlistId = config.watchlists[0]?.id;
|
|
123
|
+
// A run from Settings leaves a watchlist the user has as it is.
|
|
124
|
+
const seedWatchlist = !rerun || !watchlistId;
|
|
113
125
|
if (!watchlistId) {
|
|
114
126
|
watchlistId = "watchlist";
|
|
115
127
|
config = { ...config, watchlists: [{ id: watchlistId, name: "Watchlist" }] };
|
|
116
128
|
}
|
|
117
|
-
const plan =
|
|
129
|
+
const plan = seedWatchlist
|
|
130
|
+
? planFirstRunWatchlist(stateRef.current.tickers, watchlistId, portfolioId)
|
|
131
|
+
: { create: [], update: [] };
|
|
118
132
|
for (const metadata of plan.create) {
|
|
119
133
|
try {
|
|
120
134
|
const ticker = await pluginRegistry.tickerRepository.createTicker(metadata);
|
|
@@ -138,7 +152,7 @@ export function useOnboardingWorkspace({
|
|
|
138
152
|
watchlistId,
|
|
139
153
|
hasPane: (paneId) => pluginRegistry.panes?.has(paneId) ?? false,
|
|
140
154
|
});
|
|
141
|
-
const workspace = applyFirstRunLayout(config, home);
|
|
155
|
+
const workspace = applyFirstRunLayout(config, home, [], { rerun });
|
|
142
156
|
if (desks.length === 0) return workspace;
|
|
143
157
|
const { tickers, financials } = stateRef.current;
|
|
144
158
|
const held = [...tickers.values()]
|
|
@@ -150,13 +164,15 @@ export function useOnboardingWorkspace({
|
|
|
150
164
|
const pro = resolvePlanAccess(apiClient.getCurrentUser()).hasProAccess;
|
|
151
165
|
// A desk that fails to build is left out; it never holds up the first run.
|
|
152
166
|
const deskTabs = await Promise.all(desks.map((key) => (
|
|
153
|
-
buildDesk(getDesk(key), { catalog: pluginRegistry, config: workspace, company, pro }).
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
167
|
+
buildDesk(getDesk(key), { catalog: pluginRegistry, config: workspace, company, pro }).then(
|
|
168
|
+
(tab) => (tab ? { ...tab, id: onboardingDeskLayoutId(key) } : null),
|
|
169
|
+
(error) => {
|
|
170
|
+
onboardingLog.error("Desk build failed", { desk: key, error: String(error) });
|
|
171
|
+
return null;
|
|
172
|
+
},
|
|
173
|
+
)
|
|
157
174
|
)));
|
|
158
|
-
|
|
159
|
-
return { ...workspace, layouts: [workspace.layouts[0]!, ...tabs, ...workspace.layouts.slice(1)] };
|
|
175
|
+
return applyFirstRunLayout(config, home, deskTabs.filter((tab) => tab !== null), { rerun });
|
|
160
176
|
}, [dispatch, pluginRegistry, stateRef]);
|
|
161
177
|
|
|
162
178
|
const commitWorkspaceProgress = useCallback(async (
|
|
@@ -187,7 +203,7 @@ export function useOnboardingWorkspace({
|
|
|
187
203
|
}, [positions, saveProgressInBackground]);
|
|
188
204
|
|
|
189
205
|
/**
|
|
190
|
-
* Leaves "What do you trade?": builds the workspace with the picked desks as
|
|
206
|
+
* Leaves "What do you trade most?": builds the workspace with the picked desks as
|
|
191
207
|
* tabs (none when skipped, which is today's workspace) and moves on.
|
|
192
208
|
*/
|
|
193
209
|
const finishDesks = useCallback((desks: readonly DeskKey[]) => {
|
|
@@ -270,7 +286,8 @@ export function useOnboardingCompletion({
|
|
|
270
286
|
setPersistenceError(null);
|
|
271
287
|
try {
|
|
272
288
|
await progressSaveQueueRef.current.catch(() => {});
|
|
273
|
-
const desks = getOnboardingProgress(stateRef.current.config)
|
|
289
|
+
const { desks: picked, rerun } = getOnboardingProgress(stateRef.current.config);
|
|
290
|
+
const desks = picked?.filter(isDeskKey);
|
|
274
291
|
const nextConfig: AppConfig = {
|
|
275
292
|
...stateRef.current.config,
|
|
276
293
|
onboardingComplete: true,
|
|
@@ -282,7 +299,8 @@ export function useOnboardingCompletion({
|
|
|
282
299
|
complete: true,
|
|
283
300
|
progress: undefined,
|
|
284
301
|
});
|
|
285
|
-
|
|
302
|
+
// The funnel counts first runs; a run from Settings is not one.
|
|
303
|
+
if (!rerun) recordResearchActivity(skipped ? "onboarding_skipped" : "onboarding_completed", undefined, undefined, { desks });
|
|
286
304
|
await Promise.resolve(onComplete(nextConfig));
|
|
287
305
|
} catch (error) {
|
|
288
306
|
setPersistenceError(error instanceof Error ? error.message : String(error));
|
|
@@ -6,14 +6,12 @@ import { chatController } from "../../plugins/builtin/chat/controller";
|
|
|
6
6
|
import type { CloudBillingInterval } from "../../account/billing";
|
|
7
7
|
import { loadUpgradeOffer, type UpgradeOffer } from "../../account/upgrade-dialog";
|
|
8
8
|
import { useCloudUpgradeAction } from "../../plugins/builtin/shared/cloud-upgrade";
|
|
9
|
-
import { useUpgradePersonalization } from "../../account/upgrade-personalization";
|
|
10
9
|
import { usePlanAccess } from "../../api-client/plan-access";
|
|
11
10
|
|
|
12
11
|
export function useOnboardingUpgrade({
|
|
13
|
-
stage, progress, saveProgressInBackground, persistProgress,
|
|
12
|
+
stage, progress, saveProgressInBackground, persistProgress,
|
|
14
13
|
}: {
|
|
15
14
|
stage: OnboardingStage;
|
|
16
|
-
shown: boolean;
|
|
17
15
|
progress: OnboardingProgress;
|
|
18
16
|
saveProgressInBackground: (patch: Partial<OnboardingProgress> & Pick<OnboardingProgress, "stage">, baseConfig?: AppConfig | undefined) => void;
|
|
19
17
|
persistProgress: (patch: Partial<OnboardingProgress> & Pick<OnboardingProgress, "stage">, baseConfig?: AppConfig | undefined) => Promise<AppConfig>;
|
|
@@ -25,8 +23,6 @@ export function useOnboardingUpgrade({
|
|
|
25
23
|
const appActive = useAppActive();
|
|
26
24
|
const planAccess = usePlanAccess();
|
|
27
25
|
const openUpgrade = useCloudUpgradeAction("onboarding-pro");
|
|
28
|
-
// The step lists the features from its first frame, so that is when it is shown.
|
|
29
|
-
const personalTickers = useUpgradePersonalization("onboarding-pro", shown && stage === "upgrade");
|
|
30
26
|
// The price and whether this account still has its trial, asked again for
|
|
31
27
|
// whichever account reaches the step.
|
|
32
28
|
const accountId = planAccess.signedIn ? apiClient.getCurrentUser()?.id ?? null : null;
|
|
@@ -82,6 +78,6 @@ export function useOnboardingUpgrade({
|
|
|
82
78
|
}, [progress.accountStatus, saveProgressInBackground]);
|
|
83
79
|
|
|
84
80
|
return {
|
|
85
|
-
offer, pricing, billingInterval, setBillingInterval, planAccess, primaryUpgradeAction, continueFree,
|
|
81
|
+
offer, pricing, billingInterval, setBillingInterval, planAccess, primaryUpgradeAction, continueFree,
|
|
86
82
|
};
|
|
87
83
|
}
|
|
@@ -19,9 +19,63 @@ const LEGACY_STAGES: Partial<Record<OnboardingStage, OnboardingStage>> = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
export function getOnboardingProgress(config: AppConfig): OnboardingProgress {
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
22
|
+
const saved = config.onboardingProgress ?? { version: 1, stage: "portfolio" };
|
|
23
|
+
const legacy = LEGACY_STAGES[saved.stage];
|
|
24
|
+
const progress = legacy ? { ...saved, stage: legacy } : saved;
|
|
25
|
+
// Older builds sent Back from Gloom Cloud to the portfolio after the
|
|
26
|
+
// workspace was built; such a profile resumes on the workspace.
|
|
27
|
+
return isOnboardingStageFinished(progress, progress.stage) ? { ...progress, stage: "research" } : progress;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Stages the wizard reaches only once the workspace is built. */
|
|
31
|
+
const WORKSPACE_STAGES: ReadonlySet<OnboardingStage> = new Set(["research", "account", "upgrade", "ready"]);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Whether the workspace is built around a holding: the portfolio and desk
|
|
35
|
+
* steps are finished. Older builds saved no desks, so a later stage with a
|
|
36
|
+
* holding counts too.
|
|
37
|
+
*/
|
|
38
|
+
export function isOnboardingWorkspaceBuilt(progress: OnboardingProgress): boolean {
|
|
39
|
+
return !!progress.tickerSymbol && (Array.isArray(progress.desks) || WORKSPACE_STAGES.has(progress.stage));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* A step that is done for good: the portfolio and desk steps once the
|
|
44
|
+
* workspace is built (building twice would add every desk twice), and Pro
|
|
45
|
+
* for an account that has it. The wizard shows them as done and never asks
|
|
46
|
+
* them again.
|
|
47
|
+
*/
|
|
48
|
+
function isOnboardingStageFinished(progress: OnboardingProgress, stage: OnboardingStage, pro = false): boolean {
|
|
49
|
+
if (stage === "upgrade") return pro;
|
|
50
|
+
return (stage === "portfolio" || stage === "desks") && isOnboardingWorkspaceBuilt(progress);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Where Back (and Esc) goes: the step the user came from, passing over any
|
|
55
|
+
* that is finished for good (`pro`: the account has Pro). With no way back
|
|
56
|
+
* recorded (the app restarted on this step), the step before it in the
|
|
57
|
+
* flow. `visited` is the stages the user came through, oldest first; what
|
|
58
|
+
* comes back is what is left of it. Null when the step has no way back.
|
|
59
|
+
*/
|
|
60
|
+
export function previousOnboardingStage(
|
|
61
|
+
progress: OnboardingProgress,
|
|
62
|
+
visited: readonly OnboardingStage[],
|
|
63
|
+
{ pro = false }: { pro?: boolean } = {},
|
|
64
|
+
): { stage: OnboardingStage; visited: OnboardingStage[] } | null {
|
|
65
|
+
for (let index = visited.length - 1; index >= 0; index -= 1) {
|
|
66
|
+
const stage = visited[index]!;
|
|
67
|
+
if (stage !== progress.stage && !isOnboardingStageFinished(progress, stage, pro)) {
|
|
68
|
+
return { stage, visited: visited.slice(0, index) };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const stage: OnboardingStage | null = progress.stage === "account"
|
|
72
|
+
? isOnboardingWorkspaceBuilt(progress) ? "research" : "portfolio"
|
|
73
|
+
: progress.stage === "upgrade"
|
|
74
|
+
? "account"
|
|
75
|
+
: progress.stage === "ready"
|
|
76
|
+
? progress.accountStatus === "signed-in" && !pro ? "upgrade" : "account"
|
|
77
|
+
: null;
|
|
78
|
+
return stage ? { stage, visited: [] } : null;
|
|
25
79
|
}
|
|
26
80
|
|
|
27
81
|
export function withOnboardingProgress(
|
|
@@ -302,7 +302,7 @@ export function useOnboardingPositions({
|
|
|
302
302
|
const costBasis = avgCost ?? result.quote?.price;
|
|
303
303
|
if (costBasis === undefined || costBasis === null || !Number.isFinite(costBasis)) {
|
|
304
304
|
setFieldIdx(2);
|
|
305
|
-
setError(t("No
|
|
305
|
+
setError(t("No price yet. Enter the average cost."));
|
|
306
306
|
return false;
|
|
307
307
|
}
|
|
308
308
|
// A future is entered in contracts, sized by its terms; a cost typed as corn is quoted counts cents.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Box, Text, useUiCapabilities } from "../../ui";
|
|
2
|
+
import { useThemeColors } from "../../theme/theme-context";
|
|
3
|
+
import { tf } from "../../i18n";
|
|
4
|
+
import { displayWidth } from "../../utils/format";
|
|
5
|
+
import { ICON_GLYPHS, Icon } from "./icon";
|
|
6
|
+
|
|
7
|
+
/** The terminal's form of the mark: the clock and the delay, as the pane footer draws it (`◷15m`). */
|
|
8
|
+
function delayedMarkText(minutes: number): string {
|
|
9
|
+
return `${ICON_GLYPHS.clock}${minutes}m`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** The delay the mark spells out after its clock: `15m`. */
|
|
13
|
+
function delayedMarkDelay(minutes: number): string {
|
|
14
|
+
return `${minutes}m`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Cells the mark takes: `◷15m` in the terminal; on the desktop and the web the
|
|
19
|
+
* clock icon and its gap (12px and 4px, three cells at the narrowest cell) and `15m`.
|
|
20
|
+
*/
|
|
21
|
+
export function delayedMarkWidth(minutes: number, nativePaneChrome: boolean): number {
|
|
22
|
+
return nativePaneChrome ? 3 + displayWidth(delayedMarkDelay(minutes)) : displayWidth(delayedMarkText(minutes));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The one mark for a price shown late, beside the price: what the pane
|
|
27
|
+
* footer's clock is for a pane's data (`delayedFooterSegment`), for a price
|
|
28
|
+
* outside a footer (the header's SPY, the status bar, a quote's headline).
|
|
29
|
+
* It reads without hovering: a yellow clock and the delay (`15m`) in the dim
|
|
30
|
+
* tone of the meta text around it on the desktop and the web, `◷15m` in the
|
|
31
|
+
* terminal, with `15m delayed` in its tooltip. Callers decide when a price is
|
|
32
|
+
* late with `freeQuoteDelayMinutes` (or `useFreeQuoteDelay`); it draws nothing else.
|
|
33
|
+
*/
|
|
34
|
+
export function DelayedMark({ minutes }: { minutes: number }) {
|
|
35
|
+
const colors = useThemeColors();
|
|
36
|
+
const { nativePaneChrome } = useUiCapabilities();
|
|
37
|
+
const detail = tf("{delay} delayed", { delay: `${minutes}m` });
|
|
38
|
+
if (!nativePaneChrome) {
|
|
39
|
+
return <Text fg={colors.warning} flexShrink={0} selectable={false} aria-label={detail}>{delayedMarkText(minutes)}</Text>;
|
|
40
|
+
}
|
|
41
|
+
return (
|
|
42
|
+
<Box
|
|
43
|
+
role="img"
|
|
44
|
+
aria-label={detail}
|
|
45
|
+
title={detail}
|
|
46
|
+
flexShrink={0}
|
|
47
|
+
flexDirection="row"
|
|
48
|
+
alignItems="center"
|
|
49
|
+
data-gloom-role="delayed-mark"
|
|
50
|
+
style={{ gap: "var(--gloom-space-xs)" }}
|
|
51
|
+
>
|
|
52
|
+
<Icon name="clock" color={colors.warning} />
|
|
53
|
+
<Text fg={colors.textDim} selectable={false}>{delayedMarkDelay(minutes)}</Text>
|
|
54
|
+
</Box>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -3,7 +3,7 @@ import { Box, Text } from "../../ui";
|
|
|
3
3
|
import { TextAttributes } from "../../ui";
|
|
4
4
|
import { tf } from "../../i18n";
|
|
5
5
|
import { useThemeColors } from "../../theme/theme-context";
|
|
6
|
-
import { safeExternalUrl } from "../../utils/external-url";
|
|
6
|
+
import { safeExternalUrl, systemOpenCommand } from "../../utils/external-url";
|
|
7
7
|
import { linkContextMenuItems, useContextMenu, useRendererHost, useUiCapabilities } from "../../ui";
|
|
8
8
|
import type { ContextMenuItem } from "../../types/context-menu";
|
|
9
9
|
import { usePaneMenuItems } from "../layout/pane/footer/registration";
|
|
@@ -20,11 +20,8 @@ export function openUrl(rawUrl: string) {
|
|
|
20
20
|
|
|
21
21
|
if (typeof Bun !== "undefined" && typeof Bun.spawn === "function") {
|
|
22
22
|
const platform = typeof process !== "undefined" ? process.platform : "linux";
|
|
23
|
-
const command = platform
|
|
24
|
-
|
|
25
|
-
: platform === "win32"
|
|
26
|
-
? ["cmd", "/c", "start", "", url]
|
|
27
|
-
: ["xdg-open", url];
|
|
23
|
+
const command = systemOpenCommand(url, platform);
|
|
24
|
+
if (!command) return;
|
|
28
25
|
// Spawning throws when the opener is not installed (no xdg-open on
|
|
29
26
|
// minimal Linux and WSL); a link that does nothing beats a crash.
|
|
30
27
|
try {
|
|
@@ -138,6 +138,11 @@ export interface IconButtonProps {
|
|
|
138
138
|
size?: number;
|
|
139
139
|
/** Keep the press from also reaching a row or header behind the button. */
|
|
140
140
|
stopPropagation?: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* A few characters after the icon, in a muted tone, for a status that must
|
|
143
|
+
* read without hovering (a delay's `15m`). The label stays the accessible name.
|
|
144
|
+
*/
|
|
145
|
+
text?: string;
|
|
141
146
|
}
|
|
142
147
|
|
|
143
148
|
/**
|
|
@@ -157,6 +162,7 @@ export function IconButton({
|
|
|
157
162
|
disabled = false,
|
|
158
163
|
size = 12,
|
|
159
164
|
stopPropagation = true,
|
|
165
|
+
text,
|
|
160
166
|
}: IconButtonProps) {
|
|
161
167
|
const colors = useThemeColors();
|
|
162
168
|
const label = t(rawLabel);
|
|
@@ -182,6 +188,7 @@ export function IconButton({
|
|
|
182
188
|
disabled={disabled}
|
|
183
189
|
size={size}
|
|
184
190
|
stopPropagation={stopPropagation}
|
|
191
|
+
text={text}
|
|
185
192
|
/>
|
|
186
193
|
);
|
|
187
194
|
}
|
|
@@ -201,7 +208,7 @@ export function IconButton({
|
|
|
201
208
|
>
|
|
202
209
|
{/* Pressed takes the colour the desktop and the terminal pane header give an active toggle. */}
|
|
203
210
|
<Text fg={disabled ? colors.textMuted : color ?? (pressed ? colors.warning : colors.textDim)} selectable={false}>
|
|
204
|
-
{` ${ICON_GLYPHS[icon]} `}
|
|
211
|
+
{` ${ICON_GLYPHS[icon]}${text ?? ""} `}
|
|
205
212
|
</Text>
|
|
206
213
|
</Box>
|
|
207
214
|
);
|
|
@@ -23,15 +23,16 @@ const LETTER_STYLE: Record<LogoMarkSize, CSSProperties> = {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
export interface LogoMarkProps {
|
|
26
|
-
/** The logo, an image URL; without one,
|
|
26
|
+
/** The logo, an image URL; without one, while it loads and when it fails to load, the tile shows `name`'s initial. */
|
|
27
27
|
src?: string | null;
|
|
28
28
|
/** What the logo stands for, such as a broker. Only its initial is drawn; the label beside it names it. */
|
|
29
29
|
name: string;
|
|
30
30
|
size?: LogoMarkSize;
|
|
31
31
|
/**
|
|
32
|
-
* Draws the logo on a white plate
|
|
33
|
-
*
|
|
34
|
-
* theme, while a logo that
|
|
32
|
+
* Draws the logo on a white plate once it has loaded, never behind the
|
|
33
|
+
* initial. Company and coin logos are made for a light page: a black mark
|
|
34
|
+
* on a clear field (XRP's) would vanish on a dark theme, while a logo that
|
|
35
|
+
* fills its square covers the plate.
|
|
35
36
|
*/
|
|
36
37
|
plate?: boolean;
|
|
37
38
|
}
|
|
@@ -59,9 +60,11 @@ export function LogoMark({ src, name, size = "row", plate = false }: LogoMarkPro
|
|
|
59
60
|
src={src ?? undefined}
|
|
60
61
|
alt=""
|
|
61
62
|
objectFit="cover"
|
|
63
|
+
fallbackWhileLoading
|
|
64
|
+
imageBackground={plate ? LOGO_PLATE : undefined}
|
|
62
65
|
aria-hidden="true"
|
|
63
66
|
data-gloom-role="logo-mark"
|
|
64
|
-
style={{ width: tile.side, height: tile.side, flexShrink: 0, borderRadius: tile.radius
|
|
67
|
+
style={{ width: tile.side, height: tile.side, flexShrink: 0, borderRadius: tile.radius }}
|
|
65
68
|
>
|
|
66
69
|
<Box width="100%" height="100%" alignItems="center" justifyContent="center" backgroundColor={colors.border}>
|
|
67
70
|
<Text fg={colors.textBright} attributes={TextAttributes.BOLD} style={LETTER_STYLE[size]}>
|