feat(layout): 优化底部路由导航
This commit is contained in:
parent
c78e3ed5ff
commit
a2c9f86df9
|
|
@ -5,7 +5,6 @@ import '../css/iconfont.css';
|
|||
import '../css/iconfont-v2.css';
|
||||
import './globals.css';
|
||||
import { Providers } from '@/layout/Providers';
|
||||
import ProgressBar from '@/layout/Providers/ProgressBar';
|
||||
import Script from 'next/script';
|
||||
|
||||
const poppins = Poppins({
|
||||
|
|
@ -46,7 +45,7 @@ export default async function RootLayout({
|
|||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<html lang="en-US">
|
||||
<body
|
||||
className={`${poppins.variable} ${oleoScriptSwashCaps.variable} ${NumDisplay.variable} antialiased`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,34 +1,6 @@
|
|||
'use client';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export const useMedia = (config: Record<string, number>) => {
|
||||
// 追踪客户端是否已挂载
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [response, setResponse] = useState<Record<keyof typeof config, boolean>>();
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
const onResize = () => {
|
||||
const newResponse = Object.fromEntries(
|
||||
Object.entries(config).map(([key, value]) => {
|
||||
if (window.innerWidth > value) {
|
||||
return [key, true];
|
||||
}
|
||||
return [key, false];
|
||||
})
|
||||
) as Record<keyof typeof config, boolean>;
|
||||
setResponse(newResponse);
|
||||
};
|
||||
window.addEventListener('resize', onResize);
|
||||
onResize();
|
||||
return () => window.removeEventListener('resize', onResize);
|
||||
}, []);
|
||||
|
||||
if (!mounted) return undefined;
|
||||
|
||||
return response;
|
||||
};
|
||||
import { useState } from 'react';
|
||||
|
||||
/**
|
||||
* 异步函数hook, 自动托管loading状态
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
import { usePathname } from 'next/navigation';
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { useRef } from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useMedia } from '@/hooks/tools';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useSize } from 'ahooks';
|
||||
|
||||
export const items = [
|
||||
{
|
||||
|
|
@ -37,14 +38,18 @@ export const items = [
|
|||
export default function BottomBar() {
|
||||
const t = useTranslations('bottomBar');
|
||||
const pathname = usePathname();
|
||||
const response = useMedia({ hide: 500 });
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const size = useSize(containerRef);
|
||||
|
||||
if (!items.some((i) => i.path === pathname)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-20 border-outline-normal bg-[rgba(10,14,43,1)] z-100 flex border-t items-center justify-between">
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="h-20 border-outline-normal bg-[rgba(10,14,43,1)] z-100 flex border-t items-center justify-between"
|
||||
>
|
||||
{items.map((item) => {
|
||||
const isSelected = pathname === item.path;
|
||||
const label = t(item.labelKey as 'explore' | 'search' | 'chat' | 'me');
|
||||
|
|
@ -63,7 +68,7 @@ export default function BottomBar() {
|
|||
width={48}
|
||||
height={48}
|
||||
/>
|
||||
{response?.hide && <span>{label}</span>}
|
||||
{size?.width && size.width > 500 && <span>{label}</span>}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ interface ConditionalLayoutProps {
|
|||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
// 初始化聊天
|
||||
const useInitChat = () => {
|
||||
const { data } = useCurrentUser();
|
||||
const connect = useStreamChatStore((state) => state.connect);
|
||||
|
|
@ -31,24 +32,27 @@ const useInitChat = () => {
|
|||
}, [data]);
|
||||
};
|
||||
|
||||
export default function ConditionalLayout({ children }: ConditionalLayoutProps) {
|
||||
// 路由切换时重置滚动位置
|
||||
const useAutoScrollOnRouteChange = (ref: React.RefObject<HTMLDivElement | null>) => {
|
||||
const pathname = usePathname();
|
||||
const mainContentRef = useRef<HTMLDivElement>(null);
|
||||
const prevPathnameRef = useRef<string>(pathname);
|
||||
const response = useLayoutStore((s) => s.response);
|
||||
|
||||
// 初始化聊天
|
||||
useInitChat();
|
||||
|
||||
// 路由切换时重置滚动位置
|
||||
useEffect(() => {
|
||||
if (prevPathnameRef.current !== pathname) {
|
||||
if (mainContentRef.current) {
|
||||
mainContentRef.current.scrollTop = 0;
|
||||
if (ref.current) {
|
||||
ref.current.scrollTop = 0;
|
||||
}
|
||||
prevPathnameRef.current = pathname;
|
||||
}
|
||||
}, [pathname]);
|
||||
};
|
||||
|
||||
export default function ConditionalLayout({ children }: ConditionalLayoutProps) {
|
||||
const mainContentRef = useRef<HTMLDivElement>(null);
|
||||
const response = useLayoutStore((s) => s.response);
|
||||
|
||||
useInitChat();
|
||||
useAutoScrollOnRouteChange(mainContentRef);
|
||||
|
||||
return (
|
||||
<div className="flex h-screen bg-[url('/common-bg.png')] bg-[length:100%_30%] bg-top bg-no-repeat">
|
||||
|
|
|
|||
Loading…
Reference in New Issue