App.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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. new FontFaceObserver("SWISSC-BT").load();
  125. new FontFaceObserver("Roboto").load();
  126. new FontFaceObserver("Roboto-1").load();
  127. }
  128. //检查邀请码
  129. const checkInviteCode=()=>{
  130. let name="act";
  131. let code=getUrlParam(name);
  132. if (code!=null){
  133. localStorageSet(LOCAL_WHEEL_INVITE_CODE,code)
  134. }
  135. else {
  136. localStorageSet(LOCAL_WHEEL_INVITE_CODE,"")
  137. }
  138. let cname="c";
  139. let ccode=getUrlParam(cname);
  140. if (ccode!=null){
  141. localStorageSet(LOCAL_ACTIVITY_C,ccode);
  142. }
  143. // else{
  144. // localStorageSet(LOCAL_ACTIVITY_C,"");
  145. // }
  146. let bfp=getUrlParam("bfp");
  147. if (bfp!=null&&bfp!==""){
  148. localStorageSet(LOCAL_VISTOR_ID,bfp);
  149. global.BFP=bfp;
  150. }
  151. }
  152. const reProgressierInstallBanner=()=>{
  153. if (window.NewProgressierInstallBanner!=null)return;
  154. let ProgressierInstallBanner=window.ProgressierInstallBanner;
  155. window.NewProgressierInstallBanner=ProgressierInstallBanner;
  156. window.ProgressierInstallBanner=function (e, t) {
  157. this.remove = async function() {
  158. };
  159. this.render = async function() {
  160. };
  161. this.make = function() {
  162. };
  163. this.init = async function() {
  164. }
  165. }
  166. }
  167. const reqInitData=()=>{
  168. //未初始化
  169. if (userID===-1)return;
  170. //onChangeUser
  171. dispatch(onChangeUser(userInfo));
  172. if (userID>0){
  173. dispatch(connectHall(hallServerUrl));
  174. localStorageSet(LOCAL_WHEEL_INVITE_CODE,"");
  175. // localStorageSet(LOCAL_ACTIVITY_C,"");
  176. //Mail红点屏蔽
  177. dispatch(reqMailCheck());
  178. dispatch(reqFavoGet());
  179. checkOpenBindPrompt();
  180. }
  181. else
  182. {
  183. dispatch(disconnectHall());
  184. }
  185. //pay
  186. // reqPayConfig(dispatch,userInfo);
  187. // dispatch(reqFirstPayConfig(userID))
  188. //customer
  189. // dispatch(reqCustomService());
  190. //turnplate
  191. dispatch(reqTurnplateIndex());
  192. //redpack
  193. // dispatch(reqRedpackCheck());
  194. // dispatch(reqRedpackConfig());
  195. //agent
  196. // dispatch(reqAgentCheck());
  197. //activity
  198. // dispatch(reqGameActivity());
  199. }
  200. const appInitData=()=>{
  201. // scroll to top on route change
  202. //检查是否维护
  203. if (checkMaintain())return;
  204. if (checkAreaSelect())return;
  205. checkInviteCode();
  206. checkOpenInChrome();
  207. loadFont();
  208. //请求routes
  209. startReqRoutes();
  210. appRef.current && appRef.current.scrollTo(0, 0);
  211. preventDefault();
  212. reProgressierInstallBanner();
  213. SoundHelp.loadAllAudioFile();
  214. // preventTouchMove();
  215. }
  216. const checkFirstPay=()=>{
  217. if (!popFirst)return;
  218. if (firstPayMulti==null)return;
  219. let key="first_open_time";
  220. let now=Date.now();
  221. let lst=Number(localStorageGet(key,0));
  222. let delta=now-lst;
  223. if (delta<86400000){
  224. return false;
  225. }
  226. global.showFirstPay();
  227. localStorageSet(key,Date.now());
  228. }
  229. const checkOpenCheckin=()=>{
  230. if (userID>0){
  231. if (pathname==="/"){
  232. if(hash==null||hash===""){
  233. let key="checkin_open_time";
  234. let now=Date.now();
  235. let lst=Number(localStorageGet(key,0));
  236. let delta=now-lst;
  237. if (delta<86400000){
  238. checkFirstPay();
  239. return false;
  240. }
  241. dispatch(reqCheckinCheck((isCanCheckIn)=>{
  242. let is_check_first=true;
  243. if(hash==null||hash===""){
  244. if(isCanCheckIn===1){
  245. navigate(ROUTE_PATH.CHECK_IN,{replace:true});
  246. localStorageSet(key,Date.now());
  247. is_check_first=false;
  248. }
  249. }
  250. if (is_check_first){
  251. checkFirstPay();
  252. }
  253. }));
  254. return true;
  255. }
  256. }
  257. }
  258. checkFirstPay();
  259. return false;
  260. }
  261. const onCloseHallWheel=()=>{
  262. checkOpenCheckin();
  263. }
  264. const checkOpenInstallBox=()=>{
  265. if (promoteInstall>0){
  266. if (global.installed===1)return;
  267. global.installed=1;
  268. let time=promoteInstall*1000;
  269. // time=1000;
  270. setTimeout(async ()=>{
  271. if (!isShowInstallBox())return;
  272. let gameID=Number(objInfo.gameID);
  273. if (gameID>0)return;
  274. global.showInstallBox();
  275. },time);
  276. }
  277. }
  278. const checkOpenInChrome=()=>{
  279. let time=200;
  280. setTimeout(async ()=>{
  281. if (!isShowInstallBox())return;
  282. if (isInAppBrowser()){
  283. openUrlUseChrome();
  284. }
  285. },time);
  286. }
  287. //检查打开绑定提示
  288. const checkOpenBindPrompt=()=>{
  289. if (guest!==1)return;
  290. if (popBindPhone!==1)return;
  291. if (global.ispopBindPhone===1)return;
  292. if (pathname.startsWith(ROUTE_PATH.GAME))return;
  293. global.showBindPrompt();
  294. global.ispopBindPhone=1;
  295. }
  296. //检查维护
  297. const checkMaintain=()=>{
  298. // let sdate=new Date(2024, 7, 27, 3, 0, 0);
  299. // let edate=new Date(2024, 7, 27, 7, 0, 0);
  300. // let stime=sdate.getTime();
  301. // let etime=edate.getTime();
  302. //巴西时间
  303. let stime=getBrazilTimeStamp("2024-08-29 01:00:00");
  304. // let stime=getBrazilTimeStamp("2024-08-26 16:34:00");
  305. let etime=getBrazilTimeStamp("2024-08-29 01:10:00");
  306. let now=Date.now();
  307. let isopen=false;
  308. if (now>=stime&&now<=etime){
  309. isopen=true;
  310. setIsMaintain(isopen);
  311. }
  312. return isopen;
  313. }
  314. //检查选择地区
  315. const checkAreaSelect=()=>{
  316. let isopen=false;
  317. let areaID=global.getLocalAreaID();
  318. if (areaID<=0){
  319. isopen=true;
  320. setIsSelectArea(isopen);
  321. global.showAreaSelect(false);
  322. }
  323. return isopen;
  324. }
  325. //app Effect
  326. //初始化
  327. useEffect(() => {
  328. appInitData();
  329. return ()=>{
  330. }
  331. }, []);
  332. //用户信息改变
  333. useEffect(()=>{
  334. reqInitData();
  335. },[userID])
  336. //转盘
  337. useEffect(()=>{
  338. if(turnplate){
  339. let times=turnplate.times;
  340. if (times>0){
  341. if (pathname==="/"){
  342. if(hash==null||hash===""){
  343. if(popWheel){
  344. setIsShowWheel(true);
  345. return;
  346. }
  347. }
  348. }
  349. }
  350. }
  351. checkOpenCheckin();
  352. },[turnplate]);
  353. //监听上一次的路由
  354. useEffect(()=>{
  355. if (preLocation){
  356. let pathname=preLocation.pathname;
  357. if (pathname){
  358. if (pathname.startsWith(ROUTE_PATH.GAME)){
  359. //更新金币
  360. if (userID>0){
  361. dispatch(reqGameInfo());
  362. }
  363. }
  364. }
  365. }
  366. //检查是否维护
  367. checkMaintain();
  368. },[preLocation])
  369. //监听gameID
  370. useEffect(()=>{
  371. dispatch(updateCurrGame(gameID))
  372. dispatch(hallSendState());
  373. objInfo.gameID=gameID;
  374. },[gameID])
  375. //监听被服务器踢掉
  376. useEffect(()=>{
  377. if (serverKick===1){
  378. if (pathname.startsWith(ROUTE_PATH.GAME)){
  379. navigate(ROUTE_PATH.HOME,{replace:true});
  380. }
  381. }
  382. },[serverKick])
  383. //监听安装提示
  384. useEffect(()=>{
  385. checkOpenInstallBox();
  386. },[promoteInstall])
  387. //监听打开pay
  388. useEffect(()=>{
  389. if (openPay===1){
  390. navigate(ROUTE_PATH.PAY,{replace:true});
  391. dispatch(updateOpenPay(0));
  392. }
  393. },[openPay])
  394. //app Effect
  395. const renderLayout=()=>{
  396. if (isMaintain)return (
  397. <WMaintainBox open={true}></WMaintainBox>
  398. );
  399. if (isSelectArea)return (<></>);
  400. return (
  401. <>
  402. {
  403. fetchStatus===REQ_STATUS.IDLE?<Layout onCloseHallWheel={onCloseHallWheel} />:(<LoadingFull />)
  404. }
  405. </>
  406. )
  407. }
  408. const renderPreload=()=>{
  409. //维护
  410. if (isMaintain)return (<></>);
  411. if (isSelectArea)return (<></>);
  412. return (
  413. <>
  414. {
  415. <WInstallBox/>
  416. }
  417. </>
  418. )
  419. }
  420. const renderAreaSelect=()=>{
  421. return (
  422. <WAreaSelect/>
  423. )
  424. }
  425. return (
  426. <CacheProvider value={cacheRtl}>
  427. <MuiThemeProvider theme={muiTheme}>
  428. <ThemeProvider theme={{theme: theme}}>
  429. <SidebarProvider>
  430. <ThemeStyles/>
  431. <ToastContainer theme={theme} autoClose={2500}
  432. position={direction === 'ltr' ? 'top-right' : 'top-left'}/>
  433. <StyleSheetManager stylisPlugins={plugins}>
  434. {
  435. renderLayout()
  436. }
  437. </StyleSheetManager>
  438. {
  439. renderPreload()
  440. }
  441. {renderAreaSelect()}
  442. </SidebarProvider>
  443. </ThemeProvider>
  444. </MuiThemeProvider>
  445. </CacheProvider>
  446. );
  447. }
  448. export default App