2026-05-30 01:27:02 +08:00
|
|
|
import { useEffect, useRef, useState } from "react";
|
2026-05-28 22:36:08 +08:00
|
|
|
import type { PostScope } from "../types/post";
|
|
|
|
|
import { MessageStream } from "./messageStream/MessageStream";
|
|
|
|
|
import { SectionHeader } from "./SectionHeader";
|
|
|
|
|
|
|
|
|
|
type AssetStreamPageProps = {
|
|
|
|
|
title: string;
|
|
|
|
|
scope: PostScope;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export function AssetStreamPage({ title, scope }: AssetStreamPageProps) {
|
2026-05-30 01:27:02 +08:00
|
|
|
// Telegram-style sticky page title: once the main heading scrolls up behind
|
|
|
|
|
// the global header, a floating pill slides in so users always know which
|
|
|
|
|
// page they're on.
|
|
|
|
|
const sentinelRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
const [pinned, setPinned] = useState(false);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const el = sentinelRef.current;
|
|
|
|
|
if (!el) return;
|
|
|
|
|
const io = new IntersectionObserver(
|
|
|
|
|
([entry]) => setPinned(!entry.isIntersecting),
|
|
|
|
|
// Inset the top by the sticky header height so the pill appears exactly
|
|
|
|
|
// when the heading disappears behind it.
|
|
|
|
|
{ rootMargin: "-64px 0px 0px 0px", threshold: 0 },
|
|
|
|
|
);
|
|
|
|
|
io.observe(el);
|
|
|
|
|
return () => io.disconnect();
|
|
|
|
|
}, []);
|
|
|
|
|
|
2026-05-28 22:36:08 +08:00
|
|
|
return (
|
|
|
|
|
<section>
|
|
|
|
|
<div className="mx-auto max-w-full px-4 md:max-w-[820px] lg:max-w-[1080px] xl:max-w-[1180px]">
|
|
|
|
|
<SectionHeader title={title} />
|
|
|
|
|
</div>
|
2026-05-30 01:27:02 +08:00
|
|
|
<div ref={sentinelRef} aria-hidden className="h-0" />
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
className={`pointer-events-none fixed inset-x-0 top-[64px] z-30 flex justify-center px-4 transition-all duration-300 md:top-[70px] ${
|
|
|
|
|
pinned ? "translate-y-0 opacity-100" : "-translate-y-3 opacity-0"
|
|
|
|
|
}`}
|
|
|
|
|
aria-hidden={!pinned}
|
|
|
|
|
>
|
|
|
|
|
<div className="flex items-center gap-2 rounded-full border border-ark-line/80 bg-[#1c1c21]/90 px-4 py-1.5 shadow-lg shadow-black/40 backdrop-blur-md">
|
|
|
|
|
<span
|
|
|
|
|
className="h-3.5 w-[3px] shrink-0 rounded-full bg-ark-gold"
|
|
|
|
|
aria-hidden
|
|
|
|
|
/>
|
|
|
|
|
<span className="truncate text-sm font-semibold text-white">
|
|
|
|
|
{title}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-05-28 22:36:08 +08:00
|
|
|
<MessageStream scope={scope} />
|
|
|
|
|
</section>
|
|
|
|
|
);
|
|
|
|
|
}
|