fix: 软刷新齐套前保留旧画面,避免一点击就卸光

Logo/下拉静默预热后一次覆盖;commit 不再先 reset/loading;顺带会话预取与可配置 Feed 排序标签。
This commit is contained in:
2026-09-01 04:56:10 +08:00
parent ba60a9b1c4
commit 9e134916a4
47 changed files with 2446 additions and 636 deletions

View File

@@ -0,0 +1,75 @@
import { useEffect, useRef, useState } from 'react';
import { subscribeSpaTransition } from '../utils/spaTransition';
/**
* 视口顶部 2px 细进度条(类 Next.js / YouTube)。
* 由 spaTransition start/done 驱动,假进度爬升至约 80%,结束冲到 100%。
*/
export default function TopProgressBar() {
const [visible, setVisible] = useState(false);
const [width, setWidth] = useState(0);
const [fading, setFading] = useState(false);
const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);
const fadeRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const activeRef = useRef(false);
useEffect(() => {
const clearTick = () => {
if (timerRef.current) {
clearInterval(timerRef.current);
timerRef.current = null;
}
};
const clearFade = () => {
if (fadeRef.current) {
clearTimeout(fadeRef.current);
fadeRef.current = null;
}
};
return subscribeSpaTransition((active) => {
if (active) {
activeRef.current = true;
clearFade();
setFading(false);
setVisible(true);
setWidth(12);
clearTick();
timerRef.current = setInterval(() => {
setWidth((w) => {
if (w >= 80) return w;
// 越接近 80 越慢
const step = Math.max(0.4, (80 - w) * 0.045);
return Math.min(80, w + step);
});
}, 120);
return;
}
if (!activeRef.current) return;
activeRef.current = false;
clearTick();
setWidth(100);
setFading(true);
clearFade();
fadeRef.current = setTimeout(() => {
setVisible(false);
setFading(false);
setWidth(0);
}, 220);
});
}, []);
if (!visible && width <= 0) return null;
return (
<div
className={[
'top-progress',
fading ? 'top-progress--done' : '',
].filter(Boolean).join(' ')}
style={{ width: `${width}%` }}
aria-hidden
/>
);
}