From 07fd8fa63737db4b2bec7b1ceba46bdb369e0cc5 Mon Sep 17 00:00:00 2001 From: Christen Date: Mon, 26 Jan 2026 16:45:24 +0100 Subject: [PATCH] fix subtask status dot refresh --- src/ui/TaskCard.ts | 179 +++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 102 deletions(-) diff --git a/src/ui/TaskCard.ts b/src/ui/TaskCard.ts index 3aeb88d1..6907a574 100644 --- a/src/ui/TaskCard.ts +++ b/src/ui/TaskCard.ts @@ -139,28 +139,55 @@ function createStatusCycleHandler( return async (e: MouseEvent) => { e.stopPropagation(); try { + const updateStatusVisuals = ( + updatedTask: TaskInfo, + effectiveStatus: string, + isCompleted: boolean + ) => { + const statusConfig = plugin.statusManager.getStatusConfig(effectiveStatus); + if (statusConfig?.color) { + statusDot.style.borderColor = statusConfig.color; + } else { + statusDot.style.borderColor = ""; + } + + if (statusConfig?.icon) { + statusDot.addClass("task-card__status-dot--icon"); + statusDot.empty(); + setIcon(statusDot, statusConfig.icon); + } else { + statusDot.removeClass("task-card__status-dot--icon"); + statusDot.empty(); + } + + if (statusConfig?.color) { + card.style.setProperty("--current-status-color", statusConfig.color); + } else { + card.style.removeProperty("--current-status-color"); + } + + const nextStatus = plugin.statusManager.getNextStatus(effectiveStatus); + const nextStatusConfig = plugin.statusManager.getStatusConfig(nextStatus); + if (nextStatusConfig?.color) { + card.style.setProperty("--next-status-color", nextStatusConfig.color); + } else { + card.style.removeProperty("--next-status-color"); + } + + const checkbox = card.querySelector(".task-card__checkbox") as HTMLInputElement | null; + if (checkbox) { + checkbox.checked = isCompleted; + } + + updateCardCompletionState(card, updatedTask, plugin, isCompleted, effectiveStatus); + }; + if (task.recurrence) { // For recurring tasks, toggle completion for the target date const updatedTask = await plugin.toggleRecurringTaskComplete(task, targetDate); const newEffectiveStatus = getEffectiveTaskStatus(updatedTask, targetDate); - const newStatusConfig = plugin.statusManager.getStatusConfig(newEffectiveStatus); const isNowCompleted = plugin.statusManager.isCompletedStatus(newEffectiveStatus); - - if (newStatusConfig) { - statusDot.style.borderColor = newStatusConfig.color; - // Update icon if configured - if (newStatusConfig.icon) { - statusDot.addClass("task-card__status-dot--icon"); - statusDot.empty(); - setIcon(statusDot, newStatusConfig.icon); - } else { - statusDot.removeClass("task-card__status-dot--icon"); - statusDot.empty(); - } - } - - // Update card classes - updateCardCompletionState(card, task, plugin, isNowCompleted, newEffectiveStatus); + updateStatusVisuals(updatedTask, newEffectiveStatus, isNowCompleted); } else { // For regular tasks, cycle to next/previous status based on shift key const freshTask = await plugin.cacheManager.getTaskInfo(task.path); @@ -172,7 +199,9 @@ function createStatusCycleHandler( const nextStatus = e.shiftKey ? plugin.statusManager.getPreviousStatus(currentStatus) : plugin.statusManager.getNextStatus(currentStatus); - await plugin.updateTaskProperty(freshTask, "status", nextStatus); + const updatedTask = await plugin.updateTaskProperty(freshTask, "status", nextStatus); + const isNowCompleted = plugin.statusManager.isCompletedStatus(nextStatus); + updateStatusVisuals(updatedTask, nextStatus, isNowCompleted); } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); @@ -192,16 +221,30 @@ function updateCardCompletionState( isCompleted: boolean, effectiveStatus: string ): void { - const cardClasses = ["task-card"]; - if (isCompleted) cardClasses.push("task-card--completed"); - if (task.archived) cardClasses.push("task-card--archived"); - if (plugin.getActiveTimeSession(task)) cardClasses.push("task-card--actively-tracked"); - if (task.recurrence) cardClasses.push("task-card--recurring"); - if (task.priority) cardClasses.push(`task-card--priority-${task.priority}`); - if (effectiveStatus) cardClasses.push(`task-card--status-${effectiveStatus}`); - if (plugin.settings?.subtaskChevronPosition === "left") cardClasses.push("task-card--chevron-left"); + card.classList.toggle("task-card--completed", isCompleted); + card.classList.toggle("task-card--archived", !!task.archived); + card.classList.toggle("task-card--actively-tracked", plugin.getActiveTimeSession(task) !== null); + card.classList.toggle("task-card--recurring", !!task.recurrence); + card.classList.toggle("task-card--chevron-left", plugin.settings?.subtaskChevronPosition === "left"); + + for (const className of Array.from(card.classList)) { + if (className.startsWith("task-card--priority-")) { + card.classList.remove(className); + } + } + if (task.priority) { + card.classList.add(`task-card--priority-${task.priority}`); + } + + for (const className of Array.from(card.classList)) { + if (className.startsWith("task-card--status-")) { + card.classList.remove(className); + } + } + if (effectiveStatus) { + card.classList.add(`task-card--status-${effectiveStatus}`); + } - card.className = cardClasses.join(" "); card.dataset.status = effectiveStatus; // Update title styling @@ -1874,83 +1917,15 @@ export function updateTaskCard( if (statusConfig) { newStatusDot.style.borderColor = statusConfig.color; } - - // Add click handler to cycle through statuses - newStatusDot.addEventListener("click", async (e) => { + // Prevent mousedown from propagating to editor (fixes inline widget de-rendering) + newStatusDot.addEventListener("mousedown", (e) => { + e.preventDefault(); e.stopPropagation(); - try { - if (task.recurrence) { - // For recurring tasks, toggle completion for the target date - const updatedTask = await plugin.toggleRecurringTaskComplete( - task, - targetDate - ); - - // Immediately update the visual state of the status dot - const newEffectiveStatus = getEffectiveTaskStatus(updatedTask, targetDate); - const newStatusConfig = - plugin.statusManager.getStatusConfig(newEffectiveStatus); - const isNowCompleted = - plugin.statusManager.isCompletedStatus(newEffectiveStatus); - - // Update status dot border color - if (newStatusConfig) { - newStatusDot.style.borderColor = newStatusConfig.color; - } - - // Update the card's completion state and classes - const cardClasses = ["task-card"]; - if (isNowCompleted) { - cardClasses.push("task-card--completed"); - } - if (task.archived) cardClasses.push("task-card--archived"); - if (plugin.getActiveTimeSession(task)) - cardClasses.push("task-card--actively-tracked"); - if (task.recurrence) cardClasses.push("task-card--recurring"); - if (task.priority) cardClasses.push(`task-card--priority-${task.priority}`); - if (newEffectiveStatus) - cardClasses.push(`task-card--status-${newEffectiveStatus}`); - - element.className = cardClasses.join(" "); - element.dataset.status = newEffectiveStatus; - - // Update the title completion styling - const titleText = element.querySelector( - ".task-card__title-text" - ) as HTMLElement; - const titleContainer = element.querySelector( - ".task-card__title" - ) as HTMLElement; - if (titleText) { - titleText.classList.toggle("completed", isNowCompleted); - } - if (titleContainer) { - titleContainer.classList.toggle("completed", isNowCompleted); - } - } else { - // For regular tasks, cycle to next/previous status based on shift key - // Get fresh task data to ensure we have the latest status - const freshTask = await plugin.cacheManager.getTaskInfo(task.path); - if (!freshTask) { - new Notice("Task not found"); - return; - } - - const currentStatus = freshTask.status || "open"; - const nextStatus = e.shiftKey - ? plugin.statusManager.getPreviousStatus(currentStatus) - : plugin.statusManager.getNextStatus(currentStatus); - await plugin.updateTaskProperty(freshTask, "status", nextStatus); - } - } catch (error) { - const errorMessage = error instanceof Error ? error.message : String(error); - console.error("Error cycling task status:", { - error: errorMessage, - taskPath: task.path, - }); - new Notice(`Failed to update task status: ${errorMessage}`); - } }); + newStatusDot.addEventListener( + "click", + createStatusCycleHandler(task, plugin, element, newStatusDot, targetDate) + ); // Insert at the beginning after checkbox const checkbox = element.querySelector(".task-card__checkbox");