From 2229fdd0ef900128aa4839c75ce53d41516bf121 Mon Sep 17 00:00:00 2001 From: Yuyao Huang Date: Sat, 9 May 2026 15:52:24 +0800 Subject: [PATCH] fix: directly set in-focus on scrolled task instead of recalculating geometry Previously handleScrollFocus() recalculated the centered task during init, which could select a different task than the one scrollToTask() targeted due to scroll container clamping or DOM layout timing. Now the scrolled task directly receives the in-focus class, and handleScrollFocus is only used during user-initiated scroll events. Also removes the isInitializing flag as it's no longer needed. --- static/js/tasks.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/static/js/tasks.js b/static/js/tasks.js index ffea065..20ed1c2 100644 --- a/static/js/tasks.js +++ b/static/js/tasks.js @@ -5,7 +5,6 @@ let selectedTaskId = null; let sortableInstance = null; let persistTimer = null; let currentUser = null; -let isInitializing = false; async function loadGoals() { try { @@ -38,7 +37,6 @@ async function loadGoals() { async function loadTasks() { if (!selectedGoalId) return; - isInitializing = true; try { tasks = await get(`/api/tasks?goal_id=${selectedGoalId}`); @@ -49,7 +47,10 @@ async function loadTasks() { const savedTaskId = currentGoal ? currentGoal.selected_task_id : null; const savedTaskExists = savedTaskId && tasks.some(t => t.id === savedTaskId); + let focusTaskId = null; + if (savedTaskExists) { + focusTaskId = savedTaskId; scrollToTask(savedTaskId); selectedTaskId = savedTaskId; if (isLandscapeMode()) { @@ -58,6 +59,7 @@ async function loadTasks() { } else { const doingTask = tasks.find(t => t.status === "doing"); if (doingTask) { + focusTaskId = doingTask.id; scrollToTask(doingTask.id); if (isLandscapeMode()) { selectTask(doingTask.id); @@ -67,16 +69,23 @@ async function loadTasks() { } } + // Directly set in-focus on the scrolled task instead of recalculating + if (focusTaskId) { + document.querySelectorAll(".task-item.in-focus").forEach(el => el.classList.remove("in-focus")); + const focusEl = document.querySelector(`[data-task-id="${focusTaskId}"]`); + if (focusEl) { + focusEl.classList.add("in-focus"); + } + } + initScrollFocus(); } catch (error) { console.error("Failed to load tasks:", error); - } finally { - isInitializing = false; } } async function persistSelectedTask(taskId) { - if (!selectedGoalId || isInitializing) return; + if (!selectedGoalId) return; try { await patch(`/api/goals/${selectedGoalId}/selected-task`, { task_id: taskId }); const goal = goals.find(g => g.id === selectedGoalId); @@ -161,11 +170,6 @@ function initScrollFocus() { scrollView.removeEventListener("scroll", handleScrollFocus); scrollView.removeEventListener("scroll", handleScrollSave); - - // Initial call to set in-focus class (before binding scroll handler) - handleScrollFocus(); - - // Bind scroll handlers after initial setup scrollView.addEventListener("scroll", handleScrollFocus); scrollView.addEventListener("scroll", handleScrollSave); } @@ -207,11 +211,9 @@ function handleScrollFocus() { } function handleScrollSave() { - // Save the task that has in-focus class (determined by handleScrollFocus) const inFocusTask = document.querySelector(".task-item.in-focus"); - console.log("handleScrollSave: inFocusTask=", inFocusTask?.dataset.taskId, "isInitializing=", isInitializing); - if (inFocusTask && !isInitializing) { + if (inFocusTask) { const taskId = parseInt(inFocusTask.dataset.taskId); clearTimeout(persistTimer); persistTimer = setTimeout(() => persistSelectedTask(taskId), 400);