added task transitions to movement

This commit is contained in:
2026-03-03 18:54:40 -06:00
parent 15f518c58f
commit f1200a2c78
11 changed files with 276 additions and 95 deletions
+65
View File
@@ -0,0 +1,65 @@
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 };
}