2
0

Chapter.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // ─────────────────────────────────────────────
  2. // Props
  3. // ─────────────────────────────────────────────
  4. import { useLocation } from "react-router";
  5. import type { ArticleMode, ArticleType } from "../../api/article";
  6. import TypePali, {
  7. type ISearchParams,
  8. } from "../../components/article/TypePali";
  9. import Editor from "../../components/editor";
  10. import PaliTextToc from "../../components/tipitaka/PaliTextToc";
  11. import { useSaveRecent } from "../../hooks/useSaveRecent";
  12. import type { TTarget } from "../../types";
  13. import { useEffect } from "react";
  14. import { useAppSelector } from "../../hooks";
  15. import { currentUser } from "../../reducers/current-user";
  16. export interface ChapterEditorProps {
  17. chapterId?: string;
  18. mode?: ArticleMode;
  19. channelId?: string | null;
  20. // ── 路由事件回调(由 page 层处理导航)──
  21. /** 选择了新的 chapter 时触发 */
  22. onSelect?: (id: string) => void;
  23. onArticleChange?: (
  24. type: ArticleType,
  25. id: string,
  26. target: TTarget,
  27. param?: ISearchParams[]
  28. ) => void;
  29. }
  30. // ─────────────────────────────────────────────
  31. // Component
  32. // ─────────────────────────────────────────────
  33. export default function ChapterEditor({
  34. chapterId,
  35. mode = "read",
  36. channelId,
  37. onArticleChange,
  38. }: ChapterEditorProps) {
  39. const [book, para] = chapterId
  40. ? chapterId.split("-").map((item) => parseInt(item))
  41. : [undefined, undefined];
  42. const currUser = useAppSelector(currentUser);
  43. const { save } = useSaveRecent();
  44. const { search } = useLocation();
  45. useEffect(() => {
  46. if (!currUser?.id || !chapterId) return;
  47. save({
  48. type: "chapter",
  49. article_id: chapterId,
  50. param: search || undefined,
  51. });
  52. }, [currUser?.id, chapterId, search, save]);
  53. return (
  54. <Editor
  55. sidebarTitle="recent scan"
  56. sidebar={
  57. <PaliTextToc
  58. book={book}
  59. para={para}
  60. onSelect={(selected) => {
  61. if (selected) {
  62. onArticleChange?.("chapter", selected[0], "_self");
  63. }
  64. }}
  65. />
  66. }
  67. articleId={chapterId}
  68. articleType="chapter"
  69. channelId={channelId}
  70. onChannelSelect={(selected) => {
  71. if (chapterId) {
  72. const channelParams = [
  73. {
  74. key: "channel",
  75. value: selected.map((item) => item.id).join("_"),
  76. },
  77. ];
  78. console.debug("onChannelSelect", channelParams);
  79. onArticleChange?.("chapter", chapterId, "_self", channelParams);
  80. }
  81. }}
  82. >
  83. {({ expandButton }) => (
  84. <TypePali
  85. id={chapterId}
  86. type="chapter"
  87. mode={mode}
  88. channelId={channelId}
  89. headerExtra={expandButton}
  90. onArticleChange={onArticleChange}
  91. />
  92. )}
  93. </Editor>
  94. );
  95. }