chat-list.tsx 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import { useState, useRef, useEffect, useLayoutEffect } from "react";
  2. import DeleteIcon from "../icons/delete.svg";
  3. import styles from "./home.module.scss";
  4. import {
  5. Message,
  6. SubmitKey,
  7. useChatStore,
  8. ChatSession,
  9. BOT_HELLO,
  10. } from "../store";
  11. import Locale from "../locales";
  12. import { isMobileScreen } from "../utils";
  13. export function ChatItem(props: {
  14. onClick?: () => void;
  15. onDelete?: () => void;
  16. title: string;
  17. count: number;
  18. time: string;
  19. selected: boolean;
  20. }) {
  21. return (
  22. <div
  23. className={`${styles["chat-item"]} ${
  24. props.selected && styles["chat-item-selected"]
  25. }`}
  26. onClick={props.onClick}
  27. >
  28. <div className={styles["chat-item-title"]}>{props.title}</div>
  29. <div className={styles["chat-item-info"]}>
  30. <div className={styles["chat-item-count"]}>
  31. {Locale.ChatItem.ChatItemCount(props.count)}
  32. </div>
  33. <div className={styles["chat-item-date"]}>{props.time}</div>
  34. </div>
  35. <div className={styles["chat-item-delete"]} onClick={props.onDelete}>
  36. <DeleteIcon />
  37. </div>
  38. </div>
  39. );
  40. }
  41. export function ChatList() {
  42. const [sessions, selectedIndex, selectSession, removeSession] = useChatStore(
  43. (state) => [
  44. state.sessions,
  45. state.currentSessionIndex,
  46. state.selectSession,
  47. state.removeSession,
  48. ],
  49. );
  50. return (
  51. <div className={styles["chat-list"]}>
  52. {sessions.map((item, i) => (
  53. <ChatItem
  54. title={item.topic}
  55. time={item.lastUpdate}
  56. count={item.messages.length}
  57. key={i}
  58. selected={i === selectedIndex}
  59. onClick={() => selectSession(i)}
  60. onDelete={() =>
  61. (!isMobileScreen() || confirm(Locale.Home.DeleteChat)) &&
  62. removeSession(i)
  63. }
  64. />
  65. ))}
  66. </div>
  67. );
  68. }