year пре 2 дана
родитељ
комит
d3869eed3a

+ 2 - 1
.eslintrc.json

@@ -1,6 +1,7 @@
 {
     "extends": ["next/core-web-vitals", "prettier"],
     "rules": {
-        "@next/next/no-img-element": "off"
+        "@next/next/no-img-element": "off",
+        "react/display-name": "off"
     }
 }

+ 91 - 37
src/components/Layout/Sidebar.tsx

@@ -1,25 +1,28 @@
 "use client";
 import { ContactType, getContactsApi, getSidebarActivitiesApi } from "@/api/config";
+import { ServiceTypes } from "@/api/customservice";
 import { BannerRep, GroupType } from "@/api/home";
 import Box from "@/components/Box";
 import Item from "@/components/Item";
+import { WrapHocPosition } from "@/enums";
+import feedback from "@/feedback";
 import { usePathname, useRouter } from "@/i18n/routing";
 import { useProviderStore } from "@/stores/useProvider";
 import { useSystemStore } from "@/stores/useSystemStore";
 import { useWalletStore } from "@/stores/useWalletStore";
-import { commonMask } from "@/utils";
+import { commonMask, isPWAorAPK } from "@/utils";
 import { server } from "@/utils/client";
+import { getToken } from "@/utils/Cookies";
+import { isAndroid, isIOS } from "@/utils/methods";
 import clsx from "clsx";
 import { useLocale } from "next-intl";
 import Image from "next/image";
 import React, { FC, PropsWithChildren, useEffect, useMemo, useRef, useState } from "react";
+import CustomButton from "../CustomButton";
+import InstallAPK from "../InstallApk";
 import SvgIcon from "../SvgIcon";
 import styles from "./style.module.scss";
 
