feat: add export option to slash command menu

- Added Export as a new ContextMenuOptionType
- Modified getContextMenuOptions to include Export option at the top when "/" is typed
- Updated ContextMenu component to render Export option with appropriate icon
- Modified ChatTextArea to handle Export selection and trigger exportMode message
- Export option triggers the same action as the export button in mode settings
This commit is contained in:
Roo Code 2025-07-24 16:10:14 +00:00
parent a82455715c
commit cdb17e44fa
3 changed files with 43 additions and 3 deletions

View file

@ -264,6 +264,14 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
return
}
if (type === ContextMenuOptionType.Export) {
// Handle export action for current mode
setInputValue("")
setShowContextMenu(false)
vscode.postMessage({ type: "exportMode", slug: mode })
return
}
if (type === ContextMenuOptionType.Mode && value) {
// Handle mode selection.
setMode(value)
@ -325,7 +333,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[setInputValue, cursorPosition],
[setInputValue, cursorPosition, mode],
)
const handleKeyDown = useCallback(

View file

@ -69,6 +69,7 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
const renderOptionContent = (option: ContextMenuQueryItem) => {
switch (option.type) {
case ContextMenuOptionType.Mode:
case ContextMenuOptionType.Export:
return (
<div style={{ display: "flex", flexDirection: "column", gap: "2px" }}>
<span style={{ lineHeight: "1.2" }}>{option.label}</span>
@ -163,6 +164,8 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
switch (option.type) {
case ContextMenuOptionType.Mode:
return "symbol-misc"
case ContextMenuOptionType.Export:
return "export"
case ContextMenuOptionType.OpenedFile:
return "window"
case ContextMenuOptionType.File:
@ -263,7 +266,20 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
}}
/>
)}
{(option.type === ContextMenuOptionType.Mode ||
option.type === ContextMenuOptionType.Export) && (
<i
className={`codicon codicon-${getIconForOption(option)}`}
style={{
marginRight: "6px",
flexShrink: 0,
fontSize: "14px",
marginTop: 0,
}}
/>
)}
{option.type !== ContextMenuOptionType.Mode &&
option.type !== ContextMenuOptionType.Export &&
option.type !== ContextMenuOptionType.File &&
option.type !== ContextMenuOptionType.Folder &&
option.type !== ContextMenuOptionType.OpenedFile &&

View file

@ -105,6 +105,7 @@ export enum ContextMenuOptionType {
Git = "git",
NoResults = "noResults",
Mode = "mode", // Add mode type
Export = "export", // Add export type
}
export interface ContextMenuQueryItem {
@ -126,7 +127,18 @@ export function getContextMenuOptions(
// Handle slash commands for modes
if (query.startsWith("/") && inputValue.startsWith("/")) {
const modeQuery = query.slice(1)
if (!modes?.length) return [{ type: ContextMenuOptionType.NoResults }]
// Always include Export option at the top
const exportOption: ContextMenuQueryItem = {
type: ContextMenuOptionType.Export,
label: "Export current mode",
description: "Export the current mode configuration",
}
if (!modes?.length) {
// If no modes, just show export option
return [exportOption]
}
// Create searchable strings array for fzf
const searchableItems = modes.map((mode) => ({
@ -154,7 +166,11 @@ export function getContextMenuOptions(
description: getModeDescription(mode),
}))
return matchingModes.length > 0 ? matchingModes : [{ type: ContextMenuOptionType.NoResults }]
// Filter export option based on search query
const exportMatches = modeQuery === "" || "export".toLowerCase().includes(modeQuery.toLowerCase())
const filteredOptions = exportMatches ? [exportOption, ...matchingModes] : matchingModes
return filteredOptions.length > 0 ? filteredOptions : [{ type: ContextMenuOptionType.NoResults }]
}
const workingChanges: ContextMenuQueryItem = {