Compare commits

..

No commits in common. "01ae9c964a6d68bdbc19464f6d26ae7b2e6df0a5" and "1f4efcd7b381d90b160df6a64a66dfd03e4ae3da" have entirely different histories.

2 changed files with 22 additions and 33 deletions

View File

@ -44,7 +44,6 @@
flex: 1; flex: 1;
height: 600px; height: 600px;
overflow-y: auto; overflow-y: auto;
position: relative;
background: white; background: white;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1); box-shadow: 0 2px 4px rgba(0,0,0,0.1);

View File

@ -5,6 +5,7 @@ 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 {
@ -37,29 +38,31 @@ 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}`);
console.log("loadTasks: got", tasks.length, "tasks");
console.log("Task order:", tasks.map(t => ({id: t.id, title: t.title, status: t.status})));
renderTasks(); renderTasks();
initSortable(); initSortable();
const currentGoal = goals.find(g => g.id === selectedGoalId); const currentGoal = goals.find(g => g.id === selectedGoalId);
const savedTaskId = currentGoal ? currentGoal.selected_task_id : null; const savedTaskId = currentGoal ? currentGoal.selected_task_id : null;
console.log("loadTasks: savedTaskId from goal =", savedTaskId);
const savedTaskExists = savedTaskId && tasks.some(t => t.id === savedTaskId); const savedTaskExists = savedTaskId && tasks.some(t => t.id === savedTaskId);
console.log("loadTasks: savedTaskExists =", savedTaskExists);
let focusTaskId = null;
if (savedTaskExists) { if (savedTaskExists) {
focusTaskId = savedTaskId; console.log("loadTasks: using savedTaskId path");
scrollToTask(savedTaskId); scrollToTask(savedTaskId);
selectedTaskId = savedTaskId;
if (isLandscapeMode()) { if (isLandscapeMode()) {
selectTask(savedTaskId); selectTask(savedTaskId);
} }
} else { } else {
console.log("loadTasks: using fallback path");
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);
@ -69,32 +72,22 @@ async function loadTasks() {
} }
} }
// Wait one frame so the async scroll event from scrollToTask fires first,
// then set in-focus and bind handlers after it has been consumed.
requestAnimationFrame(() => {
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) return; if (!selectedGoalId || isInitializing) 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);
if (goal) { if (goal) {
goal.selected_task_id = taskId; goal.selected_task_id = taskId;
} }
console.log("Saved selected task:", taskId);
} catch (error) { } catch (error) {
console.error("Failed to persist selected task:", error); console.error("Failed to persist selected task:", error);
} }
@ -157,13 +150,19 @@ function initSortable() {
} }
function scrollToTask(taskId) { function scrollToTask(taskId) {
console.log("scrollToTask called:", taskId);
const taskElement = document.querySelector(`[data-task-id="${taskId}"]`); const taskElement = document.querySelector(`[data-task-id="${taskId}"]`);
if (taskElement) { if (taskElement) {
const scrollView = document.getElementById("scroll-view"); const scrollView = document.getElementById("scroll-view");
const taskTop = taskElement.offsetTop; const taskTop = taskElement.offsetTop;
const scrollViewHeight = scrollView.clientHeight; const scrollViewHeight = scrollView.clientHeight;
const taskHeight = taskElement.offsetHeight; const taskHeight = taskElement.offsetHeight;
scrollView.scrollTop = taskTop - (scrollViewHeight / 2) + (taskHeight / 2); const targetScrollTop = taskTop - (scrollViewHeight / 2) + (taskHeight / 2);
console.log("Scrolling to:", targetScrollTop, "element offsetTop:", taskTop);
scrollView.scrollTop = targetScrollTop;
console.log("scrollTop after set:", scrollView.scrollTop);
} else {
console.log("Task element not found for id:", taskId);
} }
} }
@ -171,9 +170,7 @@ function initScrollFocus() {
const scrollView = document.getElementById("scroll-view"); const scrollView = document.getElementById("scroll-view");
scrollView.removeEventListener("scroll", handleScrollFocus); scrollView.removeEventListener("scroll", handleScrollFocus);
scrollView.removeEventListener("scroll", handleScrollSave);
scrollView.addEventListener("scroll", handleScrollFocus); scrollView.addEventListener("scroll", handleScrollFocus);
scrollView.addEventListener("scroll", handleScrollSave);
} }
function handleScrollFocus() { function handleScrollFocus() {
@ -204,6 +201,9 @@ function handleScrollFocus() {
const taskId = parseInt(closestItem.dataset.taskId); const taskId = parseInt(closestItem.dataset.taskId);
clearTimeout(persistTimer);
persistTimer = setTimeout(() => persistSelectedTask(taskId), 400);
if (isLandscapeMode()) { if (isLandscapeMode()) {
if (taskId !== selectedTaskId) { if (taskId !== selectedTaskId) {
selectTask(taskId); selectTask(taskId);
@ -212,16 +212,6 @@ function handleScrollFocus() {
} }
} }
function handleScrollSave() {
const inFocusTask = document.querySelector(".task-item.in-focus");
if (inFocusTask) {
const taskId = parseInt(inFocusTask.dataset.taskId);
clearTimeout(persistTimer);
persistTimer = setTimeout(() => persistSelectedTask(taskId), 400);
}
}
function isLandscapeMode() { function isLandscapeMode() {
return window.innerWidth > window.innerHeight && window.innerWidth >= 1024; return window.innerWidth > window.innerHeight && window.innerWidth >= 1024;
} }