gloomberb 0.8.2 → 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.
Files changed (85) hide show
  1. package/README.md +9 -7
  2. package/package.json +14 -13
  3. package/patches/{@opentui%2Fcore@0.1.90.patch → @opentui%2Fcore@0.3.2.patch} +175 -90
  4. package/src/app/global-shortcuts.test.tsx +54 -4
  5. package/src/app/global-shortcuts.ts +11 -5
  6. package/src/components/command-bar/action-runtime.ts +1 -0
  7. package/src/components/command-bar/layout-items/current-layout.test.ts +115 -0
  8. package/src/components/command-bar/layout-items/current-layout.ts +33 -0
  9. package/src/components/command-bar/list/view.tsx +3 -1
  10. package/src/components/command-bar/pane-templates/items.ts +4 -1
  11. package/src/components/command-bar/panel/body.tsx +1 -0
  12. package/src/components/command-bar/routes/root/results.ts +0 -30
  13. package/src/components/command-bar/routes/root/runtime.ts +2 -20
  14. package/src/components/command-bar/routes/ticker-search/actions.ts +42 -4
  15. package/src/components/command-bar/routes/ticker-search/route.ts +4 -1
  16. package/src/components/command-bar/routing/launch-request.ts +14 -7
  17. package/src/components/command-bar/routing/list-state.ts +1 -3
  18. package/src/components/command-bar/surface/index.test.tsx +76 -4
  19. package/src/components/command-bar/surface/index.tsx +0 -2
  20. package/src/components/command-bar/surface/pane.test.tsx +1 -0
  21. package/src/components/command-bar/surface/test-harness.tsx +1 -0
  22. package/src/components/command-bar/view-model.ts +3 -3
  23. package/src/components/layout/shell/index.test.tsx +120 -2
  24. package/src/components/layout/shell/index.tsx +2 -0
  25. package/src/components/layout/shell/menu.ts +1 -7
  26. package/src/components/layout/shell/pane/actions.ts +8 -0
  27. package/src/components/layout/shell/pane/management-shortcuts.ts +12 -2
  28. package/src/components/layout/shell/shortcuts.ts +14 -6
  29. package/src/components/layout/shell/window-mode/index.ts +8 -3
  30. package/src/components/layout/window-edit/presentation.ts +4 -4
  31. package/src/components/onboarding/onboarding-steps.tsx +3 -2
  32. package/src/components/ticker/list-table-view.tsx +6 -0
  33. package/src/components/ui/remote-image.tsx +1 -14
  34. package/src/components/ui/tabs.tsx +95 -80
  35. package/src/components/ui/ui.test.tsx +54 -0
  36. package/src/core/state/app/types.ts +12 -4
  37. package/src/plugins/builtin/chat/content/channel-navigation.ts +44 -11
  38. package/src/plugins/builtin/chat/content/index.tsx +5 -4
  39. package/src/plugins/builtin/chat/content/shortcuts.ts +7 -0
  40. package/src/plugins/builtin/chat/sidebar.test.tsx +71 -0
  41. package/src/plugins/builtin/help/components.tsx +1 -1
  42. package/src/plugins/builtin/help/index.test.tsx +105 -30
  43. package/src/plugins/builtin/help/index.tsx +324 -168
  44. package/src/plugins/builtin/help/shortcut-model.ts +5 -6
  45. package/src/plugins/builtin/portfolio-list/column-values.ts +304 -1
  46. package/src/plugins/builtin/portfolio-list/metrics.test.ts +93 -0
  47. package/src/plugins/builtin/portfolio-list/pane/data.ts +7 -0
  48. package/src/plugins/builtin/portfolio-list/pane/index.tsx +25 -2
  49. package/src/plugins/builtin/portfolio-list/pane/supplemental.ts +281 -0
  50. package/src/plugins/builtin/portfolio-list/settings.ts +27 -0
  51. package/src/plugins/builtin/portfolio-list/table.tsx +4 -2
  52. package/src/plugins/builtin/portfolio-list/use-throttled-cursor-symbol.ts +10 -68
  53. package/src/plugins/builtin/substack/api/auth.ts +185 -0
  54. package/src/plugins/builtin/substack/api/cache.ts +78 -0
  55. package/src/plugins/builtin/substack/api/loaders.ts +146 -0
  56. package/src/plugins/builtin/substack/api/store.ts +186 -0
  57. package/src/plugins/builtin/substack/api/types.ts +40 -0
  58. package/src/plugins/builtin/substack/api.test.ts +298 -0
  59. package/src/plugins/builtin/substack/article-detail.tsx +359 -0
  60. package/src/plugins/builtin/substack/article-stack.tsx +129 -0
  61. package/src/plugins/builtin/substack/content.ts +478 -0
  62. package/src/plugins/builtin/substack/feed-tabs.tsx +41 -0
  63. package/src/plugins/builtin/substack/index.tsx +49 -0
  64. package/src/plugins/builtin/substack/login-view.tsx +126 -0
  65. package/src/plugins/builtin/substack/model.test.ts +155 -0
  66. package/src/plugins/builtin/substack/normalize.ts +343 -0
  67. package/src/plugins/builtin/substack/pane-footer.ts +71 -0
  68. package/src/plugins/builtin/substack/pane-state.ts +170 -0
  69. package/src/plugins/builtin/substack/pane.tsx +500 -0
  70. package/src/plugins/builtin/substack/table.ts +111 -0
  71. package/src/plugins/builtin/substack/types.ts +71 -0
  72. package/src/plugins/builtin/substack/utils.ts +131 -0
  73. package/src/plugins/builtin/ticker-detail/index.test.tsx +16 -2
  74. package/src/plugins/builtin/ticker-detail/index.tsx +1 -0
  75. package/src/plugins/builtin/ticker-detail/pane.tsx +13 -1
  76. package/src/plugins/catalog-ui.ts +2 -0
  77. package/src/plugins/pane-manager/layout-state.ts +11 -0
  78. package/src/plugins/pane-manager.ts +1 -1
  79. package/src/react/use-throttled-commit-value.ts +116 -0
  80. package/src/renderers/electrobun/bun/desktop/http-fetch.test.ts +42 -0
  81. package/src/renderers/electrobun/bun/desktop/http-fetch.ts +5 -0
  82. package/src/renderers/electrobun/view/http-fetch.ts +10 -3
  83. package/src/state/app/context/index.test.tsx +16 -0
  84. package/src/tickers/search/index.ts +1 -0
  85. package/src/version.ts +1 -1
