Desktop.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. "use client";
  2. import { Button, Popup } from "antd-mobile";
  3. import { useTranslations } from "next-intl";
  4. import Image from "next/image";
  5. import { forwardRef, memo, useEffect, useImperativeHandle, useRef, useState } from "react";
  6. /**
  7. * @description 检测pwa是否下载
  8. * if 下载 不弹窗 , else 弹窗
  9. *
  10. */
  11. export interface DesktopRefProps {
  12. onOpen: () => void;
  13. onClose: () => void;
  14. }
  15. interface Props {
  16. source?: "page" | "components";
  17. }
  18. const Desktop = forwardRef<DesktopRefProps, Props>(function Desktop(props, ref) {
  19. const prompt = useRef<Event | null>(null);
  20. const { source = "page" } = props;
  21. const elementRef = useRef<HTMLElement | null>(null);
  22. const t = useTranslations("HomePage");
  23. // const { isHasDesktop, setHasDesktop } = useSystemStore((state) => {
  24. // return {
  25. // isHasDesktop: state.isHasDesktop,
  26. // setHasDesktop: state.setHasDesktop,
  27. // };
  28. // });
  29. const [isHasDesktop, setHasDesktop] = useState(false);
  30. const downloadHandler = () => {
  31. sessionStorage.setItem("pwa_install", "cancel");
  32. // @ts-ignore
  33. prompt.current?.prompt();
  34. // 不判断是否真的包含
  35. setHasDesktop(false);
  36. };
  37. const initDesktop = (e: Event) => {
  38. if (window.matchMedia("(display-mode: standalone)").matches) {
  39. setHasDesktop(false);
  40. return;
  41. }
  42. // 有pwa 则不会触发
  43. prompt.current = e;
  44. if (source === "page" && sessionStorage.getItem("pwa_install") === null) {
  45. setHasDesktop(true);
  46. }
  47. };
  48. useEffect(() => {
  49. elementRef.current = document.getElementById("app");
  50. window.addEventListener("beforeinstallprompt", initDesktop);
  51. // @ts-ignore
  52. window.onappinstalled = function (ev) {
  53. // 安装完成
  54. console.log("The application was installed.");
  55. };
  56. return () => window.removeEventListener("beforeinstallprompt", initDesktop);
  57. }, []);
  58. useImperativeHandle(ref, () => {
  59. return {
  60. onClose: () => setHasDesktop(false),
  61. onOpen: () => {
  62. setHasDesktop(true);
  63. },
  64. };
  65. });
  66. const cancel = () => {
  67. sessionStorage.setItem("pwa_install", "cancel");
  68. setHasDesktop(false);
  69. };
  70. return (
  71. <Popup
  72. visible={!!isHasDesktop}
  73. getContainer={elementRef.current}
  74. bodyStyle={{ padding: "0.2rem", background: "#fff" }}
  75. >
  76. <div className={"flex text-[0.12rem] text-[#8d8d8d]"}>
  77. <Image
  78. src={"/icon-192x192.png"}
  79. alt={"logo"}
  80. className={"mr-[10px] flex-shrink-0"}
  81. width={80}
  82. height={80}
  83. />
  84. {t("saveTips")}
  85. </div>
  86. <div className={"mb-[0.16rem] mt-[0.1rem] text-right"}>
  87. <Button
  88. color="default"
  89. className={"mr-[10px]"}
  90. style={{ "--text-color": "#8d8d8d" }}
  91. fill="none"
  92. onClick={cancel}
  93. >
  94. {t("cancel")}
  95. </Button>
  96. <Button
  97. color="primary"
  98. style={{
  99. "--text-color": "#ff6a01",
  100. "--border-color": "#ff6a01",
  101. "--border-radius": "10px",
  102. }}
  103. fill="outline"
  104. onClick={downloadHandler}
  105. >
  106. {t("save")}
  107. </Button>
  108. </div>
  109. </Popup>
  110. );
  111. });
  112. export default memo(Desktop);