Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion webview-ui/src/components/chat/ChatTextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { KiloProfileSelector } from "../kilocode/chat/KiloProfileSelector"
import { MAX_IMAGES_PER_MESSAGE } from "./ChatView"
import ContextMenu from "./ContextMenu"
import { ImageWarningBanner } from "./ImageWarningBanner"
import { ContextFeedbackBanner, FeedbackType } from "./ContextFeedbackBanner"
import { VolumeX, Pin, Check, WandSparkles, SendHorizontal, Paperclip, MessageSquareX } from "lucide-react"
import { IndexingStatusBadge } from "./IndexingStatusBadge"
import { MicrophoneButton } from "./MicrophoneButton" // kilocode_change: STT microphone button
Expand Down Expand Up @@ -291,6 +292,14 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
return () => window.removeEventListener("message", messageHandler)
}, [setInputValue, searchRequestId, inputValue, onSend])
const [isDraggingOver, setIsDraggingOver] = useState(false)
// kilocode_change start: Context feedback state
const [contextFeedback, setContextFeedback] = useState<{
visible: boolean
type: FeedbackType
messageKey: string
interpolations?: Record<string, string | number>
}>({ visible: false, type: "success", messageKey: "" })
// kilocode_change end: Context feedback state
// kilocode_change start: Slash commands state
const [showSlashCommandsMenu, setShowSlashCommandsMenu] = useState(false)
const [selectedSlashCommandsIndex, setSelectedSlashCommandsIndex] = useState(0)
Expand Down Expand Up @@ -446,6 +455,19 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
}
}, [inputValue, setInputValue, t])

// kilocode_change start: Context feedback handlers
const showContextFeedback = useCallback(
(type: FeedbackType, messageKey: string, interpolations?: Record<string, string | number>) => {
setContextFeedback({ visible: true, type, messageKey, interpolations })
},
[],
)

const dismissContextFeedback = useCallback(() => {
setContextFeedback((prev) => ({ ...prev, visible: false }))
}, [])
// kilocode_change end: Context feedback handlers

// kilocode_change start: Image and speech handlers
const showImageWarning = useCallback(
(messageKey: string) => {
Expand Down Expand Up @@ -1237,8 +1259,18 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
const newCursorPosition = cursorPosition + totalLength
setCursorPosition(newCursorPosition)
setIntendedCursorPosition(newCursorPosition)

// kilocode_change start: Show feedback when files are added
if (lines.length === 1) {
showContextFeedback("success", "kilocode:contextFeedback.fileAddedToContext")
} else {
showContextFeedback("success", "kilocode:contextFeedback.filesAddedToContext", {
count: lines.length,
})
}
// kilocode_change end: Show feedback when files are added
}

return
}

Expand Down Expand Up @@ -1821,6 +1853,15 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
isVisible={!!imageWarning}
/>
{/* kilocode_change end: ImageWarningBanner integration */}
{/* kilocode_change start: ContextFeedbackBanner integration */}
<ContextFeedbackBanner
type={contextFeedback.type}
messageKey={contextFeedback.messageKey}
interpolations={contextFeedback.interpolations}
onDismiss={dismissContextFeedback}
isVisible={contextFeedback.visible}
/>
{/* kilocode_change end: ContextFeedbackBanner integration */}
{/* kilocode_change start: pull slash commands from Cline */}
{showSlashCommandsMenu && (
<div ref={slashCommandsMenuContainerRef}>
Expand Down
83 changes: 83 additions & 0 deletions webview-ui/src/components/chat/ContextFeedbackBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// kilocode_change - new file: Visual feedback for file drag-drop operations
import React, { useEffect } from "react"
import { CheckCircle, Info, X } from "lucide-react"

import { useAppTranslation } from "@/i18n/TranslationContext"
import { cn } from "@/lib/utils"

export type FeedbackType = "success" | "info"

interface ContextFeedbackBannerProps {
isVisible: boolean
type: FeedbackType
messageKey: string
interpolations?: Record<string, string | number>
onDismiss: () => void
className?: string
}

export const ContextFeedbackBanner: React.FC<ContextFeedbackBannerProps> = ({
isVisible,
type,
messageKey,
interpolations,
onDismiss,
className,
}) => {
const { t } = useAppTranslation()

useEffect(() => {
if (isVisible) {
const timer = setTimeout(() => {
onDismiss()
}, 3000) // 3s auto-dismiss

return () => clearTimeout(timer)
}
}, [isVisible, onDismiss])

if (!isVisible) {
return null
}

const Icon = type === "success" ? CheckCircle : Info

const styles = {
success: {
border: "1px solid var(--vscode-testing-iconPassed)",
color: "var(--vscode-testing-iconPassed)",
background: "var(--vscode-input-background)",
},
info: {
border: "1px solid var(--vscode-notificationsInfoIcon-foreground)",
color: "var(--vscode-notificationsInfoIcon-foreground)",
background: "var(--vscode-input-background)",
},
}

return (
<div
className={cn(
"flex items-center gap-2 px-3 py-2 mb-2",
"rounded-md text-sm",
"animate-in slide-in-from-top-2 duration-200",
className,
)}
style={styles[type]}
role="status"
aria-live="polite">
<Icon className="w-4 h-4 flex-shrink-0" />
<span className="flex-1">{t(messageKey, interpolations)}</span>
<button
onClick={onDismiss}
className={cn(
"flex-shrink-0 p-0.5 rounded cursor-pointer",
"hover:bg-black/10 focus:outline-none focus:ring-1",
"focus:ring-[var(--vscode-focusBorder)]",
)}
aria-label="Dismiss">
<X className="w-3 h-3" />
</button>
</div>
)
}
5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/en/kilocode.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@
"maxImagesReached": "Maximum of 20 images per message. Remove some images to add more.",
"imagesRemovedNoSupport": "Images removed, unsupported by model."
},
"contextFeedback": {
"filesAddedToContext": "{{count}} file(s) added to context",
"fileAddedToContext": "File added to context",
"shiftDragHint": "Hold Shift while dragging to add files to context"
},
"settings": {
"sections": {
"mcp": "MCP Servers"
Expand Down
5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/pt-BR/kilocode.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.