NotificationIcon.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { useEffect, useState } from "react";
  2. import { NotificationIcon } from "../../assets/icon";
  3. import { Badge, Popover } from "antd";
  4. import { get } from "../../request";
  5. import { INotificationListResponse } from "../api/notification";
  6. import NotificationList from "./NotificationList";
  7. import { useAppSelector } from "../../hooks";
  8. import { currentUser } from "../../reducers/current-user";
  9. import { IUser } from "../auth/User";
  10. const NotificationIconWidget = () => {
  11. const [count, setCount] = useState<number>();
  12. const currUser = useAppSelector(currentUser);
  13. const queryNotification = (user?: IUser) => {
  14. if (!user) {
  15. console.debug("未登录 不查询 notification");
  16. return;
  17. }
  18. const now = new Date();
  19. const notificationUpdatedAt = localStorage.getItem(
  20. "notification/updatedAt"
  21. );
  22. if (notificationUpdatedAt) {
  23. if (now.getTime() - parseInt(notificationUpdatedAt) < 59000) {
  24. const notificationCount = localStorage.getItem("notification/count");
  25. if (notificationCount !== null) {
  26. setCount(parseInt(notificationCount));
  27. console.debug("has notification count");
  28. return;
  29. }
  30. }
  31. }
  32. const url = `/v2/notification?view=to&limit=1`;
  33. console.info("notification url", url);
  34. get<INotificationListResponse>(url).then((json) => {
  35. if (json.ok) {
  36. localStorage.setItem(
  37. "notification/updatedAt",
  38. now.getTime().toString()
  39. );
  40. localStorage.setItem("notification/count", json.data.unread.toString());
  41. setCount(json.data.unread);
  42. if (json.data.count > 0) {
  43. const newMessageTime = json.data.rows[0].created_at;
  44. const lastTime = localStorage.getItem("notification/new");
  45. if (lastTime === null || lastTime !== newMessageTime) {
  46. localStorage.setItem("notification/new", newMessageTime);
  47. if (window.Notification && Notification.permission !== "denied") {
  48. Notification.requestPermission(function (status) {
  49. const notification = new Notification(
  50. json.data.rows[0].res_type,
  51. {
  52. body: json.data.rows[0].content,
  53. icon:
  54. process.env.REACT_APP_API_HOST +
  55. "/assets/images/wikipali_logo.png",
  56. tag: json.data.rows[0].id,
  57. }
  58. );
  59. notification.onclick = (event) => {
  60. event.preventDefault(); // 阻止浏览器聚焦于 Notification 的标签页
  61. window.open(json.data.rows[0].url, "_blank");
  62. };
  63. });
  64. }
  65. }
  66. }
  67. }
  68. });
  69. };
  70. useEffect(() => {
  71. let timer = setInterval(queryNotification, 1000 * 60, currUser);
  72. return () => {
  73. clearInterval(timer);
  74. };
  75. }, [currUser]);
  76. return (
  77. <>
  78. {currUser ? (
  79. <Popover
  80. placement="bottomLeft"
  81. arrowPointAtCenter
  82. destroyTooltipOnHide
  83. content={
  84. <div style={{ width: 600 }}>
  85. <NotificationList
  86. onChange={(unread: number) => setCount(unread)}
  87. />
  88. </div>
  89. }
  90. trigger="click"
  91. >
  92. <Badge count={count} size="small">
  93. <span style={{ color: "white", cursor: "pointer" }}>
  94. <NotificationIcon />
  95. </span>
  96. </Badge>
  97. </Popover>
  98. ) : (
  99. <></>
  100. )}
  101. </>
  102. );
  103. };
  104. export default NotificationIconWidget;