SarahXia0405 commited on
Commit
f08c633
·
verified ·
1 Parent(s): cc328bc

Update web/src/components/ChatArea.tsx

Browse files
Files changed (1) hide show
  1. web/src/components/ChatArea.tsx +29 -35
web/src/components/ChatArea.tsx CHANGED
@@ -568,17 +568,19 @@ export function ChatArea({
568
  }, [uploadedFiles, pendingFiles]);
569
  const { getOrCreate } = useObjectUrlCache(allThumbFiles);
570
 
571
- // ✅ NEW: a compact "chip" UI (the one with left X)
572
  const FileChip = ({
573
  file,
574
  index,
 
575
  }: {
576
  file: File;
577
  index: number;
 
578
  }) => {
579
  const ext = file.name.toLowerCase();
580
  const isImage = [".jpg", ".jpeg", ".png", ".gif", ".webp"].some((e) => ext.endsWith(e));
581
-
582
  const label = ext.endsWith(".pdf")
583
  ? "PDF"
584
  : ext.endsWith(".pptx") || ext.endsWith(".ppt")
@@ -588,61 +590,53 @@ export function ChatArea({
588
  : isImage
589
  ? "Image"
590
  : "File";
591
-
592
  const thumbUrl = isImage ? getOrCreate(file) : null;
593
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
  return (
595
  <div className="flex items-center gap-3 rounded-xl border border-border bg-card px-3 py-2 shadow-sm w-[340px] max-w-full">
596
- {/* ✅ FIX: type="button" + preventDefault/stopPropagation + direct remove */}
597
  <button
598
  type="button"
599
  aria-label="Remove file"
600
  title="Remove"
601
- onMouseDown={(e) => {
602
- // ✅ 关键:在 mouseDown 就拦截,防止 <label> / 外层点击先触发
603
- e.preventDefault();
604
- e.stopPropagation();
605
- // @ts-ignore
606
- e.nativeEvent?.stopImmediatePropagation?.();
607
- }}
608
- onPointerDown={(e) => {
609
- // ✅ 兼容触控/Pointer 事件
610
- e.preventDefault();
611
- e.stopPropagation();
612
- // @ts-ignore
613
- e.nativeEvent?.stopImmediatePropagation?.();
614
- }}
615
  onClick={(e) => {
616
- // ✅ 双保险:click 也拦截
617
- e.preventDefault();
618
- e.stopPropagation();
619
- // @ts-ignore
620
- e.nativeEvent?.stopImmediatePropagation?.();
621
-
622
- onRemoveFile(index);
623
  }}
624
  className="h-6 w-6 rounded-full border border-border bg-background flex items-center justify-center hover:bg-muted"
625
  >
626
  <X className="h-4 w-4" />
627
  </button>
628
-
629
-
630
  <div className="min-w-0 flex-1">
631
  <div className="text-sm font-medium truncate" title={file.name}>
632
  {file.name}
633
  </div>
634
  <div className="text-xs text-muted-foreground">{label}</div>
635
  </div>
636
-
637
  {isImage ? (
638
  <div className="relative h-14 w-14 flex-shrink-0 rounded-lg overflow-hidden border border-border">
639
  {thumbUrl ? (
640
- <img
641
- src={thumbUrl}
642
- alt={file.name}
643
- className="h-full w-full object-cover"
644
- draggable={false}
645
- />
646
  ) : (
647
  <div className="h-full w-full flex items-center justify-center bg-muted">
648
  <ImageIcon className="h-5 w-5 text-muted-foreground" />
 
568
  }, [uploadedFiles, pendingFiles]);
569
  const { getOrCreate } = useObjectUrlCache(allThumbFiles);
570
 
571
+ // ✅ NEW: a compact "chip" UI (the one with left X)
572
  const FileChip = ({
573
  file,
574
  index,
575
+ source,
576
  }: {
577
  file: File;
578
  index: number;
579
+ source: "uploaded" | "pending";
580
  }) => {
581
  const ext = file.name.toLowerCase();
582
  const isImage = [".jpg", ".jpeg", ".png", ".gif", ".webp"].some((e) => ext.endsWith(e));
583
+
584
  const label = ext.endsWith(".pdf")
585
  ? "PDF"
586
  : ext.endsWith(".pptx") || ext.endsWith(".ppt")
 
590
  : isImage
591
  ? "Image"
592
  : "File";
593
+
594
  const thumbUrl = isImage ? getOrCreate(file) : null;
595
+
596
+ const handleRemove = () => {
597
+ if (source === "uploaded") {
598
+ onRemoveFile(index);
599
+ } else {
600
+ setPendingFiles((prev) => prev.filter((_, i) => i !== index));
601
+ }
602
+ };
603
+
604
+ const stopAll = (e: any) => {
605
+ e.preventDefault();
606
+ e.stopPropagation();
607
+ // @ts-ignore
608
+ e.nativeEvent?.stopImmediatePropagation?.();
609
+ };
610
+
611
  return (
612
  <div className="flex items-center gap-3 rounded-xl border border-border bg-card px-3 py-2 shadow-sm w-[340px] max-w-full">
 
613
  <button
614
  type="button"
615
  aria-label="Remove file"
616
  title="Remove"
617
+ onMouseDown={stopAll}
618
+ onPointerDown={stopAll}
619
+ onTouchStart={stopAll}
 
 
 
 
 
 
 
 
 
 
 
620
  onClick={(e) => {
621
+ stopAll(e);
622
+ handleRemove();
 
 
 
 
 
623
  }}
624
  className="h-6 w-6 rounded-full border border-border bg-background flex items-center justify-center hover:bg-muted"
625
  >
626
  <X className="h-4 w-4" />
627
  </button>
628
+
 
629
  <div className="min-w-0 flex-1">
630
  <div className="text-sm font-medium truncate" title={file.name}>
631
  {file.name}
632
  </div>
633
  <div className="text-xs text-muted-foreground">{label}</div>
634
  </div>
635
+
636
  {isImage ? (
637
  <div className="relative h-14 w-14 flex-shrink-0 rounded-lg overflow-hidden border border-border">
638
  {thumbUrl ? (
639
+ <img src={thumbUrl} alt={file.name} className="h-full w-full object-cover" draggable={false} />
 
 
 
 
 
640
  ) : (
641
  <div className="h-full w-full flex items-center justify-center bg-muted">
642
  <ImageIcon className="h-5 w-5 text-muted-foreground" />