App.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. // GA
  2. import ReactGA from 'react-ga4';
  3. // utils
  4. import React, {lazy, Suspense, useState} from 'react';
  5. // styles
  6. import ThemeStyles from '@styles/theme';
  7. import './style.scss';
  8. // libs styles
  9. import 'react-toastify/dist/ReactToastify.min.css';
  10. import 'react-grid-layout/css/styles.css';
  11. import 'swiper/css';
  12. import 'swiper/css/effect-fade';
  13. import 'swiper/css/pagination';
  14. // fonts
  15. import '@fonts/icomoon/icomoon.woff';
  16. // import '@fonts/swisscbt/SWISSC-BT.ttf'
  17. // contexts
  18. import {SidebarProvider, useSidebar} from '@contexts/sidebarContext';
  19. import {ThemeProvider} from 'styled-components';
  20. // hooks
  21. import {useThemeProvider} from '@contexts/themeContext';
  22. import {useEffect, useRef} from 'react';
  23. import {useWindowSize} from 'react-use';
  24. import useAuthRoute from '@hooks/useAuthRoute';
  25. // utils
  26. import {StyleSheetManager} from 'styled-components';
  27. import {ThemeProvider as MuiThemeProvider, createTheme} from '@mui/material/styles';
  28. import {getBrazilTimeStamp, getUrlParam, localStorageGet, localStorageSet, preventDefault} from '@utils/helpers';
  29. import rtlPlugin from 'stylis-plugin-rtl';
  30. import {CacheProvider} from '@emotion/react';
  31. import createCache from '@emotion/cache';
  32. // components
  33. import {BrowserRouter, HashRouter, Route, Routes, useLocation, useNavigate} from 'react-router-dom';
  34. import {ToastContainer} from 'react-toastify';
  35. import Layout from "@layout/Layout";
  36. import {
  37. getBFP,
  38. getFetchStatus,
  39. getHallServerUrl, getKickState, getOpenPay, getPromoteInstall, getPopWheel,
  40. getUserID,
  41. getUserInfo,
  42. isLogined,
  43. updateCurrGame, updateOpenPay, getIsGuest, getPopBindPhone, getPopFirst
  44. } from '@features/mainSlice';
  45. import {useDispatch, useSelector} from "react-redux";
  46. import {REQ_STATUS} from "@api/config";
  47. import {
  48. reqAgentCheck, reqCheckinCheck,
  49. reqCustomService, reqFavoGet, reqFirstPayConfig, reqGameActivity, reqGameInfo,
  50. reqGetRoutes,
  51. reqMailCheck, reqProtectCheck,
  52. reqRedpackCheck, reqRedpackConfig,
  53. reqTurnplateIndex,
  54. reqWithdrawBaseInfo
  55. } from "@features/api";
  56. import LoadingScreen from "@components/LoadingScreen";
  57. import DropCoins from "@components/DropCoins";
  58. import {getFirstPayMulti, reqPayConfig} from "@features/paySlice";
  59. import {connectHall, disconnectHall, hallSendState} from "@features/actions/hallClient";
  60. import {toast} from "react-toastify";
  61. import {useBlocker} from "react-router";
  62. import FontFaceObserver from 'fontfaceobserver';
  63. import {getTurnplate} from "@features/turnplateSlice";
  64. import {LOCAL_ACTIVITY_C, LOCAL_VISTOR_ID, LOCAL_WHEEL_INVITE_CODE} from "@constants/localkey";
  65. import LoadingFull from "@components/Loading/LoadingFull";
  66. import {ClickAwayListener} from "@mui/base/ClickAwayListener";
  67. import useGlobalClick from "@hooks/useGlobalClick";
  68. import SoundHelp from "@utils/SoundManger";
  69. import {ROUTE_PATH} from "@constants/routes";
  70. import {onChangeUser, onChangeUserID} from "@features/actions/mainAction";
  71. import {isInAppBrowser, isShowInstallBox, openUrlUseChrome} from "@utils/UAUtils";
  72. import WInstallBox from "@widgets/WInstallBox";
  73. import WMaintainBox from "@widgets/WMaintainBox";
  74. import WAreaSelect from "@widgets/WAreaSelect";
  75. const objInfo={
  76. gameID:0
  77. }
  78. const App = () => {
  79. const dispatch = useDispatch();
  80. const fetchStatus=useSelector(getFetchStatus);
  81. const userInfo=useSelector(getUserInfo);
  82. const userID=useSelector(getUserID);
  83. const turnplate=useSelector(getTurnplate);
  84. const appRef = useRef(null);
  85. const {theme, direction,setIsShowWheel,preLocation,gameID} = useThemeProvider();
  86. const {pathname, search, hash} = useLocation();
  87. const gaKey = process.env.REACT_APP_PUBLIC_GA;
  88. gaKey && ReactGA.initialize(gaKey);
  89. const navigate = useNavigate();
  90. // auto RTL support for Material-UI components and styled-components
  91. const plugins = direction === 'rtl' ? [rtlPlugin] : [];
  92. const hallServerUrl=useSelector(getHallServerUrl);
  93. useGlobalClick();
  94. // const {preLocation,gameID}=usePreviousRoute();
  95. const serverKick=useSelector(getKickState);
  96. const promoteInstall=useSelector(getPromoteInstall);
  97. const popWheel=useSelector(getPopWheel);
  98. const openPay=useSelector(getOpenPay);
  99. const guest=useSelector(getIsGuest);
  100. const popBindPhone=useSelector(getPopBindPhone);
  101. const [isMaintain, setIsMaintain] = useState(false);
  102. //是否唤起选择area
  103. const [isSelectArea, setIsSelectArea] = useState(false);
  104. const popFirst=useSelector(getPopFirst);
  105. const firstPayMulti=useSelector(getFirstPayMulti);
  106. const muiTheme = createTheme({
  107. direction: direction,
  108. });
  109. const cacheRtl = createCache({
  110. key: 'css-rtl',
  111. stylisPlugins: plugins,
  112. });
  113. const startReqRoutes=()=>{
  114. //先请求指纹id
  115. dispatch(getBFP()).then((result)=>{
  116. dispatch(reqGetRoutes());
  117. });
  118. }
  119. const loadFont=()=>{
  120. // let swisscbt=new FontFaceObserver("SWISSC-BT");
  121. // swisscbt.load().then(() => {
  122. //
  123. // })
  124. let timeout=3000;
  125. // new FontFaceObserver("SWISSC-BT").load(null,timeout).catch(e=>{
  126. // // console.log(e);
  127. // });
  128. // new FontFaceObserver("Roboto").load(null,timeout).catch(e=>{
  129. // // console.log(e);
  130. // });
  131. // new FontFaceObserver("Roboto-1").load(null,timeout).catch(e=>{
  132. // // console.log(e);
  133. // });
  134. }
  135. //检查邀请码
  136. const checkInviteCode=()=>{
  137. let name="act";
  138. let code=getUrlParam(name);
  139. if (code!=null){
  140. localStorageSet(LOCAL_WHEEL_INVITE_CODE,code)
  141. }
  142. else {
  143. localStorageSet(LOCAL_WHEEL_INVITE_CODE,"")
  144. }
  145. let cname="c";
  146. let ccode=getUrlParam(cname);
  147. if (ccode!=null){
  148. localStorageSet(LOCAL_ACTIVITY_C,ccode);
  149. }
  150. // else{
  151. // localStorageSet(LOCAL_ACTIVITY_C,"");
  152. // }
  153. let bfp=getUrlParam("bfp");
  154. if (bfp!=null&&bfp!==""){
  155. localStorageSet(LOCAL_VISTOR_ID,bfp);
  156. global.BFP=bfp;
  157. }
  158. }
  159. const reProgressierInstallBanner=()=>{
  160. if (window.NewProgressierInstallBanner!=null)return;
  161. let ProgressierInstallBanner=window.ProgressierInstallBanner;
  162. window.NewProgressierInstallBanner=ProgressierInstallBanner;
  163. window.ProgressierInstallBanner=function (e, t) {
  164. this.remove = async function() {
  165. };
  166. this.render = async function() {
  167. };
  168. this.make = function() {
  169. };
  170. this.init = async function() {
  171. }
  172. }
  173. }
  174. const reqInitData=()=>{
  175. //未初始化
  176. if (userID===-1)return;
  177. //onChangeUser
  178. dispatch(onChangeUser(userInfo));
  179. if (userID>0){
  180. dispatch(connectHall(hallServerUrl));
  181. localStorageSet(LOCAL_WHEEL_INVITE_CODE,"");
  182. // localStorageSet(LOCAL_ACTIVITY_C,"");
  183. //Mail红点屏蔽
  184. dispatch(reqMailCheck());
  185. dispatch(reqFavoGet());
  186. checkOpenBindPrompt();
  187. }
  188. else
  189. {
  190. dispatch(disconnectHall());
  191. }
  192. //pay
  193. // reqPayConfig(dispatch,userInfo);
  194. // dispatch(reqFirstPayConfig(userID))
  195. //customer
  196. // dispatch(reqCustomService());
  197. //turnplate
  198. dispatch(reqTurnplateIndex());
  199. //redpack
  200. // dispatch(reqRedpackCheck());
  201. // dispatch(reqRedpackConfig());
  202. //agent
  203. // dispatch(reqAgentCheck());
  204. //activity
  205. // dispatch(reqGameActivity());
  206. }
  207. const appInitData=()=>{
  208. // scroll to top on route change
  209. //检查是否维护
  210. if (checkMaintain())return;
  211. if (checkAreaSelect())return;
  212. checkInviteCode();
  213. checkOpenInChrome();
  214. loadFont();
  215. //请求routes
  216. startReqRoutes();
  217. appRef.current && appRef.current.scrollTo(0, 0);
  218. preventDefault();
  219. reProgressierInstallBanner();
  220. SoundHelp.loadAllAudioFile();
  221. // preventTouchMove();
  222. }
  223. const checkFirstPay=()=>{
  224. if (!popFirst)return;
  225. if (firstPayMulti==null)return;
  226. let key="first_open_time";
  227. let now=Date.now();
  228. let lst=Number(localStorageGet(key,0));
  229. let delta=now-lst;
  230. // if (delta<86400000){
  231. // return false;
  232. // }
  233. if (pathname==="/") {
  234. if (hash == null || hash === "") {
  235. global.showFirstPay();
  236. localStorageSet(key,Date.now());
  237. }
  238. }
  239. }
  240. const checkOpenCheckin=()=>{
  241. if (userID>0){
  242. if (pathname==="/"){
  243. if(hash==null||hash===""){
  244. let key="checkin_open_time";
  245. let now=Date.now();
  246. let lst=Number(localStorageGet(key,0));
  247. let delta=now-lst;
  248. if (delta<86400000){
  249. checkFirstPay();
  250. return false;
  251. }
  252. dispatch(reqCheckinCheck((isCanCheckIn)=>{
  253. let is_check_first=true;
  254. if(hash==null||hash===""){
  255. if(isCanCheckIn===1){
  256. navigate(ROUTE_PATH.CHECK_IN,{replace:true});
  257. localStorageSet(key,Date.now());
  258. is_check_first=false;
  259. }
  260. }
  261. if (is_check_first){
  262. checkFirstPay();
  263. }
  264. }));
  265. return true;
  266. }
  267. }
  268. }
  269. checkFirstPay();
  270. return false;
  271. }
  272. const onCloseHallWheel=()=>{
  273. checkOpenCheckin();
  274. }
  275. const checkOpenInstallBox=()=>{
  276. if (promoteInstall>0){
  277. if (global.installed===1)return;
  278. global.installed=1;
  279. let time=promoteInstall*1000;
  280. // time=1000;
  281. setTimeout(async ()=>{
  282. if (!isShowInstallBox())return;
  283. let gameID=Number(objInfo.gameID);
  284. if (gameID>0)return;
  285. global.showInstallBox();
  286. },time);
  287. }
  288. }
  289. const checkOpenInChrome=()=>{
  290. let time=200;
  291. setTimeout(async ()=>{
  292. if (!isShowInstallBox())return;
  293. if (isInAppBrowser()){
  294. openUrlUseChrome();
  295. }
  296. },time);
  297. }
  298. //检查打开绑定提示
  299. const checkOpenBindPrompt=()=>{
  300. if (guest!==1)return;
  301. if (popBindPhone!==1)return;
  302. if (global.ispopBindPhone===1)return;
  303. if (pathname.startsWith(ROUTE_PATH.GAME))return;
  304. global.showBindPrompt();
  305. global.ispopBindPhone=1;
  306. }
  307. //检查维护
  308. const checkMaintain=()=>{
  309. // let sdate=new Date(2024, 7, 27, 3, 0, 0);
  310. // let edate=new Date(2024, 7, 27, 7, 0, 0);
  311. // let stime=sdate.getTime();
  312. // let etime=edate.getTime();
  313. //巴西时间
  314. let stime=getBrazilTimeStamp("2024-08-29 01:00:00");
  315. // let stime=getBrazilTimeStamp("2024-08-26 16:34:00");
  316. let etime=getBrazilTimeStamp("2024-08-29 01:10:00");
  317. let now=Date.now();
  318. let isopen=false;
  319. if (now>=stime&&now<=etime){
  320. isopen=true;
  321. setIsMaintain(isopen);
  322. }
  323. return isopen;
  324. }
  325. //检查选择地区
  326. const checkAreaSelect=()=>{
  327. let isopen=false;
  328. let areaID=global.getLocalAreaID();
  329. if (areaID<=0){
  330. isopen=true;
  331. setIsSelectArea(isopen);
  332. global.showAreaSelect(false);
  333. }
  334. return isopen;
  335. }
  336. //app Effect
  337. //初始化
  338. useEffect(() => {
  339. appInitData();
  340. return ()=>{
  341. }
  342. }, []);
  343. //用户信息改变
  344. useEffect(()=>{
  345. reqInitData();
  346. },[userID])
  347. //转盘
  348. useEffect(()=>{
  349. if(turnplate){
  350. let times=turnplate.times;
  351. if (times>0){
  352. if (pathname==="/"){
  353. if(hash==null||hash===""){
  354. if(popWheel){
  355. setIsShowWheel(true);
  356. return;
  357. }
  358. }
  359. }
  360. }
  361. }
  362. checkOpenCheckin();
  363. },[turnplate]);
  364. //监听上一次的路由
  365. useEffect(()=>{
  366. if (preLocation){
  367. let pathname=preLocation.pathname;
  368. if (pathname){
  369. if (pathname.startsWith(ROUTE_PATH.GAME)){
  370. //更新金币
  371. if (userID>0){
  372. dispatch(reqGameInfo());
  373. }
  374. //从游戏返回弹
  375. checkFirstPay();
  376. }
  377. }
  378. }
  379. //检查是否维护
  380. checkMaintain();
  381. },[preLocation])
  382. //监听gameID
  383. useEffect(()=>{
  384. dispatch(updateCurrGame(gameID))
  385. dispatch(hallSendState());
  386. objInfo.gameID=gameID;
  387. },[gameID])
  388. //监听被服务器踢掉
  389. useEffect(()=>{
  390. if (serverKick===1){
  391. if (pathname.startsWith(ROUTE_PATH.GAME)){
  392. navigate(ROUTE_PATH.HOME,{replace:true});
  393. }
  394. }
  395. },[serverKick])
  396. //监听安装提示
  397. useEffect(()=>{
  398. checkOpenInstallBox();
  399. },[promoteInstall])
  400. //监听打开pay
  401. useEffect(()=>{
  402. if (openPay===1){
  403. navigate(ROUTE_PATH.PAY,{replace:true});
  404. dispatch(updateOpenPay(0));
  405. }
  406. },[openPay])
  407. //app Effect
  408. const renderLayout=()=>{
  409. if (isMaintain)return (
  410. <WMaintainBox open={true}></WMaintainBox>
  411. );
  412. if (isSelectArea)return (<></>);
  413. return (
  414. <>
  415. {
  416. fetchStatus===REQ_STATUS.IDLE?<Layout onCloseHallWheel={onCloseHallWheel} />:(<LoadingFull />)
  417. }
  418. </>
  419. )
  420. }
  421. const renderPreload=()=>{
  422. //维护
  423. if (isMaintain)return (<></>);
  424. if (isSelectArea)return (<></>);
  425. return (
  426. <>
  427. {
  428. <WInstallBox/>
  429. }
  430. </>
  431. )
  432. }
  433. const renderAreaSelect=()=>{
  434. return (
  435. <WAreaSelect/>
  436. )
  437. }
  438. return (
  439. <CacheProvider value={cacheRtl}>
  440. <MuiThemeProvider theme={muiTheme}>
  441. <ThemeProvider theme={{theme: theme}}>
  442. <SidebarProvider>
  443. <ThemeStyles/>
  444. <ToastContainer theme={theme} autoClose={2500}
  445. position={direction === 'ltr' ? 'top-right' : 'top-left'}/>
  446. <StyleSheetManager stylisPlugins={plugins}>
  447. {
  448. renderLayout()
  449. }
  450. </StyleSheetManager>
  451. {
  452. renderPreload()
  453. }
  454. {renderAreaSelect()}
  455. </SidebarProvider>
  456. </ThemeProvider>
  457. </MuiThemeProvider>
  458. </CacheProvider>
  459. );
  460. }
  461. export default App