authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-17 16:09:05-08:00
committergravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-17 16:09:09-08:00
logba4a62eb0335805b6aeab55d55836a2dfbb6d5b5
treef825e5add29f0d72998d826c17bd3a284e584139
parent09ac18db8204e0057a6cf0f73424e4345f2070ab

fmt


5 files changed, 50 insertions(+), 39 deletions(-)

apps/web/src/chat-scroll.test.ts+1-4
...@@ -1,9 +1,6 @@...@@ -1,9 +1,6 @@
1import { describe, expect, it } from "vitest";1import { describe, expect, it } from "vitest";
22
3import {3import { AUTO_SCROLL_BOTTOM_THRESHOLD_PX, isScrollContainerNearBottom } from "./chat-scroll";
4 AUTO_SCROLL_BOTTOM_THRESHOLD_PX,
5 isScrollContainerNearBottom,
6} from "./chat-scroll";
74
8describe("isScrollContainerNearBottom", () => {5describe("isScrollContainerNearBottom", () => {
9 it("returns true when already at bottom", () => {6 it("returns true when already at bottom", () => {
apps/web/src/components/ChatView.tsx+3-1
...@@ -1447,7 +1447,9 @@ const MessagesTimeline = memo(function MessagesTimeline({...@@ -1447,7 +1447,9 @@ const MessagesTimeline = memo(function MessagesTimeline({
1447 if (!hasMessages && !isWorking) {1447 if (!hasMessages && !isWorking) {
1448 return (1448 return (
1449 <div className="flex h-full items-center justify-center">1449 <div className="flex h-full items-center justify-center">
1450 <p className="text-sm text-muted-foreground/30">Send a message to start the conversation.</p>1450 <p className="text-sm text-muted-foreground/30">
1451 Send a message to start the conversation.
1452 </p>
1451 </div>1453 </div>
1452 );1454 );
1453 }1455 }
apps/web/src/components/GitActionsControl.tsx+2-1
...@@ -627,7 +627,8 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp...@@ -627,7 +627,8 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp
627 : gitStatusForActions.aheadCount === 0 &&627 : gitStatusForActions.aheadCount === 0 &&
628 gitStatusForActions.behindCount === 0628 gitStatusForActions.behindCount === 0
629 ? "Up to date"629 ? "Up to date"
630 : gitStatusForActions.aheadCount > 0 && gitStatusForActions.behindCount > 0630 : gitStatusForActions.aheadCount > 0 &&
631 gitStatusForActions.behindCount > 0
631 ? `Diverged (+${gitStatusForActions.aheadCount} / -${gitStatusForActions.behindCount})`632 ? `Diverged (+${gitStatusForActions.aheadCount} / -${gitStatusForActions.behindCount})`
632 : gitStatusForActions.aheadCount > 0633 : gitStatusForActions.aheadCount > 0
633 ? `Ahead by ${gitStatusForActions.aheadCount}`634 ? `Ahead by ${gitStatusForActions.aheadCount}`
apps/web/src/keybindings.test.ts+27-20
...@@ -98,7 +98,9 @@ const DEFAULT_BINDINGS = compile([...@@ -98,7 +98,9 @@ const DEFAULT_BINDINGS = compile([
98describe("isTerminalToggleShortcut", () => {98describe("isTerminalToggleShortcut", () => {
99 it("matches Cmd+J on macOS", () => {99 it("matches Cmd+J on macOS", () => {
100 assert.isTrue(100 assert.isTrue(
101 isTerminalToggleShortcut(event({ metaKey: true }), DEFAULT_BINDINGS, { platform: "MacIntel" }),101 isTerminalToggleShortcut(event({ metaKey: true }), DEFAULT_BINDINGS, {
102 platform: "MacIntel",
103 }),
102 );104 );
103 });105 });
104106
...@@ -219,7 +221,10 @@ describe("shortcutLabelForCommand", () => {...@@ -219,7 +221,10 @@ describe("shortcutLabelForCommand", () => {
219 whenAst: whenNot(whenIdentifier("terminalFocus")),221 whenAst: whenNot(whenIdentifier("terminalFocus")),
220 },222 },
221 ]);223 ]);
222 assert.strictEqual(shortcutLabelForCommand(bindings, "terminal.split", "Linux"), "Ctrl+Shift+\\");224 assert.strictEqual(
225 shortcutLabelForCommand(bindings, "terminal.split", "Linux"),
226 "Ctrl+Shift+\\",
227 );
223 });228 });
224229
225 it("returns labels for non-terminal commands", () => {230 it("returns labels for non-terminal commands", () => {
...@@ -247,22 +252,14 @@ describe("chat/editor shortcuts", () => {...@@ -247,22 +252,14 @@ describe("chat/editor shortcuts", () => {
247252
248 it("matches chat.newLocal shortcut", () => {253 it("matches chat.newLocal shortcut", () => {
249 assert.isTrue(254 assert.isTrue(
250 isChatNewLocalShortcut(255 isChatNewLocalShortcut(event({ key: "n", metaKey: true, shiftKey: true }), DEFAULT_BINDINGS, {
251 event({ key: "n", metaKey: true, shiftKey: true }),256 platform: "MacIntel",
252 DEFAULT_BINDINGS,257 }),
253 {
254 platform: "MacIntel",
255 },
256 ),
257 );258 );
258 assert.isTrue(259 assert.isTrue(
259 isChatNewLocalShortcut(260 isChatNewLocalShortcut(event({ key: "n", ctrlKey: true, shiftKey: true }), DEFAULT_BINDINGS, {
260 event({ key: "n", ctrlKey: true, shiftKey: true }),261 platform: "Linux",
261 DEFAULT_BINDINGS,262 }),
262 {
263 platform: "Linux",
264 },
265 ),
266 );263 );
267 });264 });
268265
...@@ -344,11 +341,17 @@ describe("cross-command precedence", () => {...@@ -344,11 +341,17 @@ describe("cross-command precedence", () => {
344341
345describe("formatShortcutLabel", () => {342describe("formatShortcutLabel", () => {
346 it("formats labels for macOS", () => {343 it("formats labels for macOS", () => {
347 assert.strictEqual(formatShortcutLabel(modShortcut("d", { shiftKey: true }), "MacIntel"), "⇧⌘D");344 assert.strictEqual(
345 formatShortcutLabel(modShortcut("d", { shiftKey: true }), "MacIntel"),
346 "⇧⌘D",
347 );
348 });348 });
349349
350 it("formats labels for non-macOS", () => {350 it("formats labels for non-macOS", () => {
351 assert.strictEqual(formatShortcutLabel(modShortcut("d", { shiftKey: true }), "Linux"), "Ctrl+Shift+D");351 assert.strictEqual(
352 formatShortcutLabel(modShortcut("d", { shiftKey: true }), "Linux"),
353 "Ctrl+Shift+D",
354 );
352 });355 });
353356
354 it("formats labels for plus key", () => {357 it("formats labels for plus key", () => {
...@@ -368,7 +371,9 @@ describe("isTerminalClearShortcut", () => {...@@ -368,7 +371,9 @@ describe("isTerminalClearShortcut", () => {
368 });371 });
369372
370 it("ignores non-keydown events", () => {373 it("ignores non-keydown events", () => {
371 assert.isFalse(isTerminalClearShortcut(event({ type: "keyup", key: "l", ctrlKey: true }), "Linux"));374 assert.isFalse(
375 isTerminalClearShortcut(event({ type: "keyup", key: "l", ctrlKey: true }), "Linux"),
376 );
372 });377 });
373});378});
374379
...@@ -413,7 +418,9 @@ describe("terminalNavigationShortcutData", () => {...@@ -413,7 +418,9 @@ describe("terminalNavigationShortcutData", () => {
413 "MacIntel",418 "MacIntel",
414 ),419 ),
415 );420 );
416 assert.isNull(terminalNavigationShortcutData(event({ key: "ArrowLeft", metaKey: true }), "Linux"));421 assert.isNull(
422 terminalNavigationShortcutData(event({ key: "ArrowLeft", metaKey: true }), "Linux"),
423 );
417 assert.isNull(terminalNavigationShortcutData(event({ key: "a", altKey: true }), "MacIntel"));424 assert.isNull(terminalNavigationShortcutData(event({ key: "a", altKey: true }), "MacIntel"));
418 });425 });
419426
packages/contracts/src/keybindings.ts+17-13
...@@ -21,14 +21,16 @@ export const keybindingRuleSchema = z.object({...@@ -21,14 +21,16 @@ export const keybindingRuleSchema = z.object({
2121
22export const keybindingsConfigSchema = z.array(keybindingRuleSchema).max(256);22export const keybindingsConfigSchema = z.array(keybindingRuleSchema).max(256);
2323
24export const keybindingShortcutSchema = z.object({24export const keybindingShortcutSchema = z
25 key: z.string().trim().min(1).max(32),25 .object({
26 metaKey: z.boolean(),26 key: z.string().trim().min(1).max(32),
27 ctrlKey: z.boolean(),27 metaKey: z.boolean(),
28 shiftKey: z.boolean(),28 ctrlKey: z.boolean(),
29 altKey: z.boolean(),29 shiftKey: z.boolean(),
30 modKey: z.boolean(),30 altKey: z.boolean(),
31}).strict();31 modKey: z.boolean(),
32 })
33 .strict();
3234
33export type KeybindingWhenNode =35export type KeybindingWhenNode =
34 | { type: "identifier"; name: string }36 | { type: "identifier"; name: string }
...@@ -59,11 +61,13 @@ export const keybindingWhenNodeSchema: z.ZodType<KeybindingWhenNode> = z.lazy(()...@@ -59,11 +61,13 @@ export const keybindingWhenNodeSchema: z.ZodType<KeybindingWhenNode> = z.lazy(()
59 ]),61 ]),
60);62);
6163
62export const resolvedKeybindingRuleSchema = z.object({64export const resolvedKeybindingRuleSchema = z
63 command: keybindingCommandSchema,65 .object({
64 shortcut: keybindingShortcutSchema,66 command: keybindingCommandSchema,
65 whenAst: keybindingWhenNodeSchema.optional(),67 shortcut: keybindingShortcutSchema,
66}).strict();68 whenAst: keybindingWhenNodeSchema.optional(),
69 })
70 .strict();
6771
68export const resolvedKeybindingsConfigSchema = z.array(resolvedKeybindingRuleSchema).max(256);72export const resolvedKeybindingsConfigSchema = z.array(resolvedKeybindingRuleSchema).max(256);
6973