v3: code quality pass

This commit is contained in:
khannurien
2026-03-24 18:47:05 +00:00
parent cd4076343b
commit c293f3e706
39 changed files with 1464 additions and 1555 deletions

View File

@@ -26,9 +26,10 @@ import { usePlaylistListSync } from "../hooks/usePlaylistListSync.ts";
import { usePositionAwareSync } from "../hooks/usePositionAwareSync.ts";
import { useInfiniteScroll } from "../hooks/useInfiniteScroll.ts";
import { useFeedCache } from "../hooks/useFeedCache.ts";
import { Avatar } from "../components/Avatar.tsx";
import { useScrollSave } from "../hooks/useScrollSave.ts";
import { PlaylistCard } from "../components/PlaylistCard.tsx";
import { NewPlaylistForm } from "../components/NewPlaylistForm.tsx";
import { ProfileSubpageHeader } from "../components/ProfileSubpageHeader.tsx";
import { ConfirmModal } from "../components/ConfirmModal.tsx";
import { PageShell } from "../components/PageShell.tsx";
import { PageError } from "../components/PageError.tsx";
@@ -283,35 +284,24 @@ export function UserPlaylists() {
!state.followed.loadingMore,
);
// Scroll save
useEffect(() => {
if (state.status !== "loaded") return;
let timer: ReturnType<typeof setTimeout>;
const onScroll = () => {
clearTimeout(timer);
timer = setTimeout(() => {
if (state.status !== "loaded") return;
const y = globalThis.scrollY;
saveCreated(
state.created.items,
state.created.page,
state.created.hasMore,
y,
);
saveFollowed(
state.followed.items,
state.followed.page,
state.followed.hasMore,
y,
);
}, 100);
};
globalThis.addEventListener("scroll", onScroll, { passive: true });
return () => {
globalThis.removeEventListener("scroll", onScroll);
clearTimeout(timer);
};
}, [state, saveCreated, saveFollowed]);
useScrollSave(
state.status === "loaded",
useCallback((y) => {
if (state.status !== "loaded") return;
saveCreated(
state.created.items,
state.created.page,
state.created.hasMore,
y,
);
saveFollowed(
state.followed.items,
state.followed.page,
state.followed.hasMore,
y,
);
}, [state, saveCreated, saveFollowed]),
);
const scrollRestored = useRef(false);
useLayoutEffect(() => {
@@ -364,34 +354,25 @@ export function UserPlaylists() {
return (
<PageShell>
<div className="profile-subpage-header">
<Link to={`/users/${username}`} className="profile-subpage-back">
{profileUser.username}
</Link>
<div className="profile-subpage-title-row">
<Avatar
userId={profileUser.id}
username={profileUser.username}
hasAvatar={!!profileUser.avatarMime}
size={36}
<ProfileSubpageHeader
username={username!}
profileUser={profileUser}
title="Playlists"
actions={isOwnProfile && (
<NewPlaylistForm
toggleClassName="btn-primary"
onCreated={(p) =>
setState((s) => {
if (s.status !== "loaded") return s;
if (s.created.items.some((pl) => pl.id === p.id)) return s;
return {
...s,
created: { ...s.created, items: [p, ...s.created.items] },
};
})}
/>
<h1 className="profile-subpage-title">Playlists</h1>
{isOwnProfile && (
<NewPlaylistForm
toggleClassName="btn-primary"
onCreated={(p) =>
setState((s) => {
if (s.status !== "loaded") return s;
if (s.created.items.some((pl) => pl.id === p.id)) return s;
return {
...s,
created: { ...s.created, items: [p, ...s.created.items] },
};
})}
/>
)}
</div>
</div>
)}
/>
<section className="profile-section">
<div className="profile-section-header">