diff --git a/.unipi/docs/fix/2026-06-04-favorites-display-loading-fix.md b/.unipi/docs/fix/2026-06-04-favorites-display-loading-fix.md
new file mode 100644
index 0000000..ba7c05f
--- /dev/null
+++ b/.unipi/docs/fix/2026-06-04-favorites-display-loading-fix.md
@@ -0,0 +1,41 @@
+---
+title: "Favorites Display Loading Blank Page — Quick Fix"
+type: quick-fix
+date: 2026-06-04
+---
+
+# Favorites Display Loading Blank Page — Quick Fix
+
+## Bug
+
+When clicking the desktop header “我的收藏” button, the favorites page could briefly show the no-favorites empty state and then appear blank. The correct behavior is to show the user's favorited posts after loading.
+
+## Root Cause
+
+Two issues combined:
+
+1. The favorites page initialized with `loading=false` and `items=[]`. When the wallet was already logged in, React rendered the empty state once before the `useEffect` started the favorites request.
+2. The desktop header favorites link had been changed to `reloadDocument` as a previous workaround. In the local Vite/dev-browser state this could force a full document reload and land in a broken empty document state instead of keeping the React app mounted.
+
+## Fix
+
+- Added an explicit `loaded` state to `src/pages/Favorites/index.tsx`.
+- The favorites page now shows loading skeletons while logged-in favorites have not completed their first load, so the empty state only appears after a completed request returns zero items.
+- Added a loading UI for `wallet.status === "loading"` so a persisted wallet token does not briefly show the logged-out prompt.
+- Removed `reloadDocument` from the desktop header favorites link and kept client-side navigation with a top scroll reset.
+
+### Files Modified
+
+- `src/pages/Favorites/index.tsx` — tracks loaded state and gates empty-state rendering until favorites data has loaded.
+- `src/layouts/PublicLayout.tsx` — removes hard document reload from the desktop header favorites link.
+
+## Verification
+
+- `npx tsc --noEmit`
+- `npm run format:check`
+- `npm test`
+- Browser native: opened `http://192.168.1.187:5173/cn/browse`, clicked the desktop header “我的收藏”, and verified the resulting page URL is `/cn/favorites`, `document.getElementById("root")` exists, and `window.scrollY === 0`.
+
+## Notes
+
+No deploy was performed.
diff --git a/src/layouts/PublicLayout.tsx b/src/layouts/PublicLayout.tsx
index 3ff1ce1..9a0b2fe 100644
--- a/src/layouts/PublicLayout.tsx
+++ b/src/layouts/PublicLayout.tsx
@@ -698,7 +698,6 @@ export function PublicLayout() {
/>
window.scrollTo({ top: 0, left: 0 })}
className={`hidden h-10 shrink-0 items-center justify-center gap-2 rounded-full border px-3 text-sm font-bold outline-none transition focus-visible:ring-2 focus-visible:ring-ark-gold/80 focus-visible:ring-offset-2 focus-visible:ring-offset-ark-bg md:inline-flex ${
na("favorites")
diff --git a/src/pages/Favorites/index.tsx b/src/pages/Favorites/index.tsx
index 5a9dcea..68088ea 100644
--- a/src/pages/Favorites/index.tsx
+++ b/src/pages/Favorites/index.tsx
@@ -137,6 +137,7 @@ export default function Favorites() {
const [items, setItems] = useState([]);
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(false);
+ const [loaded, setLoaded] = useState(false);
const [error, setError] = useState("");
const [reloadKey, setReloadKey] = useState(0);
const [showFilters, setShowFilters] = useState(false);
@@ -151,10 +152,13 @@ export default function Favorites() {
if (!wallet.token || wallet.status !== "loggedIn") {
setItems([]);
setTotal(0);
+ setLoading(false);
+ setLoaded(false);
return;
}
let cancelled = false;
setLoading(true);
+ setLoaded(false);
setError("");
listFavorites(wallet.token, {
sort,
@@ -170,6 +174,7 @@ export default function Favorites() {
setItems(resources);
setTotal(data.total ?? resources.length);
resources.forEach((resource) => markFavorite(resource.id, true));
+ setLoaded(true);
})
.catch((err) => {
if (cancelled) return;
@@ -179,6 +184,7 @@ export default function Favorites() {
return;
}
setError(err instanceof Error ? err.message : t("loadFailed"));
+ setLoaded(true);
})
.finally(() => {
if (!cancelled) setLoading(false);
@@ -200,6 +206,16 @@ export default function Favorites() {
[t],
);
+ if (wallet.status === "loading") {
+ return (
+
+ {Array.from({ length: 4 }).map((_, index) => (
+
+ ))}
+
+ );
+ }
+
if (wallet.status !== "loggedIn") {
return (
@@ -330,7 +346,7 @@ export default function Favorites() {
) : null}
- {loading ? (
+ {loading || !loaded ? (