chat-list.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  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 { isMobileScreen } from "../utils";
  12. export function ChatItem(props: {
  13. onClick?: () => void;
  14. onDelete?: () => void;
  15. title: string;
  16. count: number;
  17. time: string;
  18. selected: boolean;
  19. id: number;
  20. index: number;
  21. }) {
  22. return (
  23. <Draggable draggableId={`${props.id}`} index={props.index}>
  24. {(provided) => (
  25. <div
  26. className={`${styles["chat-item"]} ${
  27. props.selected && styles["chat-item-selected"]
  28. }`}
  29. onClick={props.onClick}
  30. ref={provided.innerRef}
  31. {...provided.draggableProps}
  32. {...provided.dragHandleProps}
  33. >
  34. <div className={styles["chat-item-title"]}>{props.title}</div>
  35. <div className={styles["chat-item-info"]}>
  36. <div className={styles["chat-item-count"]}>
  37. {Locale.ChatItem.ChatItemCount(props.count)}
  38. </div>
  39. <div className={styles["chat-item-date"]}>{props.time}</div>
  40. </div>
  41. <div className={styles["chat-item-delete"]} onClick={props.onDelete}>
  42. <DeleteIcon />
  43. </div>
  44. </div>
  45. )}
  46. </Draggable>
  47. );
  48. }
  49. export function ChatList() {
  50. const [sessions, selectedIndex, selectSession, removeSession, moveSession] =
  51. useChatStore((state) => [
  52. state.sessions,
  53. state.currentSessionIndex,
  54. state.selectSession,
  55. state.removeSession,
  56. state.moveSession,
  57. ]);
  58. const onDragEnd: OnDragEndResponder = (result) => {
  59. const { destination, source } = result;
  60. if (!destination) {
  61. return;
  62. }
  63. if (
  64. destination.droppableId === source.droppableId &&
  65. destination.index === source.index
  66. ) {
  67. return;
  68. }
  69. moveSession(source.index, destination.index);
  70. };
  71. return (
  72. <DragDropContext onDragEnd={onDragEnd}>
  73. <Droppable droppableId="chat-list">
  74. {(provided) => (
  75. <div
  76. className={styles["chat-list"]}
  77. ref={provided.innerRef}
  78. {...provided.droppableProps}
  79. >
  80. {sessions.map((item, i) => (
  81. <ChatItem
  82. title={item.topic}
  83. time={item.lastUpdate}
  84. count={item.messages.length}
  85. key={item.id}
  86. id={item.id}
  87. index={i}
  88. selected={i === selectedIndex}
  89. onClick={() => selectSession(i)}
  90. onDelete={() =>
  91. (!isMobileScreen() || confirm(Locale.Home.DeleteChat)) &&
  92. removeSession(i)
  93. }
  94. />
  95. ))}
  96. {provided.placeholder}
  97. </div>
  98. )}
  99. </Droppable>
  100. </DragDropContext>
  101. );
  102. }