@@ -34,32 +34,69 @@ async function renderHelpPane(
34
34
  size,
35
35
  );
36
36
 
37
+ await testSetup.renderOnce();
37
38
  await testSetup.renderOnce();
38
39
  return testSetup;
39
40
  }
40
41
 
42
+ async function moveHelpTabRight(count = 1) {
43
+ await act(async () => {
44
+ for (let index = 0; index < count; index += 1) {
45
+ testSetup!.mockInput.pressArrow("right");
46
+ }
47
+ await testSetup!.renderOnce();
48
+ await testSetup!.renderOnce();
49
+ });
50
+ }
51
+
52
+ async function resetRenderedHelpPane(
53
+ runtime = createTestPluginRuntime(),
54
+ size = { width: 88, height: 36 },
55
+ ) {
56
+ if (testSetup) {
57
+ act(() => {
58
+ testSetup!.renderer.destroy();
59
+ });
60
+ testSetup = undefined;
61
+ }
62
+ return renderHelpPane(runtime, size);
63
+ }
64
+
41
65
  function withoutScrollbar(line: string) {
42
66
  const scrollThumb = String.fromCharCode(0x2588);
43
67
  return (line.endsWith(scrollThumb) ? line.slice(0, -1) : line).trimEnd();
44
68
  }
45
69
 
