gloomberb 0.8.1 → 0.9.0
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 +106 -54
- package/package.json +14 -13
- package/patches/{@opentui%2Fcore@0.1.90.patch → @opentui%2Fcore@0.3.2.patch} +175 -90
- package/src/api-client/chat.ts +8 -0
- package/src/api-client/index.test.ts +30 -0
- package/src/api-client/index.ts +4 -0
- package/src/api-client/normalizers.ts +1 -0
- package/src/api-client/types.ts +1 -0
- package/src/app/global-shortcuts.test.tsx +54 -4
- package/src/app/global-shortcuts.ts +11 -5
- package/src/capabilities/factories.ts +4 -0
- package/src/components/chart/comparison/data.test.ts +54 -0
- package/src/components/chart/comparison/data.ts +47 -24
- package/src/components/chart/core/projection.ts +51 -27
- package/src/components/command-bar/action-runtime.ts +1 -0
- package/src/components/command-bar/layout-items/current-layout.test.ts +115 -0
- package/src/components/command-bar/layout-items/current-layout.ts +33 -0
- package/src/components/command-bar/list/view.tsx +3 -1
- package/src/components/command-bar/pane-templates/items.ts +4 -1
- package/src/components/command-bar/panel/body.tsx +1 -0
- package/src/components/command-bar/routes/root/results.ts +0 -30
- package/src/components/command-bar/routes/root/runtime.ts +2 -20
- package/src/components/command-bar/routes/ticker-search/actions.ts +42 -4
- package/src/components/command-bar/routes/ticker-search/route.ts +4 -1
- package/src/components/command-bar/routing/launch-request.ts +14 -7
- package/src/components/command-bar/routing/list-state.ts +1 -3
- package/src/components/command-bar/surface/index.test.tsx +76 -4
- package/src/components/command-bar/surface/index.tsx +0 -2
- package/src/components/command-bar/surface/pane.test.tsx +1 -0
- package/src/components/command-bar/surface/test-harness.tsx +1 -0
- package/src/components/command-bar/view-model.ts +3 -3
- package/src/components/data-table/stack-view.test.tsx +14 -11
- package/src/components/data-table/stack-view.tsx +1 -2
- package/src/components/data-table/view.test.tsx +24 -18
- package/src/components/data-table/view.tsx +313 -83
- package/src/components/feed-data-table/stack-view.tsx +6 -8
- package/src/components/layout/pane/footer/index.test.tsx +6 -0
- package/src/components/layout/pane/footer/index.tsx +14 -2
- package/src/components/layout/pane/title.ts +5 -1
- package/src/components/layout/shell/index.test.tsx +120 -2
- package/src/components/layout/shell/index.tsx +2 -0
- package/src/components/layout/shell/menu.ts +1 -7
- package/src/components/layout/shell/pane/actions.ts +8 -0
- package/src/components/layout/shell/pane/management-shortcuts.ts +12 -2
- package/src/components/layout/shell/shortcuts.ts +14 -6
- package/src/components/layout/shell/window-mode/index.ts +8 -3
- package/src/components/layout/window-edit/presentation.ts +4 -4
- package/src/components/onboarding/onboarding-steps.tsx +3 -2
- package/src/components/pane-settings-dialog/field-dialogs.tsx +0 -2
- package/src/components/pane-settings-dialog/tui.tsx +1 -1
- package/src/components/ticker/list-table-view.tsx +17 -25
- package/src/components/ui/choice-dialog.tsx +12 -2
- package/src/components/ui/multi-select/dialog.tsx +17 -5
- package/src/components/ui/remote-image.tsx +1 -14
- package/src/components/ui/shortcut-hint.tsx +14 -2
- package/src/components/ui/table-layout.test.ts +2 -2
- package/src/components/ui/table-layout.ts +8 -2
- package/src/components/ui/tabs.tsx +115 -86
- package/src/components/ui/ui.test.tsx +83 -4
- package/src/core/state/app/types.ts +12 -4
- package/src/market-data/coordinator/auxiliary.ts +29 -1
- package/src/market-data/coordinator/index.ts +17 -1
- package/src/market-data/hooks.tsx +17 -1
- package/src/market-data/selectors.ts +4 -0
- package/src/plugins/builtin/account-management/form-components.tsx +0 -4
- package/src/plugins/builtin/account-management/model.test.ts +54 -0
- package/src/plugins/builtin/account-management/model.ts +13 -3
- package/src/plugins/builtin/account-management/pane.tsx +5 -11
- package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
- package/src/plugins/builtin/alerts/pane.tsx +5 -3
- package/src/plugins/builtin/analytics/index.tsx +0 -3
- package/src/plugins/builtin/analytics/view.tsx +6 -5
- package/src/plugins/builtin/broker-manager/index.tsx +6 -6
- package/src/plugins/builtin/buildout/pane/index.tsx +6 -6
- package/src/plugins/builtin/changelog/index.tsx +40 -27
- package/src/plugins/builtin/changelog/model.test.ts +77 -0
- package/src/plugins/builtin/changelog/model.ts +98 -0
- package/src/plugins/builtin/chat/channel-labels.ts +53 -0
- package/src/plugins/builtin/chat/channels.test.ts +28 -0
- package/src/plugins/builtin/chat/channels.ts +36 -19
- package/src/plugins/builtin/chat/chat.test.tsx +264 -5
- package/src/plugins/builtin/chat/content/channel-navigation.ts +50 -11
- package/src/plugins/builtin/chat/content/composer-runtime.test.tsx +144 -0
- package/src/plugins/builtin/chat/content/composer-runtime.ts +151 -20
- package/src/plugins/builtin/chat/content/composer.tsx +23 -2
- package/src/plugins/builtin/chat/content/index.tsx +66 -4
- package/src/plugins/builtin/chat/content/layout-metrics.ts +3 -1
- package/src/plugins/builtin/chat/content/shortcuts.ts +27 -1
- package/src/plugins/builtin/chat/content/transcript.tsx +8 -0
- package/src/plugins/builtin/chat/content/types.ts +1 -0
- package/src/plugins/builtin/chat/controller/index.ts +41 -0
- package/src/plugins/builtin/chat/controller/messages.ts +18 -0
- package/src/plugins/builtin/chat/controller/notifications.ts +10 -4
- package/src/plugins/builtin/chat/controller/utils.ts +6 -3
- package/src/plugins/builtin/chat/controller/view.ts +1 -1
- package/src/plugins/builtin/chat/controller.test.ts +189 -0
- package/src/plugins/builtin/chat/edit-window.ts +24 -0
- package/src/plugins/builtin/chat/layout.ts +94 -31
- package/src/plugins/builtin/chat/message/action-chip.tsx +1 -0
- package/src/plugins/builtin/chat/message/desktop.tsx +53 -20
- package/src/plugins/builtin/chat/message/inline-tokens.tsx +16 -10
- package/src/plugins/builtin/chat/message/render-state.ts +5 -1
- package/src/plugins/builtin/chat/message/terminal.tsx +49 -20
- package/src/plugins/builtin/chat/message/types.ts +2 -0
- package/src/plugins/builtin/chat/pane.tsx +35 -7
- package/src/plugins/builtin/chat/sidebar.test.tsx +72 -0
- package/src/plugins/builtin/chat/status-widget.tsx +29 -11
- package/src/plugins/builtin/chat/test-harness.tsx +2 -0
- package/src/plugins/builtin/cloud/plugin.tsx +3 -0
- package/src/plugins/builtin/cloud-tweets/table.tsx +7 -11
- package/src/plugins/builtin/congress-trades/pane.tsx +14 -22
- package/src/plugins/builtin/earnings/index.tsx +8 -7
- package/src/plugins/builtin/econ/index.tsx +6 -8
- package/src/plugins/builtin/help/components.tsx +1 -1
- package/src/plugins/builtin/help/index.test.tsx +105 -30
- package/src/plugins/builtin/help/index.tsx +326 -164
- package/src/plugins/builtin/help/shortcut-model.ts +5 -6
- package/src/plugins/builtin/holders/pane.tsx +7 -6
- package/src/plugins/builtin/market-movers/index.tsx +6 -3
- package/src/plugins/builtin/news/wire/news/table.tsx +7 -6
- package/src/plugins/builtin/options/view.tsx +16 -8
- package/src/plugins/builtin/portfolio-list/column-values.ts +304 -1
- package/src/plugins/builtin/portfolio-list/metrics.test.ts +93 -0
- package/src/plugins/builtin/portfolio-list/pane/data.ts +7 -0
- package/src/plugins/builtin/portfolio-list/pane/index.tsx +25 -2
- package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +281 -0
- package/src/plugins/builtin/portfolio-list/settings.ts +27 -0
- package/src/plugins/builtin/portfolio-list/table.tsx +4 -2
- package/src/plugins/builtin/portfolio-list/use-throttled-cursor-symbol.ts +10 -68
- package/src/plugins/builtin/research/analyst-pane.tsx +1 -2
- package/src/plugins/builtin/research/corporate-actions-pane.tsx +358 -7
- package/src/plugins/builtin/research/index.test.ts +30 -1
- package/src/plugins/builtin/research/relative-valuation-pane.tsx +6 -8
- package/src/plugins/builtin/sec/filing-documents.ts +66 -0
- package/src/plugins/builtin/sec/index.tsx +132 -20
- package/src/plugins/builtin/sectors/index.tsx +13 -23
- package/src/plugins/builtin/shared/ticker-request.ts +1 -0
- package/src/plugins/builtin/substack/api/auth.ts +185 -0
- package/src/plugins/builtin/substack/api/cache.ts +78 -0
- package/src/plugins/builtin/substack/api/loaders.ts +146 -0
- package/src/plugins/builtin/substack/api/store.ts +186 -0
- package/src/plugins/builtin/substack/api/types.ts +40 -0
- package/src/plugins/builtin/substack/api.test.ts +298 -0
- package/src/plugins/builtin/substack/article-detail.tsx +359 -0
- package/src/plugins/builtin/substack/article-stack.tsx +129 -0
- package/src/plugins/builtin/substack/content.ts +478 -0
- package/src/plugins/builtin/substack/feed-tabs.tsx +41 -0
- package/src/plugins/builtin/substack/index.tsx +49 -0
- package/src/plugins/builtin/substack/login-view.tsx +126 -0
- package/src/plugins/builtin/substack/model.test.ts +155 -0
- package/src/plugins/builtin/substack/normalize.ts +343 -0
- package/src/plugins/builtin/substack/pane-footer.ts +71 -0
- package/src/plugins/builtin/substack/pane-state.ts +170 -0
- package/src/plugins/builtin/substack/pane.tsx +500 -0
- package/src/plugins/builtin/substack/table.ts +111 -0
- package/src/plugins/builtin/substack/types.ts +71 -0
- package/src/plugins/builtin/substack/utils.ts +131 -0
- package/src/plugins/builtin/thirteenf/pane.tsx +26 -25
- package/src/plugins/builtin/ticker-detail/data-panes/fundamental-graph/content.tsx +5 -4
- package/src/plugins/builtin/ticker-detail/data-panes/historical-prices.tsx +5 -4
- package/src/plugins/builtin/ticker-detail/data-panes/provider-search.tsx +6 -5
- package/src/plugins/builtin/ticker-detail/financials/tab.tsx +10 -8
- package/src/plugins/builtin/ticker-detail/index.test.tsx +16 -2
- package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
- package/src/plugins/builtin/ticker-detail/pane.tsx +13 -1
- package/src/plugins/builtin/world-indices/index.tsx +9 -6
- package/src/plugins/catalog-ui.ts +2 -0
- package/src/plugins/pane-manager/layout-state.ts +11 -0
- package/src/plugins/pane-manager.ts +1 -1
- package/src/plugins/prediction-markets/pane.tsx +10 -9
- package/src/plugins/registry/index.ts +3 -0
- package/src/plugins/runtime/context.tsx +1 -0
- package/src/plugins/runtime/index.tsx +4 -0
- package/src/react/use-throttled-commit-value.ts +116 -0
- package/src/renderers/electrobun/bun/desktop/http-fetch.test.ts +42 -0
- package/src/renderers/electrobun/bun/desktop/http-fetch.ts +5 -0
- package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +1 -0
- package/src/renderers/electrobun/view/data-table/index.tsx +3 -2
- package/src/renderers/electrobun/view/data-table/row.tsx +2 -2
- package/src/renderers/electrobun/view/host/input.tsx +23 -2
- package/src/renderers/electrobun/view/http-fetch.ts +10 -3
- package/src/renderers/electrobun/view/remote/asset-data-client.ts +1 -0
- package/src/sources/gloomberb-cloud/index.ts +4 -0
- package/src/sources/provider-router/cache.ts +1 -0
- package/src/sources/provider-router/document-routes.ts +45 -0
- package/src/sources/provider-router/index.ts +4 -0
- package/src/sources/sec-edgar/content.ts +9 -3
- package/src/sources/sec-edgar.test.ts +108 -1
- package/src/sources/sec-edgar.ts +105 -1
- package/src/sources/yahoo-finance.ts +4 -0
- package/src/state/app/context/index.test.tsx +16 -0
- package/src/test-support/plugin-runtime.ts +1 -0
- package/src/tickers/search/index.ts +1 -0
- package/src/types/data-provider.ts +11 -0
- package/src/ui/host.tsx +1 -0
- package/src/version.ts +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
diff --git a/index-
|
|
2
|
-
index
|
|
3
|
-
--- a/index-
|
|
4
|
-
+++ b/index-
|
|
5
|
-
@@ -
|
|
1
|
+
diff --git a/index-218h9p3f.js b/index-218h9p3f.js
|
|
2
|
+
index b9445d2cca9477dfe06026da451b6d19268fcbdd..3efd05fa41eb713ac6e539764b15c346939bb068 100644
|
|
3
|
+
--- a/index-218h9p3f.js
|
|
4
|
+
+++ b/index-218h9p3f.js
|
|
5
|
+
@@ -6487,17 +6487,27 @@ class MouseParser {
|
|
6
6
|
const buf = Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
|
|
7
7
|
return buf.toString("latin1");
|
|
8
8
|
}
|
|
@@ -17,14 +17,14 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
17
17
|
+ const projected = Math.floor(Math.max(pixel, 0) * cellCount / pixelExtent);
|
|
18
18
|
+ return Math.max(0, Math.min(projected, cellCount - 1));
|
|
19
19
|
+ }
|
|
20
|
-
+ parseMouseEvent(data, context =
|
|
20
|
+
+ parseMouseEvent(data, context = undefined) {
|
|
21
21
|
const str = this.decodeInput(data);
|
|
22
22
|
- const parsed = this.parseMouseSequenceAt(str, 0);
|
|
23
23
|
+ const parsed = this.parseMouseSequenceAt(str, 0, context);
|
|
24
24
|
return parsed?.event ?? null;
|
|
25
25
|
}
|
|
26
26
|
- parseAllMouseEvents(data) {
|
|
27
|
-
+ parseAllMouseEvents(data, context =
|
|
27
|
+
+ parseAllMouseEvents(data, context = undefined) {
|
|
28
28
|
const str = this.decodeInput(data);
|
|
29
29
|
const events = [];
|
|
30
30
|
let offset = 0;
|
|
@@ -34,12 +34,12 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
34
34
|
if (!parsed) {
|
|
35
35
|
break;
|
|
36
36
|
}
|
|
37
|
-
@@ -
|
|
37
|
+
@@ -6506,19 +6516,19 @@ class MouseParser {
|
|
38
38
|
}
|
|
39
39
|
return events;
|
|
40
40
|
}
|
|
41
41
|
- parseMouseSequenceAt(str, offset) {
|
|
42
|
-
+ parseMouseSequenceAt(str, offset, context =
|
|
42
|
+
+ parseMouseSequenceAt(str, offset, context = undefined) {
|
|
43
43
|
if (!str.startsWith("\x1B[", offset))
|
|
44
44
|
return null;
|
|
45
45
|
const introducer = str[offset + 2];
|
|
@@ -53,11 +53,11 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
53
53
|
return null;
|
|
54
54
|
}
|
|
55
55
|
- parseSgrSequence(str, offset) {
|
|
56
|
-
+ parseSgrSequence(str, offset, context =
|
|
56
|
+
+ parseSgrSequence(str, offset, context = undefined) {
|
|
57
57
|
let index = offset + 3;
|
|
58
58
|
const values = [0, 0, 0];
|
|
59
59
|
let part = 0;
|
|
60
|
-
@@ -
|
|
60
|
+
@@ -6546,7 +6556,7 @@ class MouseParser {
|
|
61
61
|
if (!hasDigit || part !== 2)
|
|
62
62
|
return null;
|
|
63
63
|
return {
|
|
@@ -66,13 +66,13 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
66
66
|
consumed: index - offset + 1
|
|
67
67
|
};
|
|
68
68
|
}
|
|
69
|
-
@@ -
|
|
69
|
+
@@ -6567,10 +6577,12 @@ class MouseParser {
|
|
70
70
|
consumed: 6
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
- decodeSgrEvent(rawButtonCode, wireX, wireY, pressRelease) {
|
|
74
74
|
- const button = rawButtonCode & 3;
|
|
75
|
-
+ decodeSgrEvent(rawButtonCode, wireX, wireY, pressRelease, context =
|
|
75
|
+
+ decodeSgrEvent(rawButtonCode, wireX, wireY, pressRelease, context = undefined) {
|
|
76
76
|
+ const encodedButton = rawButtonCode & 3;
|
|
77
77
|
+ const isExtendedButton = (rawButtonCode & 128) !== 0;
|
|
78
78
|
+ const button = isExtendedButton ? 8 + encodedButton : encodedButton;
|
|
@@ -82,7 +82,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
82
82
|
const isMotion = (rawButtonCode & 32) !== 0;
|
|
83
83
|
const modifiers = {
|
|
84
84
|
shift: (rawButtonCode & 4) !== 0,
|
|
85
|
-
@@ -
|
|
85
|
+
@@ -6581,7 +6593,7 @@ class MouseParser {
|
|
86
86
|
let scrollInfo;
|
|
87
87
|
if (isMotion) {
|
|
88
88
|
const isDragging = this.mouseButtonsPressed.size > 0;
|
|
@@ -91,7 +91,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
91
91
|
type = "move";
|
|
92
92
|
} else if (isDragging) {
|
|
93
93
|
type = "drag";
|
|
94
|
-
@@ -
|
|
94
|
+
@@ -6596,17 +6608,24 @@ class MouseParser {
|
|
95
95
|
};
|
|
96
96
|
} else {
|
|
97
97
|
type = pressRelease === "M" ? "down" : "up";
|
|
@@ -104,36 +104,28 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
104
104
|
}
|
|
105
105
|
+ const pixelModeRequested = context?.mouseUsesPixels === true;
|
|
106
106
|
+ const pixelModeConfirmed = context?.mousePixelsConfirmed === true;
|
|
107
|
-
+ const pixelModeDetected = pixelModeRequested && (
|
|
108
|
-
+
|
|
109
|
-
+
|
|
110
|
-
+ wireY > (context?.terminalHeight ?? Number.POSITIVE_INFINITY)
|
|
111
|
-
+ );
|
|
112
|
-
+ const pixelX = pixelModeDetected ? Math.max(wireX - 1, 0) : void 0;
|
|
113
|
-
+ const pixelY = pixelModeDetected ? Math.max(wireY - 1, 0) : void 0;
|
|
107
|
+
+ const pixelModeDetected = pixelModeRequested && (pixelModeConfirmed || wireX > (context?.terminalWidth ?? Number.POSITIVE_INFINITY) || wireY > (context?.terminalHeight ?? Number.POSITIVE_INFINITY));
|
|
108
|
+
+ const pixelX = pixelModeDetected ? Math.max(wireX - 1, 0) : undefined;
|
|
109
|
+
+ const pixelY = pixelModeDetected ? Math.max(wireY - 1, 0) : undefined;
|
|
114
110
|
return {
|
|
115
111
|
type,
|
|
116
112
|
- button: button === 3 ? 0 : button,
|
|
117
113
|
- x: wireX - 1,
|
|
118
114
|
- y: wireY - 1,
|
|
119
115
|
+ button: !isExtendedButton && encodedButton === 3 ? 0 : button,
|
|
120
|
-
+ x: pixelModeDetected && pixelX !==
|
|
121
|
-
+
|
|
122
|
-
+ : wireX - 1,
|
|
123
|
-
+ y: pixelModeDetected && pixelY !== void 0
|
|
124
|
-
+ ? this.projectPixelToCell(pixelY, context?.pixelHeight ?? 0, context?.terminalHeight ?? 0)
|
|
125
|
-
+ : wireY - 1,
|
|
116
|
+
+ x: pixelModeDetected && pixelX !== undefined ? this.projectPixelToCell(pixelX, context?.pixelWidth ?? 0, context?.terminalWidth ?? 0) : wireX - 1,
|
|
117
|
+
+ y: pixelModeDetected && pixelY !== undefined ? this.projectPixelToCell(pixelY, context?.pixelHeight ?? 0, context?.terminalHeight ?? 0) : wireY - 1,
|
|
126
118
|
+ pixelX,
|
|
127
119
|
+ pixelY,
|
|
128
120
|
modifiers,
|
|
129
121
|
scroll: scrollInfo
|
|
130
122
|
};
|
|
131
|
-
@@ -
|
|
132
|
-
kittyKeyboardEnabled: false,
|
|
123
|
+
@@ -7030,7 +7049,13 @@ var DEFAULT_PROTOCOL_CONTEXT = {
|
|
133
124
|
privateCapabilityRepliesActive: false,
|
|
134
125
|
pixelResolutionQueryActive: false,
|
|
135
|
-
|
|
136
|
-
|
|
126
|
+
explicitWidthCprActive: false,
|
|
127
|
+
- startupCursorCprActive: false
|
|
128
|
+
+ startupCursorCprActive: false,
|
|
137
129
|
+ mouseUsesPixels: false,
|
|
138
130
|
+ mousePixelsConfirmed: false,
|
|
139
131
|
+ terminalWidth: 0,
|
|
@@ -143,12 +135,12 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
143
135
|
};
|
|
144
136
|
var RXVT_DOLLAR_CSI_RE = /^\x1b\[\d+\$$/;
|
|
145
137
|
var SYSTEM_CLOCK = new SystemClock;
|
|
146
|
-
@@ -
|
|
147
|
-
kittyKeyboardEnabled: options.protocolContext?.kittyKeyboardEnabled ?? false,
|
|
138
|
+
@@ -7369,7 +7394,13 @@ class StdinParser {
|
|
148
139
|
privateCapabilityRepliesActive: options.protocolContext?.privateCapabilityRepliesActive ?? false,
|
|
149
140
|
pixelResolutionQueryActive: options.protocolContext?.pixelResolutionQueryActive ?? false,
|
|
150
|
-
|
|
151
|
-
|
|
141
|
+
explicitWidthCprActive: options.protocolContext?.explicitWidthCprActive ?? false,
|
|
142
|
+
- startupCursorCprActive: options.protocolContext?.startupCursorCprActive ?? false
|
|
143
|
+
+ startupCursorCprActive: options.protocolContext?.startupCursorCprActive ?? false,
|
|
152
144
|
+ mouseUsesPixels: options.protocolContext?.mouseUsesPixels ?? false,
|
|
153
145
|
+ mousePixelsConfirmed: options.protocolContext?.mousePixelsConfirmed ?? false,
|
|
154
146
|
+ terminalWidth: options.protocolContext?.terminalWidth ?? 0,
|
|
@@ -158,7 +150,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
158
150
|
};
|
|
159
151
|
}
|
|
160
152
|
get bufferCapacity() {
|
|
161
|
-
@@ -
|
|
153
|
+
@@ -8298,11 +8329,14 @@ class StdinParser {
|
|
162
154
|
});
|
|
163
155
|
}
|
|
164
156
|
emitMouse(rawBytes, encoding) {
|
|
@@ -168,13 +160,57 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
168
160
|
this.emitOpaqueResponse("unknown", rawBytes);
|
|
169
161
|
return;
|
|
170
162
|
}
|
|
171
|
-
+ if (event.pixelX !==
|
|
163
|
+
+ if (event.pixelX !== undefined && event.pixelY !== undefined && !this.protocolContext.mousePixelsConfirmed) {
|
|
172
164
|
+ this.updateProtocolContext({ mousePixelsConfirmed: true });
|
|
173
165
|
+ }
|
|
174
166
|
this.events.push({
|
|
175
167
|
type: "mouse",
|
|
176
168
|
raw: decodeLatin1(rawBytes),
|
|
177
|
-
@@ -
|
|
169
|
+
@@ -12538,34 +12572,35 @@ function validateLinuxLibcOverride() {
|
|
170
|
+
throw new Error(`OPENTUI_LIBC must be "glibc" or "musl", got "${libc}"`);
|
|
171
|
+
}
|
|
172
|
+
async function resolveNativePackage() {
|
|
173
|
+
+ const loadNativePackage = async (packageName) => await import(packageName);
|
|
174
|
+
if (process.platform === "darwin") {
|
|
175
|
+
if (process.arch === "x64")
|
|
176
|
+
- return await import("@opentui/core-darwin-x64");
|
|
177
|
+
+ return await loadNativePackage("@opentui/core-darwin-x64");
|
|
178
|
+
if (process.arch === "arm64")
|
|
179
|
+
- return await import("@opentui/core-darwin-arm64");
|
|
180
|
+
+ return await loadNativePackage("@opentui/core-darwin-arm64");
|
|
181
|
+
}
|
|
182
|
+
if (process.platform === "linux") {
|
|
183
|
+
validateLinuxLibcOverride();
|
|
184
|
+
if (process.arch === "x64") {
|
|
185
|
+
if (process.env.OPENTUI_LIBC === "musl") {
|
|
186
|
+
- return await import("@opentui/core-linux-x64-musl");
|
|
187
|
+
+ return await loadNativePackage("@opentui/core-linux-x64-musl");
|
|
188
|
+
} else {
|
|
189
|
+
- return await import("@opentui/core-linux-x64");
|
|
190
|
+
+ return await loadNativePackage("@opentui/core-linux-x64");
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (process.arch === "arm64") {
|
|
194
|
+
if (process.env.OPENTUI_LIBC === "musl") {
|
|
195
|
+
- return await import("@opentui/core-linux-arm64-musl");
|
|
196
|
+
+ return await loadNativePackage("@opentui/core-linux-arm64-musl");
|
|
197
|
+
} else {
|
|
198
|
+
- return await import("@opentui/core-linux-arm64");
|
|
199
|
+
+ return await loadNativePackage("@opentui/core-linux-arm64");
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (process.platform === "win32") {
|
|
204
|
+
if (process.arch === "x64")
|
|
205
|
+
- return await import("@opentui/core-win32-x64");
|
|
206
|
+
+ return await loadNativePackage("@opentui/core-win32-x64");
|
|
207
|
+
if (process.arch === "arm64")
|
|
208
|
+
- return await import("@opentui/core-win32-arm64");
|
|
209
|
+
+ return await loadNativePackage("@opentui/core-win32-arm64");
|
|
210
|
+
}
|
|
211
|
+
throw new Error(`opentui is not supported on the current platform: ${process.platform}-${process.arch}`);
|
|
212
|
+
}
|
|
213
|
+
@@ -22288,6 +22323,8 @@ class MouseEvent {
|
|
178
214
|
button;
|
|
179
215
|
x;
|
|
180
216
|
y;
|
|
@@ -183,7 +219,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
183
219
|
source;
|
|
184
220
|
modifiers;
|
|
185
221
|
scroll;
|
|
186
|
-
@@ -
|
|
222
|
+
@@ -22307,6 +22344,8 @@ class MouseEvent {
|
|
187
223
|
this.button = attributes.button;
|
|
188
224
|
this.x = attributes.x;
|
|
189
225
|
this.y = attributes.y;
|
|
@@ -192,30 +228,30 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
192
228
|
this.modifiers = attributes.modifiers;
|
|
193
229
|
this.scroll = attributes.scroll;
|
|
194
230
|
this.source = attributes.source;
|
|
195
|
-
@@ -
|
|
231
|
+
@@ -22457,6 +22496,8 @@ class CliRenderer extends EventEmitter9 {
|
|
196
232
|
resizeDebounceDelay = 100;
|
|
197
233
|
enableMouseMovement = false;
|
|
198
234
|
_useMouse = true;
|
|
199
235
|
+ _mouseProtocolSignature = "disabled";
|
|
200
236
|
+ _pixelMouseEnabled = false;
|
|
201
237
|
autoFocus = true;
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
@@ -
|
|
238
|
+
_screenMode = "alternate-screen";
|
|
239
|
+
_footerHeight = DEFAULT_FOOTER_HEIGHT;
|
|
240
|
+
@@ -22491,7 +22532,7 @@ class CliRenderer extends EventEmitter9 {
|
|
205
241
|
this.handleResize(width, height);
|
|
206
242
|
}).bind(this);
|
|
207
243
|
_capabilities = null;
|
|
208
244
|
- _latestPointer = { x: 0, y: 0 };
|
|
209
|
-
+ _latestPointer = { x: 0, y: 0, pixelX:
|
|
245
|
+
+ _latestPointer = { x: 0, y: 0, pixelX: undefined, pixelY: undefined };
|
|
210
246
|
_hasPointer = false;
|
|
211
|
-
_lastPointerModifiers = {
|
|
212
|
-
|
|
213
|
-
@@ -
|
|
214
|
-
kittyKeyboardEnabled: useKittyForParsing,
|
|
247
|
+
_lastPointerModifiers = {
|
|
248
|
+
shift: false,
|
|
249
|
+
@@ -22738,7 +22779,13 @@ Captured external output:
|
|
215
250
|
privateCapabilityRepliesActive: false,
|
|
216
251
|
pixelResolutionQueryActive: false,
|
|
217
|
-
|
|
218
|
-
|
|
252
|
+
explicitWidthCprActive: false,
|
|
253
|
+
- startupCursorCprActive: false
|
|
254
|
+
+ startupCursorCprActive: false,
|
|
219
255
|
+ mouseUsesPixels: false,
|
|
220
256
|
+ mousePixelsConfirmed: false,
|
|
221
257
|
+ terminalWidth: this._terminalWidth,
|
|
@@ -225,7 +261,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
225
261
|
},
|
|
226
262
|
clock: this.clock
|
|
227
263
|
});
|
|
228
|
-
@@ -
|
|
264
|
+
@@ -24021,12 +24068,14 @@ Captured external output:
|
|
229
265
|
enableMouse() {
|
|
230
266
|
this._useMouse = true;
|
|
231
267
|
this.lib.enableMouse(this.rendererPtr, this.enableMouseMovement);
|
|
@@ -240,7 +276,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
240
276
|
}
|
|
241
277
|
enableKittyKeyboard(flags = 3) {
|
|
242
278
|
this.lib.enableKittyKeyboard(this.rendererPtr, flags);
|
|
243
|
-
@@ -
|
|
279
|
+
@@ -24036,6 +24085,52 @@ Captured external output:
|
|
244
280
|
this.lib.disableKittyKeyboard(this.rendererPtr);
|
|
245
281
|
this.updateStdinParserProtocolContext({ kittyKeyboardEnabled: false }, true);
|
|
246
282
|
}
|
|
@@ -248,27 +284,15 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
248
284
|
+ return this.enableMouseMovement ? "any" : "press";
|
|
249
285
|
+ }
|
|
250
286
|
+ buildMouseProtocolSequence(pixelEnabled) {
|
|
251
|
-
+ const trackingSequence = this.enableMouseMovement
|
|
252
|
-
+ ? "\x1B[?1000l\x1B[?1002l\x1B[?1003h"
|
|
253
|
-
+ : "\x1B[?1003l\x1B[?1002l\x1B[?1000h";
|
|
287
|
+
+ const trackingSequence = this.enableMouseMovement ? "\x1B[?1000l\x1B[?1002l\x1B[?1003h" : "\x1B[?1003l\x1B[?1002l\x1B[?1000h";
|
|
254
288
|
+ return "\x1B[?1005l\x1B[?1015l\x1B[?1006h" + trackingSequence + (pixelEnabled ? "\x1B[?1016h" : "\x1B[?1016l");
|
|
255
289
|
+ }
|
|
256
290
|
+ syncPixelMouseMode(force = false) {
|
|
257
291
|
+ const nextEnabled = Boolean(this._useMouse);
|
|
258
|
-
+ const pixelMouseDisabled = typeof process !== "undefined" && process?.env?.GLOOMBERB_DISABLE_PIXEL_MOUSE === "1";
|
|
259
292
|
+ const hasPixelCapability = this._capabilities?.sgr_pixels === true;
|
|
260
293
|
+ const hasPixelResolution = (this._resolution?.width ?? 0) > 0 && (this._resolution?.height ?? 0) > 0;
|
|
261
|
-
+ const nextPixelEnabled = Boolean(
|
|
262
|
-
+
|
|
263
|
-
+ !pixelMouseDisabled &&
|
|
264
|
-
+ hasPixelCapability &&
|
|
265
|
-
+ hasPixelResolution &&
|
|
266
|
-
+ this._terminalWidth > 0 &&
|
|
267
|
-
+ this._terminalHeight > 0
|
|
268
|
-
+ );
|
|
269
|
-
+ const nextSignature = nextEnabled
|
|
270
|
-
+ ? `${this.getMouseProtocolTrackingMode()}:${nextPixelEnabled ? "pixel" : "cell"}`
|
|
271
|
-
+ : "disabled";
|
|
294
|
+
+ const nextPixelEnabled = Boolean(nextEnabled && hasPixelCapability && hasPixelResolution && this._terminalWidth > 0 && this._terminalHeight > 0);
|
|
295
|
+
+ const nextSignature = nextEnabled ? `${this.getMouseProtocolTrackingMode()}:${nextPixelEnabled ? "pixel" : "cell"}` : "disabled";
|
|
272
296
|
+ if (nextEnabled) {
|
|
273
297
|
+ if (force || this._mouseProtocolSignature !== nextSignature) {
|
|
274
298
|
+ this.writeOut(this.buildMouseProtocolSequence(nextPixelEnabled));
|
|
@@ -305,23 +329,15 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
305
329
|
set useThread(useThread) {
|
|
306
330
|
this._useThread = useThread;
|
|
307
331
|
this.lib.setUseThread(this.rendererPtr, useThread);
|
|
308
|
-
@@ -
|
|
309
|
-
if (this._useMouse) {
|
|
310
|
-
this.enableMouse();
|
|
332
|
+
@@ -24141,6 +24236,7 @@ Captured external output:
|
|
311
333
|
}
|
|
334
|
+
this.lib.processCapabilityResponse(this.rendererPtr, sequence);
|
|
335
|
+
this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
|
|
312
336
|
+ this.syncPixelMouseMode();
|
|
313
|
-
this.
|
|
314
|
-
|
|
315
|
-
stdinListener = ((chunk) => {
|
|
316
|
-
@@ -18070,6 +18185,7 @@ Captured output:
|
|
317
|
-
if (isCapabilityResponse(sequence)) {
|
|
318
|
-
this.lib.processCapabilityResponse(this.rendererPtr, sequence);
|
|
319
|
-
this._capabilities = this.lib.getTerminalCapabilities(this.rendererPtr);
|
|
320
|
-
+ this.syncPixelMouseMode();
|
|
321
|
-
this.emit("capabilities" /* CAPABILITIES */, this._capabilities);
|
|
322
|
-
return true;
|
|
337
|
+
if (this._capabilities?.terminal?.from_xtversion) {
|
|
338
|
+
this.resolveXtVersionWaiters();
|
|
323
339
|
}
|
|
324
|
-
@@ -
|
|
340
|
+
@@ -24170,6 +24266,7 @@ Captured external output:
|
|
325
341
|
if (sequence === "\x1B[I") {
|
|
326
342
|
if (this.shouldRestoreModesOnNextFocus) {
|
|
327
343
|
this.lib.restoreTerminalModes(this.rendererPtr);
|
|
@@ -329,7 +345,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
329
345
|
this.shouldRestoreModesOnNextFocus = false;
|
|
330
346
|
}
|
|
331
347
|
if (this._terminalFocusState !== true) {
|
|
332
|
-
@@ -
|
|
348
|
+
@@ -24264,6 +24361,7 @@ Captured external output:
|
|
333
349
|
}
|
|
334
350
|
this.waitingForPixelResolution = false;
|
|
335
351
|
this.updateStdinParserProtocolContext({ pixelResolutionQueryActive: false }, true);
|
|
@@ -337,11 +353,11 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
337
353
|
return true;
|
|
338
354
|
}
|
|
339
355
|
return false;
|
|
340
|
-
@@ -
|
|
356
|
+
@@ -24298,9 +24396,15 @@ Captured external output:
|
|
341
357
|
return false;
|
|
342
358
|
}
|
|
343
359
|
mouseEvent.y -= this.renderOffset;
|
|
344
|
-
+ if (mouseEvent.pixelY !==
|
|
360
|
+
+ if (mouseEvent.pixelY !== undefined && this._resolution) {
|
|
345
361
|
+ const cellHeight = this._resolution.height / Math.max(this._terminalHeight, 1);
|
|
346
362
|
+ mouseEvent.pixelY = Math.max(mouseEvent.pixelY - this.renderOffset * cellHeight, 0);
|
|
347
363
|
+ }
|
|
@@ -353,7 +369,7 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
353
369
|
this._hasPointer = true;
|
|
354
370
|
this._lastPointerModifiers = mouseEvent.modifiers;
|
|
355
371
|
if (this._console.visible) {
|
|
356
|
-
@@ -
|
|
372
|
+
@@ -24441,6 +24545,8 @@ Captured external output:
|
|
357
373
|
button: 0,
|
|
358
374
|
x: this._latestPointer.x,
|
|
359
375
|
y: this._latestPointer.y,
|
|
@@ -362,19 +378,88 @@ index e3b6cf9f90b13698966eec991fa7a1b2e1e22d96..709940f3998e5cb1caa88642fa68fa9a
|
|
|
362
378
|
modifiers: this._lastPointerModifiers
|
|
363
379
|
};
|
|
364
380
|
if (lastOver && !lastOver.isDestroyed) {
|
|
365
|
-
@@ -
|
|
366
|
-
const
|
|
381
|
+
@@ -24531,6 +24637,7 @@ Captured external output:
|
|
382
|
+
const visiblePreviousSplitHeight = pendingSplitFooterTransition?.sourceHeight ?? previousGeometry.effectiveFooterHeight;
|
|
367
383
|
this._terminalWidth = width;
|
|
368
384
|
this._terminalHeight = height;
|
|
369
385
|
+ this.syncPixelMouseMode();
|
|
370
386
|
this.queryPixelResolution();
|
|
371
387
|
this.setCapturedRenderable(undefined);
|
|
372
388
|
this.stdinParser?.resetMouseState();
|
|
373
|
-
@@ -
|
|
374
|
-
|
|
389
|
+
@@ -24848,6 +24955,7 @@ Captured external output:
|
|
390
|
+
this.themeModeState.cancelRefresh();
|
|
375
391
|
this._isRunning = false;
|
|
376
392
|
this.waitingForPixelResolution = false;
|
|
377
393
|
+ this.disablePixelMouseMode();
|
|
378
394
|
this.updateStdinParserProtocolContext({
|
|
379
395
|
privateCapabilityRepliesActive: false,
|
|
380
396
|
pixelResolutionQueryActive: false,
|
|
397
|
+
diff --git a/lib/parse.mouse.d.ts b/lib/parse.mouse.d.ts
|
|
398
|
+
index c29f953fde0b78f09d2ec7a830e5a72452c1fe7e..04613b921bd9b4a9a7a1a4fbd0234d4012df67a1 100644
|
|
399
|
+
--- a/lib/parse.mouse.d.ts
|
|
400
|
+
+++ b/lib/parse.mouse.d.ts
|
|
401
|
+
@@ -8,6 +8,8 @@ export type RawMouseEvent = {
|
|
402
|
+
button: number;
|
|
403
|
+
x: number;
|
|
404
|
+
y: number;
|
|
405
|
+
+ pixelX?: number;
|
|
406
|
+
+ pixelY?: number;
|
|
407
|
+
modifiers: {
|
|
408
|
+
shift: boolean;
|
|
409
|
+
alt: boolean;
|
|
410
|
+
@@ -20,8 +22,23 @@ export declare class MouseParser {
|
|
411
|
+
private static readonly SCROLL_DIRECTIONS;
|
|
412
|
+
reset(): void;
|
|
413
|
+
private decodeInput;
|
|
414
|
+
- parseMouseEvent(data: Buffer | Uint8Array): RawMouseEvent | null;
|
|
415
|
+
- parseAllMouseEvents(data: Buffer | Uint8Array): RawMouseEvent[];
|
|
416
|
+
+ private projectPixelToCell;
|
|
417
|
+
+ parseMouseEvent(data: Buffer | Uint8Array, context?: {
|
|
418
|
+
+ mouseUsesPixels?: boolean;
|
|
419
|
+
+ mousePixelsConfirmed?: boolean;
|
|
420
|
+
+ terminalWidth?: number;
|
|
421
|
+
+ terminalHeight?: number;
|
|
422
|
+
+ pixelWidth?: number;
|
|
423
|
+
+ pixelHeight?: number;
|
|
424
|
+
+ }): RawMouseEvent | null;
|
|
425
|
+
+ parseAllMouseEvents(data: Buffer | Uint8Array, context?: {
|
|
426
|
+
+ mouseUsesPixels?: boolean;
|
|
427
|
+
+ mousePixelsConfirmed?: boolean;
|
|
428
|
+
+ terminalWidth?: number;
|
|
429
|
+
+ terminalHeight?: number;
|
|
430
|
+
+ pixelWidth?: number;
|
|
431
|
+
+ pixelHeight?: number;
|
|
432
|
+
+ }): RawMouseEvent[];
|
|
433
|
+
private parseMouseSequenceAt;
|
|
434
|
+
private parseSgrSequence;
|
|
435
|
+
private parseBasicSequence;
|
|
436
|
+
diff --git a/lib/stdin-parser.d.ts b/lib/stdin-parser.d.ts
|
|
437
|
+
index 6b733d534d8e9b77c5c2773f93c7a22063c18d84..a5c318d591e9f3775e276e555c15052c8dbd20cb 100644
|
|
438
|
+
--- a/lib/stdin-parser.d.ts
|
|
439
|
+
+++ b/lib/stdin-parser.d.ts
|
|
440
|
+
@@ -28,6 +28,12 @@ export interface StdinParserProtocolContext {
|
|
441
|
+
pixelResolutionQueryActive: boolean;
|
|
442
|
+
explicitWidthCprActive: boolean;
|
|
443
|
+
startupCursorCprActive: boolean;
|
|
444
|
+
+ mouseUsesPixels: boolean;
|
|
445
|
+
+ mousePixelsConfirmed: boolean;
|
|
446
|
+
+ terminalWidth: number;
|
|
447
|
+
+ terminalHeight: number;
|
|
448
|
+
+ pixelWidth: number;
|
|
449
|
+
+ pixelHeight: number;
|
|
450
|
+
}
|
|
451
|
+
export interface StdinParserOptions {
|
|
452
|
+
timeoutMs?: number;
|
|
453
|
+
diff --git a/renderer.d.ts b/renderer.d.ts
|
|
454
|
+
index 96189246f423809fc52d2ad182d57ed2e80ac098..7dd0baf1697041cf8ad556b115cd13ad2e18bc65 100644
|
|
455
|
+
--- a/renderer.d.ts
|
|
456
|
+
+++ b/renderer.d.ts
|
|
457
|
+
@@ -143,6 +143,8 @@ export declare class MouseEvent {
|
|
458
|
+
readonly button: number;
|
|
459
|
+
readonly x: number;
|
|
460
|
+
readonly y: number;
|
|
461
|
+
+ readonly pixelX?: number;
|
|
462
|
+
+ readonly pixelY?: number;
|
|
463
|
+
readonly source?: Renderable;
|
|
464
|
+
readonly modifiers: {
|
|
465
|
+
shift: boolean;
|
package/src/api-client/chat.ts
CHANGED
|
@@ -93,6 +93,14 @@ export class CloudChatApi {
|
|
|
93
93
|
return normalizeChatMessage(message);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
async editMessage(channelId: string, messageId: string, content: string): Promise<ChatMessage> {
|
|
97
|
+
const message = await this.options.request<ChatMessage>(`/chat/channels/${channelId}/messages/${messageId}`, {
|
|
98
|
+
method: "PATCH",
|
|
99
|
+
body: JSON.stringify({ content }),
|
|
100
|
+
});
|
|
101
|
+
return normalizeChatMessage(message);
|
|
102
|
+
}
|
|
103
|
+
|
|
96
104
|
connectChannel(
|
|
97
105
|
channelId: string,
|
|
98
106
|
onMessage: (msg: ChatMessage) => void,
|
|
@@ -379,6 +379,36 @@ describe("apiClient chat timestamps", () => {
|
|
|
379
379
|
expect(sentMessage.createdAt).toBe("2026-04-08T07:29:27.625Z");
|
|
380
380
|
});
|
|
381
381
|
|
|
382
|
+
test("edits a chat message and normalizes the edit timestamp", async () => {
|
|
383
|
+
const requests: Array<{ path: string; method: string; body: unknown }> = [];
|
|
384
|
+
globalThis.fetch = mockFetch(async (input: Request | string | URL, init?: RequestInit) => {
|
|
385
|
+
requests.push({
|
|
386
|
+
path: new URL(String(input)).pathname,
|
|
387
|
+
method: init?.method ?? "GET",
|
|
388
|
+
body: init?.body ? JSON.parse(String(init.body)) : null,
|
|
389
|
+
});
|
|
390
|
+
return createResponse({
|
|
391
|
+
id: "m2",
|
|
392
|
+
channelId: "everyone",
|
|
393
|
+
content: "hello edited",
|
|
394
|
+
replyToId: null,
|
|
395
|
+
createdAt: "2026-04-08 07:29:27.625",
|
|
396
|
+
editedAt: "2026-04-08 07:30:27.625",
|
|
397
|
+
user: { id: "u1", username: "alice", displayName: "Alice" },
|
|
398
|
+
replyTo: null,
|
|
399
|
+
});
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
const editedMessage = await apiClient.editMessage("everyone", "m2", "hello edited");
|
|
403
|
+
|
|
404
|
+
expect(requests).toEqual([{
|
|
405
|
+
path: "/chat/channels/everyone/messages/m2",
|
|
406
|
+
method: "PATCH",
|
|
407
|
+
body: { content: "hello edited" },
|
|
408
|
+
}]);
|
|
409
|
+
expect(editedMessage.editedAt).toBe("2026-04-08T07:30:27.625Z");
|
|
410
|
+
});
|
|
411
|
+
|
|
382
412
|
test("normalizes websocket chat timestamps before notifying listeners", async () => {
|
|
383
413
|
const seenCreatedAts: string[] = [];
|
|
384
414
|
const channel = apiClient.connectChannel("everyone", (message) => {
|
package/src/api-client/index.ts
CHANGED
|
@@ -244,6 +244,10 @@ class GloomApiClient {
|
|
|
244
244
|
return this.chat.sendMessage(channelId, content, replyToId, clientMessageId);
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
async editMessage(channelId: string, messageId: string, content: string): Promise<ChatMessage> {
|
|
248
|
+
return this.chat.editMessage(channelId, messageId, content);
|
|
249
|
+
}
|
|
250
|
+
|
|
247
251
|
connectChannel(
|
|
248
252
|
channelId: string,
|
|
249
253
|
onMessage: (msg: ChatMessage) => void,
|
package/src/api-client/types.ts
CHANGED
|
@@ -28,6 +28,7 @@ export interface ChatMessage {
|
|
|
28
28
|
content: string;
|
|
29
29
|
replyToId: string | null;
|
|
30
30
|
createdAt: string;
|
|
31
|
+
editedAt?: string | null;
|
|
31
32
|
user: ChatUserSummary;
|
|
32
33
|
replyTo?: { content: string; user: { id?: string; username: string } } | null;
|
|
33
34
|
clientStatus?: "sending" | "failed";
|
|
@@ -44,26 +44,38 @@ function createRegistry(shortcutExecute?: () => void): PluginRegistry {
|
|
|
44
44
|
|
|
45
45
|
function ShortcutHarness({
|
|
46
46
|
dispatch,
|
|
47
|
+
focusedTickerSymbol = null,
|
|
47
48
|
pluginRegistry,
|
|
49
|
+
refreshTicker = () => {},
|
|
48
50
|
state,
|
|
49
51
|
}: {
|
|
50
52
|
dispatch: (action: AppAction) => void;
|
|
53
|
+
focusedTickerSymbol?: string | null;
|
|
51
54
|
pluginRegistry: PluginRegistry;
|
|
55
|
+
refreshTicker?: (symbol: string, exchange?: string, tickerOverride?: any, priority?: number) => void;
|
|
52
56
|
state: AppState;
|
|
53
57
|
}) {
|
|
54
58
|
useAppGlobalShortcuts({
|
|
55
59
|
dispatch,
|
|
56
|
-
focusedTickerSymbol
|
|
60
|
+
focusedTickerSymbol,
|
|
57
61
|
isDetachedWindow: false,
|
|
58
62
|
pluginRegistry,
|
|
59
|
-
refreshTicker
|
|
63
|
+
refreshTicker,
|
|
60
64
|
startUpdate: () => {},
|
|
61
65
|
state,
|
|
62
66
|
});
|
|
63
67
|
return <text>ready</text>;
|
|
64
68
|
}
|
|
65
69
|
|
|
66
|
-
async function renderHarness(
|
|
70
|
+
async function renderHarness(
|
|
71
|
+
state: AppState,
|
|
72
|
+
registry: PluginRegistry,
|
|
73
|
+
dispatch: (action: AppAction) => void,
|
|
74
|
+
options: {
|
|
75
|
+
focusedTickerSymbol?: string | null;
|
|
76
|
+
refreshTicker?: (symbol: string, exchange?: string, tickerOverride?: any, priority?: number) => void;
|
|
77
|
+
} = {},
|
|
78
|
+
) {
|
|
67
79
|
testSetup = await createTestRenderer({ width: 40, height: 8 });
|
|
68
80
|
root = createRoot(testSetup.renderer);
|
|
69
81
|
act(() => {
|
|
@@ -71,14 +83,16 @@ async function renderHarness(state: AppState, registry: PluginRegistry, dispatch
|
|
|
71
83
|
<TestDialogProvider>
|
|
72
84
|
<ShortcutHarness
|
|
73
85
|
dispatch={dispatch}
|
|
86
|
+
focusedTickerSymbol={options.focusedTickerSymbol}
|
|
74
87
|
pluginRegistry={registry}
|
|
88
|
+
refreshTicker={options.refreshTicker}
|
|
75
89
|
state={state}
|
|
76
90
|
/>
|
|
77
91
|
</TestDialogProvider>,
|
|
78
92
|
);
|
|
79
93
|
});
|
|
80
94
|
await act(async () => {
|
|
81
|
-
await testSetup
|
|
95
|
+
await testSetup!.renderOnce();
|
|
82
96
|
});
|
|
83
97
|
}
|
|
84
98
|
|
|
@@ -121,6 +135,23 @@ describe("useAppGlobalShortcuts", () => {
|
|
|
121
135
|
expect(event.propagationStopped).toBe(true);
|
|
122
136
|
});
|
|
123
137
|
|
|
138
|
+
test("opens ticker search with backtick", async () => {
|
|
139
|
+
const actions: AppAction[] = [];
|
|
140
|
+
const state = createInitialState(createDefaultConfig("/tmp/gloomberb-global-shortcuts"));
|
|
141
|
+
await renderHarness(state, createRegistry(), (action) => actions.push(action));
|
|
142
|
+
|
|
143
|
+
const event = await emitKeypress({ name: "`" });
|
|
144
|
+
|
|
145
|
+
expect(actions).toEqual([{
|
|
146
|
+
type: "SET_COMMAND_BAR",
|
|
147
|
+
open: true,
|
|
148
|
+
query: "",
|
|
149
|
+
launch: { kind: "ticker-search", query: "" },
|
|
150
|
+
}]);
|
|
151
|
+
expect(event.defaultPrevented).toBe(true);
|
|
152
|
+
expect(event.propagationStopped).toBe(true);
|
|
153
|
+
});
|
|
154
|
+
|
|
124
155
|
test("does not run plain plugin shortcuts while input is captured", async () => {
|
|
125
156
|
let executed = 0;
|
|
126
157
|
const actions: AppAction[] = [];
|
|
@@ -163,4 +194,23 @@ describe("useAppGlobalShortcuts", () => {
|
|
|
163
194
|
expect(event.defaultPrevented).toBe(true);
|
|
164
195
|
expect(event.propagationStopped).toBe(true);
|
|
165
196
|
});
|
|
197
|
+
|
|
198
|
+
test("does not treat modified Shift-R as force refresh", async () => {
|
|
199
|
+
const refreshes: Array<{ symbol: string; priority?: number }> = [];
|
|
200
|
+
const state = createInitialState(createDefaultConfig("/tmp/gloomberb-global-shortcuts-resize"));
|
|
201
|
+
state.tickers.set("AAPL", {
|
|
202
|
+
metadata: { ticker: "AAPL", exchange: "NASDAQ" },
|
|
203
|
+
} as any);
|
|
204
|
+
await renderHarness(state, createRegistry(), () => {}, {
|
|
205
|
+
refreshTicker: (symbol, _exchange, _ticker, priority) => {
|
|
206
|
+
refreshes.push({ symbol, priority });
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
const event = await emitKeypress({ name: "r", ctrl: true, shift: true });
|
|
211
|
+
|
|
212
|
+
expect(refreshes).toEqual([]);
|
|
213
|
+
expect(event.defaultPrevented).toBe(false);
|
|
214
|
+
expect(event.propagationStopped).toBe(false);
|
|
215
|
+
});
|
|
166
216
|
});
|