refactor(task-view): remove debouncing from task list rendering

Removed debounced rendering in TaskListRendererComponent and TaskListItemComponent
to provide more responsive UI updates. Task changes now reflect immediately in
the view instead of waiting for debounce delays.

Changes:
- TaskList.ts: Removed debounceUpdateTasks wrapper, calls renderTaskItem directly
- listItem.ts: Removed debounceUpdateTaskItem, updates display immediately
- Added debug logging for priority field inspection
This commit is contained in:
Quorafind 2025-10-29 15:16:46 +08:00
parent f7456af12d
commit dc74b9c9ae
2 changed files with 53 additions and 76 deletions

View file

@ -1,7 +1,8 @@
import { App, Component, debounce } from "obsidian";
import { App, Component } from "obsidian";
import { Task } from "@/types/task";
import { TaskListItemComponent } from "./listItem";
import { TaskTreeItemComponent } from "./treeItem";
import { tasksToTree } from "@/utils/ui/tree-view-utils";
import { t } from "@/translations/helper";
import TaskProgressBarPlugin from "@/index";
@ -21,7 +22,7 @@ export class TaskListRendererComponent extends Component {
private containerEl: HTMLElement, // The HTML element to render tasks into
private plugin: TaskProgressBarPlugin,
private app: App,
private context: string, // Context identifier (e.g., "projects", "review")
private context: string // Context identifier (e.g., "projects", "review")
) {
super();
// Add this renderer as a child of the parent component
@ -42,66 +43,45 @@ export class TaskListRendererComponent extends Component {
isTreeView: boolean,
allTasksMap: Map<string, Task>, // Make it optional but required for tree view
emptyMessage: string = t("No tasks found."),
append: boolean = false,
append: boolean = false
) {
this.debounceUpdateTasks(
tasks,
isTreeView,
allTasksMap,
emptyMessage,
append,
);
}
if (!append) {
this.cleanupComponents();
this.containerEl.empty();
}
private debounceUpdateTasks = debounce(
(
tasks: Task[],
isTreeView: boolean,
allTasksMap: Map<string, Task>, // Make it optional but required for tree view
emptyMessage: string = t("No tasks found."),
append = false,
) => {
if (!append) {
this.cleanupComponents();
this.containerEl.empty();
}
if (tasks.length === 0 && !append) {
this.renderEmptyState(emptyMessage);
return;
}
if (tasks.length === 0 && !append) {
this.renderEmptyState(emptyMessage);
// Store the map if provided (primarily for tree view)
if (allTasksMap) {
this.allTasksMap = allTasksMap;
} else if (isTreeView) {
// Fallback: if tree view is requested but no map provided, build it from section tasks
// This might lead to incomplete trees if parents are outside the section.
console.warn(
"TaskListRendererComponent: allTasksMap not provided for tree view. Tree may be incomplete."
);
this.allTasksMap = new Map(tasks.map((task) => [task.id, task]));
}
if (isTreeView) {
if (!this.allTasksMap || this.allTasksMap.size === 0) {
console.error(
"TaskListRendererComponent: Cannot render tree view without allTasksMap."
);
this.renderEmptyState(
"Error: Task data unavailable for tree view."
); // Show error
return;
}
// Store the map if provided (primarily for tree view)
if (allTasksMap) {
this.allTasksMap = allTasksMap;
} else if (isTreeView) {
// Fallback: if tree view is requested but no map provided, build it from section tasks
// This might lead to incomplete trees if parents are outside the section.
console.warn(
"TaskListRendererComponent: allTasksMap not provided for tree view. Tree may be incomplete.",
);
this.allTasksMap = new Map(
tasks.map((task) => [task.id, task]),
);
}
if (isTreeView) {
if (!this.allTasksMap || this.allTasksMap.size === 0) {
console.error(
"TaskListRendererComponent: Cannot render tree view without allTasksMap.",
);
this.renderEmptyState(
"Error: Task data unavailable for tree view.",
); // Show error
return;
}
this.renderTreeView(tasks, this.allTasksMap); // Pass the map
} else {
this.renderListView(tasks);
}
},
1000,
);
this.renderTreeView(tasks, this.allTasksMap); // Pass the map
} else {
this.renderListView(tasks);
}
}
private renderListView(tasks: Task[]) {
const fragment = document.createDocumentFragment();
@ -110,7 +90,7 @@ export class TaskListRendererComponent extends Component {
task,
this.context,
this.app,
this.plugin,
this.plugin
);
// Set up event handlers
@ -129,13 +109,13 @@ export class TaskListRendererComponent extends Component {
"TaskListRendererComponent onTaskUpdate",
this.onTaskUpdate,
originalTask.content,
updatedTask.content,
updatedTask.content
);
if (this.onTaskUpdate) {
console.log(
"TaskListRendererComponent onTaskUpdate",
originalTask.content,
updatedTask.content,
updatedTask.content
);
await this.onTaskUpdate(originalTask, updatedTask);
}
@ -161,7 +141,7 @@ export class TaskListRendererComponent extends Component {
private renderTreeView(
sectionTasks: Task[],
allTasksMap: Map<string, Task>,
allTasksMap: Map<string, Task>
) {
const fragment = document.createDocumentFragment();
const sectionTaskIds = new Set(sectionTasks.map((t) => t.id)); // IDs of tasks belonging to this section
@ -171,7 +151,7 @@ export class TaskListRendererComponent extends Component {
const markSubtreeAsProcessed = (
rootTask: Task,
sectionTaskIds: Set<string>,
processedTaskIds: Set<string>,
processedTaskIds: Set<string>
) => {
if (sectionTaskIds.has(rootTask.id)) {
processedTaskIds.add(rootTask.id);
@ -184,7 +164,7 @@ export class TaskListRendererComponent extends Component {
markSubtreeAsProcessed(
childTask,
sectionTaskIds,
processedTaskIds,
processedTaskIds
);
}
});
@ -217,11 +197,11 @@ export class TaskListRendererComponent extends Component {
!sectionTaskIds.has(currentTask.metadata.parent)
) {
const parentTask = allTasksMap.get(
currentTask.metadata.parent,
currentTask.metadata.parent
);
if (!parentTask) {
console.warn(
`Parent task ${currentTask.metadata.parent} not found in allTasksMap.`,
`Parent task ${currentTask.metadata.parent} not found in allTasksMap.`
);
break;
}
@ -239,7 +219,7 @@ export class TaskListRendererComponent extends Component {
markSubtreeAsProcessed(
actualRoot,
sectionTaskIds,
processedTaskIds,
processedTaskIds
);
}
}
@ -258,7 +238,7 @@ export class TaskListRendererComponent extends Component {
directChildren.push(childTask);
} else {
console.warn(
`Child task ${childId} (parent: ${rootTask.id}) not found in allTasksMap.`,
`Child task ${childId} (parent: ${rootTask.id}) not found in allTasksMap.`
);
}
});
@ -273,7 +253,7 @@ export class TaskListRendererComponent extends Component {
0, // Root level is 0
directChildren, // Pass the actual children from the full map
allTasksMap, // Pass the full map for recursive building
this.plugin,
this.plugin
);
// Set up event handlers
@ -322,7 +302,7 @@ export class TaskListRendererComponent extends Component {
// Try updating in list view components
const listItemComponent = this.taskComponents.find(
(c) => c.getTask().id === updatedTask.id,
(c) => c.getTask().id === updatedTask.id
);
if (listItemComponent) {
listItemComponent.updateTask(updatedTask);

View file

@ -6,7 +6,6 @@ import {
Keymap,
Platform,
Workspace,
debounce,
} from "obsidian";
import { Task } from "@/types/task";
import { MarkdownRendererComponent } from "@/components/ui/renderers/MarkdownRenderer";
@ -213,7 +212,7 @@ export class TaskListItemComponent extends Component {
}
});
this.debounceUpdateTaskItem();
this.renderTaskItem();
this.updateSelectionVisualState();
}
@ -281,6 +280,8 @@ export class TaskListItemComponent extends Component {
// Priority indicator if available
if (this.task.metadata.priority) {
console.log("priority", this.task.metadata.priority);
// Convert priority to numeric value
let numericPriority: number;
if (typeof this.task.metadata.priority === "string") {
@ -928,13 +929,9 @@ export class TaskListItemComponent extends Component {
});
}
private debounceUpdateTaskItem = debounce(() => {
this.renderTaskItem();
}, 200);
private updateTaskDisplay() {
// Re-render the entire task item
this.debounceUpdateTaskItem();
this.renderTaskItem();
}
public getTask(): Task {