|
1 | 1 | import React, { useState, useRef, useEffect } from 'react'; |
2 | | -import { FiSend, FiX, FiRefreshCw, FiImage, FiLoader } from 'react-icons/fi'; |
| 2 | +import { FiSend, FiX, FiRefreshCw, FiImage, FiLoader, FiSquare } from 'react-icons/fi'; |
3 | 3 | import { motion, AnimatePresence } from 'framer-motion'; |
4 | 4 | import { ConnectionStatus } from '@/common/types'; |
5 | 5 | import { ChatCompletionContentPart } from '@tarko/agent-interface'; |
@@ -214,15 +214,19 @@ export const MessageInputField: React.FC<MessageInputFieldProps> = ({ |
214 | 214 | }; |
215 | 215 |
|
216 | 216 | const handleAbort = async () => { |
217 | | - if (!isProcessing) return; |
| 217 | + if (!isProcessing || isAborting) return; |
218 | 218 |
|
219 | 219 | setIsAborting(true); |
220 | 220 | try { |
221 | | - await abortQuery(); |
| 221 | + const success = await abortQuery(); |
| 222 | + if (!success) { |
| 223 | + console.warn('Abort request may have failed'); |
| 224 | + } |
222 | 225 | } catch (error) { |
223 | 226 | console.error('Failed to abort:', error); |
224 | 227 | } finally { |
225 | | - setIsAborting(false); |
| 228 | + // Add a small delay to prevent UI flickering |
| 229 | + setTimeout(() => setIsAborting(false), 100); |
226 | 230 | } |
227 | 231 | }; |
228 | 232 |
|
@@ -407,22 +411,27 @@ export const MessageInputField: React.FC<MessageInputFieldProps> = ({ |
407 | 411 | ) : isProcessing ? ( |
408 | 412 | <motion.button |
409 | 413 | {...{ ['ke' + 'y']: 'abort-btn' }} |
410 | | - initial={{ opacity: 0, scale: 0.8 }} |
411 | | - animate={{ opacity: 1, scale: 1 }} |
412 | | - exit={{ opacity: 0, scale: 0.8 }} |
413 | | - whileTap={{ scale: 0.9 }} |
414 | | - whileHover={{ scale: 1.05 }} |
| 414 | + initial={{ opacity: 0 }} |
| 415 | + animate={{ opacity: 1 }} |
| 416 | + exit={{ opacity: 0 }} |
| 417 | + transition={{ duration: 0.2 }} |
| 418 | + whileTap={{ scale: 0.95 }} |
| 419 | + whileHover={{ scale: 1.02 }} |
415 | 420 | type="button" |
416 | 421 | onClick={handleAbort} |
417 | 422 | disabled={isAborting} |
418 | | - className={`absolute right-3 bottom-3 p-2 rounded-full ${ |
| 423 | + className={`absolute right-3 bottom-3 w-10 h-10 rounded-full flex items-center justify-center ${ |
419 | 424 | isAborting |
420 | | - ? 'text-gray-300 dark:text-gray-600 cursor-not-allowed' |
421 | | - : 'text-gray-500 hover:bg-gray-50 dark:hover:bg-gray-700/30 dark:text-gray-400' |
422 | | - } transition-all duration-200`} |
423 | | - title="Abort current operation" |
| 425 | + ? 'bg-gradient-to-r from-indigo-100 via-purple-100 to-pink-100 dark:from-indigo-800/30 dark:via-purple-800/30 dark:to-pink-800/30 text-indigo-400 dark:text-indigo-500 cursor-not-allowed border-2 border-indigo-200 dark:border-indigo-700/50' |
| 426 | + : 'bg-gradient-to-r from-indigo-50 via-purple-50 to-pink-50 hover:from-indigo-100 hover:via-purple-100 hover:to-pink-100 dark:from-indigo-900/20 dark:via-purple-900/20 dark:to-pink-900/20 dark:hover:from-indigo-900/30 dark:hover:via-purple-900/30 dark:hover:to-pink-900/30 text-indigo-600 dark:text-indigo-400 border-2 border-indigo-200 dark:border-indigo-700/50' |
| 427 | + } transition-all duration-200 shadow-sm bg-[length:200%_200%] animate-border-flow`} |
| 428 | + title="Stop generation" |
424 | 429 | > |
425 | | - {isAborting ? <FiLoader className="animate-spin" size={20} /> : <FiX size={20} />} |
| 430 | + {isAborting ? ( |
| 431 | + <div className="w-4 h-4 border-2 border-current border-t-transparent rounded-full animate-spin" /> |
| 432 | + ) : ( |
| 433 | + <div className="w-3 h-3 bg-current rounded-sm" /> |
| 434 | + )} |
426 | 435 | </motion.button> |
427 | 436 | ) : ( |
428 | 437 | <motion.button |
|
0 commit comments