46
70
  describe("HelpPane", () => {
47
- test("puts section spacing before headings instead of after them", async () => {
71
+ test("starts on basics and puts section spacing before headings instead of after them", async () => {
48
72
  await renderHelpPane(createTestPluginRuntime(), { width: 88, height: 80 });
49
73
 
50
74
  const lines = testSetup!.captureCharFrame().split("\n").map(withoutScrollbar);
51
75
  const commandBarRow = lines.findIndex((line) => line.includes("Command Bar"));
52
- const templatesRow = lines.findIndex((line) => line.includes("Window Templates"));
53
-
76
+ const layoutRow = lines.findIndex((line) => line.includes("Layout Basics"));
77
+
78
+ expect(lines[0]).toContain("Basics");
79
+ expect(testSetup!.captureCharFrame()).toContain("Basics");
80
+ expect(testSetup!.captureCharFrame()).toContain("Functions");
81
+ expect(testSetup!.captureCharFrame()).toContain("Issues");
82
+ expect(testSetup!.captureCharFrame()).not.toContain("Issues/Debug");
83
+ expect(testSetup!.captureCharFrame()).not.toContain("Window Templates");
84
+ expect(testSetup!.captureCharFrame()).not.toContain("Search for a ticker or open the best matching security.");
54
85
  expect(commandBarRow).toBeGreaterThan(0);
55
- expect(templatesRow).toBeGreaterThan(commandBarRow);
86
+ expect(layoutRow).toBeGreaterThan(commandBarRow);
56
87
  expect(lines[commandBarRow - 1]?.trim()).toBe("");
57
- expect(lines[commandBarRow + 1]).toContain("Open or toggle the command bar");
58
- expect(lines[templatesRow - 1]?.trim()).toBe("");
59
- expect(lines[templatesRow + 1]?.trim()).not.toBe("");
88
+ expect(lines[commandBarRow + 1]).toContain("Open command mode");
89
+ expect(testSetup!.captureCharFrame()).toContain("Open ticker search directly.");
90
+ expect(testSetup!.captureCharFrame()).toContain("DES");
91
+ expect(testSetup!.captureCharFrame()).toContain("Clear command text.");
92
+ expect(testSetup!.captureCharFrame()).toContain("Delete the previous word");
93
+ expect(testSetup!.captureCharFrame()).toContain("Submit multiline command forms.");
94
+ expect(testSetup!.captureCharFrame()).toContain("close all floating panes");
95
+ expect(lines[layoutRow - 1]?.trim()).toBe("");
96
+ expect(lines[layoutRow + 1]?.trim()).not.toBe("");
60
97
  });
61
98
 
62
- test("lists core, plugin command, template, and keyboard shortcuts", async () => {
99
+ test("separates functions from keyboard shortcuts", async () => {
63
100
  setSharedRegistryForTests({
64
101
  commands: new Map([[
65
102
  "set-alert",
@@ -106,24 +143,52 @@ describe("HelpPane", () => {
106
143
  } as any);
107
144
 
108
145
  await renderHelpPane(createTestPluginRuntime(), { width: 88, height: 80 });
109
-
110
- const frame = testSetup!.captureCharFrame();
111
- expect(frame).toMatch(/AW\s+<ticker>/);
112
- expect(frame).toMatch(/SA\s+<symbol condition price>/);
113
- expect(frame).toMatch(/QQ\s+<tickers>/);
114
- expect(frame).toContain("Add Alert (Alerts)");
115
- expect(frame).toContain("Shift+X");
116
- expect(frame).toContain("Sync data (Gloom Cloud)");
117
- expect(frame).toContain("Ctrl+W");
118
- expect(frame).toContain("Ctrl+,");
119
- expect(frame).not.toContain("Ctrl+Shift+O");
120
- expect(frame).not.toContain("Pop the focused pane");
121
- expect(frame).not.toContain("Cmd+W");
122
- expect(frame).not.toContain("Cmd+,");
123
- expect(frame).not.toContain("Cmd+K");
124
- expect(frame).not.toContain("Cmd/Ctrl");
125
- expect(frame).not.toContain("CmdOrCtrl");
126
- expect(frame).not.toContain("Open ticker actions for the focused ticker.");
146
+ await moveHelpTabRight();
147
+
148
+ const functionsFrame = testSetup!.captureCharFrame();
149
+ expect(functionsFrame).toContain("Manage Plugins");
150
+ expect(functionsFrame).toMatch(/AW\s+<ticker>/);
151
+ expect(functionsFrame).toMatch(/SA\s+<symbol condition price>/);
152
+ expect(functionsFrame).toMatch(/QQ\s+<tickers>/);
153
+ expect(functionsFrame).toContain("Alerts");
154
+ expect(functionsFrame).toContain("Add Alert");
155
+ expect(functionsFrame).toContain("Shift+X");
156
+ expect(functionsFrame).toContain("Gloom Cloud");
157
+ expect(functionsFrame).toContain("Sync data");
158
+ expect(functionsFrame).toContain("Ticker Research");
159
+ expect(functionsFrame).toContain("Quote Monitor");
160
+ expect(functionsFrame).not.toContain("Add Alert (Alerts)");
161
+ expect(functionsFrame).not.toContain("Sync data (Gloom Cloud)");
162
+ expect(functionsFrame).not.toContain("Quote Monitor (Ticker Research)");
163
+ expect(functionsFrame).not.toContain("Ctrl+W");
164
+
165
+ await resetRenderedHelpPane(createTestPluginRuntime(), { width: 88, height: 80 });
166
+ await moveHelpTabRight(2);
167
+
168
+ const shortcutsFrame = testSetup!.captureCharFrame();
169
+ expect(shortcutsFrame).toContain("Ctrl+W");
170
+ expect(shortcutsFrame).toContain("Ctrl+Alt+W");
171
+ expect(shortcutsFrame).toContain("Ctrl+Shift+M");
172
+ expect(shortcutsFrame).toContain("Ctrl+Shift+R");
173
+ expect(shortcutsFrame).toContain("Ctrl+,");
174
+ expect(shortcutsFrame).toContain("Navigation");
175
+ expect(shortcutsFrame).toContain("Up/Down");
176
+ expect(shortcutsFrame).toContain("j/k");
177
+ expect(shortcutsFrame).toContain("Left/Right");
178
+ expect(shortcutsFrame).toContain("h/l");
179
+ expect(shortcutsFrame).toContain("PageUp/PageDown");
180
+ expect(shortcutsFrame).toContain("Window Mode");
181
+ expect(shortcutsFrame).toContain("h/j/k/l");
182
+ expect(shortcutsFrame).toContain("Close all floating panes.");
183
+ expect(shortcutsFrame).not.toContain("AW");
184
+ expect(shortcutsFrame).not.toContain("Ctrl+Shift+O");
185
+ expect(shortcutsFrame).not.toContain("Pop the focused pane");
186
+ expect(shortcutsFrame).not.toContain("Cmd+W");
187
+ expect(shortcutsFrame).not.toContain("Cmd+,");
188
+ expect(shortcutsFrame).not.toContain("Cmd+K");
189
+ expect(shortcutsFrame).not.toContain("Cmd/Ctrl");
190
+ expect(shortcutsFrame).not.toContain("CmdOrCtrl");
191
+ expect(shortcutsFrame).not.toContain("Open ticker actions for the focused ticker.");
127
192
  });
128
193
 
129
194
  test("keeps shortcuts and descriptions on the same row when narrow", async () => {
@@ -131,14 +196,18 @@ describe("HelpPane", () => {
131
196
 
132
197
  const lines = testSetup!.captureCharFrame().split("\n").map(withoutScrollbar);
133
198
  const closeCommandRow = lines.findIndex((line) => line.includes("Close the command bar."));
134
- const securityDetailsRow = lines.findIndex((line) => line.includes("Open security details"));
135
199
 
136
200
  expect(closeCommandRow).toBeGreaterThanOrEqual(0);
137
201
  expect(lines[closeCommandRow]).toContain("Esc");
138
202
  expect(lines[closeCommandRow]).toContain("`");
203
+
204
+ await moveHelpTabRight();
205
+
206
+ const functionLines = testSetup!.captureCharFrame().split("\n").map(withoutScrollbar);
207
+ const securityDetailsRow = functionLines.findIndex((line) => line.includes("Open security details"));
139
208
  expect(securityDetailsRow).toBeGreaterThanOrEqual(0);
140
- expect(lines[securityDetailsRow]).toContain("DES");
141
- expect(lines[securityDetailsRow]).toContain("<ticker>");
209
+ expect(functionLines[securityDetailsRow]).toContain("DES");
210
+ expect(functionLines[securityDetailsRow]).toContain("<ticker>");
142
211
  });
143
212
 
144
213
  test("opens the debug log from the mouse action", async () => {
@@ -149,8 +218,14 @@ describe("HelpPane", () => {
149
218
  });
150
219
 
151
220
  await renderHelpPane(runtime);
221
+ await moveHelpTabRight(3);
222
+
223
+ const frame = testSetup!.captureCharFrame();
224
+ expect(frame).toContain("GitHub Issues");
225
+ expect(frame).not.toContain("Issues/Debug");
226
+ expect(frame).not.toContain("plugin,\n");
152
227
 
153
- const lines = testSetup!.captureCharFrame().split("\n");
228
+ const lines = frame.split("\n");
154
229
  const row = lines.findIndex((line) => line.includes("Open Debug Log"));
155
230
  const col = lines[row]?.indexOf("Open Debug Log") ?? -1;
156
231