| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- import styles from './styles.module.scss';
- // components
- import SidebarTrigger from '@ui/SidebarTrigger';
- import Headroom from 'react-headroom';
- import Logo from '@components/Logo';
- import AppBar from "@mui/material/AppBar";
- import {useSidebar} from "@contexts/sidebarContext";
- import {useThemeProvider} from "@contexts/themeContext";
- import {useEffect, useRef, useState} from 'react';
- import styled from 'styled-components/macro';
- import {Tab, Tabs} from "@mui/material";
- // import LINKS from "@constants/links";
- import Button from "@mui/material/Button";
- import {NavLink, useLocation, useNavigate} from "react-router-dom";
- import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
- import ToggleButton from "@mui/material/ToggleButton";
- import symbol from "@assets/symbol-defs.svg";
- import symbol_m from "@assets/symbol-mobile.svg";
- import {string} from "prop-types";
- import IconButton from "@mui/material/IconButton";
- import {animated,easings} from "@react-spring/web";
- import {useSpring} from "@react-spring/core";
- import {useWindowSize} from "react-use";
- import ResizeObserver from "resize-observer-polyfill";
- import {useSelector} from "react-redux";
- import {allTopNavs, getRoute, getRouteChain, getUserInfo, isLogin, isLogined} from "@features/mainSlice";
- import LazyImage from "@components/LazyImage";
- import {numFormatter, sleep} from "@utils/helpers";
- import {ROUTE_PATH} from "@constants/routes";
- import {toast} from "react-toastify";
- import LazyImgix from "@components/Imgix/LazyImgix";
- const i18n=global.i18n;
- const StyledToggleGroup= styled(ToggleButtonGroup)`
- border-radius: 0px !important;
- gap: 12px;
- `;
- const StyledToggle=styled(ToggleButton)`
- gap: 12px;
- text-transform:none !important;
- border: none !important;
- border-radius: var(--border-radius) !important;
- padding: 0px !important;
- &:hover, &:focus ,&.Mui-selected, &.active {
- background-color: var(--nav-item-hover) !important;
- a {
- color: var(--header);
- font-weight: 600;
- .icon {
- fill:${props => props.fill};
- }
- }
- }
- a {
- display: flex;
- align-items: center;
- color: var(--text);
- padding: 12px !important;
- transition: all var(--transition);
- font-family: var(--heading-font);
- gap: 8px;
- .icon {
- display: flex;
- align-items: center;
- justify-content: center;
- width: 18px;
- height: 18px;
- fill: var(--text);
- }
- }
- `;
- const DesktopNavToggle=()=>{
- const LINKS=useSelector(allTopNavs);
- const links=LINKS.slice(0,4);
- const {pathname} = useLocation();
- const [alignment, setAlignment] = useState(pathname);
- const currRoute=useSelector(getRoute(pathname));
- const getRootRoute=(pathname)=>{
- let route="";
- if (currRoute){
- let clv=currRoute.lv;
- if (clv==null)return route;
- for (let i = 0; i < LINKS.length; i++) {
- let link=LINKS[i];
- let lv=link.lv;
- if (clv.startsWith(lv)){
- route=link.path;
- break;
- }
- }
- }
- return route;
- }
- useEffect(() => {
- setAlignment(getRootRoute(pathname));
- }, [pathname]);
- const handleChange = (event, newAlignment) => {
- // setAlignment(newAlignment);
- };
- return (
- <StyledToggleGroup
- value={alignment}
- exclusive
- onChange={handleChange}
- >
- {
- links.map((link, index) => (
- <StyledToggle value={link.path} fill={link.fill.split(";").pop()} key={link.title}>
- <NavLink className="h4" to={link.path}>
- <svg className={"icon"}>
- <use xlinkHref={`${symbol}#${link.icon}`} />
- </svg>
- {i18n.t(link.title)}
- </NavLink>
- </StyledToggle>
- ))
- }
- </StyledToggleGroup>
- )
- }
- const DesktopSignInUp=()=>{
- const navigate=useNavigate();
- const isLogin=useSelector(isLogined);
- const {setIsShowLang} = useThemeProvider();
- return (
- <div className="d-flex align-items-center justify-content-end">
- {/*<IconButton aria-label="search">*/}
- {/* <svg className={"ls-icon"} style={{width:'20px',height:'20px'}}>*/}
- {/* <use xlinkHref={`${symbol}#icon_Search`} />*/}
- {/* </svg>*/}
- {/*</IconButton>*/}
- {
- !isLogin?(
- <>
- <Button className={`m-button ${styles.btn_sign_in}`} onClick={()=>{
- navigate(ROUTE_PATH.SIGN_IN);
- }}>{i18n.t('sign_in')}</Button>
- <Button className={`${styles.btn_sign_up}`} onClick={()=>{
- navigate(ROUTE_PATH.SIGN_UP);
- }}>{i18n.t('sign_up')}</Button>
- </>
- ):(
- <>
- </>
- )
- }
- {/*<Button className="m-button">*/}
- {/* <svg className={"ls-icon"} style={{width:'20px',height:'20px'}}>*/}
- {/* <use xlinkHref={`${symbol}#icon_Chat`} />*/}
- {/* </svg>*/}
- {/* <div className="chat-green-dont"></div>*/}
- {/*</Button>*/}
- <Button className="m-button" style={{marginLeft: '0.5rem',marginRight:'0.5rem'}} onClick={()=>{
- setIsShowLang(true);
- }}>
- <svg className={"ls-icon"} style={{width:'20px',height:'20px'}}>
- <use xlinkHref={`${symbol}#icon_Language`} />
- </svg>
- </Button>
- {
- isLogin?(<UserInfo />):(<></>)
- }
- </div>
- )
- }
- const DesktopNav = () => {
- const {open} = useSidebar();
- const navstyle=open?styles.nav_open:"";
- return (
- <div
- className={`d-flex align-items-center justify-content-between ${styles.header} ${navstyle}`}>
- <DesktopNavToggle />
- <DesktopSignInUp/>
- </div>
- );
- }
- const MobileSignInUp=()=>{
- const navigate=useNavigate();
- const isLogin=useSelector(isLogined);
- return (
- <div className="d-flex align-items-center justify-content-end">
- {
- !isLogin?(
- <>
- <Button className={`m-button ${styles.btn_sign_in} ${styles.btn_sign_in_mobile}`} onClick={()=>{
- navigate(ROUTE_PATH.SIGN_IN);
- }}>{i18n.t('sign_in')}</Button>
- <Button className={`${styles.btn_sign_up} ${styles.btn_sign_up_mobile}`} onClick={()=>{
- navigate(ROUTE_PATH.SIGN_UP);
- }}>{i18n.t('sign_up')}</Button>
- </>
- ):(
- <></>
- )
- }
- {/*<Button className="m-button">*/}
- {/* <svg className={"ls-icon"} style={{width:'1.4rem',height:'1.4rem'}}>*/}
- {/* <use xlinkHref={`${symbol}#icon_Language`} />*/}
- {/* </svg>*/}
- {/*</Button>*/}
- </div>
- );
- }
- const MobileNav=()=>{
- return (
- <div
- className={`d-flex align-items-center justify-content-between ${styles.header} ${styles.header_mobile}`}>
- <div className={`d-flex flex-row flex-1`} style={{maxWidth:"55%"}}>
- <SidebarTrigger/>
- <Logo size="sm"/>
- </div>
- <MobileSignInUp/>
- <UserInfo />
- </div>
- )
- }
- const UserInfo=()=>{
- const isLogin=useSelector(isLogined);
- const user=useSelector(getUserInfo);
- const navigate=useNavigate();
- return (
- <>
- {
- isLogin?(
- <div className={`d-flex align-items-center ${styles.user_info}`} onClick={()=>{
- navigate(ROUTE_PATH.SETTINGS);
- }}>
- <div className={styles.info}>
- <div className={styles.nick}>{user.NickName}</div>
- <div className={styles.score}>{global.DOLLAR+" "+numFormatter(user.Score)}</div>
- </div>
- {/*<LazyImage wrapperClassName={styles.avatar} src={user.img} alt={"Head"}/>*/}
- <LazyImgix className={styles.avatar} src={user.img} alt={"Head"} width={80}/>
- </div>
- ):(<></>)
- }
- </>
- )
- }
- const PageHeader = () => {
- const LINKS=useSelector(allTopNavs);
- const {initHeaderHeight,installOpen} = useThemeProvider();
- const {pathname} = useLocation();
- const navigate=useNavigate();
- const barRef = useRef(null);
- const currRoute=useSelector(getRoute(pathname));
- const chain=useSelector(getRouteChain(pathname));
- const {isMobile,showHeader,setShowHeader} = useThemeProvider();
- const [showMHeader, setShowMHeader] = useState(false);
- const isLogin=useSelector(isLogined);
- let lastscroll=0;
- const {open} = useSidebar();
- const navstyle=open?styles.nav_open:"";
- const checkNavActive=(lv)=>{
- if (currRoute&&currRoute.lv)return currRoute.lv.startsWith(lv);
- else return false;
- }
- const getHeaderHeight = () => {
- // console.log(document.querySelector('div.progressier-install-banner'))
- const header = document.querySelector('#appbar');
- let offset = 0;
- if (barRef){
- const headerRoom=document.querySelector('#headerRoom');
- if (headerRoom){
- if (!barRef.showHeader){
- offset=headerRoom.clientHeight;
- const hstyle = window.getComputedStyle(headerRoom);
- if (hstyle!=null){
- let paddingBottom=hstyle.paddingBottom;
- paddingBottom=Number(paddingBottom.replace("px",""));
- offset=offset-paddingBottom;
- }
- }
- }
- }
- if (header!=null)return `${(header.offsetHeight-offset) || 0}px`
- else return '0px';
- }
- const handleScroll=()=>{
- if (!barRef.showHeader)return;
- let scrollTop = document.documentElement.scrollTop; //滚动条滚动高度
- let dt=scrollTop-lastscroll;
- lastscroll=scrollTop;
- let show=false;
- if (dt>20){
- show=false;
- setShowMHeader(show);
- }
- else if (dt<-20){
- show=true;
- setShowMHeader(show);
- }
- if (scrollTop<20){
- setShowMHeader(true);
- }
- }
- const changeHeaderHeight=()=>{
- document.documentElement.style.setProperty('--header-active', getHeaderHeight());
- initHeaderHeight(getHeaderHeight());
- }
- const resizeObserver = new ResizeObserver(entries => {
- for (let entry of entries) {
- // 获取目标元素的高度
- const { height } = entry.contentRect;
- // 可在这里处理高度变化的逻辑
- changeHeaderHeight();
- }
- });
- const getProgressierInstallBanner=(params,callback)=>{
- let banner=new window.NewProgressierInstallBanner(
- params,
- callback
- )
- banner.remove = async ()=>{
- if (banner.deny && !banner.data.preview) {
- banner.deny()
- }
- banner.element.classList.remove("in");
- // await progressier.utils.wait(1e3);
- banner.element.remove()
- }
- banner.make=()=>{
- document.querySelectorAll("." + banner.className).forEach(function(e) {
- e.remove()
- });
- let installBanner=document.querySelector("#installBanner");
- if (installBanner){
- banner.element = window.progressier.utils.node("div", banner.className, {
- parent: installBanner
- });
- banner.element.classList.add(styles.install_banner);
- }
- }
- window.install_banner=banner;
- return banner;
- }
- // const reProgressierInstallBanner=()=>{
- // if (window.NewProgressierInstallBanner!=null)return;
- // let ProgressierInstallBanner=window.ProgressierInstallBanner;
- // window.NewProgressierInstallBanner=ProgressierInstallBanner;
- // window.ProgressierInstallBanner=function (e, t) {
- // this.remove = async function() {
- //
- // };
- // this.render = async function() {
- //
- // };
- // this.make = function() {
- //
- // };
- // this.init = async function() {
- //
- // }
- // }
- // }
- const checkInstall=(l)=>{
- if (!installOpen){
- return false;
- }
- if (l.parent.detection.isStandalone()) {
- return false;
- }
- return true;
- }
- const startListening=async ()=>{
- if (window.progressier==null)return ;
- let l=window.progressier.banners;
- await l.parent.data.waitForData();
- l.data = l.parent.data.params;
- if (!l.reinstallTimer) {
- l.reinstallTimer = setInterval(function() {
- // window.alert(window.progressier["native"].justInstalled)
- // if (!l.showInstall()) {
- // return
- // }
- if (!checkInstall(l)){
- clearInterval(l.reinstallTimer)
- l.reinstallTimer=null;
- return;
- }
- // window.alert("222")
- // if (l.showed) {
- // clearInterval(l.reinstallTimer)
- // l.reinstallTimer=null;
- // return
- // }
- // window.alert("3333")
- l.showed = true;
- // new window.NewProgressierInstallBanner({
- // icon: l.icon(),
- // color: l.data.buttonColor,
- // btnColor: l.data.buttonTextColor,
- // text: l.data.installBannerPitch
- // },function() {
- // l.deny(l.installCookie)
- // }
- // ).init();
- let InstallBanner=getProgressierInstallBanner(
- {
- icon: l.icon(),
- color: l.data.buttonColor,
- btnColor: l.data.buttonTextColor,
- text: l.data.installBannerPitch
- },()=>{
- l.deny(l.installCookie)
- }
- ).init();
- clearInterval(l.reinstallTimer)
- }, l.interval)
- }
- else
- {
- clearInterval(l.reinstallTimer)
- l.reinstallTimer=null;
- }
- }
- const checkProgressier=async ()=>{
- // return ;
- if (window.progressier){
- // reProgressierInstallBanner();
- // let l=window.progressier.banners;
- // await l.parent.data.waitForData();
- // await checkWaitForData();
- // let data=l.data;
- // if (data){
- // if (window.NewProgressierInstallBanner){
- // let InstallBanner=getProgressierInstallBanner(
- // {
- // icon: l.icon(),
- // color: l.data.buttonColor,
- // btnColor: l.data.buttonTextColor,
- // text: l.data.installBannerPitch
- // }
- // ).init();
- // }
- // }
- startListening();
- }
- }
- const stopListener=()=>{
- if (window.progressier==null)return;
- let l=window.progressier.banners;
- if(l){
- if (l.reinstallTimer!=null){
- clearInterval(l.reinstallTimer);
- l.reinstallTimer=null;
- }
- }
- }
- const checkInstallOpen=()=>{
- if (installOpen){
- checkProgressier();
- }
- else
- {
- if (window.install_banner){
- window.install_banner.remove();
- }
- }
- }
- useEffect(() => {
- // 这里的代码会在组件挂载时执行
- // console.log('Component mounted');
- window.addEventListener('scroll', handleScroll);
- if (barRef.current) {
- resizeObserver.observe(barRef.current);
- }
- // testBefore();
- // checkProgressier();
- return () => {
- // 可选的清除函数,当组件卸载时执行
- // console.log('Component unmounted');
- window.removeEventListener('scroll', handleScroll);
- if (barRef.current) {
- resizeObserver.unobserve(barRef.current);
- }
- // stopListener();
- };
- }, []);
- // }, [pathname]);
- useEffect(()=>{
- setShowMHeader(showHeader);
- barRef.showHeader=showHeader;
- changeHeaderHeight();
- },[showHeader]);
- useEffect(()=>{
- let len=chain.length;
- let isShowH=len<=1;
- if (LINKS===null||LINKS.length<=1){
- isShowH=false;
- }
- setShowHeader(isShowH);
- },[pathname]);
- useEffect(()=>{
- checkInstallOpen();
- return ()=>{
- stopListener();
- }
- },[installOpen])
- const headerAni=useSpring({
- from: {transform: 'translateY(-100%) translateZ(0px)'},
- transform:showMHeader?'translateY(0%) translateZ(0px)':'translateY(-100%) translateZ(0px)',
- config: {
- easing: easings.easeOutBack,
- duration:300
- },
- });
- const changePath=(path)=>{
- navigate(path);
- }
- const renderHeaderRoom=()=>{
- const active=styles.active;
- return (
- <animated.div id={'headerRoom'} className={`${styles.header_room}`} style={headerAni}>
- <div className={`${styles['mobile-top-navigate-list']}`}>
- <button className={`${styles['mb-top-navigate-item']} ${pathname==='/'?active:''}`} onClick={()=>{
- changePath('/');
- }}>
- <svg className={"icon"}>
- <use xlinkHref={`${symbol_m}#icon_Home`} />
- </svg>
- <span>{i18n.t("links.home")}</span>
- </button>
- {
- LINKS.map((link, index) => (
- <button key={index} className={`${styles['mb-top-navigate-item']} ${checkNavActive(link.lv)?active:''}`} onClick={()=>{
- changePath(link.path);
- }}>
- <svg className={"icon"}>
- <use xlinkHref={`${symbol_m}#${link.icon}`} />
- </svg>
- <span>{i18n.t(link.title)}</span>
- </button>
- ))
- }
- </div>
- </animated.div>
- );
- }
- const renderMobileInstall=()=>{
- return (
- <div id={'installBanner'} className={styles.header_install}></div>
- )
- }
- const renderMobile=()=>{
- return (
- <>
- {renderMobileInstall()}
- <MobileNav />
- {renderHeaderRoom()}
- </>
- )
- }
- const renderDesktopInstall=()=>{
- return (
- <div id={'installBanner'} className={`${styles.header_install} ${styles.header_install_desk} ${navstyle}`}></div>
- )
- }
- const renderDesktop=()=>{
- return (
- <>
- {renderDesktopInstall()}
- <DesktopNav/>
- </>
- );
- }
- return (
- <div id={'appbar'} ref={barRef} className={`${styles.appbar} ${isMobile()?styles.mobile:''} ${isMobile()&&!showHeader?styles.hide_header:''}`}>
- {
- isMobile()?renderMobile():renderDesktop()
- }
- </div>
- )
- }
- export default PageHeader
|