gloomberb 0.10.3 → 0.10.4
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 +3 -3
- package/README.zh-CN.md +2 -2
- package/package.json +2 -1
- package/src/api-client/auth.ts +8 -0
- package/src/api-client/index.ts +70 -0
- package/src/api-client/types.ts +49 -0
- package/src/app/runtime/desktop-deeplink.test.ts +8 -0
- package/src/app/runtime/desktop-deeplink.ts +14 -1
- package/src/components/chart/composite/composite-chart.test.tsx +340 -17
- package/src/components/chart/composite/composite-chart.tsx +859 -68
- package/src/components/chart/composite/interactions.test.ts +78 -22
- package/src/components/chart/composite/interactions.ts +45 -17
- package/src/components/chart/composite/rasterizer.ts +8 -2
- package/src/components/chart/composite/renderers.test.ts +61 -1
- package/src/components/chart/composite/scene.ts +14 -4
- package/src/components/chart/composite/tools.test.ts +371 -0
- package/src/components/chart/composite/tools.ts +508 -0
- package/src/components/chart/composite/types.ts +4 -0
- package/src/components/chart/core/pointer.ts +2 -0
- package/src/components/chart/native/raster/primitives.ts +18 -0
- package/src/components/chart/price-axis-labels.tsx +42 -2
- package/src/components/chart/static/chart/axis-overlays.test.tsx +2 -0
- package/src/components/chart/static/chart/axis-overlays.tsx +46 -0
- package/src/components/command-bar/action-runtime.ts +3 -0
- package/src/components/command-bar/assist/inventory.test.ts +93 -0
- package/src/components/command-bar/assist/inventory.ts +92 -0
- package/src/components/command-bar/assist/model.test.ts +104 -0
- package/src/components/command-bar/assist/model.ts +169 -0
- package/src/components/command-bar/assist/runtime.ts +185 -0
- package/src/components/command-bar/commands/direct/index.ts +1 -1
- package/src/components/command-bar/keyboard-shortcuts.ts +5 -0
- package/src/components/command-bar/list/model.ts +15 -2
- package/src/components/command-bar/list/navigation.ts +6 -0
- package/src/components/command-bar/list/view.tsx +16 -3
- package/src/components/command-bar/pane-templates/workflow.ts +1 -0
- package/src/components/command-bar/panel/body.tsx +2 -0
- package/src/components/command-bar/panel/index.tsx +3 -0
- package/src/components/command-bar/panel/runtime.ts +6 -0
- package/src/components/command-bar/panel/types.ts +1 -0
- package/src/components/command-bar/routes/root/results.ts +28 -2
- package/src/components/command-bar/routes/root/runtime.ts +66 -36
- package/src/components/command-bar/routes/root/shortcuts.ts +8 -4
- package/src/components/command-bar/routing/navigation-state.ts +17 -0
- package/src/components/command-bar/selection-runtime.ts +26 -0
- package/src/components/command-bar/surface/assist.test.tsx +276 -0
- package/src/components/command-bar/surface/index.tsx +93 -2
- package/src/components/command-bar/surface/portfolio.test.tsx +2 -1
- package/src/components/command-bar/view-model.ts +7 -1
- package/src/components/command-bar/workflow/broker.test.ts +22 -0
- package/src/components/command-bar/workflow/broker.ts +1 -0
- package/src/components/layout/detached-pane-shell.tsx +40 -2
- package/src/components/layout/floating-pane.tsx +4 -1
- package/src/components/layout/pane/header.tsx +64 -6
- package/src/components/layout/pane/index.tsx +4 -1
- package/src/components/layout/shell/index.tsx +23 -0
- package/src/components/layout/shell/pane/layers.tsx +5 -0
- package/src/components/onboarding/account-step/chooser-panel.tsx +74 -0
- package/src/components/onboarding/account-step/form-panel.tsx +157 -0
- package/src/components/onboarding/account-step/index.tsx +58 -0
- package/src/components/onboarding/account-step/model.test.ts +67 -0
- package/src/components/onboarding/account-step/model.ts +126 -0
- package/src/components/onboarding/account-step/signed-in-panel.tsx +31 -0
- package/src/components/onboarding/onboarding-steps.tsx +91 -55
- package/src/components/onboarding/onboarding-wizard.test.tsx +73 -6
- package/src/components/onboarding/onboarding-wizard.tsx +93 -9
- package/src/components/onboarding/portfolio-step/broker-fields-panel.tsx +3 -3
- package/src/components/onboarding/wizard-account.ts +235 -0
- package/src/components/onboarding/wizard-keyboard.ts +67 -1
- package/src/components/onboarding/wizard-model.ts +2 -2
- package/src/i18n/es.ts +1093 -0
- package/src/i18n/index.test.ts +5 -2
- package/src/i18n/index.ts +3 -0
- package/src/i18n/ja.ts +64 -3
- package/src/i18n/ko.ts +64 -3
- package/src/i18n/languages.test.ts +4 -1
- package/src/i18n/languages.ts +12 -1
- package/src/i18n/zh-cn.ts +64 -3
- package/src/i18n/zh-tw.ts +64 -3
- package/src/market-data/coordinator/quotes.ts +63 -1
- package/src/market-data/coordinator/subscriptions.test.ts +33 -0
- package/src/market-data/quotes/cadence.ts +2 -0
- package/src/plugins/builtin/account-management/footer.ts +9 -3
- package/src/plugins/builtin/account-management/model.ts +53 -1
- package/src/plugins/builtin/account-management/pane.tsx +107 -24
- package/src/plugins/builtin/ai/index.tsx +7 -2
- package/src/plugins/builtin/ai/screener/market-runtime.ts +4 -2
- package/src/plugins/builtin/ai/screener/pane.tsx +3 -0
- package/src/plugins/builtin/chart-composer/editor.tsx +0 -1
- package/src/plugins/builtin/chart-composer/index.tsx +10 -2
- package/src/plugins/builtin/chart-composer/pane.tsx +111 -44
- package/src/plugins/builtin/chart-composer/quick-add.tsx +27 -3
- package/src/plugins/builtin/chart-composer/semantic.ts +21 -0
- package/src/plugins/builtin/chat/controller/persistence.ts +5 -0
- package/src/plugins/builtin/cloud/plugin.tsx +9 -1
- package/src/plugins/builtin/cloud/upgrade-command.ts +28 -0
- package/src/plugins/builtin/cloud/upgrade-status-widget.tsx +54 -0
- package/src/plugins/builtin/help/index.tsx +38 -0
- package/src/plugins/builtin/news/wire/news/footer.ts +18 -38
- package/src/plugins/builtin/options/footer.test.ts +20 -124
- package/src/plugins/builtin/options/footer.ts +32 -90
- package/src/plugins/builtin/options/index.tsx +6 -0
- package/src/plugins/builtin/options/view.tsx +3 -0
- package/src/plugins/builtin/portfolio-list/index.tsx +12 -4
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +22 -1
- package/src/plugins/builtin/portfolio-list/pane/streaming.ts +17 -13
- package/src/plugins/builtin/portfolio-list/use-throttled-ticker-order.test.tsx +76 -0
- package/src/plugins/builtin/portfolio-list/use-throttled-ticker-order.ts +78 -0
- package/src/plugins/builtin/shared/cloud-upgrade.ts +131 -0
- package/src/plugins/builtin/shared/live-streaming.ts +60 -0
- package/src/plugins/builtin/shared/plan-access.test.ts +69 -0
- package/src/plugins/builtin/shared/plan-access.ts +109 -0
- package/src/plugins/builtin/ticker-detail/chart-tab-switch.test.tsx +1 -1
- package/src/plugins/builtin/ticker-detail/index.tsx +11 -2
- package/src/plugins/builtin/ticker-detail/pane.tsx +21 -3
- package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +4 -2
- package/src/plugins/registry/index.test.ts +51 -0
- package/src/plugins/registry/index.ts +12 -0
- package/src/plugins/registry/pane-settings.ts +29 -0
- package/src/renderers/electrobun/view/host/box.test.tsx +97 -0
- package/src/renderers/electrobun/view/host/box.tsx +3 -0
- package/src/renderers/electrobun/view/host/chart-surface.tsx +85 -1
- package/src/renderers/electrobun/view/host/focus-scope.test.ts +37 -0
- package/src/renderers/electrobun/view/host/focus-scope.ts +56 -0
- package/src/renderers/electrobun/view/host/input.tsx +16 -1
- package/src/renderers/electrobun/view/host/mouse.ts +1 -0
- package/src/renderers/electrobun/view/host/style.ts +1 -1
- package/src/renderers/electrobun/view/host/tabs.tsx +4 -2
- package/src/renderers/electrobun/view/main.tsx +2 -0
- package/src/renderers/opentui/chart-surface.tsx +2 -0
- package/src/renderers/opentui/host.tsx +3 -0
- package/src/sources/gloomberb-cloud/index.test.ts +8 -0
- package/src/sources/gloomberb-cloud/index.ts +4 -4
- package/src/sources/provider-router/history.test.ts +3 -3
- package/src/sources/provider-router/history.ts +15 -4
- package/src/sources/yahoo-finance/history.test.ts +47 -0
- package/src/sources/yahoo-finance/history.ts +5 -1
- package/src/state/hooks/quote-streaming.test.tsx +124 -1
- package/src/state/hooks/quote-streaming.ts +90 -7
- package/src/theme/colors.ts +20 -1
- package/src/theme/themes.test.ts +3 -0
- package/src/{sources/gloomberb-cloud → time-series}/history-quality.ts +27 -3
- package/src/time-series/resolution.test.ts +51 -0
- package/src/time-series/resolution.ts +41 -0
- package/src/time-series/resolve.test.ts +207 -1
- package/src/time-series/resolve.ts +196 -29
- package/src/time-series/spec-studies.test.ts +4 -0
- package/src/time-series/spec.ts +15 -1
- package/src/time-series/types.ts +7 -0
- package/src/time-series/use-chart-resolution.test.tsx +37 -0
- package/src/time-series/use-chart-resolution.ts +17 -1
- package/src/types/plugin.ts +9 -0
- package/src/ui/host.tsx +17 -0
package/README.md
CHANGED
|
@@ -285,15 +285,15 @@ The toolbar controls preset or exact date ranges, intervals from one minute thro
|
|
|
285
285
|
| `VF` | Toggle quote value flashing |
|
|
286
286
|
| `TH <theme>` | Change color theme |
|
|
287
287
|
| `CR` | Cycle chart renderer |
|
|
288
|
-
| `LANG <locale>` | Change interface language (`auto`, `en`, `zh-CN`, `zh-TW`, `ja`, or `ko`) |
|
|
288
|
+
| `LANG <locale>` | Change interface language (`auto`, `en`, `es`, `zh-CN`, `zh-TW`, `ja`, or `ko`) |
|
|
289
289
|
| `PL <plugin>` | Manage plugins |
|
|
290
290
|
|
|
291
291
|
## Localized interface
|
|
292
292
|
|
|
293
|
-
Gloomberb includes English, Simplified Chinese, Traditional Chinese, Japanese, and Korean UI support. English remains the default fallback language.
|
|
293
|
+
Gloomberb includes English, Spanish, Simplified Chinese, Traditional Chinese, Japanese, and Korean UI support. English remains the default fallback language.
|
|
294
294
|
|
|
295
295
|
- **Automatic detection:** supported `LANG` / `LC_ALL` and desktop system locales select the matching interface automatically.
|
|
296
|
-
- **Command switching:** enter `LANG` in the command bar (Ctrl+P) to cycle languages, or use `LANG auto`, `LANG en`, `LANG zh-CN`, `LANG zh-TW`, `LANG ja`, or `LANG ko`. The choice is persisted in `config.json`.
|
|
296
|
+
- **Command switching:** enter `LANG` in the command bar (Ctrl+P) to cycle languages, or use `LANG auto`, `LANG en`, `LANG es`, `LANG zh-CN`, `LANG zh-TW`, `LANG ja`, or `LANG ko`. The choice is persisted in `config.json`.
|
|
297
297
|
- **One-run override:** `GLOOMBERB_LANG=ja gloomberb` (or another supported locale) takes highest priority in environments that expose process locale variables.
|
|
298
298
|
|
|
299
299
|
Implementation notes:
|
package/README.zh-CN.md
CHANGED
|
@@ -267,7 +267,7 @@ gloomberb
|
|
|
267
267
|
| `VF` | 切换行情数值闪烁 |
|
|
268
268
|
| `TH <theme>` | 更换配色主题 |
|
|
269
269
|
| `CR` | 切换图表渲染器 |
|
|
270
|
-
| `LANG <locale>` | 切换界面语言(`auto`、`en`、`zh-CN`、`zh-TW`、`ja` 或 `ko`) |
|
|
270
|
+
| `LANG <locale>` | 切换界面语言(`auto`、`en`、`es`、`zh-CN`、`zh-TW`、`ja` 或 `ko`) |
|
|
271
271
|
| `PL <plugin>` | 管理插件 |
|
|
272
272
|
|
|
273
273
|
## 本地化界面
|
|
@@ -275,7 +275,7 @@ gloomberb
|
|
|
275
275
|
Gloomberb 内置 English、简体中文、繁體中文、日本語和한국어界面支持;英文仍是默认回退语言。
|
|
276
276
|
|
|
277
277
|
- **自动检测**:终端 `LANG` / `LC_ALL` 与桌面系统语言会自动选择受支持的界面语言。
|
|
278
|
-
- **命令切换**:在命令栏(Ctrl+P)输入 `LANG` 可循环切换,也可直接输入 `LANG auto`、`LANG en`、`LANG zh-CN`、`LANG zh-TW`、`LANG ja` 或 `LANG ko`。选择会保存到 `config.json`。
|
|
278
|
+
- **命令切换**:在命令栏(Ctrl+P)输入 `LANG` 可循环切换,也可直接输入 `LANG auto`、`LANG en`、`LANG es`、`LANG zh-CN`、`LANG zh-TW`、`LANG ja` 或 `LANG ko`。选择会保存到 `config.json`。
|
|
279
279
|
- **单次覆盖**:在可读取进程语言变量的环境中,可用 `GLOOMBERB_LANG=ja gloomberb`(或其他受支持的语言代码)进行最高优先级覆盖。
|
|
280
280
|
|
|
281
281
|
实现说明:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gloomberb",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.4",
|
|
4
4
|
"packageManager": "bun@1.3.11",
|
|
5
5
|
"description": "Market research and portfolio tracker for the terminal",
|
|
6
6
|
"module": "src/index.tsx",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"@types/react-dom": "^19.2.3",
|
|
50
50
|
"@types/three": "0.165.0",
|
|
51
51
|
"electrobun": "^1.18.1",
|
|
52
|
+
"happy-dom": "^20.11.1",
|
|
52
53
|
"png-to-ico": "^2.1.8",
|
|
53
54
|
"rcedit": "^4.0.1"
|
|
54
55
|
},
|
package/src/api-client/auth.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
AuthUser,
|
|
6
6
|
BuildoutAccountResponse,
|
|
7
7
|
BuildoutTokenResponse,
|
|
8
|
+
CloudPricing,
|
|
8
9
|
CloudVerificationResponse,
|
|
9
10
|
PersistedAuthUser,
|
|
10
11
|
} from "./types";
|
|
@@ -39,6 +40,8 @@ export class CloudAuthApi {
|
|
|
39
40
|
emailVerified: user.emailVerified === true,
|
|
40
41
|
image: typeof user.image === "string" ? user.image : null,
|
|
41
42
|
plan: user.plan,
|
|
43
|
+
trialEndsAt: typeof user.trialEndsAt === "string" ? user.trialEndsAt : null,
|
|
44
|
+
effectivePlan: user.effectivePlan,
|
|
42
45
|
syncEnabled: user.syncEnabled === false ? false : true,
|
|
43
46
|
weeklyRoundupEnabled: user.weeklyRoundupEnabled === false ? false : true,
|
|
44
47
|
positionAlertsEnabled: user.positionAlertsEnabled === false ? false : true,
|
|
@@ -122,6 +125,11 @@ export class CloudAuthApi {
|
|
|
122
125
|
return result.profile;
|
|
123
126
|
}
|
|
124
127
|
|
|
128
|
+
/** Public Cloud Pro pricing, including the founding discount and trial length. */
|
|
129
|
+
async getCloudPricing(): Promise<CloudPricing> {
|
|
130
|
+
return this.options.request<CloudPricing>("/pricing", { method: "GET" });
|
|
131
|
+
}
|
|
132
|
+
|
|
125
133
|
async getBuildoutAccount(): Promise<BuildoutAccountResponse> {
|
|
126
134
|
return this.options.request<BuildoutAccountResponse>("/account/buildout", {
|
|
127
135
|
method: "GET",
|
package/src/api-client/index.ts
CHANGED
|
@@ -13,7 +13,10 @@ import type {
|
|
|
13
13
|
CloudTickerTweetsParams,
|
|
14
14
|
CloudTweetSearchParams,
|
|
15
15
|
} from "./paths";
|
|
16
|
+
import { withDeadline } from "../utils/async-deadline";
|
|
16
17
|
import type {
|
|
18
|
+
AssistCommandDescriptor,
|
|
19
|
+
AssistCommandResponse,
|
|
17
20
|
ChatMessage,
|
|
18
21
|
ChatChannel,
|
|
19
22
|
ChatChannelState,
|
|
@@ -24,6 +27,7 @@ import type {
|
|
|
24
27
|
AccountProfile,
|
|
25
28
|
BuildoutAccountResponse,
|
|
26
29
|
BuildoutTokenResponse,
|
|
30
|
+
CloudPricing,
|
|
27
31
|
AccountProfileUpdate,
|
|
28
32
|
CloudQuotePayload,
|
|
29
33
|
CloudOptionsChainPayload,
|
|
@@ -54,8 +58,14 @@ import type { SyncSettings, SyncSnapshot } from "../sync/types";
|
|
|
54
58
|
export type * from "./types";
|
|
55
59
|
export { setCloudApiFetchTransport } from "./request";
|
|
56
60
|
|
|
61
|
+
/** Server-side caps for `/assist/command`; enforced here so a 422 is never sent. */
|
|
62
|
+
const ASSIST_QUERY_MAX_LENGTH = 200;
|
|
63
|
+
const ASSIST_COMMAND_LIMIT = 150;
|
|
64
|
+
const ASSIST_REQUEST_TIMEOUT_MS = 6_000;
|
|
65
|
+
|
|
57
66
|
class GloomApiClient {
|
|
58
67
|
private currentUser: AuthUser | null = null;
|
|
68
|
+
private readonly currentUserListeners = new Set<() => void>();
|
|
59
69
|
private readonly transport = new CloudApiRequestTransport();
|
|
60
70
|
private readonly auth: CloudAuthApi;
|
|
61
71
|
private readonly socket: CloudApiSocket;
|
|
@@ -110,6 +120,7 @@ class GloomApiClient {
|
|
|
110
120
|
this.transport.setSessionToken(token);
|
|
111
121
|
if (!token) {
|
|
112
122
|
this.currentUser = null;
|
|
123
|
+
this.emitCurrentUserChange();
|
|
113
124
|
}
|
|
114
125
|
this.socket.syncAuthState({ reconnect: changed });
|
|
115
126
|
}
|
|
@@ -124,6 +135,14 @@ class GloomApiClient {
|
|
|
124
135
|
return this.currentUser;
|
|
125
136
|
}
|
|
126
137
|
|
|
138
|
+
/** Notifies when the signed-in user changes, including plan and trial entitlement. */
|
|
139
|
+
subscribeCurrentUser(listener: () => void): () => void {
|
|
140
|
+
this.currentUserListeners.add(listener);
|
|
141
|
+
return () => {
|
|
142
|
+
this.currentUserListeners.delete(listener);
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
127
146
|
restoreCachedUser(user: PersistedAuthUser | null): void {
|
|
128
147
|
this.auth.restoreCachedUser(user);
|
|
129
148
|
}
|
|
@@ -136,6 +155,11 @@ class GloomApiClient {
|
|
|
136
155
|
const changed = this.socketEntitlementKey(this.currentUser) !== this.socketEntitlementKey(user);
|
|
137
156
|
this.currentUser = user;
|
|
138
157
|
this.socket.syncAuthState({ reconnect: changed });
|
|
158
|
+
this.emitCurrentUserChange();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private emitCurrentUserChange(): void {
|
|
162
|
+
for (const listener of this.currentUserListeners) listener();
|
|
139
163
|
}
|
|
140
164
|
|
|
141
165
|
private updateCurrentUser(updater: (user: AuthUser) => AuthUser): void {
|
|
@@ -149,6 +173,8 @@ class GloomApiClient {
|
|
|
149
173
|
user.id,
|
|
150
174
|
user.emailVerified === true ? "verified" : "unverified",
|
|
151
175
|
user.plan,
|
|
176
|
+
// A trial starting or lapsing changes the stream entitlement without touching `plan`.
|
|
177
|
+
user.effectivePlan,
|
|
152
178
|
].join(":");
|
|
153
179
|
}
|
|
154
180
|
|
|
@@ -195,6 +221,10 @@ class GloomApiClient {
|
|
|
195
221
|
return this.auth.getAccountProfile();
|
|
196
222
|
}
|
|
197
223
|
|
|
224
|
+
async getCloudPricing(): Promise<CloudPricing> {
|
|
225
|
+
return this.auth.getCloudPricing();
|
|
226
|
+
}
|
|
227
|
+
|
|
198
228
|
async getBuildoutAccount(): Promise<BuildoutAccountResponse> {
|
|
199
229
|
return this.auth.getBuildoutAccount();
|
|
200
230
|
}
|
|
@@ -255,6 +285,46 @@ class GloomApiClient {
|
|
|
255
285
|
return this.auth.deleteAccount();
|
|
256
286
|
}
|
|
257
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Resolves a natural-language command-bar query into runnable command-bar
|
|
290
|
+
* inputs. Requires a verified session; free accounts are included. The
|
|
291
|
+
* request is bounded client-side so a stalled upstream cannot hold the
|
|
292
|
+
* command bar in its loading state.
|
|
293
|
+
*/
|
|
294
|
+
async assistCommand(
|
|
295
|
+
query: string,
|
|
296
|
+
commands: AssistCommandDescriptor[],
|
|
297
|
+
options?: { signal?: AbortSignal },
|
|
298
|
+
): Promise<AssistCommandResponse> {
|
|
299
|
+
const controller = new AbortController();
|
|
300
|
+
const callerSignal = options?.signal;
|
|
301
|
+
const abortFromCaller = () => controller.abort(callerSignal?.reason);
|
|
302
|
+
if (callerSignal?.aborted) {
|
|
303
|
+
abortFromCaller();
|
|
304
|
+
} else {
|
|
305
|
+
callerSignal?.addEventListener("abort", abortFromCaller, { once: true });
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
try {
|
|
309
|
+
const request = this.request<AssistCommandResponse>("/assist/command", {
|
|
310
|
+
method: "POST",
|
|
311
|
+
body: JSON.stringify({
|
|
312
|
+
query: query.trim().slice(0, ASSIST_QUERY_MAX_LENGTH),
|
|
313
|
+
commands: commands.slice(0, ASSIST_COMMAND_LIMIT),
|
|
314
|
+
}),
|
|
315
|
+
signal: controller.signal,
|
|
316
|
+
});
|
|
317
|
+
return await withDeadline(
|
|
318
|
+
request,
|
|
319
|
+
ASSIST_REQUEST_TIMEOUT_MS,
|
|
320
|
+
`Assist request timed out after ${ASSIST_REQUEST_TIMEOUT_MS}ms`,
|
|
321
|
+
(error) => controller.abort(error),
|
|
322
|
+
);
|
|
323
|
+
} finally {
|
|
324
|
+
callerSignal?.removeEventListener("abort", abortFromCaller);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
258
328
|
async getChannels(): Promise<ChatChannel[]> {
|
|
259
329
|
return this.chat.getChannels();
|
|
260
330
|
}
|
package/src/api-client/types.ts
CHANGED
|
@@ -75,6 +75,10 @@ export interface AuthUser {
|
|
|
75
75
|
emailVerified: boolean;
|
|
76
76
|
image: string | null;
|
|
77
77
|
plan?: "free" | "pro";
|
|
78
|
+
/** ISO timestamp when the free Pro trial ends; null once it has lapsed or was never started. */
|
|
79
|
+
trialEndsAt?: string | null;
|
|
80
|
+
/** Plan the server actually entitles right now, i.e. `plan` upgraded to "pro" while a trial is running. */
|
|
81
|
+
effectivePlan?: "free" | "pro";
|
|
78
82
|
company?: string | null;
|
|
79
83
|
title?: string | null;
|
|
80
84
|
bio?: string | null;
|
|
@@ -101,6 +105,10 @@ export interface AccountProfile {
|
|
|
101
105
|
email: string;
|
|
102
106
|
emailVerified: boolean;
|
|
103
107
|
plan: "free" | "pro";
|
|
108
|
+
/** ISO timestamp when the free Pro trial ends; null once it has lapsed or was never started. */
|
|
109
|
+
trialEndsAt?: string | null;
|
|
110
|
+
/** Plan the server actually entitles right now, i.e. `plan` upgraded to "pro" while a trial is running. */
|
|
111
|
+
effectivePlan?: "free" | "pro";
|
|
104
112
|
username: string | null;
|
|
105
113
|
name: string;
|
|
106
114
|
company: string | null;
|
|
@@ -159,6 +167,47 @@ export interface BuildoutTokenResponse {
|
|
|
159
167
|
expiresAt: string;
|
|
160
168
|
}
|
|
161
169
|
|
|
170
|
+
export interface CloudPricingTier {
|
|
171
|
+
/** Charged amount, in integer cents. */
|
|
172
|
+
amount: number;
|
|
173
|
+
/** List price the charged amount is discounted from, in integer cents. */
|
|
174
|
+
anchorAmount: number;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Public `/pricing` payload; no session required. */
|
|
178
|
+
export interface CloudPricing {
|
|
179
|
+
currency: "usd";
|
|
180
|
+
trialDays: number;
|
|
181
|
+
/** When false the anchor amount is the price, so it is shown without a strikethrough. */
|
|
182
|
+
founding: boolean;
|
|
183
|
+
monthly: CloudPricingTier;
|
|
184
|
+
yearly: CloudPricingTier;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** One command-bar prefix described for `/assist/command`. */
|
|
188
|
+
export interface AssistCommandDescriptor {
|
|
189
|
+
prefix: string;
|
|
190
|
+
name: string;
|
|
191
|
+
description?: string;
|
|
192
|
+
arg?: {
|
|
193
|
+
placeholder?: string;
|
|
194
|
+
kind: "text" | "ticker" | "ticker-list";
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** A command-bar line the assistant believes answers the query. */
|
|
199
|
+
export interface AssistCommandCandidate {
|
|
200
|
+
/** Exact command-bar text to run, e.g. "G NVDA AMD". */
|
|
201
|
+
input: string;
|
|
202
|
+
title: string;
|
|
203
|
+
prefix: string;
|
|
204
|
+
confidence: number;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface AssistCommandResponse {
|
|
208
|
+
candidates: AssistCommandCandidate[];
|
|
209
|
+
}
|
|
210
|
+
|
|
162
211
|
export type AccountProfileUpdate = Partial<{
|
|
163
212
|
username: string;
|
|
164
213
|
name: string;
|
|
@@ -18,6 +18,14 @@ describe("desktop deeplinks", () => {
|
|
|
18
18
|
});
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
+
test("routes the post-checkout success link to account management", () => {
|
|
22
|
+
expect(resolveDesktopDeepLinkAction("gloomberb://cloud/success")).toEqual({
|
|
23
|
+
type: "open-account-management",
|
|
24
|
+
route: { kind: "cloud-success", week: null },
|
|
25
|
+
message: "Pro is active.",
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
21
29
|
test("routes ticker links with arbitrary registered tab ids", () => {
|
|
22
30
|
expect(resolveDesktopDeepLinkAction("gloomberb://ticker/NVDA?tab=analyst-research")).toEqual({
|
|
23
31
|
type: "open-ticker",
|
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
import type { DesktopDeepLinkBridge } from "../../types/desktop-deeplink";
|
|
11
11
|
import type { DesktopWindowBridge } from "../../types/desktop-window";
|
|
12
12
|
import { requestAccountManagementTab } from "../../plugins/builtin/account-management/navigation";
|
|
13
|
+
import { chatController } from "../../plugins/builtin/chat/controller";
|
|
13
14
|
|
|
14
15
|
type CloudDeepLinkRoute = {
|
|
15
|
-
kind: "cloud-alerts" | "cloud-emails" | "cloud-roundup";
|
|
16
|
+
kind: "cloud-alerts" | "cloud-emails" | "cloud-roundup" | "cloud-success";
|
|
16
17
|
week: string | null;
|
|
17
18
|
};
|
|
18
19
|
|
|
@@ -159,6 +160,13 @@ function parseCloudDeepLink(parsed: ParsedGloomUrl): DesktopDeepLinkAction {
|
|
|
159
160
|
message: "Opened email settings.",
|
|
160
161
|
};
|
|
161
162
|
}
|
|
163
|
+
if (route === "success") {
|
|
164
|
+
return {
|
|
165
|
+
type: "open-account-management",
|
|
166
|
+
route: { kind: "cloud-success", week: null },
|
|
167
|
+
message: "Pro is active.",
|
|
168
|
+
};
|
|
169
|
+
}
|
|
162
170
|
return { type: "unsupported", message: "Unsupported Gloomberb cloud link." };
|
|
163
171
|
}
|
|
164
172
|
|
|
@@ -465,6 +473,11 @@ export function handleDesktopDeepLink(rawUrl: string, options: DesktopDeepLinkHa
|
|
|
465
473
|
case "open-account-management":
|
|
466
474
|
if (!requirePane(options.pluginRegistry, "account-management", "Account management is unavailable.")) return;
|
|
467
475
|
if (action.route.kind === "cloud-emails") requestAccountManagementTab("emails");
|
|
476
|
+
if (action.route.kind === "cloud-success") {
|
|
477
|
+
requestAccountManagementTab("pro");
|
|
478
|
+
// Checkout just completed: re-read the session so the new plan shows at once.
|
|
479
|
+
void chatController.refreshSession().catch(() => {});
|
|
480
|
+
}
|
|
468
481
|
options.pluginRegistry.showPane("account-management");
|
|
469
482
|
notifySuccess(options.pluginRegistry, action.message);
|
|
470
483
|
return;
|