gloomberb 0.10.0 → 0.10.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/package.json +8 -1
- package/src/api-client/auth.ts +1 -0
- package/src/api-client/index.test.ts +359 -108
- package/src/api-client/index.ts +24 -13
- package/src/api-client/socket.ts +70 -35
- package/src/api-client/types.ts +1 -1
- package/src/app/language-observer.test.tsx +82 -0
- package/src/app/language-observer.tsx +13 -0
- package/src/app/pane-runtime/index.tsx +2 -2
- package/src/app/pane-runtime/pane-settings-runtime.tsx +2 -2
- package/src/app/pane-runtime/pane-template-runtime.ts +2 -2
- package/src/app/pane-runtime/plugin-bindings.ts +2 -2
- package/src/app/pane-runtime/ticker-open-runtime.ts +2 -2
- package/src/app/runtime/broker-import.ts +2 -2
- package/src/app/runtime/plugin-bindings.ts +2 -2
- package/src/app/runtime/startup.ts +2 -2
- package/src/app.tsx +16 -7
- package/src/brokers/account-cache.ts +6 -6
- package/src/brokers/broker-ticker-sync.ts +3 -3
- package/src/brokers/remote-broker-adapter.ts +2 -2
- package/src/brokers/sync-broker-instance.ts +5 -6
- package/src/cli/commands/api.ts +3 -6
- package/src/cli/commands/automation.ts +7 -15
- package/src/cli/commands/market.ts +26 -61
- package/src/cli/commands/overview.ts +34 -45
- package/src/cli/commands/search.ts +25 -27
- package/src/cli/commands/system.ts +27 -57
- package/src/cli/commands/ticker.ts +62 -63
- package/src/cli/context.test.ts +63 -0
- package/src/cli/context.ts +15 -1
- package/src/cli/index.ts +1 -1
- package/src/cli/pane-functions/data.ts +2 -19
- package/src/cli/pane-functions/index.ts +26 -25
- package/src/cli/pane-functions/report.ts +1 -1
- package/src/cli/pane-functions/screenshot.ts +3 -3
- package/src/cli/scoped-context.ts +41 -0
- package/src/components/chart/composite/composite-chart.test.tsx +615 -18
- package/src/components/chart/composite/composite-chart.tsx +179 -79
- package/src/components/chart/composite/format.test.ts +20 -7
- package/src/components/chart/composite/index.ts +0 -21
- package/src/components/chart/composite/interactions.test.ts +90 -3
- package/src/components/chart/composite/interactions.ts +189 -24
- package/src/components/chart/composite/price-series.ts +0 -2
- package/src/components/chart/composite/rasterizer.ts +10 -9
- package/src/components/chart/composite/renderers.test.ts +108 -2
- package/src/components/chart/composite/scene.test.ts +36 -0
- package/src/components/chart/composite/scene.ts +5 -2
- package/src/components/chart/composite/text-renderer.ts +37 -25
- package/src/components/chart/composite/time-axis.test.ts +243 -0
- package/src/components/chart/composite/time-axis.ts +608 -0
- package/src/components/chart/composite/types.ts +12 -1
- package/src/components/chart/core/data.ts +2 -159
- package/src/components/chart/core/date-window.ts +6 -225
- package/src/components/chart/core/palette.ts +1 -12
- package/src/components/chart/core/pointer.ts +0 -142
- package/src/components/chart/core/types.ts +1 -58
- package/src/components/chart/cursor-motion.ts +2 -4
- package/src/components/chart/indicators/types.ts +0 -9
- package/src/components/chart/market-session.ts +0 -11
- package/src/components/chart/native/kitty/protocol.ts +1 -1
- package/src/components/chart/native/raster/layout.ts +3 -10
- package/src/components/chart/static/chart/axis-overlays.test.tsx +64 -0
- package/src/components/chart/static/chart/axis-overlays.tsx +59 -14
- package/src/components/chart/static/chart/surface.tsx +1 -2
- package/src/components/command-bar/action-runtime.ts +2 -2
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/panel/body.tsx +2 -2
- package/src/components/command-bar/panel/index.tsx +11 -9
- package/src/components/command-bar/routes/ticker-search/actions.ts +2 -2
- package/src/components/command-bar/surface/index.tsx +2 -2
- package/src/components/command-bar/workflow/body.tsx +3 -3
- package/src/components/command-bar/workflow/collection-actions.ts +2 -2
- package/src/components/command-bar/workflow/coordinator.ts +2 -2
- package/src/components/command-bar/workflow/field-row.tsx +25 -11
- package/src/components/command-bar/workflow/tickers.ts +2 -2
- package/src/components/feed-data-table/stack-view.test.tsx +28 -36
- package/src/components/feed-data-table/stack-view.tsx +3 -1
- package/src/components/layout/detached-pane-shell.tsx +6 -6
- package/src/components/layout/header.tsx +13 -9
- package/src/components/layout/pane/content.test.tsx +42 -3
- package/src/components/layout/pane/content.tsx +3 -1
- package/src/components/layout/pane/footer/index.test.tsx +45 -2
- package/src/components/layout/pane/footer/registration.tsx +3 -1
- package/src/components/layout/shell/index.tsx +1 -2
- package/src/components/layout/shell/native/surfaces.ts +1 -1
- package/src/components/layout/shell/native/window-state.ts +1 -1
- package/src/components/layout/status-bar.tsx +12 -8
- package/src/components/layout/window-controls.tsx +8 -6
- package/src/components/onboarding/onboarding-wizard.tsx +3 -1
- package/src/components/pane-settings-dialog/desktop.tsx +0 -2
- package/src/components/pane-settings-dialog.tsx +0 -2
- package/src/components/pane-template-wizard.tsx +10 -9
- package/src/components/price-performance.tsx +2 -113
- package/src/components/price-sparkline/model.ts +15 -17
- package/src/components/price-sparkline/view.tsx +8 -7
- package/src/components/speedometer-gauge/desktop.tsx +2 -1
- package/src/components/speedometer-gauge/index.tsx +0 -2
- package/src/components/speedometer-gauge/terminal.tsx +24 -5
- package/src/components/ticker/badge/index.tsx +1 -18
- package/src/components/ui/data-table/opentui/index.tsx +3 -3
- package/src/components/ui/frame.tsx +1 -2
- package/src/components/ui/page-stack-view.test.tsx +126 -0
- package/src/components/ui/page-stack-view.tsx +24 -12
- package/src/components/ui/tabs.tsx +7 -3
- package/src/components/ui/ui.test.tsx +23 -2
- package/src/components/use-external-link-footer.ts +4 -2
- package/src/core/app-service-ports.ts +46 -0
- package/src/core/app-services.test.ts +66 -0
- package/src/core/app-services.ts +17 -15
- package/src/data/config/chart-settings.ts +3 -10
- package/src/data/config/store/index.test.ts +99 -2
- package/src/data/config/store/migrations.ts +278 -0
- package/src/data/config/store/normalize.ts +44 -186
- package/src/data/resource-store.ts +73 -12
- package/src/data/sqlite/cache.test.ts +104 -15
- package/src/i18n/index.test.ts +17 -0
- package/src/i18n/index.ts +23 -6
- package/src/i18n/ja.ts +13 -0
- package/src/i18n/ko.ts +13 -0
- package/src/i18n/react.ts +6 -0
- package/src/i18n/zh-cn.ts +13 -0
- package/src/i18n/zh-tw.ts +13 -0
- package/src/market-data/coordinator/auxiliary.ts +7 -3
- package/src/market-data/coordinator/chart.ts +1 -1
- package/src/market-data/coordinator/index.test.ts +26 -0
- package/src/market-data/coordinator/index.ts +11 -5
- package/src/market-data/coordinator/quotes.ts +4 -40
- package/src/market-data/coordinator/subscriptions.test.ts +89 -1
- package/src/market-data/hooks.tsx +47 -1
- package/src/market-data/market/status.ts +6 -6
- package/src/market-data/performance.ts +1 -1
- package/src/market-data/quote-subscription-target.test.ts +37 -0
- package/src/market-data/quote-subscription-target.ts +60 -0
- package/src/market-data/quotes/freshness.ts +1 -0
- package/src/market-data/quotes/resolution.ts +4 -0
- package/src/market-data/request-types.ts +3 -3
- package/src/news/aggregator.test.ts +97 -1
- package/src/news/aggregator.ts +100 -57
- package/src/news/hooks.test.tsx +64 -0
- package/src/news/hooks.ts +18 -25
- package/src/plugins/builtin/account-management/footer.ts +4 -2
- package/src/plugins/builtin/account-management/pane.tsx +9 -4
- package/src/plugins/builtin/ai/agent-history.ts +11 -7
- package/src/plugins/builtin/ai/ask-ai-detail-tab.tsx +0 -5
- package/src/plugins/builtin/ai/ask-ai.test.tsx +3 -4
- package/src/plugins/builtin/ai/index.test.ts +2 -2
- package/src/plugins/builtin/ai/index.tsx +10 -11
- package/src/plugins/builtin/ai/pane-settings.ts +1 -1
- package/src/plugins/builtin/ai/pi/runtime.ts +6 -5
- package/src/plugins/builtin/ai/providers.ts +1 -9
- package/src/plugins/builtin/ai/runner.ts +0 -6
- package/src/plugins/builtin/ai/screener/footer.ts +4 -1
- package/src/plugins/builtin/ai/screener/pane.test.tsx +9 -9
- package/src/plugins/builtin/ai/workspace/model.ts +2 -27
- package/src/plugins/builtin/ai/workspace/pane.tsx +2 -2
- package/src/plugins/builtin/analytics/metrics.ts +1 -7
- package/src/plugins/builtin/broker-manager/detail.tsx +3 -2
- package/src/plugins/builtin/broker-manager/index.tsx +4 -2
- package/src/plugins/builtin/chart-composer/editor/controller.ts +643 -0
- package/src/plugins/builtin/chart-composer/editor/desktop-view.tsx +134 -0
- package/src/plugins/builtin/chart-composer/editor/model.test.ts +85 -0
- package/src/plugins/builtin/chart-composer/editor/model.ts +292 -0
- package/src/plugins/builtin/chart-composer/editor/opentui-view.tsx +108 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +65 -947
- package/src/plugins/builtin/chart-composer/index.tsx +0 -6
- package/src/plugins/builtin/chart-composer/pane.tsx +69 -36
- package/src/plugins/builtin/chart-composer/presets.ts +1 -19
- package/src/plugins/builtin/chart-composer/settings.ts +1 -1
- package/src/plugins/builtin/chat/content/composer-runtime.ts +1 -1
- package/src/plugins/builtin/chat/content/shortcuts.ts +0 -1
- package/src/plugins/builtin/chat/controller/fetch.ts +8 -2
- package/src/plugins/builtin/chat/controller/persistence.ts +2 -0
- package/src/plugins/builtin/chat/controller/session.test.ts +25 -0
- package/src/plugins/builtin/chat/controller/session.ts +2 -0
- package/src/plugins/builtin/chat/controller/state.ts +7 -0
- package/src/plugins/builtin/chat/controller.test.ts +73 -20
- package/src/plugins/builtin/chat/message/desktop.tsx +2 -0
- package/src/plugins/builtin/cloud-tweets/footer.ts +9 -28
- package/src/plugins/builtin/cloud-tweets/pane.tsx +0 -5
- package/src/plugins/builtin/cloud-tweets/table.tsx +12 -17
- package/src/plugins/builtin/correlation/compute.ts +4 -10
- package/src/plugins/builtin/econ/index.tsx +17 -19
- package/src/plugins/builtin/holders/types.ts +0 -1
- package/src/plugins/builtin/insider/index.tsx +6 -31
- package/src/plugins/builtin/news/index.tsx +5 -7
- package/src/plugins/builtin/news/wire/breaking/pane.test.tsx +6 -8
- package/src/plugins/builtin/news/wire/news/footer.ts +10 -11
- package/src/plugins/builtin/news/wire/read-state.test.ts +7 -0
- package/src/plugins/builtin/news/wire/read-state.ts +18 -28
- package/src/plugins/builtin/news/wire/rss/parser.ts +1 -11
- package/src/plugins/builtin/options/footer.test.ts +115 -0
- package/src/plugins/builtin/options/footer.ts +110 -0
- package/src/plugins/builtin/options/live-quotes.test.ts +238 -0
- package/src/plugins/builtin/options/live-quotes.ts +147 -0
- package/src/plugins/builtin/options/view.test.tsx +71 -1
- package/src/plugins/builtin/options/view.tsx +39 -24
- package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +103 -117
- package/src/plugins/builtin/portfolio-list/cli/render.ts +11 -5
- package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -135
- package/src/plugins/builtin/portfolio-list/header.tsx +9 -4
- package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +6 -1
- package/src/plugins/builtin/portfolio-list/quick-add/resolution.ts +4 -2
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +24 -52
- package/src/plugins/builtin/sec/filing-content.test.ts +41 -0
- package/src/plugins/builtin/sec/filing-content.ts +94 -0
- package/src/plugins/builtin/sec/index.tsx +21 -104
- package/src/plugins/builtin/sectors/sector-model.ts +1 -7
- package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -0
- package/src/plugins/builtin/shared/pane-footer.ts +82 -0
- package/src/plugins/builtin/shared/read-state.ts +64 -3
- package/src/plugins/builtin/substack/read-state.ts +16 -41
- package/src/plugins/builtin/thirteenf/pane.tsx +24 -73
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +10 -10
- package/src/plugins/builtin/yield-curve/index.tsx +11 -9
- package/src/plugins/ibkr/dialogs.tsx +3 -3
- package/src/plugins/ibkr/gateway/fundamentals.ts +1 -1
- package/src/plugins/ibkr/gateway/history-requests.ts +2 -2
- package/src/plugins/ibkr/gateway/history.ts +2 -2
- package/src/plugins/ibkr/gateway/selection.ts +2 -2
- package/src/plugins/ibkr/gateway/service/index.ts +2 -2
- package/src/plugins/ibkr/gateway/service/native.ts +2 -2
- package/src/plugins/plugin-persistence.ts +3 -4
- package/src/plugins/prediction-markets/controller/keyboard.ts +1 -1
- package/src/plugins/prediction-markets/controller/live-updates.ts +6 -5
- package/src/plugins/prediction-markets/detail/book.tsx +2 -2
- package/src/plugins/prediction-markets/detail/outcomes.tsx +3 -1
- package/src/plugins/prediction-markets/detail/pane.tsx +3 -1
- package/src/plugins/prediction-markets/detail/trades.tsx +3 -3
- package/src/plugins/registry/context.ts +3 -4
- package/src/plugins/registry/index.ts +5 -6
- package/src/react/input.test.ts +126 -3
- package/src/react/input.ts +120 -1
- package/src/remote/app-host.tsx +2 -13
- package/src/renderers/electrobun/bun/desktop/backend-requests.ts +44 -60
- package/src/renderers/electrobun/bun/desktop/capability-bridge.ts +15 -13
- package/src/renderers/electrobun/bun/desktop/host-requests.ts +26 -22
- package/src/renderers/electrobun/bun/desktop/http-fetch.ts +5 -1
- package/src/renderers/electrobun/bun/desktop/initialization.ts +11 -6
- package/src/renderers/electrobun/bun/desktop/media.ts +5 -3
- package/src/renderers/electrobun/bun/desktop/plugin-state.ts +21 -22
- package/src/renderers/electrobun/bun/desktop/window-controls.ts +3 -1
- package/src/renderers/electrobun/bun/desktop/workspace/requests.ts +18 -18
- package/src/renderers/electrobun/bun/index.ts +123 -83
- package/src/renderers/electrobun/shared/protocol.ts +146 -7
- package/src/renderers/electrobun/view/app-services.ts +5 -8
- package/src/renderers/electrobun/view/backend-rpc.ts +18 -8
- package/src/renderers/electrobun/view/broker-remote-client.ts +2 -2
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +5 -22
- package/src/renderers/electrobun/view/config-host.ts +1 -1
- package/src/renderers/electrobun/view/context-menu.ts +1 -17
- package/src/renderers/electrobun/view/data-table/index.tsx +0 -1
- package/src/renderers/electrobun/view/data-table/row.tsx +0 -4
- package/src/renderers/electrobun/view/desktop/control-styles.ts +37 -34
- package/src/renderers/electrobun/view/desktop/controls.tsx +36 -33
- package/src/renderers/electrobun/view/desktop/list-view.tsx +15 -12
- package/src/renderers/electrobun/view/desktop/popover.tsx +2 -3
- package/src/renderers/electrobun/view/dialog-host.tsx +2 -3
- package/src/renderers/electrobun/view/fatal-screen.tsx +0 -1
- package/src/renderers/electrobun/view/host/box.tsx +0 -1
- package/src/renderers/electrobun/view/host/chart-surface.tsx +0 -1
- package/src/renderers/electrobun/view/host/input.tsx +0 -1
- package/src/renderers/electrobun/view/host/media-surface.tsx +0 -1
- package/src/renderers/electrobun/view/host/native.ts +0 -1
- package/src/renderers/electrobun/view/host/scroll-box.tsx +0 -1
- package/src/renderers/electrobun/view/host/tabs.tsx +0 -1
- package/src/renderers/electrobun/view/host/text.tsx +0 -1
- package/src/renderers/electrobun/view/http-fetch.ts +3 -11
- package/src/renderers/electrobun/view/input-host.tsx +10 -53
- package/src/renderers/electrobun/view/key-event.ts +0 -1
- package/src/renderers/electrobun/view/main.tsx +3 -3
- package/src/renderers/electrobun/view/native-renderer.ts +0 -1
- package/src/renderers/electrobun/view/native-stubs/backend-rpc.ts +13 -1
- package/src/renderers/electrobun/view/native-stubs/chart/surface-manager.ts +11 -0
- package/src/renderers/electrobun/view/native-stubs/native-stubs.test.ts +47 -0
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +6 -44
- package/src/renderers/electrobun/view/remote/persistence.ts +6 -2
- package/src/renderers/electrobun/view/remote/quote-subscription-registry.test.ts +86 -0
- package/src/renderers/electrobun/view/remote/quote-subscription-registry.ts +72 -0
- package/src/renderers/electrobun/view/remote/ticker-repository.ts +2 -2
- package/src/renderers/electrobun/view/toast-host.tsx +0 -1
- package/src/renderers/electrobun/view/ui-host.tsx +1 -2
- package/src/renderers/electrobun/view/update-host.ts +1 -1
- package/src/renderers/opentui/chart-surface.tsx +2 -1
- package/src/renderers/opentui/dialog-host.tsx +20 -4
- package/src/renderers/opentui/image/loader.ts +12 -2
- package/src/renderers/opentui/input-host.tsx +7 -49
- package/src/renderers/opentui/start.tsx +2 -0
- package/src/sources/gloomberb-cloud/history-quality.ts +44 -0
- package/src/sources/gloomberb-cloud/index.test.ts +173 -0
- package/src/sources/gloomberb-cloud/index.ts +42 -20
- package/src/sources/gloomberb-cloud/normalizers.ts +9 -3
- package/src/sources/provider-router/cache.ts +1 -1
- package/src/sources/provider-router/document-routes.ts +10 -5
- package/src/sources/provider-router/financials.test.ts +14 -0
- package/src/sources/provider-router/financials.ts +6 -1
- package/src/sources/provider-router/history.test.ts +163 -1
- package/src/sources/provider-router/history.ts +278 -347
- package/src/sources/provider-router/index.ts +2 -2
- package/src/sources/provider-router/routing.test.ts +39 -0
- package/src/sources/provider-router/routing.ts +24 -11
- package/src/sources/provider-router/supplemental.ts +37 -17
- package/src/sources/sec-edgar/content.ts +2 -12
- package/src/sources/sec-edgar.ts +2 -13
- package/src/sources/yahoo-finance/history.ts +2 -2
- package/src/sources/yahoo-finance/options.ts +5 -0
- package/src/sources/yahoo-finance.ts +2 -2
- package/src/state/app/bootstrap.ts +2 -2
- package/src/state/app/context/index.tsx +2 -2
- package/src/state/hooks/quote-streaming.ts +66 -1
- package/src/state/hooks/session-snapshot.ts +2 -2
- package/src/state/selectors.ts +0 -9
- package/src/sync/controller.test.ts +98 -0
- package/src/sync/controller.ts +29 -5
- package/src/sync/react.ts +2 -2
- package/src/sync/types.ts +2 -2
- package/src/theme/colors.test.ts +10 -0
- package/src/theme/colors.ts +75 -78
- package/src/theme/theme-context.test.tsx +67 -0
- package/src/theme/theme-context.tsx +9 -5
- package/src/tickers/open-target.ts +2 -2
- package/src/tickers/search/upsert.ts +2 -2
- package/src/time-series/alignment.ts +0 -7
- package/src/time-series/chart-data.ts +145 -0
- package/src/time-series/date-window.ts +44 -0
- package/src/time-series/history-window.ts +21 -0
- package/src/time-series/hooks.test.ts +59 -0
- package/src/time-series/hooks.ts +33 -12
- package/src/time-series/market-resolution.ts +2 -2
- package/src/time-series/market.ts +1 -1
- package/src/time-series/range.ts +9 -0
- package/src/{components/chart/core → time-series}/resolution.ts +3 -102
- package/src/time-series/resolve.test.ts +203 -1
- package/src/time-series/resolve.ts +96 -18
- package/src/time-series/spec-studies.test.ts +15 -0
- package/src/time-series/spec.ts +2 -2
- package/src/time-series/studies.ts +5 -2
- package/src/time-series/types.ts +3 -1
- package/src/time-series/use-chart-resolution.test.tsx +358 -0
- package/src/time-series/use-chart-resolution.ts +46 -4
- package/src/types/broker.ts +2 -2
- package/src/types/data-provider.ts +3 -3
- package/src/types/financials.ts +12 -0
- package/src/types/plugin.ts +2 -2
- package/src/ui/context-menu.tsx +3 -2
- package/src/ui/dialog.tsx +2 -2
- package/src/utils/html-entities.ts +3 -5
- package/src/utils/main-thread-monitor.ts +1 -1
- package/src/utils/price-history.ts +5 -5
- package/src/version.ts +3 -1
- package/src/components/chart/core/viewport.test.ts +0 -8
- package/src/components/chart/core/viewport.ts +0 -24
- package/src/time-series/index.ts +0 -14
- /package/src/{components/chart/core → time-series}/resolution.test.ts +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Dispatch } from "react";
|
|
2
2
|
import type { AppAction, AppState } from "../../../state/app/context";
|
|
3
|
-
import type {
|
|
3
|
+
import type { AppTickerRepositoryPort } from "../../../core/app-service-ports";
|
|
4
4
|
import type { PluginRegistry } from "../../../plugins/registry";
|
|
5
5
|
import { isManualPortfolio } from "../../../plugins/builtin/portfolio-list/mutations";
|
|
6
6
|
import type { DataProvider } from "../../../types/data-provider";
|
|
@@ -10,7 +10,7 @@ import { parseTickerListInput } from "../../../tickers/list";
|
|
|
10
10
|
|
|
11
11
|
export interface SharedWorkflowDeps {
|
|
12
12
|
dataProvider: DataProvider;
|
|
13
|
-
tickerRepository:
|
|
13
|
+
tickerRepository: AppTickerRepositoryPort;
|
|
14
14
|
pluginRegistry: PluginRegistry;
|
|
15
15
|
dispatch: Dispatch<AppAction>;
|
|
16
16
|
getState: () => AppState;
|
|
@@ -3,52 +3,44 @@ import { act } from "react";
|
|
|
3
3
|
import { testRender } from "../../renderers/opentui/test-utils";
|
|
4
4
|
import { AppContext, PaneInstanceProvider, createInitialState } from "../../state/app/context";
|
|
5
5
|
import { createDefaultConfig } from "../../types/config";
|
|
6
|
-
import { Box, Text } from "../../ui";
|
|
7
6
|
import { FeedDataTableStackView } from "./stack-view";
|
|
7
|
+
import { setLanguage } from "../../i18n";
|
|
8
8
|
|
|
9
9
|
let testSetup: Awaited<ReturnType<typeof testRender>> | undefined;
|
|
10
10
|
|
|
11
11
|
afterEach(async () => {
|
|
12
12
|
await act(async () => testSetup?.renderer.destroy());
|
|
13
13
|
testSetup = undefined;
|
|
14
|
+
setLanguage("en");
|
|
14
15
|
});
|
|
15
16
|
|
|
16
|
-
test("
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
await
|
|
20
|
-
|
|
21
|
-
<
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
</AppContext>,
|
|
39
|
-
{ width: 80, height: 12 },
|
|
40
|
-
);
|
|
41
|
-
await testSetup.renderOnce();
|
|
42
|
-
});
|
|
17
|
+
test("rebuilds translated columns when the app language changes", async () => {
|
|
18
|
+
const state = createInitialState(createDefaultConfig("/tmp/gloomberb-feed-table-language"));
|
|
19
|
+
const items = [{ id: "story", eyebrow: "Wire", title: "Story", timestamp: "2026-01-01" }];
|
|
20
|
+
testSetup = await testRender(
|
|
21
|
+
<AppContext value={{ state, dispatch: () => {} }}>
|
|
22
|
+
<PaneInstanceProvider paneId="news:test">
|
|
23
|
+
<FeedDataTableStackView
|
|
24
|
+
width={80}
|
|
25
|
+
height={8}
|
|
26
|
+
focused
|
|
27
|
+
items={items}
|
|
28
|
+
selectedIdx={0}
|
|
29
|
+
onSelect={() => {}}
|
|
30
|
+
sourceLabel="Source"
|
|
31
|
+
titleLabel="Headline"
|
|
32
|
+
/>
|
|
33
|
+
</PaneInstanceProvider>
|
|
34
|
+
</AppContext>,
|
|
35
|
+
{ width: 80, height: 8 },
|
|
36
|
+
);
|
|
37
|
+
await act(async () => testSetup?.renderOnce());
|
|
38
|
+
expect(testSetup.captureCharFrame()).toContain("Source");
|
|
43
39
|
|
|
44
40
|
await act(async () => {
|
|
45
|
-
(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
preventDefault() {}, stopPropagation() {},
|
|
49
|
-
});
|
|
50
|
-
await testSetup!.renderOnce();
|
|
41
|
+
setLanguage("zh-CN");
|
|
42
|
+
await testSetup?.renderOnce();
|
|
43
|
+
await testSetup?.renderOnce();
|
|
51
44
|
});
|
|
52
|
-
|
|
53
|
-
expect(keyHits).toBe(1);
|
|
45
|
+
expect(testSetup.captureCharFrame()).toContain("来源");
|
|
54
46
|
});
|
|
@@ -2,6 +2,7 @@ import { Box, ScrollBox, Text } from "../../ui";
|
|
|
2
2
|
import { TextAttributes, type ScrollBoxRenderable } from "../../ui";
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react";
|
|
4
4
|
import { t } from "../../i18n";
|
|
5
|
+
import { useAppLanguage } from "../../i18n/react";
|
|
5
6
|
import { displayWidth, formatTimeAgo } from "../../utils/format";
|
|
6
7
|
import { colors } from "../../theme/colors";
|
|
7
8
|
import { isPlainKey } from "../../utils/keyboard";
|
|
@@ -148,6 +149,7 @@ export function FeedDataTableStackView({
|
|
|
148
149
|
onOpenItem,
|
|
149
150
|
onOpenItemIdChange,
|
|
150
151
|
}: FeedDataTableStackViewProps) {
|
|
152
|
+
const language = useAppLanguage();
|
|
151
153
|
const [sortPreference, setSortPreference] = useState<SortPreference>({
|
|
152
154
|
columnId: "time",
|
|
153
155
|
direction: "desc",
|
|
@@ -157,7 +159,7 @@ export function FeedDataTableStackView({
|
|
|
157
159
|
const detailTextWidth = Math.max(width - 2, 12);
|
|
158
160
|
const columns = useMemo(
|
|
159
161
|
() => buildColumns(width, t(sourceLabel), t(titleLabel), items),
|
|
160
|
-
[items, sourceLabel, titleLabel, width],
|
|
162
|
+
[items, language, sourceLabel, titleLabel, width],
|
|
161
163
|
);
|
|
162
164
|
const sortedRows = useMemo(() => {
|
|
163
165
|
return sortIndexedStackRows(items, sortPreference, compareRows);
|
|
@@ -6,7 +6,7 @@ import { useAppDispatch, useAppSelector } from "../../state/app/context";
|
|
|
6
6
|
import type { DesktopWindowBridge } from "../../types/desktop-window";
|
|
7
7
|
import { findPaneInstance } from "../../types/config";
|
|
8
8
|
import type { PluginRegistry } from "../../plugins/registry";
|
|
9
|
-
import {
|
|
9
|
+
import { floatingPaneBg, floatingPaneTitleBg, paneTitleText } from "../../theme/colors";
|
|
10
10
|
import { useThemeColors } from "../../theme/theme-context";
|
|
11
11
|
import { hasPaneFooterContent, PaneFooterBar, PaneFooterProvider } from "./pane/footer";
|
|
12
12
|
import { PaneBodyFrame, getPaneWindowAttributes } from "./pane/frame";
|
|
@@ -32,7 +32,7 @@ function stopMouse(event?: { stopPropagation?: () => void; preventDefault?: () =
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export function DetachedPaneShell({ pluginRegistry, desktopWindowBridge }: DetachedPaneShellProps) {
|
|
35
|
-
useThemeColors();
|
|
35
|
+
const colors = useThemeColors();
|
|
36
36
|
const dispatch = useAppDispatch();
|
|
37
37
|
const rendererHost = useRendererHost();
|
|
38
38
|
const config = useAppSelector((state) => state.config);
|
|
@@ -134,8 +134,8 @@ export function DetachedPaneShell({ pluginRegistry, desktopWindowBridge }: Detac
|
|
|
134
134
|
const reserveFooter = shouldReservePaneFooter(nativePaneChrome, showFooter);
|
|
135
135
|
const renderFooter = reserveFooter || showFooter;
|
|
136
136
|
const headerHeightRows = titleBarOverlay ? TITLEBAR_OVERLAY_HEIGHT_PX / cellHeightPx : 1;
|
|
137
|
-
const background = floatingPaneBg(focused);
|
|
138
|
-
const titleBackground = floatingPaneTitleBg(focused);
|
|
137
|
+
const background = floatingPaneBg(focused, colors);
|
|
138
|
+
const titleBackground = floatingPaneTitleBg(focused, colors);
|
|
139
139
|
const bodyFrame = resolvePaneBodyFrame({
|
|
140
140
|
width,
|
|
141
141
|
height,
|
|
@@ -184,11 +184,11 @@ export function DetachedPaneShell({ pluginRegistry, desktopWindowBridge }: Detac
|
|
|
184
184
|
style={{ position: "relative" }}
|
|
185
185
|
>
|
|
186
186
|
<Box flexGrow={1} minWidth={0} overflow="hidden">
|
|
187
|
-
<Text fg={paneTitleText(focused, true)} selectable={false} data-gloom-role="pane-title">{title}</Text>
|
|
187
|
+
<Text fg={paneTitleText(focused, true, colors)} selectable={false} data-gloom-role="pane-title">{title}</Text>
|
|
188
188
|
</Box>
|
|
189
189
|
{hasPaneSettings && (
|
|
190
190
|
<Text
|
|
191
|
-
fg={paneTitleText(focused, true)}
|
|
191
|
+
fg={paneTitleText(focused, true, colors)}
|
|
192
192
|
selectable={false}
|
|
193
193
|
className="electrobun-webkit-app-region-no-drag"
|
|
194
194
|
data-gloom-role="pane-action"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Box, SpinnerMark, Text, TextAttributes, useRendererHost, useUiCapabilities } from "../../ui";
|
|
2
2
|
import { useCallback, useEffect, type ReactNode } from "react";
|
|
3
|
-
import { blendHex,
|
|
3
|
+
import { blendHex, priceColor } from "../../theme/colors";
|
|
4
4
|
import { useThemeColors } from "../../theme/theme-context";
|
|
5
5
|
import { useAppActive } from "../../state/app/activity";
|
|
6
6
|
import { useAppDispatch, useAppSelector } from "../../state/app/context";
|
|
@@ -26,21 +26,24 @@ const UPDATE_NOTICE_DURATION_MS = 5_000;
|
|
|
26
26
|
|
|
27
27
|
function DesktopHeaderPill({
|
|
28
28
|
children,
|
|
29
|
-
backgroundColor
|
|
30
|
-
borderColor
|
|
29
|
+
backgroundColor,
|
|
30
|
+
borderColor,
|
|
31
31
|
}: {
|
|
32
32
|
children: ReactNode;
|
|
33
33
|
backgroundColor?: string;
|
|
34
34
|
borderColor?: string;
|
|
35
35
|
}) {
|
|
36
|
+
const colors = useThemeColors();
|
|
37
|
+
const resolvedBackgroundColor = backgroundColor ?? blendHex(colors.header, colors.bg, 0.28);
|
|
38
|
+
const resolvedBorderColor = borderColor ?? blendHex(colors.border, colors.headerText, 0.22);
|
|
36
39
|
return (
|
|
37
40
|
<Box
|
|
38
41
|
height={1}
|
|
39
42
|
flexDirection="row"
|
|
40
43
|
alignItems="center"
|
|
41
|
-
backgroundColor={
|
|
44
|
+
backgroundColor={resolvedBackgroundColor}
|
|
42
45
|
style={{
|
|
43
|
-
border: `1px solid ${
|
|
46
|
+
border: `1px solid ${resolvedBorderColor}`,
|
|
44
47
|
borderRadius: 5,
|
|
45
48
|
paddingInline: 6,
|
|
46
49
|
}}
|
|
@@ -51,6 +54,7 @@ function DesktopHeaderPill({
|
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
function UpdateStatus() {
|
|
57
|
+
const colors = useThemeColors();
|
|
54
58
|
const dispatch = useAppDispatch();
|
|
55
59
|
const updateAvailable = useAppSelector(selectUpdateAvailable);
|
|
56
60
|
const updateProgress = useAppSelector(selectUpdateProgress);
|
|
@@ -91,7 +95,7 @@ function UpdateStatus() {
|
|
|
91
95
|
return <Text fg={colors.headerText}>{t(updateProgress.message ?? "Update installed, restart to apply")}</Text>;
|
|
92
96
|
}
|
|
93
97
|
if (updateProgress.phase === "error") {
|
|
94
|
-
return <Text fg={colors.headerText}>{tf("Update failed: {error}", { error: updateProgress.error })}</Text>;
|
|
98
|
+
return <Text fg={colors.headerText}>{tf("Update failed: {error}", { error: updateProgress.error ?? "Unknown error" })}</Text>;
|
|
95
99
|
}
|
|
96
100
|
}
|
|
97
101
|
|
|
@@ -130,7 +134,7 @@ function UpdateStatus() {
|
|
|
130
134
|
}
|
|
131
135
|
|
|
132
136
|
export function Header() {
|
|
133
|
-
useThemeColors();
|
|
137
|
+
const colors = useThemeColors();
|
|
134
138
|
const rendererHost = useRendererHost();
|
|
135
139
|
const baseCurrency = useAppSelector(selectBaseCurrency);
|
|
136
140
|
const appActive = useAppActive();
|
|
@@ -153,7 +157,7 @@ export function Header() {
|
|
|
153
157
|
}, [appActive]);
|
|
154
158
|
|
|
155
159
|
const activeSpyQuote = getActiveQuoteDisplay(spyQuote);
|
|
156
|
-
const spyColor = activeSpyQuote ? priceColor(activeSpyQuote.change) : colors.headerText;
|
|
160
|
+
const spyColor = activeSpyQuote ? priceColor(activeSpyQuote.change, colors) : colors.headerText;
|
|
157
161
|
const spyText = activeSpyQuote
|
|
158
162
|
? `SPY ${formatMarketPrice(activeSpyQuote.price, { assetCategory: "ETF" })} ${formatPercentRaw(activeSpyQuote.changePercent)}`
|
|
159
163
|
: "SPY —";
|
|
@@ -166,7 +170,7 @@ export function Header() {
|
|
|
166
170
|
// Market status
|
|
167
171
|
const mktState = spyQuote?.marketState;
|
|
168
172
|
const mktLabel = mktState ? t(marketStateLabel(mktState)) : "";
|
|
169
|
-
const mktColor = mktState ? marketStateColor(mktState) : colors.headerText;
|
|
173
|
+
const mktColor = mktState ? marketStateColor(mktState, colors) : colors.headerText;
|
|
170
174
|
|
|
171
175
|
if (titleBarOverlay) {
|
|
172
176
|
return (
|
|
@@ -2,6 +2,7 @@ import { afterEach, describe, expect, test } from "bun:test";
|
|
|
2
2
|
import { act, type Dispatch } from "react";
|
|
3
3
|
import { testRender } from "../../../renderers/opentui/test-utils";
|
|
4
4
|
import { AppProvider, useAppDispatch, type AppAction } from "../../../state/app/context";
|
|
5
|
+
import { setLanguage, t } from "../../../i18n";
|
|
5
6
|
import { applyTheme, colors } from "../../../theme/colors";
|
|
6
7
|
import { getTheme } from "../../../theme/themes";
|
|
7
8
|
import { createDefaultConfig } from "../../../types/config";
|
|
@@ -19,15 +20,22 @@ function ThemeColorProbe() {
|
|
|
19
20
|
return <text>{colors.textBright}</text>;
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
function LanguageProbe() {
|
|
24
|
+
return <text>{t("Done")}</text>;
|
|
25
|
+
}
|
|
26
|
+
|
|
22
27
|
describe("PaneContent", () => {
|
|
23
|
-
afterEach(() => {
|
|
24
|
-
testSetup
|
|
28
|
+
afterEach(async () => {
|
|
29
|
+
if (testSetup) {
|
|
30
|
+
await act(async () => testSetup?.renderer.destroy());
|
|
31
|
+
}
|
|
25
32
|
testSetup = undefined;
|
|
26
33
|
capturedDispatch = null;
|
|
27
34
|
applyTheme("amber");
|
|
35
|
+
setLanguage("en");
|
|
28
36
|
});
|
|
29
37
|
|
|
30
|
-
test("rerenders
|
|
38
|
+
test("rerenders legacy pane colors when the theme preview changes", async () => {
|
|
31
39
|
const config = {
|
|
32
40
|
...createDefaultConfig("/tmp/gloomberb-test"),
|
|
33
41
|
theme: "amber",
|
|
@@ -61,4 +69,35 @@ describe("PaneContent", () => {
|
|
|
61
69
|
expect(frame).toContain(getTheme("green").textBright);
|
|
62
70
|
expect(frame).not.toContain(getTheme("amber").textBright);
|
|
63
71
|
});
|
|
72
|
+
|
|
73
|
+
test("rerenders pane bodies when the app language changes", async () => {
|
|
74
|
+
const config = createDefaultConfig("/tmp/gloomberb-language-test");
|
|
75
|
+
|
|
76
|
+
testSetup = await testRender(
|
|
77
|
+
<AppProvider config={config}>
|
|
78
|
+
<PaneContent
|
|
79
|
+
component={LanguageProbe}
|
|
80
|
+
paneId="language:test"
|
|
81
|
+
paneType="test"
|
|
82
|
+
focused
|
|
83
|
+
width={24}
|
|
84
|
+
height={4}
|
|
85
|
+
/>
|
|
86
|
+
</AppProvider>,
|
|
87
|
+
{ width: 32, height: 6 },
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
await testSetup.renderOnce();
|
|
91
|
+
expect(testSetup.captureCharFrame()).toContain("Done");
|
|
92
|
+
|
|
93
|
+
await act(async () => {
|
|
94
|
+
setLanguage("zh-CN");
|
|
95
|
+
await testSetup!.renderOnce();
|
|
96
|
+
});
|
|
97
|
+
await testSetup.renderOnce();
|
|
98
|
+
|
|
99
|
+
const frame = testSetup.captureCharFrame();
|
|
100
|
+
expect(frame).toContain("完成");
|
|
101
|
+
expect(frame).not.toContain("Done");
|
|
102
|
+
});
|
|
64
103
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { memo, useCallback } from "react";
|
|
2
|
+
import { useAppLanguage } from "../../../i18n/react";
|
|
2
3
|
import { PaneInstanceProvider } from "../../../state/app/context";
|
|
3
|
-
import { PaneKeyboardScrollController } from "../../../state/pane-scroll-registry";
|
|
4
4
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
5
|
+
import { PaneKeyboardScrollController } from "../../../state/pane-scroll-registry";
|
|
5
6
|
import type { PaneDef } from "../../../types/plugin";
|
|
6
7
|
import { Box } from "../../../ui";
|
|
7
8
|
|
|
@@ -24,6 +25,7 @@ export const PaneContent = memo(function PaneContent({
|
|
|
24
25
|
height,
|
|
25
26
|
onClose,
|
|
26
27
|
}: PaneContentProps) {
|
|
28
|
+
useAppLanguage();
|
|
27
29
|
useThemeColors();
|
|
28
30
|
const close = useCallback(() => {
|
|
29
31
|
onClose?.(paneId);
|
|
@@ -8,14 +8,16 @@ import {
|
|
|
8
8
|
usePaneFooter,
|
|
9
9
|
} from "./index";
|
|
10
10
|
import { useExternalLinkFooter } from "../../../use-external-link-footer";
|
|
11
|
+
import { setLanguage, t } from "../../../../i18n";
|
|
11
12
|
|
|
12
13
|
let testSetup: Awaited<ReturnType<typeof testRender>> | undefined;
|
|
13
14
|
|
|
14
|
-
afterEach(() => {
|
|
15
|
+
afterEach(async () => {
|
|
15
16
|
if (testSetup) {
|
|
16
|
-
testSetup
|
|
17
|
+
await act(async () => testSetup?.renderer.destroy());
|
|
17
18
|
testSetup = undefined;
|
|
18
19
|
}
|
|
20
|
+
setLanguage("en");
|
|
19
21
|
});
|
|
20
22
|
|
|
21
23
|
function Registration({
|
|
@@ -54,6 +56,26 @@ function ExternalLinkRegistration() {
|
|
|
54
56
|
return null;
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
function TranslatedRegistration() {
|
|
60
|
+
usePaneFooter("translated", () => ({
|
|
61
|
+
info: [{ id: "state", parts: [{ text: t("Open"), tone: "value" }] }],
|
|
62
|
+
}), []);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function TranslatedFooterHarness() {
|
|
67
|
+
return (
|
|
68
|
+
<PaneFooterProvider>
|
|
69
|
+
{(footer) => (
|
|
70
|
+
<Box width={40} height={1}>
|
|
71
|
+
<TranslatedRegistration />
|
|
72
|
+
<PaneFooterBar footer={footer} focused width={40} />
|
|
73
|
+
</Box>
|
|
74
|
+
)}
|
|
75
|
+
</PaneFooterProvider>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
57
79
|
function FooterHarness({
|
|
58
80
|
focused = false,
|
|
59
81
|
onRefresh,
|
|
@@ -89,6 +111,27 @@ function ExternalLinkFooterHarness() {
|
|
|
89
111
|
}
|
|
90
112
|
|
|
91
113
|
describe("PaneFooterBar", () => {
|
|
114
|
+
test("rebuilds translated registrations when the app language changes", async () => {
|
|
115
|
+
testSetup = await testRender(<TranslatedFooterHarness />, { width: 40, height: 1 });
|
|
116
|
+
await act(async () => {
|
|
117
|
+
await testSetup?.renderOnce();
|
|
118
|
+
await testSetup?.renderOnce();
|
|
119
|
+
});
|
|
120
|
+
expect(testSetup.captureCharFrame()).toContain("Open");
|
|
121
|
+
|
|
122
|
+
await act(async () => {
|
|
123
|
+
setLanguage("zh-CN");
|
|
124
|
+
await Promise.resolve();
|
|
125
|
+
});
|
|
126
|
+
await act(async () => {
|
|
127
|
+
await testSetup?.renderOnce();
|
|
128
|
+
await testSetup?.renderOnce();
|
|
129
|
+
await Promise.resolve();
|
|
130
|
+
await testSetup?.renderOnce();
|
|
131
|
+
});
|
|
132
|
+
expect(testSetup.captureCharFrame()).toContain("打开");
|
|
133
|
+
});
|
|
134
|
+
|
|
92
135
|
test("hides hints on inactive footers but keeps info visible", async () => {
|
|
93
136
|
testSetup = await testRender(<FooterHarness />, { width: 64, height: 1 });
|
|
94
137
|
await act(async () => {
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
type PaneFooterRegistration,
|
|
18
18
|
type PaneHint,
|
|
19
19
|
} from "./model";
|
|
20
|
+
import { useAppLanguage } from "../../../../i18n/react";
|
|
20
21
|
|
|
21
22
|
const usePaneFooterRegistrationEffect =
|
|
22
23
|
typeof document === "undefined" ? useEffect : useLayoutEffect;
|
|
@@ -86,6 +87,7 @@ export function usePaneFooter(
|
|
|
86
87
|
factory: () => PaneFooterRegistration | null | undefined,
|
|
87
88
|
deps: DependencyList,
|
|
88
89
|
) {
|
|
90
|
+
const language = useAppLanguage();
|
|
89
91
|
const context = useContext(PaneFooterContext);
|
|
90
92
|
const previousRegistrationRef = useRef<PaneFooterRegistration | null>(null);
|
|
91
93
|
|
|
@@ -103,7 +105,7 @@ export function usePaneFooter(
|
|
|
103
105
|
previousRegistrationRef.current = nextRegistration;
|
|
104
106
|
context.register(registrationId, nextRegistration);
|
|
105
107
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
106
|
-
}, [context, registrationId, ...deps]);
|
|
108
|
+
}, [context, language, registrationId, ...deps]);
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
export function usePaneHints(
|
|
@@ -28,7 +28,6 @@ import {
|
|
|
28
28
|
selectLayout,
|
|
29
29
|
selectStatusBarVisible,
|
|
30
30
|
} from "../../../state/selectors-ui";
|
|
31
|
-
import { colors } from "../../../theme/colors";
|
|
32
31
|
import { useThemeColors } from "../../../theme/theme-context";
|
|
33
32
|
import { getPaneDisplayTitle } from "../pane/title";
|
|
34
33
|
import { getShortcutDisplayMode } from "../../../utils/shortcut-labels";
|
|
@@ -90,7 +89,7 @@ export function Shell({
|
|
|
90
89
|
desktopDockPreview,
|
|
91
90
|
commandBarNativeOccluder = null,
|
|
92
91
|
}: ShellProps) {
|
|
93
|
-
useThemeColors();
|
|
92
|
+
const colors = useThemeColors();
|
|
94
93
|
const dispatch = useAppDispatch();
|
|
95
94
|
const config = useAppSelector((state) => state.config);
|
|
96
95
|
const paneState = useAppSelector((state) => state.paneState);
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
resolveNativeDockDividers,
|
|
15
15
|
type DividerPreviewState,
|
|
16
16
|
} from "./window-state";
|
|
17
|
-
import type { WindowEditDockMovePreview } from "../../window-edit/
|
|
17
|
+
import type { WindowEditDockMovePreview } from "../../window-edit/presentation";
|
|
18
18
|
|
|
19
19
|
interface ShellNativeSurfaceMenuState {
|
|
20
20
|
paneId: string;
|
|
@@ -3,7 +3,7 @@ import type { NativeOccluder, NativePaneLayer } from "../../../chart/native/surf
|
|
|
3
3
|
import { DEFAULT_HEADER_HEIGHT } from "../chrome";
|
|
4
4
|
import type { DragPreview, HoverOverlay } from "../drag";
|
|
5
5
|
import { MENU_Z_INDEX } from "../menu";
|
|
6
|
-
import type { WindowEditDockMovePreview } from "../../window-edit/
|
|
6
|
+
import type { WindowEditDockMovePreview } from "../../window-edit/presentation";
|
|
7
7
|
|
|
8
8
|
export interface FloatingPreviewRect {
|
|
9
9
|
paneId: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Box, Span, Text, TextAttributes, contextMenuDivider, useContextMenu, useUiCapabilities } from "../../ui";
|
|
2
2
|
import { useCallback, useEffect, useState } from "react";
|
|
3
|
-
import { blendHex,
|
|
3
|
+
import { blendHex, hoverBg } from "../../theme/colors";
|
|
4
4
|
import { t, tf } from "../../i18n";
|
|
5
5
|
import { useThemeColors } from "../../theme/theme-context";
|
|
6
6
|
import { useAppDispatch, useAppSelector } from "../../state/app/context";
|
|
@@ -55,7 +55,6 @@ function truncate(text: string, width: number): string {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
export function StatusBar() {
|
|
58
|
-
useThemeColors();
|
|
59
58
|
const { nativePaneChrome, nativeContextMenu } = useUiCapabilities();
|
|
60
59
|
const { showContextMenu } = useContextMenu();
|
|
61
60
|
const registry = getSharedRegistry();
|
|
@@ -255,6 +254,7 @@ function NativeStatusBar({
|
|
|
255
254
|
showGridlockTip,
|
|
256
255
|
...props
|
|
257
256
|
}: StatusBarViewProps) {
|
|
257
|
+
const colors = useThemeColors();
|
|
258
258
|
return (
|
|
259
259
|
<Box
|
|
260
260
|
flexDirection="row"
|
|
@@ -271,9 +271,9 @@ function NativeStatusBar({
|
|
|
271
271
|
paddingInline: 8,
|
|
272
272
|
}}
|
|
273
273
|
>
|
|
274
|
-
<StatusBarLayoutControl
|
|
274
|
+
<StatusBarLayoutControl nativePaneChrome {...props} />
|
|
275
275
|
{showGridlockTip && <NativeGridlockTip {...props} />}
|
|
276
|
-
<StatusBarWidgets
|
|
276
|
+
<StatusBarWidgets />
|
|
277
277
|
</Box>
|
|
278
278
|
);
|
|
279
279
|
}
|
|
@@ -284,6 +284,7 @@ function TerminalStatusBar({
|
|
|
284
284
|
showGridlockTip,
|
|
285
285
|
...props
|
|
286
286
|
}: StatusBarViewProps) {
|
|
287
|
+
const colors = useThemeColors();
|
|
287
288
|
return (
|
|
288
289
|
<Box
|
|
289
290
|
flexDirection="row"
|
|
@@ -295,9 +296,9 @@ function TerminalStatusBar({
|
|
|
295
296
|
void openLayoutContextMenu(activeLayoutIdx, event);
|
|
296
297
|
}}
|
|
297
298
|
>
|
|
298
|
-
<StatusBarLayoutControl
|
|
299
|
+
<StatusBarLayoutControl nativePaneChrome={false} {...props} />
|
|
299
300
|
{showGridlockTip && <TerminalGridlockTip {...props} />}
|
|
300
|
-
<StatusBarWidgets
|
|
301
|
+
<StatusBarWidgets />
|
|
301
302
|
</Box>
|
|
302
303
|
);
|
|
303
304
|
}
|
|
@@ -360,11 +361,12 @@ function CommandBarHint({
|
|
|
360
361
|
}: Pick<StatusBarViewProps, "hoveredControl" | "openCommandBar" | "setHoveredControl"> & {
|
|
361
362
|
nativePaneChrome: boolean;
|
|
362
363
|
}) {
|
|
364
|
+
const colors = useThemeColors();
|
|
363
365
|
const hovered = hoveredControl === "command-bar";
|
|
364
366
|
return (
|
|
365
367
|
<Text
|
|
366
368
|
fg={hovered ? colors.text : colors.textDim}
|
|
367
|
-
{...(!nativePaneChrome ? { bg: hovered ? hoverBg() : undefined } : {})}
|
|
369
|
+
{...(!nativePaneChrome ? { bg: hovered ? hoverBg(colors) : undefined } : {})}
|
|
368
370
|
onMouseOver={() => setHoveredControl((current) => (current === "command-bar" ? current : "command-bar"))}
|
|
369
371
|
onMouseDown={openCommandBar}
|
|
370
372
|
{...(nativePaneChrome ? { "data-gloom-interactive": "true" } : {})}
|
|
@@ -380,6 +382,7 @@ function NativeGridlockTip({
|
|
|
380
382
|
hoveredControl,
|
|
381
383
|
setHoveredControl,
|
|
382
384
|
}: Pick<StatusBarViewProps, "dismissGridlockTip" | "handleGridlockTip" | "hoveredControl" | "setHoveredControl">) {
|
|
385
|
+
const colors = useThemeColors();
|
|
383
386
|
return (
|
|
384
387
|
<Box paddingLeft={2} flexShrink={0} flexDirection="row" alignItems="center" gap={1}>
|
|
385
388
|
<Text fg={colors.textDim}>{t("Snapped a window?")}</Text>
|
|
@@ -410,12 +413,13 @@ function TerminalGridlockTip({
|
|
|
410
413
|
hoveredControl,
|
|
411
414
|
setHoveredControl,
|
|
412
415
|
}: Pick<StatusBarViewProps, "dismissGridlockTip" | "handleGridlockTip" | "hoveredControl" | "setHoveredControl">) {
|
|
416
|
+
const colors = useThemeColors();
|
|
413
417
|
return (
|
|
414
418
|
<Box paddingLeft={1} flexShrink={0} flexDirection="row">
|
|
415
419
|
<Text fg={colors.textDim}>{t("Snapped a window?")}</Text>
|
|
416
420
|
<Box width={1} />
|
|
417
421
|
<Box
|
|
418
|
-
backgroundColor={hoveredControl === "gridlock-tip" ? hoverBg() : colors.header}
|
|
422
|
+
backgroundColor={hoveredControl === "gridlock-tip" ? hoverBg(colors) : colors.header}
|
|
419
423
|
onMouseOver={() => setHoveredControl((current) => (current === "gridlock-tip" ? current : "gridlock-tip"))}
|
|
420
424
|
onMouseDown={handleGridlockTip}
|
|
421
425
|
>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Box, useRendererHost } from "../../ui";
|
|
2
2
|
import { useCallback } from "react";
|
|
3
3
|
import { t } from "../../i18n";
|
|
4
|
+
import { useAppLanguage } from "../../i18n/react";
|
|
4
5
|
import { TITLEBAR_OVERLAY_HEIGHT_PX } from "./titlebar-overlay";
|
|
5
6
|
|
|
6
7
|
const WINDOWS_CONTROL_SIZE_PX = TITLEBAR_OVERLAY_HEIGHT_PX;
|
|
@@ -10,11 +11,11 @@ type WindowControlAction = "minimize" | "toggle-maximize" | "close";
|
|
|
10
11
|
|
|
11
12
|
const WINDOWS_CONTROLS: Array<{
|
|
12
13
|
action: WindowControlAction;
|
|
13
|
-
|
|
14
|
+
labelKey: string;
|
|
14
15
|
}> = [
|
|
15
|
-
{ action: "minimize",
|
|
16
|
-
{ action: "toggle-maximize",
|
|
17
|
-
{ action: "close",
|
|
16
|
+
{ action: "minimize", labelKey: "Minimize" },
|
|
17
|
+
{ action: "toggle-maximize", labelKey: "Maximize" },
|
|
18
|
+
{ action: "close", labelKey: "Close" },
|
|
18
19
|
];
|
|
19
20
|
|
|
20
21
|
function stopMouse(event: { stopPropagation?: () => void; preventDefault?: () => void }) {
|
|
@@ -51,6 +52,7 @@ interface WindowControlsProps {
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
export function WindowControls({ windowKind = "main" }: WindowControlsProps) {
|
|
55
|
+
useAppLanguage();
|
|
54
56
|
const rendererHost = useRendererHost();
|
|
55
57
|
|
|
56
58
|
const controlWindow = useCallback((action: WindowControlAction, event: { stopPropagation?: () => void; preventDefault?: () => void }) => {
|
|
@@ -88,8 +90,8 @@ export function WindowControls({ windowKind = "main" }: WindowControlsProps) {
|
|
|
88
90
|
data-window-control-action={control.action}
|
|
89
91
|
data-gloom-interactive="true"
|
|
90
92
|
role="button"
|
|
91
|
-
aria-label={control.
|
|
92
|
-
title={control.
|
|
93
|
+
aria-label={t(control.labelKey)}
|
|
94
|
+
title={t(control.labelKey)}
|
|
93
95
|
onMouseDown={(event: { stopPropagation?: () => void; preventDefault?: () => void }) => controlWindow(control.action, event)}
|
|
94
96
|
>
|
|
95
97
|
<WindowControlIcon action={control.action} />
|
|
@@ -3,6 +3,7 @@ import { Box, Text, type InputRenderable } from "../../ui";
|
|
|
3
3
|
import { useViewport } from "../../react/input";
|
|
4
4
|
import { colors, applyTheme } from "../../theme/colors";
|
|
5
5
|
import { t } from "../../i18n";
|
|
6
|
+
import { useAppLanguage } from "../../i18n/react";
|
|
6
7
|
import { getThemeIds } from "../../theme/themes";
|
|
7
8
|
import type { AppConfig } from "../../types/config";
|
|
8
9
|
import type { PluginRegistry } from "../../plugins/registry";
|
|
@@ -32,6 +33,7 @@ interface OnboardingWizardProps {
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
export function OnboardingWizard({ config, pluginRegistry, onComplete }: OnboardingWizardProps) {
|
|
36
|
+
const language = useAppLanguage();
|
|
35
37
|
const { width: termWidth, height: termHeight } = useViewport();
|
|
36
38
|
const [step, setStep] = useState<OnboardingStep>("welcome");
|
|
37
39
|
const [themeIdx, setThemeIdx] = useState(0);
|
|
@@ -67,7 +69,7 @@ export function OnboardingWizard({ config, pluginRegistry, onComplete }: Onboard
|
|
|
67
69
|
});
|
|
68
70
|
}
|
|
69
71
|
return choices;
|
|
70
|
-
}, [brokerOptions]);
|
|
72
|
+
}, [brokerOptions, language]);
|
|
71
73
|
|
|
72
74
|
const activeBrokerFields = useMemo((): BrokerConfigField[] => {
|
|
73
75
|
if (!selectedBrokerId) return [];
|