-
Notifications
You must be signed in to change notification settings - Fork 2.5k
feat: add message scheduling via right-click on Send button #7739
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| import React, { forwardRef, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react" | ||
| import { useEvent } from "react-use" | ||
| import DynamicTextArea from "react-textarea-autosize" | ||
| import { VolumeX, Image, WandSparkles, SendHorizontal, MessageSquareX } from "lucide-react" | ||
| import { VolumeX, Image, WandSparkles, SendHorizontal, MessageSquareX, Clock } from "lucide-react" | ||
|
|
||
| import { mentionRegex, mentionRegexGlobal, commandRegexGlobal, unescapeSpaces } from "@roo/context-mentions" | ||
| import { WebviewMessage } from "@roo/WebviewMessage" | ||
|
|
@@ -21,7 +21,13 @@ import { | |
| } from "@src/utils/context-mentions" | ||
| import { cn } from "@src/lib/utils" | ||
| import { convertToMentionPath } from "@src/utils/path-mentions" | ||
| import { StandardTooltip } from "@src/components/ui" | ||
| import { | ||
| StandardTooltip, | ||
| DropdownMenu, | ||
| DropdownMenuContent, | ||
| DropdownMenuItem, | ||
| DropdownMenuTrigger, | ||
| } from "@src/components/ui" | ||
|
|
||
| import Thumbnails from "../common/Thumbnails" | ||
| import { ModeSelector } from "./ModeSelector" | ||
|
|
@@ -1102,7 +1108,7 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>( | |
| </StandardTooltip> | ||
| </div> | ||
|
|
||
| <div className="absolute bottom-1 right-1 z-30"> | ||
| <div className="absolute bottom-1 right-1 z-30 flex items-center gap-1"> | ||
| {isEditMode && ( | ||
| <StandardTooltip content={t("chat:cancel.title")}> | ||
| <button | ||
|
|
@@ -1124,25 +1130,66 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>( | |
| </button> | ||
| </StandardTooltip> | ||
| )} | ||
| <StandardTooltip content={t("chat:sendMessage")}> | ||
| <button | ||
| aria-label={t("chat:sendMessage")} | ||
| disabled={false} | ||
| onClick={onSend} | ||
| className={cn( | ||
| "relative inline-flex items-center justify-center", | ||
| "bg-transparent border-none p-1.5", | ||
| "rounded-md min-w-[28px] min-h-[28px]", | ||
| "opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground", | ||
| "transition-all duration-150", | ||
| "hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]", | ||
| "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder", | ||
| "active:bg-[rgba(255,255,255,0.1)]", | ||
| "cursor-pointer", | ||
| )}> | ||
| <SendHorizontal className="w-4 h-4" /> | ||
| </button> | ||
| </StandardTooltip> | ||
| <DropdownMenu> | ||
| <DropdownMenuTrigger asChild> | ||
| <button | ||
| aria-label={t("chat:sendMessage")} | ||
| disabled={false} | ||
| onContextMenu={(e) => { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this accessible to keyboard-only users? The right-click context menu might not be discoverable or usable without a mouse. Could we consider adding a keyboard shortcut or making the dropdown accessible via keyboard navigation? |
||
| e.preventDefault() | ||
| // Trigger dropdown on right-click | ||
| const event = new MouseEvent("click", { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This indirect approach of dispatching a synthetic click event feels a bit hacky. Would it be cleaner to show the dropdown directly on right-click using the dropdown's API, or use a proper context menu library? |
||
| bubbles: true, | ||
| cancelable: true, | ||
| view: window, | ||
| }) | ||
| e.currentTarget.dispatchEvent(event) | ||
| }} | ||
| onClick={(e) => { | ||
| // If it's a regular left click, just send the message | ||
| if (e.button === 0 && !e.ctrlKey && !e.metaKey) { | ||
| e.preventDefault() | ||
| e.stopPropagation() | ||
| onSend() | ||
| } | ||
| }} | ||
| className={cn( | ||
| "relative inline-flex items-center justify-center", | ||
| "bg-transparent border-none p-1.5", | ||
| "rounded-md min-w-[28px] min-h-[28px]", | ||
| "opacity-60 hover:opacity-100 text-vscode-descriptionForeground hover:text-vscode-foreground", | ||
| "transition-all duration-150", | ||
| "hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)]", | ||
| "focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder", | ||
| "active:bg-[rgba(255,255,255,0.1)]", | ||
| "cursor-pointer", | ||
| )}> | ||
| <SendHorizontal className="w-4 h-4" /> | ||
| </button> | ||
| </DropdownMenuTrigger> | ||
| <DropdownMenuContent align="end" className="w-56"> | ||
| <DropdownMenuItem onClick={onSend}> | ||
| <SendHorizontal className="mr-2 h-4 w-4" /> | ||
| <span>{t("chat:sendMessage")}</span> | ||
| </DropdownMenuItem> | ||
| <DropdownMenuItem | ||
| onClick={() => { | ||
| // Queue the message for after task completion | ||
| if (inputValue.trim() || selectedImages.length > 0) { | ||
| vscode.postMessage({ | ||
| type: "queueMessage", | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The message structure with 'text' and 'images' properties doesn't appear to be strongly typed. Could we improve type safety by properly typing the WebviewMessage for queueMessage? |
||
| text: inputValue, | ||
| images: selectedImages, | ||
| }) | ||
| setInputValue("") | ||
| setSelectedImages([]) | ||
| } | ||
| }}> | ||
| <Clock className="mr-2 h-4 w-4" /> | ||
| <span>{t("chat:scheduleForAfterTask")}</span> | ||
| </DropdownMenuItem> | ||
| </DropdownMenuContent> | ||
| </DropdownMenu> | ||
| </div> | ||
|
|
||
| {!inputValue && ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,7 +41,10 @@ export const QueuedMessages = ({ queue, onRemove, onUpdate }: QueuedMessagesProp | |
|
|
||
| return ( | ||
| <div className="px-[15px] py-[10px] pr-[6px]" data-testid="queued-messages"> | ||
| <div className="text-vscode-descriptionForeground text-md mb-2">{t("queuedMessages.title")}</div> | ||
| <div className="text-vscode-descriptionForeground text-md mb-2"> | ||
| <span className="codicon codicon-clock mr-2" /> | ||
| {t("queuedMessages.scheduledTitle")} | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this title always accurate? The component shows 'Scheduled for after task completion' regardless of whether messages are actually scheduled or just queued. Should this be conditional based on the actual queue state? |
||
| </div> | ||
| <div className="flex flex-col gap-2 max-h-[300px] overflow-y-auto pr-2"> | ||
| {queue.map((message, index) => { | ||
| const editState = getEditState(message.id, message.text) | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing test coverage for this new dropdown functionality. Could we add tests to ensure the right-click behavior and message queueing work as expected?