Files
TasGrid/src/hooks/useDelayedSort.ts
T

66 lines
2.5 KiB
TypeScript

import { createSignal, createEffect, onCleanup, untrack } from "solid-js";
import type { Task } from "@/store";
export function useDelayedSort(
sourceTasks: () => Task[],
sortFn: (a: Task, b: Task) => number,
delayMs = 300
) {
const initialTasks = untrack(() => [...sourceTasks()].sort(sortFn));
const [displayedTasks, setDisplayedTasks] = createSignal<Task[]>(initialTasks);
const [shakingTaskIds, setShakingTaskIds] = createSignal<string[]>([]);
let timer: number | undefined;
createEffect(() => {
const sorted = [...sourceTasks()].sort(sortFn);
const currentDisplayed = untrack(() => displayedTasks());
// Initial load (though now handled by initial state, kept for safety if it resets)
if (currentDisplayed.length === 0 && sorted.length > 0) {
setDisplayedTasks(sorted);
return;
}
// Check if anything fundamentally changed order
const newIds = sorted.map(t => t.id).join(',');
const oldIds = currentDisplayed.map(t => t.id).join(',');
if (newIds !== oldIds) {
// Find which IDs have moved or changed their presence
// To be safe, let's just shake all currently visible ones, or maybe just the ones moving.
// A simple "shake everything" works perfectly for a brief warning: "Items are shifting!"
// The user wanted "tasks an animation when they rearange where they shake"
const changedSet = new Set<string>();
sorted.forEach((t: Task, i: number) => {
if (currentDisplayed[i]?.id !== t.id) {
changedSet.add(t.id);
if (currentDisplayed[i]) changedSet.add(currentDisplayed[i].id);
}
});
if (changedSet.size > 0) {
setShakingTaskIds(Array.from(changedSet));
if (timer) clearTimeout(timer);
timer = window.setTimeout(() => {
setShakingTaskIds([]);
setDisplayedTasks(sorted);
}, delayMs);
} else {
setDisplayedTasks(sorted);
}
} else {
// Identical order, just data updates (e.g. title changes)
// We want these to pass through instantly without rearranging
setDisplayedTasks(sorted);
}
});
onCleanup(() => {
if (timer) clearTimeout(timer);
});
return { displayedTasks, shakingTaskIds };
}