mirror of
https://github.com/aaif-goose/goose.git
synced 2026-07-03 14:10:03 +02:00
feat: improve built-in command styling with consistent disabled state and overlay pill
- Update built-in command badges to use grey styling matching ActionPopover - Add blur effect to disabled edit/copy/delete buttons for built-in commands - Position built-in pill as overlay on top of disabled action buttons - Center align action buttons within their container space - Add 8px left spacing to built-in pill overlay for better visual balance
This commit is contained in:
@@ -6,7 +6,7 @@ import React, {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Zap, FileText, Code, Settings, Search, Play, Hash, Plus } from 'lucide-react';
|
||||
import { CustomCommand } from '../types/customCommands';
|
||||
import { CustomCommand, BUILT_IN_COMMANDS } from '../types/customCommands';
|
||||
import { Button } from './ui/button';
|
||||
|
||||
interface ActionItem {
|
||||
@@ -36,28 +36,47 @@ const ActionPopover = forwardRef<
|
||||
>(({ isOpen, onClose, onSelect, position, selectedIndex, onSelectedIndexChange, query = '', onCreateCommand }, ref) => {
|
||||
const popoverRef = useRef<HTMLDivElement>(null);
|
||||
const listRef = useRef<HTMLDivElement>(null);
|
||||
const [customCommands, setCustomCommands] = useState<CustomCommand[]>([]);
|
||||
const [allCommands, setAllCommands] = useState<CustomCommand[]>([]);
|
||||
|
||||
// Load custom commands on mount
|
||||
// Load both built-in and user commands on mount
|
||||
useEffect(() => {
|
||||
const loadCustomCommands = () => {
|
||||
const loadAllCommands = () => {
|
||||
try {
|
||||
const stored = localStorage.getItem('goose-custom-commands');
|
||||
if (stored) {
|
||||
const parsed = JSON.parse(stored);
|
||||
setCustomCommands(parsed.map((cmd: any) => ({
|
||||
...cmd,
|
||||
createdAt: new Date(cmd.createdAt),
|
||||
updatedAt: new Date(cmd.updatedAt)
|
||||
})));
|
||||
// Load user commands
|
||||
const userStored = localStorage.getItem('goose-custom-commands');
|
||||
let userCommands: CustomCommand[] = [];
|
||||
if (userStored) {
|
||||
const parsed = JSON.parse(userStored);
|
||||
userCommands = parsed
|
||||
.filter((cmd: any) => !cmd.isBuiltIn) // Only user commands
|
||||
.map((cmd: any) => ({
|
||||
...cmd,
|
||||
createdAt: new Date(cmd.createdAt),
|
||||
updatedAt: new Date(cmd.updatedAt)
|
||||
}));
|
||||
}
|
||||
|
||||
// Load built-in command favorites/usage
|
||||
const builtInStored = localStorage.getItem('goose-builtin-commands');
|
||||
let builtInCommands = [...BUILT_IN_COMMANDS];
|
||||
if (builtInStored) {
|
||||
const builtInData = JSON.parse(builtInStored);
|
||||
builtInCommands = BUILT_IN_COMMANDS.map(cmd => ({
|
||||
...cmd,
|
||||
isFavorite: builtInData[cmd.id]?.isFavorite || false,
|
||||
usageCount: builtInData[cmd.id]?.usageCount || 0,
|
||||
}));
|
||||
}
|
||||
|
||||
// Combine all commands
|
||||
setAllCommands([...builtInCommands, ...userCommands]);
|
||||
} catch (error) {
|
||||
console.error('Failed to load custom commands:', error);
|
||||
console.error('Failed to load commands:', error);
|
||||
}
|
||||
};
|
||||
|
||||
if (isOpen) {
|
||||
loadCustomCommands();
|
||||
loadAllCommands();
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
@@ -75,27 +94,46 @@ const ActionPopover = forwardRef<
|
||||
return iconMap[iconName || 'Zap'] || <Zap size={16} />;
|
||||
};
|
||||
|
||||
// Convert custom commands to action items
|
||||
const customActions: ActionItem[] = customCommands.map(cmd => ({
|
||||
// Convert all commands to action items
|
||||
const allActions: ActionItem[] = allCommands.map(cmd => ({
|
||||
id: cmd.id,
|
||||
label: cmd.label,
|
||||
description: cmd.description,
|
||||
icon: getCustomCommandIcon(cmd.icon),
|
||||
isCustom: true,
|
||||
isCustom: !cmd.isBuiltIn, // Built-in commands are not "custom"
|
||||
prompt: cmd.prompt,
|
||||
action: () => {
|
||||
console.log('Custom command action triggered:', cmd.name);
|
||||
// Increment usage count
|
||||
const updatedCommands = customCommands.map(c =>
|
||||
c.id === cmd.id ? { ...c, usageCount: c.usageCount + 1 } : c
|
||||
);
|
||||
localStorage.setItem('goose-custom-commands', JSON.stringify(updatedCommands));
|
||||
console.log('Command action triggered:', cmd.name);
|
||||
// Increment usage count for both built-in and user commands
|
||||
if (cmd.isBuiltIn) {
|
||||
// Update built-in command usage
|
||||
const builtInStored = localStorage.getItem('goose-builtin-commands');
|
||||
let builtInData: Record<string, { isFavorite: boolean; usageCount: number }> = {};
|
||||
if (builtInStored) {
|
||||
builtInData = JSON.parse(builtInStored);
|
||||
}
|
||||
builtInData[cmd.id] = {
|
||||
isFavorite: builtInData[cmd.id]?.isFavorite || cmd.isFavorite,
|
||||
usageCount: (builtInData[cmd.id]?.usageCount || cmd.usageCount) + 1,
|
||||
};
|
||||
localStorage.setItem('goose-builtin-commands', JSON.stringify(builtInData));
|
||||
} else {
|
||||
// Update user command usage
|
||||
const userStored = localStorage.getItem('goose-custom-commands');
|
||||
if (userStored) {
|
||||
const userCommands = JSON.parse(userStored);
|
||||
const updatedCommands = userCommands.map((c: any) =>
|
||||
c.id === cmd.id ? { ...c, usageCount: c.usageCount + 1 } : c
|
||||
);
|
||||
localStorage.setItem('goose-custom-commands', JSON.stringify(updatedCommands));
|
||||
}
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
||||
// Filter custom commands based on query
|
||||
const filteredActions = customActions.filter(action => {
|
||||
const cmd = customCommands.find(c => c.id === action.id);
|
||||
// Filter commands based on query
|
||||
const filteredActions = allActions.filter(action => {
|
||||
const cmd = allCommands.find(c => c.id === action.id);
|
||||
|
||||
// If no query, show only starred commands
|
||||
if (!query) {
|
||||
@@ -113,8 +151,8 @@ const ActionPopover = forwardRef<
|
||||
|
||||
// Sort actions: favorites first, then by usage count, then alphabetically
|
||||
const sortedActions = filteredActions.sort((a, b) => {
|
||||
const cmdA = customCommands.find(c => c.id === a.id);
|
||||
const cmdB = customCommands.find(c => c.id === b.id);
|
||||
const cmdA = allCommands.find(c => c.id === a.id);
|
||||
const cmdB = allCommands.find(c => c.id === b.id);
|
||||
|
||||
if (cmdA?.isFavorite && !cmdB?.isFavorite) return -1;
|
||||
if (!cmdA?.isFavorite && cmdB?.isFavorite) return 1;
|
||||
@@ -239,8 +277,12 @@ const ActionPopover = forwardRef<
|
||||
<div className="text-sm font-medium text-textStandard">
|
||||
{action.label}
|
||||
</div>
|
||||
<span className="text-xs px-1.5 py-0.5 bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300 rounded-full font-medium">
|
||||
Custom
|
||||
<span className={`text-xs px-1.5 py-0.5 rounded-full font-medium ${
|
||||
action.isCustom
|
||||
? 'bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300'
|
||||
: 'bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400'
|
||||
}`}>
|
||||
{action.isCustom ? 'Custom' : 'Built-in'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-xs text-textSubtle">
|
||||
@@ -254,8 +296,8 @@ const ActionPopover = forwardRef<
|
||||
<div className="text-sm mb-2">
|
||||
{query
|
||||
? `No commands match "${query}"`
|
||||
: customCommands.length === 0
|
||||
? 'No custom commands found'
|
||||
: allCommands.length === 0
|
||||
? 'No commands found'
|
||||
: 'No starred commands found'
|
||||
}
|
||||
</div>
|
||||
@@ -271,7 +313,7 @@ const ActionPopover = forwardRef<
|
||||
<Plus size={14} />
|
||||
Create Command
|
||||
</Button>
|
||||
) : !query && customCommands.length === 0 ? (
|
||||
) : !query && allCommands.length === 0 ? (
|
||||
onCreateCommand ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
@@ -285,7 +327,7 @@ const ActionPopover = forwardRef<
|
||||
Create Command
|
||||
</Button>
|
||||
) : (
|
||||
<div className="text-xs">Create custom commands in Settings → Chat</div>
|
||||
<div className="text-xs">Create commands in Settings → Chat</div>
|
||||
)
|
||||
) : (
|
||||
<div className="text-xs">Star commands to see them here when you type /</div>
|
||||
|
||||
@@ -36,28 +36,52 @@ const getCustomCommandIcon = (iconName?: string) => {
|
||||
return iconMap[iconName || 'Zap'] || <Zap size={12} />;
|
||||
};
|
||||
|
||||
// Dynamic action mapping that loads from localStorage
|
||||
// Import built-in commands
|
||||
import { BUILT_IN_COMMANDS } from '../types/customCommands';
|
||||
|
||||
// Dynamic action mapping that loads both built-in and user commands
|
||||
const getActionMap = () => {
|
||||
const actionMap: Record<string, { label: string; icon: React.ReactNode }> = {};
|
||||
|
||||
try {
|
||||
// Add built-in commands
|
||||
const builtInStored = localStorage.getItem('goose-builtin-commands');
|
||||
let builtInCommands = [...BUILT_IN_COMMANDS];
|
||||
if (builtInStored) {
|
||||
const builtInData = JSON.parse(builtInStored);
|
||||
builtInCommands = BUILT_IN_COMMANDS.map(cmd => ({
|
||||
...cmd,
|
||||
isFavorite: builtInData[cmd.id]?.isFavorite || false,
|
||||
usageCount: builtInData[cmd.id]?.usageCount || 0,
|
||||
}));
|
||||
}
|
||||
|
||||
builtInCommands.forEach((cmd: any) => {
|
||||
actionMap[cmd.id] = {
|
||||
label: cmd.label,
|
||||
icon: getCustomCommandIcon(cmd.icon),
|
||||
};
|
||||
});
|
||||
|
||||
// Add user commands
|
||||
const stored = localStorage.getItem('goose-custom-commands');
|
||||
if (stored) {
|
||||
const commands = JSON.parse(stored);
|
||||
const actionMap: Record<string, { label: string; icon: React.ReactNode }> = {};
|
||||
|
||||
commands.forEach((cmd: any) => {
|
||||
actionMap[cmd.id] = {
|
||||
label: cmd.label,
|
||||
icon: getCustomCommandIcon(cmd.icon),
|
||||
};
|
||||
});
|
||||
|
||||
return actionMap;
|
||||
commands
|
||||
.filter((cmd: any) => !cmd.isBuiltIn) // Only user commands
|
||||
.forEach((cmd: any) => {
|
||||
actionMap[cmd.id] = {
|
||||
label: cmd.label,
|
||||
icon: getCustomCommandIcon(cmd.icon),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return actionMap;
|
||||
} catch (error) {
|
||||
console.error('Error loading custom commands for action map:', error);
|
||||
console.error('Error loading commands for action map:', error);
|
||||
return {};
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
export interface RichChatInputRef {
|
||||
|
||||
@@ -6,7 +6,8 @@ import { AddCustomCommandModal } from '../AddCustomCommandModal';
|
||||
import {
|
||||
CustomCommand,
|
||||
CustomCommandCategory,
|
||||
DEFAULT_CATEGORIES
|
||||
DEFAULT_CATEGORIES,
|
||||
BUILT_IN_COMMANDS
|
||||
} from '../../types/customCommands';
|
||||
|
||||
interface CustomCommandsSettingsProps {
|
||||
@@ -21,12 +22,16 @@ const ICON_MAP = {
|
||||
};
|
||||
|
||||
export const CustomCommandsSettings: React.FC<CustomCommandsSettingsProps> = () => {
|
||||
const [commands, setCommands] = useState<CustomCommand[]>([]);
|
||||
const [userCommands, setUserCommands] = useState<CustomCommand[]>([]);
|
||||
const [builtInCommands, setBuiltInCommands] = useState<CustomCommand[]>(BUILT_IN_COMMANDS);
|
||||
const [categories] = useState<CustomCommandCategory[]>(DEFAULT_CATEGORIES);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [editingCommand, setEditingCommand] = useState<CustomCommand | null>(null);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
|
||||
// Combine built-in and user commands
|
||||
const allCommands = [...builtInCommands, ...userCommands];
|
||||
|
||||
// Load commands from storage on mount
|
||||
useEffect(() => {
|
||||
loadCommands();
|
||||
@@ -34,53 +39,86 @@ export const CustomCommandsSettings: React.FC<CustomCommandsSettingsProps> = ()
|
||||
|
||||
const loadCommands = async () => {
|
||||
try {
|
||||
// TODO: Load from actual storage (localStorage, config API, etc.)
|
||||
// Load user commands from localStorage
|
||||
const stored = localStorage.getItem('goose-custom-commands');
|
||||
if (stored) {
|
||||
const parsed = JSON.parse(stored);
|
||||
setCommands(parsed.map((cmd: any) => ({
|
||||
const userCmds = parsed
|
||||
.filter((cmd: any) => !cmd.isBuiltIn) // Only user commands
|
||||
.map((cmd: any) => ({
|
||||
...cmd,
|
||||
createdAt: new Date(cmd.createdAt),
|
||||
updatedAt: new Date(cmd.updatedAt)
|
||||
}));
|
||||
setUserCommands(userCmds);
|
||||
}
|
||||
|
||||
// Load built-in command favorites/usage from localStorage
|
||||
const builtInStored = localStorage.getItem('goose-builtin-commands');
|
||||
if (builtInStored) {
|
||||
const builtInData = JSON.parse(builtInStored);
|
||||
const updatedBuiltIns = BUILT_IN_COMMANDS.map(cmd => ({
|
||||
...cmd,
|
||||
createdAt: new Date(cmd.createdAt),
|
||||
updatedAt: new Date(cmd.updatedAt)
|
||||
})));
|
||||
} else {
|
||||
// Load some example commands for demo
|
||||
setCommands(getExampleCommands());
|
||||
isFavorite: builtInData[cmd.id]?.isFavorite || false,
|
||||
usageCount: builtInData[cmd.id]?.usageCount || 0,
|
||||
}));
|
||||
setBuiltInCommands(updatedBuiltIns);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load custom commands:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const saveCommands = async (updatedCommands: CustomCommand[]) => {
|
||||
const saveUserCommands = async (updatedUserCommands: CustomCommand[]) => {
|
||||
try {
|
||||
localStorage.setItem('goose-custom-commands', JSON.stringify(updatedCommands));
|
||||
setCommands(updatedCommands);
|
||||
localStorage.setItem('goose-custom-commands', JSON.stringify(updatedUserCommands));
|
||||
setUserCommands(updatedUserCommands);
|
||||
} catch (error) {
|
||||
console.error('Failed to save custom commands:', error);
|
||||
console.error('Failed to save user commands:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const saveBuiltInCommandData = async (updatedBuiltInCommands: CustomCommand[]) => {
|
||||
try {
|
||||
// Only save favorites and usage count for built-in commands
|
||||
const builtInData: Record<string, { isFavorite: boolean; usageCount: number }> = {};
|
||||
updatedBuiltInCommands.forEach(cmd => {
|
||||
builtInData[cmd.id] = {
|
||||
isFavorite: cmd.isFavorite,
|
||||
usageCount: cmd.usageCount,
|
||||
};
|
||||
});
|
||||
localStorage.setItem('goose-builtin-commands', JSON.stringify(builtInData));
|
||||
setBuiltInCommands(updatedBuiltInCommands);
|
||||
} catch (error) {
|
||||
console.error('Failed to save built-in command data:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleModalSave = (command: CustomCommand) => {
|
||||
const now = new Date();
|
||||
let updatedCommands: CustomCommand[];
|
||||
let updatedUserCommands: CustomCommand[];
|
||||
|
||||
if (editingCommand) {
|
||||
// Update existing command
|
||||
updatedCommands = commands.map(cmd =>
|
||||
if (editingCommand && !editingCommand.isBuiltIn) {
|
||||
// Update existing user command
|
||||
updatedUserCommands = userCommands.map(cmd =>
|
||||
cmd.id === editingCommand.id
|
||||
? { ...command, id: editingCommand.id, createdAt: editingCommand.createdAt, updatedAt: now }
|
||||
: cmd
|
||||
);
|
||||
} else {
|
||||
// Create new command
|
||||
updatedCommands = [...commands, { ...command, createdAt: now, updatedAt: now }];
|
||||
// Create new user command
|
||||
updatedUserCommands = [...userCommands, { ...command, createdAt: now, updatedAt: now }];
|
||||
}
|
||||
|
||||
saveCommands(updatedCommands);
|
||||
saveUserCommands(updatedUserCommands);
|
||||
};
|
||||
|
||||
const handleEdit = (command: CustomCommand) => {
|
||||
// Built-in commands cannot be edited
|
||||
if (command.isBuiltIn) {
|
||||
return;
|
||||
}
|
||||
setEditingCommand(command);
|
||||
setIsModalOpen(true);
|
||||
};
|
||||
@@ -96,17 +134,34 @@ export const CustomCommandsSettings: React.FC<CustomCommandsSettingsProps> = ()
|
||||
};
|
||||
|
||||
const handleDelete = (commandId: string) => {
|
||||
// Built-in commands cannot be deleted
|
||||
const command = allCommands.find(cmd => cmd.id === commandId);
|
||||
if (command?.isBuiltIn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (confirm('Are you sure you want to delete this command?')) {
|
||||
const updatedCommands = commands.filter(cmd => cmd.id !== commandId);
|
||||
saveCommands(updatedCommands);
|
||||
const updatedUserCommands = userCommands.filter(cmd => cmd.id !== commandId);
|
||||
saveUserCommands(updatedUserCommands);
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleFavorite = (commandId: string) => {
|
||||
const updatedCommands = commands.map(cmd =>
|
||||
// Handle built-in commands separately
|
||||
const builtInCommand = builtInCommands.find(cmd => cmd.id === commandId);
|
||||
if (builtInCommand) {
|
||||
const updatedBuiltInCommands = builtInCommands.map(cmd =>
|
||||
cmd.id === commandId ? { ...cmd, isFavorite: !cmd.isFavorite } : cmd
|
||||
);
|
||||
saveBuiltInCommandData(updatedBuiltInCommands);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle user commands
|
||||
const updatedUserCommands = userCommands.map(cmd =>
|
||||
cmd.id === commandId ? { ...cmd, isFavorite: !cmd.isFavorite } : cmd
|
||||
);
|
||||
saveCommands(updatedCommands);
|
||||
saveUserCommands(updatedUserCommands);
|
||||
};
|
||||
|
||||
const handleDuplicate = (command: CustomCommand) => {
|
||||
@@ -118,11 +173,12 @@ export const CustomCommandsSettings: React.FC<CustomCommandsSettingsProps> = ()
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
usageCount: 0,
|
||||
isBuiltIn: false, // Duplicates are always user commands
|
||||
};
|
||||
saveCommands([...commands, duplicatedCommand]);
|
||||
saveUserCommands([...userCommands, duplicatedCommand]);
|
||||
};
|
||||
|
||||
const filteredCommands = commands.filter(cmd => {
|
||||
const filteredCommands = allCommands.filter(cmd => {
|
||||
const matchesSearch = !searchQuery ||
|
||||
cmd.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
cmd.label.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
@@ -158,18 +214,20 @@ export const CustomCommandsSettings: React.FC<CustomCommandsSettingsProps> = ()
|
||||
{/* Commands List - Row Style */}
|
||||
{filteredCommands.map(command => (
|
||||
<div key={command.id} className="group hover:cursor-pointer text-sm">
|
||||
<div className="flex items-center justify-between text-text-default py-2 px-2 bg-background-default hover:bg-background-muted rounded-lg transition-all">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-center text-text-default py-2 px-2 bg-background-default hover:bg-background-muted rounded-lg transition-all relative">
|
||||
<div className="flex items-center gap-3 flex-1">
|
||||
<div className="flex items-center justify-center text-text-muted">
|
||||
{ICON_MAP[command.icon as keyof typeof ICON_MAP] || ICON_MAP.Zap}
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-text-default font-medium">/{command.name}</h3>
|
||||
<div className="flex items-center gap-2">
|
||||
<h3 className="text-text-default font-medium">/{command.name}</h3>
|
||||
</div>
|
||||
<p className="text-text-muted text-xs mt-[2px]">{command.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center justify-center gap-2 relative w-40">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@@ -192,7 +250,8 @@ export const CustomCommandsSettings: React.FC<CustomCommandsSettingsProps> = ()
|
||||
e.stopPropagation();
|
||||
handleEdit(command);
|
||||
}}
|
||||
className="p-1 h-6 w-6"
|
||||
disabled={command.isBuiltIn}
|
||||
className={`p-1 h-6 w-6 ${command.isBuiltIn ? 'opacity-50 cursor-not-allowed blur-sm' : ''}`}
|
||||
>
|
||||
<Edit size={12} className="text-text-muted hover:text-text-default" />
|
||||
</Button>
|
||||
@@ -203,7 +262,8 @@ export const CustomCommandsSettings: React.FC<CustomCommandsSettingsProps> = ()
|
||||
e.stopPropagation();
|
||||
handleDuplicate(command);
|
||||
}}
|
||||
className="p-1 h-6 w-6"
|
||||
disabled={command.isBuiltIn}
|
||||
className={`p-1 h-6 w-6 ${command.isBuiltIn ? 'opacity-50 cursor-not-allowed blur-sm' : ''}`}
|
||||
>
|
||||
<Copy size={12} className="text-text-muted hover:text-text-default" />
|
||||
</Button>
|
||||
@@ -214,10 +274,20 @@ export const CustomCommandsSettings: React.FC<CustomCommandsSettingsProps> = ()
|
||||
e.stopPropagation();
|
||||
handleDelete(command.id);
|
||||
}}
|
||||
className="p-1 h-6 w-6 text-red-600 hover:text-red-700"
|
||||
disabled={command.isBuiltIn}
|
||||
className={`p-1 h-6 w-6 ${command.isBuiltIn ? 'opacity-50 cursor-not-allowed blur-sm' : ''}`}
|
||||
>
|
||||
<Trash2 size={12} />
|
||||
<Trash2 size={12} className={command.isBuiltIn ? 'text-text-muted' : 'text-red-600 hover:text-red-700'} />
|
||||
</Button>
|
||||
|
||||
{/* Built-in pill overlay */}
|
||||
{command.isBuiltIn && (
|
||||
<div className="absolute inset-0 flex items-center justify-center pointer-events-none pl-2">
|
||||
<span className="text-xs px-2 py-1 bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-400 rounded-full font-medium shadow-sm border border-gray-200 dark:border-gray-700">
|
||||
Built-in
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,6 +11,7 @@ export interface CustomCommand {
|
||||
updatedAt: Date;
|
||||
usageCount: number; // Track how often it's used
|
||||
isFavorite: boolean; // User can mark favorites
|
||||
isBuiltIn?: boolean; // Built-in commands cannot be deleted, only favorited
|
||||
}
|
||||
|
||||
export interface CustomCommandVariable {
|
||||
@@ -127,3 +128,149 @@ export const COMMON_VARIABLES: CustomCommandVariable[] = [
|
||||
required: false,
|
||||
}
|
||||
];
|
||||
|
||||
// Built-in commands that cannot be deleted, only favorited
|
||||
export const BUILT_IN_COMMANDS: CustomCommand[] = [
|
||||
{
|
||||
id: 'builtin_explain',
|
||||
name: 'explain',
|
||||
label: 'Explain Code',
|
||||
description: 'Provide detailed explanation of code or concepts',
|
||||
prompt: `Please explain the provided code or concept in detail. Include:
|
||||
|
||||
1. What it does (high-level purpose)
|
||||
2. How it works (step-by-step breakdown)
|
||||
3. Key concepts and patterns used
|
||||
4. Dependencies and requirements
|
||||
5. Potential use cases
|
||||
6. Any notable design decisions
|
||||
|
||||
Make the explanation accessible and comprehensive.`,
|
||||
icon: 'Search',
|
||||
category: 'development',
|
||||
variables: [],
|
||||
createdAt: new Date('2024-01-01'),
|
||||
updatedAt: new Date('2024-01-01'),
|
||||
usageCount: 0,
|
||||
isFavorite: false,
|
||||
isBuiltIn: true,
|
||||
},
|
||||
{
|
||||
id: 'builtin_review',
|
||||
name: 'review',
|
||||
label: 'Code Review',
|
||||
description: 'Perform thorough code review with suggestions',
|
||||
prompt: `Please perform a comprehensive code review. Focus on:
|
||||
|
||||
1. Code quality and readability
|
||||
2. Performance optimizations
|
||||
3. Security considerations
|
||||
4. Best practices and conventions
|
||||
5. Potential bugs or issues
|
||||
6. Suggestions for improvement
|
||||
|
||||
Provide specific, actionable feedback with examples where appropriate.`,
|
||||
icon: 'Search',
|
||||
category: 'development',
|
||||
variables: [],
|
||||
createdAt: new Date('2024-01-01'),
|
||||
updatedAt: new Date('2024-01-01'),
|
||||
usageCount: 0,
|
||||
isFavorite: false,
|
||||
isBuiltIn: true,
|
||||
},
|
||||
{
|
||||
id: 'builtin_document',
|
||||
name: 'document',
|
||||
label: 'Create Documentation',
|
||||
description: 'Generate comprehensive documentation',
|
||||
prompt: `Please create comprehensive documentation for the provided code or project. Include:
|
||||
|
||||
1. Overview and purpose
|
||||
2. Installation/setup instructions
|
||||
3. Usage examples
|
||||
4. API reference (if applicable)
|
||||
5. Configuration options
|
||||
6. Troubleshooting guide
|
||||
|
||||
Make the documentation clear, well-structured, and suitable for both beginners and experienced users.`,
|
||||
icon: 'FileText',
|
||||
category: 'documentation',
|
||||
variables: [],
|
||||
createdAt: new Date('2024-01-01'),
|
||||
updatedAt: new Date('2024-01-01'),
|
||||
usageCount: 0,
|
||||
isFavorite: false,
|
||||
isBuiltIn: true,
|
||||
},
|
||||
{
|
||||
id: 'builtin_optimize',
|
||||
name: 'optimize',
|
||||
label: 'Optimize Code',
|
||||
description: 'Suggest optimizations for better performance',
|
||||
prompt: `Please analyze the provided code and suggest optimizations for better performance, efficiency, and maintainability. Consider:
|
||||
|
||||
1. Algorithm efficiency and time complexity
|
||||
2. Memory usage optimization
|
||||
3. Code structure and organization
|
||||
4. Best practices for the specific language/framework
|
||||
5. Potential refactoring opportunities
|
||||
6. Performance bottlenecks
|
||||
|
||||
Provide specific, actionable recommendations with code examples where helpful.`,
|
||||
icon: 'Zap',
|
||||
category: 'development',
|
||||
variables: [],
|
||||
createdAt: new Date('2024-01-01'),
|
||||
updatedAt: new Date('2024-01-01'),
|
||||
usageCount: 0,
|
||||
isFavorite: false,
|
||||
isBuiltIn: true,
|
||||
},
|
||||
{
|
||||
id: 'builtin_test',
|
||||
name: 'test',
|
||||
label: 'Generate Tests',
|
||||
description: 'Create comprehensive unit tests',
|
||||
prompt: `Please generate comprehensive unit tests for the provided code. Include:
|
||||
|
||||
1. Test cases for normal/expected behavior
|
||||
2. Edge cases and boundary conditions
|
||||
3. Error handling and exception cases
|
||||
4. Mock objects where appropriate
|
||||
5. Test setup and teardown if needed
|
||||
6. Clear, descriptive test names
|
||||
|
||||
Use the appropriate testing framework for the language and follow testing best practices.`,
|
||||
icon: 'Code',
|
||||
category: 'development',
|
||||
variables: [],
|
||||
createdAt: new Date('2024-01-01'),
|
||||
updatedAt: new Date('2024-01-01'),
|
||||
usageCount: 0,
|
||||
isFavorite: false,
|
||||
isBuiltIn: true,
|
||||
},
|
||||
{
|
||||
id: 'builtin_summarize',
|
||||
name: 'summarize',
|
||||
label: 'Summarize Content',
|
||||
description: 'Create concise summary of content',
|
||||
prompt: `Please create a concise summary of the provided content. Include:
|
||||
|
||||
1. Main points and key takeaways
|
||||
2. Important details and findings
|
||||
3. Conclusions or recommendations
|
||||
4. Action items (if applicable)
|
||||
|
||||
Keep the summary clear, well-organized, and focused on the most important information.`,
|
||||
icon: 'FileText',
|
||||
category: 'general',
|
||||
variables: [],
|
||||
createdAt: new Date('2024-01-01'),
|
||||
updatedAt: new Date('2024-01-01'),
|
||||
usageCount: 0,
|
||||
isFavorite: false,
|
||||
isBuiltIn: true,
|
||||
},
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user