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.
This commit is contained in:
Yuyao Huang 2026-05-09 15:52:24 +08:00
parent 1a23558cad
commit 2229fdd0ef

View File

@ -5,7 +5,6 @@ let selectedTaskId = null;
let sortableInstance = null; let sortableInstance = null;
let persistTimer = null; let persistTimer = null;
let currentUser = null; let currentUser = null;
let isInitializing = false;
async function loadGoals() { async function loadGoals() {
try { try {
@ -38,7 +37,6 @@ async function loadGoals() {
async function loadTasks() { async function loadTasks() {
if (!selectedGoalId) return; if (!selectedGoalId) return;
isInitializing = true;
try { try {
tasks = await get(`/api/tasks?goal_id=${selectedGoalId}`); tasks = await get(`/api/tasks?goal_id=${selectedGoalId}`);
@ -49,7 +47,10 @@ async function loadTasks() {
const savedTaskId = currentGoal ? currentGoal.selected_task_id : null; const savedTaskId = currentGoal ? currentGoal.selected_task_id : null;
const savedTaskExists = savedTaskId && tasks.some(t => t.id === savedTaskId); const savedTaskExists = savedTaskId && tasks.some(t => t.id === savedTaskId);
let focusTaskId = null;
if (savedTaskExists) { if (savedTaskExists) {
focusTaskId = savedTaskId;
scrollToTask(savedTaskId); scrollToTask(savedTaskId);
selectedTaskId = savedTaskId; selectedTaskId = savedTaskId;
if (isLandscapeMode()) { if (isLandscapeMode()) {
@ -58,6 +59,7 @@ async function loadTasks() {
} else { } else {
const doingTask = tasks.find(t => t.status === "doing"); const doingTask = tasks.find(t => t.status === "doing");
if (doingTask) { if (doingTask) {
focusTaskId = doingTask.id;
scrollToTask(doingTask.id); scrollToTask(doingTask.id);
if (isLandscapeMode()) { if (isLandscapeMode()) {
selectTask(doingTask.id); 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(); initScrollFocus();
} catch (error) { } catch (error) {
console.error("Failed to load tasks:", error); console.error("Failed to load tasks:", error);
} finally {
isInitializing = false;
} }
} }
async function persistSelectedTask(taskId) { async function persistSelectedTask(taskId) {
if (!selectedGoalId || isInitializing) return; if (!selectedGoalId) return;
try { try {
await patch(`/api/goals/${selectedGoalId}/selected-task`, { task_id: taskId }); await patch(`/api/goals/${selectedGoalId}/selected-task`, { task_id: taskId });
const goal = goals.find(g => g.id === selectedGoalId); const goal = goals.find(g => g.id === selectedGoalId);
@ -161,11 +170,6 @@ function initScrollFocus() {
scrollView.removeEventListener("scroll", handleScrollFocus); scrollView.removeEventListener("scroll", handleScrollFocus);
scrollView.removeEventListener("scroll", handleScrollSave); 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", handleScrollFocus);
scrollView.addEventListener("scroll", handleScrollSave); scrollView.addEventListener("scroll", handleScrollSave);
} }
@ -207,11 +211,9 @@ function handleScrollFocus() {
} }
function handleScrollSave() { function handleScrollSave() {
// Save the task that has in-focus class (determined by handleScrollFocus)
const inFocusTask = document.querySelector(".task-item.in-focus"); 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); const taskId = parseInt(inFocusTask.dataset.taskId);
clearTimeout(persistTimer); clearTimeout(persistTimer);
persistTimer = setTimeout(() => persistSelectedTask(taskId), 400); persistTimer = setTimeout(() => persistSelectedTask(taskId), 400);