Video.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import { Button, Card, Collapse, Modal, Popover, Space } from "antd";
  2. import { Typography } from "antd";
  3. import { useEffect, useState } from "react";
  4. import { CloseOutlined } from "@ant-design/icons";
  5. import { Link } from "react-router-dom";
  6. import { TDisplayStyle } from "./Article";
  7. import Video from "../general/Video";
  8. import { VideoIcon } from "../../assets/icon";
  9. import { useIntl } from "react-intl";
  10. import { IAttachmentResponse } from "../api/Attachments";
  11. import { get } from "../../request";
  12. const { Text } = Typography;
  13. interface IVideoCtl {
  14. url?: string;
  15. id?: string;
  16. title?: React.ReactNode;
  17. style?: TDisplayStyle;
  18. _style?: TDisplayStyle;
  19. }
  20. export const VideoCtl = ({
  21. url,
  22. id,
  23. title,
  24. style = "modal",
  25. _style,
  26. }: IVideoCtl) => {
  27. const intl = useIntl();
  28. const [isModalOpen, setIsModalOpen] = useState(false);
  29. const [fetchUrl, setFetchUrl] = useState<string>();
  30. style = _style ? _style : style;
  31. useEffect(() => {
  32. if (id) {
  33. const url = `/v2/attachment/${id}`;
  34. console.info("url", url);
  35. get<IAttachmentResponse>(url).then((json) => {
  36. console.log(json);
  37. if (json.ok) {
  38. setFetchUrl(json.data.url);
  39. }
  40. });
  41. }
  42. }, [id]);
  43. const showModal = () => {
  44. setIsModalOpen(true);
  45. };
  46. const handleOk = () => {
  47. setIsModalOpen(false);
  48. };
  49. const handleCancel = () => {
  50. setIsModalOpen(false);
  51. };
  52. let output = <></>;
  53. let articleLink = url ? url : fetchUrl ? fetchUrl : "";
  54. const VideoModal = () => {
  55. return (
  56. <>
  57. <Typography.Link
  58. onClick={(event: React.MouseEvent<HTMLElement, MouseEvent>) => {
  59. if (event.ctrlKey || event.metaKey) {
  60. window.open(articleLink, "_blank");
  61. } else {
  62. showModal();
  63. }
  64. }}
  65. >
  66. <Space>
  67. <VideoIcon />
  68. {title}
  69. </Space>
  70. </Typography.Link>
  71. <Modal
  72. width={"90%"}
  73. destroyOnClose
  74. style={{ maxWidth: 1000, top: 20, height: 700 }}
  75. title={
  76. <div
  77. style={{
  78. display: "flex",
  79. justifyContent: "space-between",
  80. marginRight: 30,
  81. }}
  82. >
  83. <Text>{title}</Text>
  84. <Text>
  85. <Link to={articleLink} target="_blank">
  86. {intl.formatMessage({
  87. id: "buttons.open.in.new.tab",
  88. })}
  89. </Link>
  90. </Text>
  91. </div>
  92. }
  93. open={isModalOpen}
  94. onOk={handleOk}
  95. onCancel={handleCancel}
  96. footer={[]}
  97. >
  98. <div style={{ height: 550 }}>
  99. <Video src={url} />
  100. </div>
  101. </Modal>
  102. </>
  103. );
  104. };
  105. const VideoCard = () => {
  106. return (
  107. <Card title={title} bodyStyle={{ width: 550, height: 400 }}>
  108. <Video src={url} />
  109. </Card>
  110. );
  111. };
  112. const VideoWindow = () => {
  113. return (
  114. <div style={{ width: 550, height: 320 }}>
  115. <Video src={url} />
  116. </div>
  117. );
  118. };
  119. const VideoToggle = () => {
  120. return (
  121. <Collapse bordered={false}>
  122. <Collapse.Panel header={title} key="parent2">
  123. <Video src={url} />
  124. </Collapse.Panel>
  125. </Collapse>
  126. );
  127. };
  128. const VideoLink = () => {
  129. return (
  130. <Link to={articleLink} target="_blank">
  131. <Space>
  132. <VideoIcon />
  133. {title}
  134. </Space>
  135. </Link>
  136. );
  137. };
  138. const VideoPopover = () => {
  139. const [popOpen, setPopOpen] = useState(false);
  140. return (
  141. <Popover
  142. title={
  143. <div>
  144. {title}
  145. <Button
  146. type="link"
  147. icon={<CloseOutlined />}
  148. onClick={() => {
  149. setPopOpen(false);
  150. }}
  151. />
  152. </div>
  153. }
  154. content={
  155. <div style={{ width: 600, height: 350 }}>
  156. <Video src={url} />
  157. </div>
  158. }
  159. trigger={"click"}
  160. placement="bottom"
  161. open={popOpen}
  162. >
  163. <span onClick={() => setPopOpen(true)}>
  164. <VideoIcon />
  165. {title}
  166. </span>
  167. </Popover>
  168. );
  169. };
  170. switch (style) {
  171. case "modal":
  172. output = <VideoModal />;
  173. break;
  174. case "card":
  175. output = <VideoCard />;
  176. break;
  177. case "window":
  178. output = <VideoWindow />;
  179. break;
  180. case "toggle":
  181. output = <VideoToggle />;
  182. break;
  183. case "link":
  184. output = <VideoLink />;
  185. break;
  186. case "popover":
  187. output = <VideoPopover />;
  188. break;
  189. default:
  190. break;
  191. }
  192. return output;
  193. };
  194. interface IWidget {
  195. props: string;
  196. children?: React.ReactNode;
  197. }
  198. const VideoWidget = ({ props, children }: IWidget) => {
  199. const prop = JSON.parse(atob(props)) as IVideoCtl;
  200. return <VideoCtl {...prop} />;
  201. };
  202. export default VideoWidget;