mirror of
https://github.com/vrc-get/vrc-get.git
synced 2026-06-21 09:58:08 +00:00
feat: animate row colors during drag with O(k) re-renders
Replace useDndContext() + arrayMove approach with transform.y sign detection to compute visual row index. Previously all n rows subscribed to the dnd context and re-rendered on every collision change, each doing an O(n) arrayMove+indexOf -- O(n^2) total. Now only rows whose transform changes re-render, and each computes its visual index in O(1) from the sign of transform.y from useSortable. Total cost is O(k) where k is the number of displaced rows (typically 1-2). Also adds background-color to the inline transition string so the 200ms color animation works correctly alongside the transform animation, and removes guiAnimation prop drilling through RepositoryTableBody.
This commit is contained in:
parent
54113144a8
commit
ebd117afd2
1 changed files with 21 additions and 3 deletions
|
|
@ -324,6 +324,7 @@ function RepositoryTableBody({
|
|||
displayName={tt("vpm repositories:source:official")}
|
||||
hiddenUserRepos={hiddenUserRepos}
|
||||
canRemove={false}
|
||||
rowIndex={0}
|
||||
/>
|
||||
<RepositoryRow
|
||||
repoId={"com.vrchat.repos.curated"}
|
||||
|
|
@ -332,12 +333,13 @@ function RepositoryTableBody({
|
|||
hiddenUserRepos={hiddenUserRepos}
|
||||
className={"border-b border-primary/10"}
|
||||
canRemove={false}
|
||||
rowIndex={1}
|
||||
/>
|
||||
<SortableContext
|
||||
items={orderedIds}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
{orderedIds.map((id) => {
|
||||
{orderedIds.map((id, index) => {
|
||||
const repo = userRepoMap.get(id);
|
||||
if (!repo) return null;
|
||||
return (
|
||||
|
|
@ -347,6 +349,7 @@ function RepositoryTableBody({
|
|||
displayName={repo.display_name}
|
||||
url={repo.url}
|
||||
hiddenUserRepos={hiddenUserRepos}
|
||||
rowIndex={2 + index}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
|
@ -461,6 +464,7 @@ function RepositoryRow({
|
|||
hiddenUserRepos,
|
||||
className,
|
||||
canRemove = true,
|
||||
rowIndex,
|
||||
}: {
|
||||
repoId: TauriUserRepository["id"];
|
||||
displayName: TauriUserRepository["display_name"];
|
||||
|
|
@ -468,6 +472,7 @@ function RepositoryRow({
|
|||
hiddenUserRepos: Set<string>;
|
||||
className?: string;
|
||||
canRemove?: boolean;
|
||||
rowIndex: number;
|
||||
}) {
|
||||
const labelId = useId();
|
||||
|
||||
|
|
@ -486,10 +491,20 @@ function RepositoryRow({
|
|||
isDragging,
|
||||
} = useSortable({ id: repoId, disabled: !canRemove });
|
||||
|
||||
const visualIndex = useMemo(() => {
|
||||
if (isDragging) return rowIndex;
|
||||
const dy = transform?.y ?? 0;
|
||||
if (dy < 0) return rowIndex - 1;
|
||||
if (dy > 0) return rowIndex + 1;
|
||||
return rowIndex;
|
||||
}, [rowIndex, transform?.y, isDragging]);
|
||||
|
||||
const dragStyle = useMemo<React.CSSProperties>(
|
||||
() => ({
|
||||
transform: transform ? `translateY(${transform.y}px)` : undefined,
|
||||
transition: guiAnimation ? transition : undefined,
|
||||
transition: guiAnimation
|
||||
? [transition, "background-color 200ms ease"].filter(Boolean).join(", ")
|
||||
: undefined,
|
||||
opacity: isDragging ? 0 : 1,
|
||||
position: "relative",
|
||||
}),
|
||||
|
|
@ -547,7 +562,10 @@ function RepositoryRow({
|
|||
<tr
|
||||
ref={setNodeRef}
|
||||
style={dragStyle}
|
||||
className={cn("even:bg-secondary/30", className)}
|
||||
className={cn(
|
||||
visualIndex % 2 === 1 ? "bg-secondary/30" : "",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<RepositoryRowCells
|
||||
labelId={labelId}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue