chat-list.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import DeleteIcon from "../icons/delete.svg";
  2. import styles from "./home.module.scss";
  3. import {
  4. DragDropContext,
  5. Droppable,
  6. Draggable,
  7. OnDragEndResponder,
  8. } from "@hello-pangea/dnd";
  9. import { useChatStore } from "../store";
  10. import Locale from "../locales";
  11. import { Link, useNavigate } from "react-router-dom";
  12. import { Path } from "../constant";
  13. export function ChatItem(props: {
  14. onClick?: () => void;
  15. onDelete?: () => void;
  16. title: string;
  17. count: number;
  18. time: string;
  19. selected: boolean;
  20. id: number;
  21. index: number;
  22. }) {
  23. return (
  24. <Draggable draggableId={`${props.id}`} index={props.index}>
  25. {(provided) => (
  26. <div
  27. className={`${styles["chat-item"]} ${
  28. props.selected && styles["chat-item-selected"]
  29. }`}
  30. onClick={props.onClick}
  31. ref={provided.innerRef}
  32. {...provided.draggableProps}
  33. {...provided.dragHandleProps}
  34. >
  35. <div className={styles["chat-item-title"]}>{props.title}</div>
  36. <div className={styles["chat-item-info"]}>
  37. <div className={styles["chat-item-count"]}>
  38. {Locale.ChatItem.ChatItemCount(props.count)}
  39. </div>
  40. <div className={styles["chat-item-date"]}>{props.time}</div>
  41. </div>
  42. <div className={styles["chat-item-delete"]} onClick={props.onDelete}>
  43. <DeleteIcon />
  44. </div>
  45. </div>
  46. )}
  47. </Draggable>
  48. );
  49. }
  50. export function ChatList() {
  51. const [sessions, selectedIndex, selectSession, removeSession, moveSession] =
  52. useChatStore((state) => [
  53. state.sessions,
  54. state.currentSessionIndex,
  55. state.selectSession,
  56. state.removeSession,
  57. state.moveSession,
  58. ]);
  59. const chatStore = useChatStore();
  60. const navigate = useNavigate();
  61. const onDragEnd: OnDragEndResponder = (result) => {
  62. const { destination, source } = result;
  63. if (!destination) {
  64. return;
  65. }
  66. if (
  67. destination.droppableId === source.droppableId &&
  68. destination.index === source.index
  69. ) {
  70. return;
  71. }
  72. moveSession(source.index, destination.index);
  73. };
  74. return (
  75. <DragDropContext onDragEnd={onDragEnd}>
  76. <Droppable droppableId="chat-list">
  77. {(provided) => (
  78. <div
  79. className={styles["chat-list"]}
  80. ref={provided.innerRef}
  81. {...provided.droppableProps}
  82. >
  83. {sessions.map((item, i) => (
  84. <ChatItem
  85. title={item.topic}
  86. time={item.lastUpdate}
  87. count={item.messages.length}
  88. key={item.id}
  89. id={item.id}
  90. index={i}
  91. selected={i === selectedIndex}
  92. onClick={() => {
  93. navigate(Path.Chat);
  94. selectSession(i);
  95. }}
  96. onDelete={() => chatStore.deleteSession(i)}
  97. />
  98. ))}
  99. {provided.placeholder}
  100. </div>
  101. )}
  102. </Droppable>
  103. </DragDropContext>
  104. );
  105. }