-import { ServiceTypes } from "@/api/customservice";
-import { getToken } from "@/utils/Cookies";
-import CustomButton from "../CustomButton";
-
 export const getServicesApi = async () => {
     return server
         .request<ServiceTypes[]>({
@@ -80,6 +83,43 @@ enum PageEnum {
     "Vip",
 }
 
+interface AppInfoTypes {
+    /**
+     * 创建时间
+     */
+    created_at: number;
+    /**
+     * ID 编号
+     */
+    id: number;
+    /**
+     * 名称
+     */
+    name: string;
+    /**
+     * 文件大小
+     */
+    size: number;
+    /**
+     * 更新时间
+     */
+    updated_at: number;
+    /**
+     * 下载地址
+     */
+    url: string;
+    /**
+     * 版本号
+     */
+    version: string;
+}
+const getAppInfoApi = async () => {
+    return server.request<AppInfoTypes>({
+        url: "/v1/api/front/app/info",
+        method: "POST",
+    });
+};
+
 const PageEnumMap = new Map<PageEnum, { url: string }>([
     [PageEnum.home, { url: "/" }],
     [PageEnum.sports, { url: "/promo" }],
@@ -106,6 +146,8 @@ const Sidebar: FC<PropsWithChildren<Props>> = (props) => {
     const bgRef = useRef<HTMLDivElement>(null);
     const [isShowAll, setIsShowAll] = useState(false);
 
+    const [data, setData] = React.useState<AppInfoTypes | null>(null);
+
     const pathname = usePathname();
     const { isCollapse, setCollapse, service, show_free_game, show_again_game, setService } =
         useSystemStore((state) => ({
@@ -134,6 +176,16 @@ const Sidebar: FC<PropsWithChildren<Props>> = (props) => {
         //     Router.events.emit("routeChangeComplete");
         // }, 10000);
     }, [pathname]);
+    React.useEffect(() => {
+        getApkInfo();
+    }, []);
+
+    const getApkInfo = async () => {
+        const res = await getAppInfoApi();
+        if (res?.code === 200) {
+            setData(res.data);
+        }
+    };
 
     const getData = async () => {
         const res = await getServicesApi();
@@ -200,7 +252,7 @@ const Sidebar: FC<PropsWithChildren<Props>> = (props) => {
     }, [service]);
 
     const listCfg = useMemo(() => {
-        return [
+        const result = [
             {
                 text: "Mensagem",
                 icon: (
@@ -222,6 +274,7 @@ const Sidebar: FC<PropsWithChildren<Props>> = (props) => {
                 },
             },
             {
+                key: "installApp",
                 text: "Adicionar à tela inicial",
                 icon: (
                     <SvgIcon
@@ -232,8 +285,34 @@ const Sidebar: FC<PropsWithChildren<Props>> = (props) => {
                     ></SvgIcon>
                 ),
                 handle: () => {
+                    if (isPWAorAPK()) return;
+
+                    if (isIOS()) {
+                        setCollapse(false);
+                        feedback.showImage({
+                            imgUrl: "/store/ios.webp",
+                        });
+                        return;
+                    }
+                    if (isAndroid()) {
+                        const a = document.createElement("a");
+                        a.href = data?.url || "";
+                        a.target = "_blank";
+                        a.download = data?.name || "";
+                        a.click();
+                        return;
+                    }
                     setCollapse(false);
-                    router.push("/download");
+                    feedback.showModal({
+                        content: () => {
+                            return <InstallAPK></InstallAPK>;
+                        },
+                        position: WrapHocPosition.bottom,
+                        showClose: false,
+                        containerClassName: styles.installApk,
+                        useDefaultFooter: false,
+                        maskClose: true,
+                    });
                 },
             },
             {
@@ -255,36 +334,10 @@ const Sidebar: FC<PropsWithChildren<Props>> = (props) => {
                     );
                 },
             },
-            // {
-            //     text: "VIP",
-            //     icon: "/sidebar/vip.webp",
-            //     handle: () => {
-            //         setCollapse(false);
-            //         tabHandler(PageEnum.Vip);
-            //     },
-            // },
-            // {
-            //     text: "FAQ",
-            //     icon: "/sidebar/faq.webp",
-            //     handle: () => {
-            //         setCollapse(false);
-            //         tabHandler(PageEnum.help);
-            //     },
-            // },
-            // {
-            //     text: "Envie-nos um e-mail",
-            //     icon: "/sidebar/email.webp",
-            //     noRender: !(contacts && contacts?.length > 0),
-            //     handle: () => {
-            //         if (contacts) {
-            //             const a = document.createElement("a");
-            //             a.href = `mailto:${contacts[0].email}`;
-            //             a.target = "email";
-            //             a.click();
-            //         }
-            //     },
-            // },
         ];
+
+        // router.push("/download");
+        return result;
         // eslint-disable-next-line react-hooks/exhaustive-deps
     }, [serviceUrl, locale]);
 
@@ -336,7 +389,7 @@ const Sidebar: FC<PropsWithChildren<Props>> = (props) => {
         // });
     };
     return (
-        <Box pt={false} className={"h-[100%] bg-[var(--primary1)] px-[0px]"}>
+        <Box pt={false} className={"h-[100%] w-[100%] bg-[var(--primary1)] px-[0px]"}>
             <div className={"relative flex h-[100%] flex-1 flex-col"}>
                 <div className={"sticky top-[0] bg-[var(--primary3)]"}>
                     <div
@@ -542,6 +595,7 @@ const Sidebar: FC<PropsWithChildren<Props>> = (props) => {
                                 <span className="text-[.12rem]">{item.text}</span>
                             </Item>
                         );
+                        // if (isPWAorAPK() && item.key === "installApp") return null;
                         return Wrap ? (
                             <Wrap key={item.text}>
                                 <BaseItem></BaseItem>

+ 3 - 1
src/components/Layout/style.module.scss

@@ -28,7 +28,9 @@
         background-size: auto 100%;
     }
 }
-
+.installApk {
+    border-radius: 0.1rem 0.1rem 0 0 !important;
+}
 .providerBox {
     display: grid;
     grid-template-columns: repeat(3, 1fr);

+ 2 - 0
src/components/Wheel/index.tsx

@@ -101,4 +101,6 @@ const Wheel: React.FC<Props> = ({
     );
 };
 
+Wheel.displayName = "Wheel";
+
 export default Wheel;

+ 8 - 5
src/utils/index.ts

@@ -171,14 +171,17 @@ export const cryptoStr = (str: string | string) => {
     return masked;
 };
 export const isPWAorAPK = (): boolean => {
-    const displayModes = ["fullscreen", "standalone", "minimal-ui"];
-    const matchesPwa = displayModes.some(
-        (displayMode) => window.matchMedia("(display-mode: " + displayMode + ")").matches
+    if (!window) return false;
+
+    const displayModes = ["standalone", "fullscreen", "minimal-ui"];
+    const isMatch = displayModes.some(
+        (mode) => window.matchMedia(`(display-mode: ${mode})`).matches
     );
+
     return (
-        matchesPwa ||
+        isMatch ||
         (window.navigator as any)?.standalone ||
         document.referrer.includes("android-app://") ||
-        window?.isAndroidAPK
+        !!window?.isAndroidAPK
     );
 };