From 0a18d611401ea72a762b561fc65063c3613397f6 Mon Sep 17 00:00:00 2001 From: leonongoing <264549643+leonongoing@users.noreply.github.com> Date: Wed, 11 Nov 2026 04:42:09 +0800 Subject: [PATCH 1/2] fix(chat): label queued actions that stop the running turn --- src/components/ComposerQueuedMessages.test.ts | 22 ++++++++++++++++--- src/components/ComposerQueuedMessages.tsx | 16 +++++++++----- src/locales/en.json | 3 +++ 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/components/ComposerQueuedMessages.test.ts b/src/components/ComposerQueuedMessages.test.ts index 7fec099cb3d..0d3d4cf19cd 100644 --- a/src/components/ComposerQueuedMessages.test.ts +++ b/src/components/ComposerQueuedMessages.test.ts @@ -134,14 +134,16 @@ describe("QueuedComposerMessages", () => { expect(withoutEdit).not.toContain("Edit queued message"); }); - it("says the fallback Steer stops the running turn when the engine cannot steer live", () => { + it("shows Stop and send on the button when the engine cannot steer live", () => { const base = { items: oneItem, onSteer: () => undefined, onCancel: () => undefined } as const; const liveMarkup = renderToStaticMarkup(createElement(QueuedComposerMessages, base)); expect(liveMarkup).toContain("aria-label=\"Steer queued message now\""); const interruptMarkup = renderToStaticMarkup( createElement(QueuedComposerMessages, { ...base, steerInterrupts: true }), ); - expect(interruptMarkup).toContain("aria-label=\"Stop the running turn and send this message now\""); + expect(interruptMarkup).toContain(">Stop and send"); + expect(interruptMarkup).toContain('aria-label="Stop and send"'); + expect(interruptMarkup).toContain('title="Stop the running turn and send this message now"'); expect(interruptMarkup).not.toContain("aria-label=\"Steer queued message now\""); }); @@ -174,10 +176,24 @@ describe("QueuedComposerMessages", () => { onCancel: () => undefined, }), ); - expect(markup).toContain("aria-label=\"Stop the running turn and send the next queued message now\""); + expect(markup).toContain(">Stop and send next"); + expect(markup).toContain('aria-label="Stop and send next"'); + expect(markup).toContain('title="Stop the running turn and send the next queued message now"'); expect(markup).not.toContain("aria-label=\"Steer the next queued message now\""); }); + it("shows Stop and send all when the action will stop the turn and drain the direct queue", () => { + const markup = renderToStaticMarkup(createElement(QueuedComposerMessages, { + items: [{ queueId: "q1", text: "first" }, { queueId: "q2", text: "second" }], + onSteer: () => undefined, + onCancel: () => undefined, + steerInterrupts: true, + })); + expect(markup).toContain(">Stop and send all"); + expect(markup).toContain('aria-label="Stop and send all"'); + expect(markup).toContain('title="Stop the running turn and send all 2 queued messages now"'); + }); + it("puts the queue-level Steer action on the head only and keeps every delete distinct", () => { const markup = renderToStaticMarkup( createElement(QueuedComposerMessages, { diff --git a/src/components/ComposerQueuedMessages.tsx b/src/components/ComposerQueuedMessages.tsx index 7768c957c90..f776d6fd194 100644 --- a/src/components/ComposerQueuedMessages.tsx +++ b/src/components/ComposerQueuedMessages.tsx @@ -68,11 +68,15 @@ export function QueuedComposerMessages({ const multiple = items.length > 1; const steerLabel = steering ? t("composer.queued.steering") - : multiple - ? steerMode === "all" - ? t("composer.queued.steerAll") - : t("composer.queued.steerNext") - : t("composer.queued.steer"); + : steerInterrupts + ? multiple + ? t(steerMode === "all" ? "composer.queued.stopAndSendAll" : "composer.queued.stopAndSendNext") + : t("composer.queued.stopAndSend") + : multiple + ? steerMode === "all" + ? t("composer.queued.steerAll") + : t("composer.queued.steerNext") + : t("composer.queued.steer"); const steerDescription = steerInterrupts ? multiple ? steerMode === "all" @@ -122,7 +126,7 @@ export function QueuedComposerMessages({ type="button" onClick={onSteer} disabled={steering} - aria-label={steering ? t("composer.queued.steeringAria") : steerDescription} + aria-label={steering ? t("composer.queued.steeringAria") : steerInterrupts ? steerLabel : steerDescription} title={steerDescription} className="flex h-7 shrink-0 items-center gap-1 rounded-lg px-2 text-[13px] font-medium text-ink-secondary outline-none hover:bg-raised-hover hover:text-ink focus-visible:ring-2 focus-visible:ring-accent/60 disabled:cursor-wait disabled:opacity-60" > diff --git a/src/locales/en.json b/src/locales/en.json index 676994cb67a..ca32f1ce032 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -2935,6 +2935,9 @@ "composer.queued.steerAll": "Steer all", "composer.queued.steerNext": "Steer next", "composer.queued.steer": "Steer", + "composer.queued.stopAndSend": "Stop and send", + "composer.queued.stopAndSendAll": "Stop and send all", + "composer.queued.stopAndSendNext": "Stop and send next", "composer.queued.steerAllHint": "Steer all {count} queued messages now", "composer.queued.steerNextHint": "Steer the next queued message now", "composer.queued.steerHint": "Steer queued message now", From 7a8c8575b16c5caceadf4eb2af28bec9282481b5 Mon Sep 17 00:00:00 2001 From: leonongoing <264549643+leonongoing@users.noreply.github.com> Date: Wed, 11 Nov 2026 07:27:19 +0800 Subject: [PATCH 2/2] Translate the stop and send queue actions --- src/locales/pt-br.json | 3 +++ src/locales/source-hashes.json | 10 ++++++++-- src/locales/zh-tw.json | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/locales/pt-br.json b/src/locales/pt-br.json index 6ccccd5d3ea..a076c6d9944 100644 --- a/src/locales/pt-br.json +++ b/src/locales/pt-br.json @@ -2802,6 +2802,9 @@ "composer.queued.steerAll": "Enviar todas agora", "composer.queued.steerNext": "Enviar a próxima agora", "composer.queued.steer": "Enviar agora", + "composer.queued.stopAndSend": "Parar e enviar", + "composer.queued.stopAndSendAll": "Parar e enviar todas", + "composer.queued.stopAndSendNext": "Parar e enviar a próxima", "composer.queued.steerAllHint": "Enviar agora todas as {count} mensagens na fila", "composer.queued.steerNextHint": "Enviar agora a próxima mensagem da fila", "composer.queued.steerHint": "Enviar agora a mensagem da fila", diff --git a/src/locales/source-hashes.json b/src/locales/source-hashes.json index d34fc4668d3..2b73c2eda46 100644 --- a/src/locales/source-hashes.json +++ b/src/locales/source-hashes.json @@ -33852,7 +33852,10 @@ "secretCard.modelgo.description": "b09e97c010524be77e50e4429d199218a3a3199a187f3edbacd81c9c661b1439", "native.teamLink.otherTitle": "d160e3032fd4f4fedabfad5fc84852563d0cf85dcdbf92e82f9a06359a8d8522", "native.teamLink.otherDetail": "11b8a9828b4afd5d0e6aef778751b00fe688893eee2e81e9865e834f21f8391d", - "native.teamLink.signIn": "bdfe6b9bdb9f911ecbe705d31d1dcc1b58295c05617c16d8b743cffa8084c2e0" + "native.teamLink.signIn": "bdfe6b9bdb9f911ecbe705d31d1dcc1b58295c05617c16d8b743cffa8084c2e0", + "composer.queued.stopAndSend": "87c1a8d4e59f78757cd4549151cb0d736016067816c2ff780b121616144f9331", + "composer.queued.stopAndSendAll": "58414c1551260488f933d956477c5fef7a27cbcf9ed1614b688bb81b79fe4350", + "composer.queued.stopAndSendNext": "02338a95dff6690ac551c64e81e1765afc5e69326918bca87ee64b189e074a6e" }, "zh": { "pro.fromPrice": "a48a04a457d60b08b54fc83e7a6c4584ffedb1e23621859084900c8521a3af7b", @@ -51346,7 +51349,10 @@ "automations.run.waitingOnTeam": "9765029257ea4e83e5f94c3e6d2dd37e11b5aa9459e50eeb878aaba8fbecd833", "botLimit.created.title": "c8ed0785d466a4784db1862131dd84767f22eefd5ef7edabf794ae5a328df0f7", "botLimit.created.body": "5ab519ffccc837cc76b1e1c3437077b4f997add4e7226556ab395ebfd62074d8", - "native.connect.desktopApp": "8a430f237e81cf9cca9ea0bb61a612ee0c408247919acbfeb9b76963b0c94ee2" + "native.connect.desktopApp": "8a430f237e81cf9cca9ea0bb61a612ee0c408247919acbfeb9b76963b0c94ee2", + "composer.queued.stopAndSend": "87c1a8d4e59f78757cd4549151cb0d736016067816c2ff780b121616144f9331", + "composer.queued.stopAndSendAll": "58414c1551260488f933d956477c5fef7a27cbcf9ed1614b688bb81b79fe4350", + "composer.queued.stopAndSendNext": "02338a95dff6690ac551c64e81e1765afc5e69326918bca87ee64b189e074a6e" }, "uk": { "pro.fromPrice": "a48a04a457d60b08b54fc83e7a6c4584ffedb1e23621859084900c8521a3af7b", diff --git a/src/locales/zh-tw.json b/src/locales/zh-tw.json index 3b2e0a96ac6..9d06b0e63f6 100644 --- a/src/locales/zh-tw.json +++ b/src/locales/zh-tw.json @@ -2877,6 +2877,9 @@ "composer.queued.steerAll": "全部引導", "composer.queued.steerNext": "引導下一則", "composer.queued.steer": "引導", + "composer.queued.stopAndSend": "停止並傳送", + "composer.queued.stopAndSendAll": "停止並傳送全部", + "composer.queued.stopAndSendNext": "停止並傳送下一則", "composer.queued.steerAllHint": "立即引導佇列中全部 {count} 則訊息", "composer.queued.steerNextHint": "立即引導佇列中的下一則訊息", "composer.queued.steerHint": "立即引導佇列中的訊息",