ios pwa沉浸式状态栏
This commit is contained in:
@@ -14,6 +14,7 @@ const manifestPath = path.join(publicDir, 'manifest.json');
|
|||||||
const siteName = process.env.NEXT_PUBLIC_SITE_NAME || 'MoonTVPlus';
|
const siteName = process.env.NEXT_PUBLIC_SITE_NAME || 'MoonTVPlus';
|
||||||
|
|
||||||
// manifest.json 模板
|
// manifest.json 模板
|
||||||
|
// Apple 状态栏等配置应写在 HTML meta(layout appleWebApp),非标准 manifest 字段浏览器会忽略
|
||||||
const manifestTemplate = {
|
const manifestTemplate = {
|
||||||
name: siteName,
|
name: siteName,
|
||||||
short_name: siteName,
|
short_name: siteName,
|
||||||
@@ -22,8 +23,6 @@ const manifestTemplate = {
|
|||||||
scope: '/',
|
scope: '/',
|
||||||
display: 'standalone',
|
display: 'standalone',
|
||||||
background_color: '#000000',
|
background_color: '#000000',
|
||||||
'apple-mobile-web-app-capable': 'yes',
|
|
||||||
'apple-mobile-web-app-status-bar-style': 'black',
|
|
||||||
icons: [
|
icons: [
|
||||||
{
|
{
|
||||||
src: '/icons/icon-192x192.png',
|
src: '/icons/icon-192x192.png',
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ export async function generateMetadata(): Promise<Metadata> {
|
|||||||
title: siteName,
|
title: siteName,
|
||||||
description: '影视聚合',
|
description: '影视聚合',
|
||||||
manifest: '/manifest.json',
|
manifest: '/manifest.json',
|
||||||
|
// iOS 添加到主屏幕:沉浸式状态栏(需配合 viewport-fit=cover + 顶部 safe-area)
|
||||||
|
appleWebApp: {
|
||||||
|
capable: true,
|
||||||
|
statusBarStyle: 'black-translucent',
|
||||||
|
title: siteName,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2093,7 +2093,10 @@ export default function MusicClient({ children: _children }: { children?: React.
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<header className="fixed top-0 left-0 right-0 z-40 bg-zinc-950/95 backdrop-blur-md border-b border-white/10 px-4 md:px-6">
|
<header
|
||||||
|
className="fixed top-0 left-0 right-0 z-40 bg-zinc-950/95 backdrop-blur-md border-b border-white/10 px-4 md:px-6"
|
||||||
|
style={{ paddingTop: 'env(safe-area-inset-top)' }}
|
||||||
|
>
|
||||||
<div className="w-full mx-auto flex items-center justify-between gap-3 md:gap-4 py-3">
|
<div className="w-full mx-auto flex items-center justify-between gap-3 md:gap-4 py-3">
|
||||||
<div className="flex items-center justify-between md:justify-start md:gap-6 w-full md:w-auto">
|
<div className="flex items-center justify-between md:justify-start md:gap-6 w-full md:w-auto">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
@@ -2118,7 +2121,7 @@ export default function MusicClient({ children: _children }: { children?: React.
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
{/* Main Content */}
|
{/* Main Content */}
|
||||||
<main className="pt-[80px] md:pt-[76px] pb-32 px-4 md:px-6">
|
<main className="pt-[calc(80px+env(safe-area-inset-top))] md:pt-[calc(76px+env(safe-area-inset-top))] pb-32 px-4 md:px-6">
|
||||||
<div className="max-w-7xl mx-auto">
|
<div className="max-w-7xl mx-auto">
|
||||||
{_children}
|
{_children}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,8 +15,11 @@ interface MobileHeaderProps {
|
|||||||
const MobileHeader = ({ showBackButton = false }: MobileHeaderProps) => {
|
const MobileHeader = ({ showBackButton = false }: MobileHeaderProps) => {
|
||||||
const { siteName } = useSite();
|
const { siteName } = useSite();
|
||||||
return (
|
return (
|
||||||
<header className='md:hidden fixed top-0 left-0 right-0 z-[999] w-full bg-white/70 backdrop-blur-xl border-b border-gray-200/50 shadow-sm dark:bg-gray-900/70 dark:border-gray-700/50'>
|
<header
|
||||||
<div className='h-12 flex items-center justify-between px-4'>
|
className='md:hidden fixed top-0 left-0 right-0 z-[999] w-full bg-white/70 backdrop-blur-xl border-b border-gray-200/50 shadow-sm dark:bg-gray-900/70 dark:border-gray-700/50'
|
||||||
|
style={{ paddingTop: 'env(safe-area-inset-top)' }}
|
||||||
|
>
|
||||||
|
<div className='relative h-12 flex items-center justify-between px-4'>
|
||||||
{/* 左侧:搜索按钮、返回按钮和设置按钮 */}
|
{/* 左侧:搜索按钮、返回按钮和设置按钮 */}
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
<Link
|
<Link
|
||||||
@@ -47,17 +50,17 @@ const MobileHeader = ({ showBackButton = false }: MobileHeaderProps) => {
|
|||||||
<UserMenu />
|
<UserMenu />
|
||||||
<UpdateNotification />
|
<UpdateNotification />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 中间:Logo(绝对居中) */}
|
{/* 中间:Logo(相对内容行居中,避免被 safe-area 顶偏) */}
|
||||||
<div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'>
|
<div className='absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'>
|
||||||
<Link
|
<Link
|
||||||
href='/'
|
href='/'
|
||||||
prefetch={false}
|
prefetch={false}
|
||||||
className='text-2xl font-bold text-green-600 tracking-tight hover:opacity-80 transition-opacity'
|
className='text-2xl font-bold text-green-600 tracking-tight hover:opacity-80 transition-opacity'
|
||||||
>
|
>
|
||||||
{siteName}
|
{siteName}
|
||||||
</Link>
|
</Link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ const PageLayout = ({ children, activePath = '/', hideNavigation = false }: Page
|
|||||||
|
|
||||||
{/* 主内容 */}
|
{/* 主内容 */}
|
||||||
<main
|
<main
|
||||||
className='flex-1 md:min-h-0 mb-14 md:mb-0 md:mt-0 mt-12'
|
className='flex-1 md:min-h-0 mb-14 md:mb-0 md:mt-0 mt-[calc(3rem+env(safe-area-inset-top))]'
|
||||||
style={{
|
style={{
|
||||||
paddingBottom: 'calc(3.5rem + env(safe-area-inset-bottom))',
|
paddingBottom: 'calc(3.5rem + env(safe-area-inset-bottom))',
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -119,7 +119,10 @@ export default function BooksLayout({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='min-h-screen bg-[radial-gradient(circle_at_top_left,#fce7f3_0,transparent_34rem),linear-gradient(180deg,#fff7fb_0%,#f8fafc_44%,#f8fafc_100%)] text-slate-900 dark:bg-[radial-gradient(circle_at_top_left,rgba(6,95,70,0.26)_0,transparent_32rem),linear-gradient(180deg,#050505_0%,#09090b_100%)] dark:text-gray-100'>
|
<div className='min-h-screen bg-[radial-gradient(circle_at_top_left,#fce7f3_0,transparent_34rem),linear-gradient(180deg,#fff7fb_0%,#f8fafc_44%,#f8fafc_100%)] text-slate-900 dark:bg-[radial-gradient(circle_at_top_left,rgba(6,95,70,0.26)_0,transparent_32rem),linear-gradient(180deg,#050505_0%,#09090b_100%)] dark:text-gray-100'>
|
||||||
<header className='fixed inset-x-0 top-0 z-40 border-b border-emerald-100/80 bg-white/85 shadow-sm shadow-emerald-950/5 backdrop-blur-xl dark:border-emerald-500/10 dark:bg-gray-950/85 dark:shadow-black/20'>
|
<header
|
||||||
|
className='fixed inset-x-0 top-0 z-40 border-b border-emerald-100/80 bg-white/85 shadow-sm shadow-emerald-950/5 backdrop-blur-xl dark:border-emerald-500/10 dark:bg-gray-950/85 dark:shadow-black/20'
|
||||||
|
style={{ paddingTop: 'env(safe-area-inset-top)' }}
|
||||||
|
>
|
||||||
<div className='mx-auto flex h-16 max-w-6xl items-center gap-3 px-4'>
|
<div className='mx-auto flex h-16 max-w-6xl items-center gap-3 px-4'>
|
||||||
{isRead || pathname === '/books/detail' ? (
|
{isRead || pathname === '/books/detail' ? (
|
||||||
<Link
|
<Link
|
||||||
@@ -240,7 +243,11 @@ export default function BooksLayout({
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<main
|
<main
|
||||||
className={`mx-auto max-w-6xl ${isRead ? 'pt-16' : 'px-4 pb-24 pt-24'}`}
|
className={`mx-auto max-w-6xl ${
|
||||||
|
isRead
|
||||||
|
? 'pt-[calc(4rem+env(safe-area-inset-top))]'
|
||||||
|
: 'px-4 pb-24 pt-[calc(6rem+env(safe-area-inset-top))]'
|
||||||
|
}`}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -64,7 +64,10 @@ export default function MangaLayout({ children }: MangaLayoutProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='min-h-screen bg-gray-50 text-gray-900 dark:bg-black dark:text-gray-100'>
|
<div className='min-h-screen bg-gray-50 text-gray-900 dark:bg-black dark:text-gray-100'>
|
||||||
<header className='fixed inset-x-0 top-0 z-[999] border-b border-gray-200/70 bg-white/85 backdrop-blur-xl shadow-sm dark:border-gray-800/80 dark:bg-gray-950/85'>
|
<header
|
||||||
|
className='fixed inset-x-0 top-0 z-[999] border-b border-gray-200/70 bg-white/85 backdrop-blur-xl shadow-sm dark:border-gray-800/80 dark:bg-gray-950/85'
|
||||||
|
style={{ paddingTop: 'env(safe-area-inset-top)' }}
|
||||||
|
>
|
||||||
<div className='mx-auto flex h-14 max-w-7xl items-center gap-3 px-3 sm:h-16 sm:px-6'>
|
<div className='mx-auto flex h-14 max-w-7xl items-center gap-3 px-3 sm:h-16 sm:px-6'>
|
||||||
<div className='flex min-w-0 flex-1 items-center gap-2'>
|
<div className='flex min-w-0 flex-1 items-center gap-2'>
|
||||||
{meta.backHref ? (
|
{meta.backHref ? (
|
||||||
@@ -154,7 +157,7 @@ export default function MangaLayout({ children }: MangaLayoutProps) {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main
|
<main
|
||||||
className={`mx-auto max-w-7xl pt-20 sm:pt-24 ${
|
className={`mx-auto max-w-7xl pt-[calc(5rem+env(safe-area-inset-top))] sm:pt-[calc(6rem+env(safe-area-inset-top))] ${
|
||||||
isReadingPage
|
isReadingPage
|
||||||
? 'px-0 pb-24 sm:px-0 sm:pb-28 lg:pb-10'
|
? 'px-0 pb-24 sm:px-0 sm:pb-28 lg:pb-10'
|
||||||
: 'px-3 pb-[calc(5rem+env(safe-area-inset-bottom))] sm:px-6 sm:pb-[calc(5rem+env(safe-area-inset-bottom))] lg:pb-10'
|
: 'px-3 pb-[calc(5rem+env(safe-area-inset-bottom))] sm:px-6 sm:pb-[calc(5rem+env(safe-area-inset-bottom))] lg:pb-10'
|
||||||
|
|||||||
Reference in New Issue
Block a user