| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- import styles from "@components/GameList/styles.module.scss";
- import React, { useCallback, useEffect, useRef, useState } from "react";
- import GameItem, { GameImgAspectRatio } from "@components/GameItem";
- import { REQ_STATUS } from "@api/config";
- import SmallLoading from "@components/SmallLoading";
- import { useThemeProvider } from "@contexts/themeContext";
- import GameRoom from "@components/GameRoom";
- import { useWindowSize } from "react-use";
- const i18n = global.i18n;
- const objInfo = {
- timer: null
- }
- const GameList = ({ data, status, reqMore, user }) => {
- // data={
- // type:0,//游戏分类
- // page:1,
- // pageSize:40,
- // total:42,
- // totalPage:1,
- // data:[
- // {
- // gid:0,//gameid
- // img:"https://bc.imgix.net/game/image/f76d3f4a-9712-4bd1-9426-f3ab7069b6a2.png?auto=format&dpr=3&w=200",//图片
- // link:"",//跳转的链接
- // online:1006,//游戏人数
- // desc:"BC Originals",//描述
- // },
- // {
- // gid:0,//gameid
- // img:"https://bc.imgix.net/game/image/ff0b0511-1f48-43d1-8dd3-294bb6437b4b.png?auto=format&dpr=3&w=200",//图片
- // link:"",//跳转的链接
- // online:100,//游戏人数
- // desc:"BC Originals",//描述
- // },
- // {
- // gid:0,//gameid
- // img:"https://bc.imgix.net/game/image/d33b3fad-b6df-450b-bd85-528a17383043.png?auto=format&dpr=3&w=200",//图片
- // link:"",//跳转的链接
- // online:100,//游戏人数
- // desc:"BC Originals",//描述
- // },
- // {
- // gid:0,//gameid
- // img:"https://bc.imgix.net/game/image/5b3a4099-9462-4d3c-a854-ade78aad0d60.png?auto=format&dpr=3&w=200",//图片
- // link:"",//跳转的链接
- // online:100,//游戏人数
- // desc:"BC Originals",//描述
- // },
- // {
- // gid:0,//gameid
- // img:"https://bc.imgix.net/game/image/f76d3f4a-9712-4bd1-9426-f3ab7069b6a2.png?auto=format&dpr=3&w=200",//图片
- // link:"",//跳转的链接
- // online:100,//游戏人数
- // desc:"BC Originals",//描述
- // },
- // {
- // gid:0,//gameid
- // img:"https://bc.imgix.net/game/image/ff0b0511-1f48-43d1-8dd3-294bb6437b4b.png?auto=format&dpr=3&w=200",//图片
- // link:"",//跳转的链接
- // online:100,//游戏人数
- // desc:"BC Originals",//描述
- // },
- // {
- // gid:0,//gameid
- // img:"https://bc.imgix.net/game/image/d33b3fad-b6df-450b-bd85-528a17383043.png?auto=format&dpr=3&w=200",//图片
- // link:"",//跳转的链接
- // online:100,//游戏人数
- // desc:"BC Originals",//描述
- // },
- // {
- // gid:0,//gameid
- // img:"https://bc.imgix.net/game/image/5b3a4099-9462-4d3c-a854-ade78aad0d60.png?auto=format&dpr=3&w=200",//图片
- // link:"",//跳转的链接
- // online:100,//游戏人数
- // desc:"BC Originals",//描述
- // },
- // ]
- // }
- const { isMobile, fontScale } = useThemeProvider();
- const M_LIST_COL = 3;
- const [selected, setSelected] = useState(-1);
- const [roomRow, setRoomRow] = useState({});
- const [showPopRoom, setShowPopRoom] = useState(false);
- const roomHeight = 5.2;
- const rowTop = roomHeight + 0.75;
- const gameListRef = useRef(null);
- const [gridInfo, setGridInfo] = useState({});
- const { width } = useWindowSize();
- const mobile = isMobile();
- const handleReset = (e) => {
- setSelected(-1);
- setRoomRow({});
- }
- useEffect(() => {
- document.addEventListener("click", handleReset);
- return () => {
- document.removeEventListener("click", handleReset);
- resetTimer();
- }
- }, [])
- const getDesktopCol = useCallback(() => {
- if (width >= 1264 && width <= 1564) return 6;
- else if (width >= 963 && width <= 1263) return 5;
- else if (width >= 622 && width <= 962) return 4;
- else if (width <= 621) return 3;
- return 7;
- }, [width]);
- const initGridsInfo = useCallback(() => {
- let parent = gameListRef.current;
- let totalCol = 3;
- if (!mobile) totalCol = getDesktopCol();
- let gridBaseRatio = GameImgAspectRatio;
- let totalWidth = mobile ? 100 * totalCol : 160 * totalCol;
- if (parent != null) totalWidth = parent.clientWidth;
- let rowGap = parent != null ? window.getComputedStyle(parent).getPropertyValue('grid-row-gap') : "0px";
- let gap = Number(rowGap.replace("px", ""));
- if (gap === 0 || isNaN(gap)) gap = 0.75 * 16 * fontScale;
- let gridsData = {};
- for (let i = 1; i <= 6; i++) {
- let gridNum = i;
- let gridWidth = (totalWidth - (totalCol - 1) * gap) / totalCol;
- let itemWidth = gridWidth * gridNum + (gridNum - 1) * gap;
- let width = itemWidth + "px";
- let aspectRatio = gridBaseRatio * (itemWidth / gridWidth);
- gridsData[i] = { width, aspectRatio };
- }
- setGridInfo(gridsData);
- }, [fontScale, getDesktopCol, mobile]);
- useEffect(() => {
- initGridsInfo();
- }, [initGridsInfo]);
- const resetTimer = () => {
- if (objInfo.timer != null) {
- clearTimeout(objInfo.timer);
- objInfo.timer = null;
- }
- }
- const checkSetRoom = (e, item, row, total) => {
- let target = e.target;
- if (target) {
- let rect = target.getBoundingClientRect();
- let cH = document.documentElement.clientHeight;
- let cB = rect.bottom;
- if (cH - cB > 90) row = row + 1;
- } else row = row + 1;
- if (row >= total) row = total - 1;
- let roomRowItem = {
- row: row,
- data: item
- }
- if (roomRow.row === row) {
- setRoomRow({
- hide: true,
- ...roomRowItem
- });
- resetTimer();
- objInfo.timer = setTimeout(() => {
- setRoomRow(roomRowItem);
- }, 10)
- }
- else setRoomRow(roomRowItem);
- }
- const handleSelect = (e, data, row, total) => {
- e.stopPropagation();
- if (data.id === selected) {
- handleReset();
- }
- else {
- setSelected(data.id);
- checkSetRoom(e, data, row, total);
- }
- }
- const handlePopSelected = (e, data, row, totall) => {
- e.stopPropagation();
- setRoomRow({
- row: -1,
- data: data
- });
- setShowPopRoom(true);
- }
- const handlePopClose = () => {
- setRoomRow({});
- setShowPopRoom(false);
- }
- const renderGameListDesktop = () => {
- let list = data.data;
- if (list == null) list = [];
- return (
- <>
- <div ref={gameListRef} id={"gameList"} className={styles.game_list}>
- {
- list.map((item, index) => {
- let gridNum = item.gridNum != null ? item.gridNum : 1;
- // gridNum=Math.floor(Math.random()*3)+1;
- let whStyle = gridInfo[gridNum];
- if (whStyle == null) return null;
- return (
- <GameItem key={index} data={item} handleRoom={handlePopSelected} whStyle={whStyle}></GameItem>
- )
- })
- }
- </div>
- <GameRoom open={showPopRoom} data={roomRow.data} user={user} onClose={handlePopClose}></GameRoom>
- </>
- )
- }
- const formatMList = (list) => {
- let mList = [];
- if (list) {
- let count = 0;
- for (let i = 0; i < list.length; i++) {
- let item = list[i];
- let gridNum = item.gridNum != null ? item.gridNum : 1;
- let row = Math.floor(count / M_LIST_COL);
- let rowData = mList[row];
- if (rowData == null) rowData = [];
- let nitem = { ...item, gridNum: gridNum }
- rowData.push(nitem);
- mList[row] = rowData;
- count += gridNum;
- }
- }
- return mList;
- }
- const renderRoom = (row, len) => {
- if (roomRow == null) return (<></>);
- if (roomRow.hide) return (<></>);
- let rrow = roomRow.row;
- let data = roomRow.data;
- if (rrow === row) {
- return (
- <GameRoom open={true} data={data} height={roomHeight + "rem"} mobile={true} user={user}></GameRoom>
- )
- }
- else return (<></>);
- }
- const renderGameListMobile = () => {
- let list = data.data;
- if (list == null) list = [];
- list = formatMList(list);
- let len = list.length;
- return (
- <div ref={gameListRef} id={"gameList"} className={styles.game_list_mobile}>
- {
- list.map((rowArr, row) => {
- let rowStyle = {};
- if (roomRow != null) {
- if (row >= roomRow.row) {
- rowStyle.transform = `translateY(${rowTop + "rem"})`;
- }
- }
- return (
- <React.Fragment key={row}>
- {renderRoom(row, len)}
- <div key={row} className={styles.list_row} style={rowStyle}>
- {
- rowArr.map((item, col) => {
- let itemStyle = {}
- if (selected !== -1) {
- if (item.id !== selected) {
- itemStyle.filter = "brightness(60%)"
- }
- else {
- itemStyle.transform = "scale(1.05)";
- }
- }
- let gridNum = item.gridNum != null ? item.gridNum : 1;
- let whStyle = gridInfo[gridNum];
- return (
- <GameItem key={`${row}-${col}`} data={item} handleRoom={(e, data) => {
- handleSelect(e, data, row, len)
- }} row={row} whStyle={whStyle} style={itemStyle}></GameItem>
- )
- })
- }
- </div>
- </React.Fragment>
- )
- })
- }
- </div>
- )
- }
- const renderGameList = () => {
- if (isMobile()) return renderGameListMobile();
- else return renderGameListDesktop();
- }
- const renderProgress = () => {
- let list = data.data;
- if (list == null) list = [];
- let current = list.length;
- let total = data.total;
- let progress = Math.ceil((current / total) * 100);
- let spro = progress + "%";
- return (
- <div className={styles.page_progress}>
- <span>{current} / {total}</span>
- <div className={styles.progress}>
- <div className={styles.green} style={{ width: spro }}></div>
- </div>
- <span>{spro}</span>
- </div>
- )
- }
- const renderLoading = () => {
- return (<SmallLoading fill={"#fff"} />)
- }
- const onClickMore = () => {
- if (reqMore) {
- let page = Number(data.page) + 1;
- let tabtype = data.tabtype;
- let id = data.id;
- reqMore(id, tabtype, page);
- }
- }
- const renderShowMoreBtn = () => {
- let isNomore = Number(data.page) === Number(data.totalPage);
- let label = isNomore ? i18n.t("game_list.no_more") : i18n.t("game_list.show_more");
- return (
- <div className={styles.show_more}>
- <button className={styles.more_btn} disabled={isNomore} onClick={() => {
- if (status !== REQ_STATUS.LOADING) {
- onClickMore();
- }
- }}>
- {
- status === REQ_STATUS.LOADING ? renderLoading() : (<div>{label}</div>)
- }
- </button>
- </div>
- )
- }
- const renderShowMore = () => {
- let isNomore = Number(data.page) === Number(data.totalPage);
- let moreStyle = {};
- if (roomRow && roomRow.row != null) {
- let row = roomRow.row;
- if (row >= 0) {
- moreStyle.transform = `translateY(${rowTop + "rem"})`;
- moreStyle.marginBottom = rowTop + "rem";
- }
- }
- if (isNomore) {
- if (isMobile()) return (<div className={`${styles.page_con} ${styles.page_nomore}`} style={moreStyle}></div>)
- else return (<></>);
- }
- return (
- <div className={styles.page_con} style={moreStyle}>
- {renderProgress()}
- {renderShowMoreBtn()}
- </div>
- )
- }
- return (
- <div className={`w-100 ${styles.list_container}`}>
- {renderGameList()}
- {renderShowMore()}
- </div>
- )
- }
- export default GameList;
|