SentContent.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. import type { ISentence } from "../SentEdit"
  2. import SentCell from "./SentCell";
  3. import { WbwSentCtl } from "../WbwSent";
  4. import { useAppSelector } from "../../../hooks";
  5. import { settingInfo } from "../../../reducers/setting";
  6. import { useEffect, useLayoutEffect, useRef, useState } from "react";
  7. import { GetUserSetting } from "../../auth/setting/default";
  8. import { mode as _mode } from "../../../reducers/article-mode";
  9. import type { IWbw } from "../Wbw/WbwWord"
  10. import type { ArticleMode } from "../../article/Article"
  11. import SuggestionFocus from "./SuggestionFocus";
  12. import store from "../../../store";
  13. import { push } from "../../../reducers/sentence";
  14. import NissayaSent from "../Nissaya/NissayaSent";
  15. interface ILayoutFlex {
  16. left: number;
  17. right: number;
  18. }
  19. type TDirection = "row" | "column";
  20. interface IWidgetSentContent {
  21. sid?: string;
  22. book: number;
  23. para: number;
  24. wordStart: number;
  25. wordEnd: number;
  26. origin?: ISentence[];
  27. translation?: ISentence[];
  28. answer?: ISentence;
  29. layout?: TDirection;
  30. magicDict?: string;
  31. compact?: boolean;
  32. mode?: ArticleMode;
  33. wbwProgress?: boolean;
  34. readonly?: boolean;
  35. onWbwChange?: Function;
  36. onTranslationChange?: (data: ISentence) => void;
  37. onMagicDictDone?: Function;
  38. }
  39. const SentContentWidget = ({
  40. sid,
  41. book,
  42. para,
  43. wordStart,
  44. wordEnd,
  45. origin,
  46. translation,
  47. answer,
  48. layout = "column",
  49. compact = false,
  50. mode,
  51. ___magicDict,
  52. wbwProgress = false,
  53. readonly = false,
  54. onWbwChange,
  55. onTranslationChange,
  56. onMagicDictDone,
  57. }: IWidgetSentContent) => {
  58. const [layoutDirection, setLayoutDirection] = useState<TDirection>(layout);
  59. const [layoutFlex, setLayoutFlex] = useState<ILayoutFlex>({
  60. left: 5,
  61. right: 5,
  62. });
  63. const divShell = useRef<HTMLDivElement>(null);
  64. const settings = useAppSelector(settingInfo);
  65. const [_divShellWidth, setDivShellWidth] = useState<number>();
  66. useEffect(() => {
  67. store.dispatch(
  68. push({
  69. id: `${book}-${para}-${wordStart}-${wordEnd}`,
  70. origin: origin?.map((item) => item.html),
  71. translation: translation?.map((item) => item.html),
  72. })
  73. );
  74. }, [book, origin, para, translation, wordEnd, wordStart]);
  75. useEffect(() => {
  76. const width = divShell.current?.offsetWidth;
  77. if (width && width < 550) {
  78. setLayoutDirection("column");
  79. return;
  80. }
  81. const layoutDirection = GetUserSetting(
  82. "setting.layout.direction",
  83. settings
  84. );
  85. if (typeof layoutDirection === "string") {
  86. setLayoutDirection(layoutDirection as TDirection);
  87. }
  88. }, [settings]);
  89. const newMode = useAppSelector(_mode);
  90. useEffect(() => {
  91. let currMode: ArticleMode | undefined;
  92. if (typeof mode !== "undefined") {
  93. currMode = mode;
  94. } else if (typeof newMode !== "undefined") {
  95. if (typeof newMode.id === "undefined") {
  96. currMode = newMode.mode;
  97. } else {
  98. const sentId = newMode.id.split("-");
  99. if (sentId.length === 2) {
  100. if (book === parseInt(sentId[0]) && para === parseInt(sentId[1])) {
  101. currMode = newMode.mode;
  102. }
  103. }
  104. }
  105. } else {
  106. return;
  107. }
  108. switch (currMode) {
  109. case "edit":
  110. setLayoutFlex({
  111. left: 5,
  112. right: 5,
  113. });
  114. break;
  115. case "wbw":
  116. setLayoutFlex({
  117. left: 7,
  118. right: 3,
  119. });
  120. break;
  121. }
  122. }, [book, mode, newMode, para]);
  123. useLayoutEffect(() => {
  124. const width = divShell.current?.offsetWidth;
  125. setDivShellWidth(width);
  126. if (width && width < 550) {
  127. setLayoutDirection("column");
  128. return;
  129. }
  130. }, []);
  131. return (
  132. <div
  133. ref={divShell}
  134. style={{
  135. display: "flex",
  136. flexDirection: layoutDirection,
  137. marginBottom: 0,
  138. }}
  139. >
  140. <div
  141. dangerouslySetInnerHTML={{
  142. __html: `<div class="pcd_sent" id="sent_${sid}"></div>`,
  143. }}
  144. />
  145. <div style={{ flex: layoutFlex.left, color: "#9f3a01" }}>
  146. {origin?.map((item, id) => {
  147. if (item.contentType === "json") {
  148. if (item.channel.type === "nissaya") {
  149. return <NissayaSent data={JSON.parse(item.content ?? "[])")} />;
  150. } else {
  151. return (
  152. <WbwSentCtl
  153. key={id}
  154. book={book}
  155. para={para}
  156. wordStart={wordStart}
  157. wordEnd={wordEnd}
  158. studio={item.studio}
  159. channelId={item.channel.id}
  160. channelType={item.channel.type}
  161. channelLang={item.channel.lang}
  162. data={JSON.parse(item.content ?? "")}
  163. answer={answer ? JSON.parse(answer.content ?? "") : undefined}
  164. mode={mode}
  165. wbwProgress={wbwProgress}
  166. readonly={readonly}
  167. onChange={(data: IWbw[]) => {
  168. if (typeof onWbwChange !== "undefined") {
  169. onWbwChange(data);
  170. }
  171. }}
  172. onMagicDictDone={() => {
  173. if (typeof onMagicDictDone !== "undefined") {
  174. onMagicDictDone();
  175. }
  176. }}
  177. />
  178. );
  179. }
  180. } else {
  181. return <SentCell key={id} initValue={item} wordWidget={true} />;
  182. }
  183. })}
  184. </div>
  185. <div style={{ flex: layoutFlex.right }}>
  186. {translation?.map((item, id) => {
  187. return (
  188. <SuggestionFocus
  189. key={id}
  190. book={item.book}
  191. para={item.para}
  192. start={item.wordStart}
  193. end={item.wordEnd}
  194. channelId={item.channel.id}
  195. >
  196. <SentCell
  197. key={id}
  198. initValue={item}
  199. compact={compact}
  200. onChange={onTranslationChange}
  201. />
  202. </SuggestionFocus>
  203. );
  204. })}
  205. </div>
  206. </div>
  207. );
  208. };
  209. export default SentContentWidget;