refactor: deprecate old cache methods and simplify todoistToObsidian

- taskParser.ts: replace loadTaskFromCacheyID with todoistSyncAPI.GetTaskById
- todoistToObsidian.ts: simplify to use taskFileMapping instead of old cache methods
- cacheOperation.ts: deprecate old cache methods (make them no-ops), keep taskFileMapping methods
This commit is contained in:
HeroBlackInk 2026-02-17 15:11:17 +08:00
parent c17953bb57
commit e828aff2a9
3 changed files with 51 additions and 334 deletions

View file

@ -256,300 +256,58 @@ export class CacheOperation {
}
// 从 Cache读取所有task
// DEPRECATED: Using syncData from Todoist API instead - no longer needed
loadTasksFromCache() {
try {
const savedTasks = this.plugin.settings.todoistTasksData.tasks
return savedTasks;
} catch (error) {
console.error(`Error loading tasks from Cache: ${error}`);
return [];
}
}
// 覆盖保存所有task到cache
saveTasksToCache(newTasks) {
try {
this.plugin.settings.todoistTasksData.tasks = newTasks
} catch (error) {
console.error(`Error saving tasks to Cache: ${error}`);
return false;
}
}
// append event 到 Cache
appendEventToCache(event:Object[]) {
try {
this.plugin.settings.todoistTasksData.events.push(event)
} catch (error) {
console.error(`Error append event to Cache: ${error}`);
}
// DEPRECATED: Using syncData from Todoist API instead - no longer needed
saveTasksToCache(_newTasks: any): boolean {
return true;
}
// append events 到 Cache
appendEventsToCache(events:Object[]) {
try {
this.plugin.settings.todoistTasksData.events.push(...events)
} catch (error) {
console.error(`Error append events to Cache: ${error}`);
}
}
// 从 Cache 文件中读取所有events
loadEventsFromCache() {
try {
// DEPRECATED: Event tracking no longer needed for one-way sync
appendEventToCache(_event: Object[]): void {}
appendEventsToCache(_events: Object[]): void {}
loadEventsFromCache(): any[] { return []; }
appendTaskToCache(_task: any): void {}
loadTaskFromCacheyID(_taskId: string): any { return null; }
updateTaskToCacheByID(_task: any): void {}
modifyTaskToCacheByID(_taskId: string, _params: { content?: string, due?: Due }): void {}
reopenTaskToCacheByID(_taskId: string): void {}
closeTaskToCacheByID(_taskId: string): void {}
deleteTaskFromCache(_taskId: string): void {}
deleteTaskFromCacheByIDs(_deletedTaskIds: string[]): void {}
const savedEvents = this.plugin.settings.todoistTasksData.events
return savedEvents;
} catch (error) {
console.error(`Error loading events from Cache: ${error}`);
}
// DEPRECATED: Using todoistSyncAPI.getProjectByName instead
getProjectIdByNameFromCache(projectName: string): any {
return this.plugin.todoistSyncAPI.getSyncData()?.projects?.find((p: any) => p.name === projectName)?.id || null;
}
// DEPRECATED: Using todoistSyncAPI.getProjectById instead
getProjectNameByIdFromCache(projectId: string): any {
return this.plugin.todoistSyncAPI.getSyncData()?.projects?.find((p: any) => p.id === projectId)?.name || null;
}
// 追加到 Cache 文件
appendTaskToCache(task) {
try {
if(task === null){
return
// DEPRECATED: Using syncData from Todoist API instead
async saveProjectsToCache(): Promise<boolean> { return true; }
// DEPRECATED: Using taskFileMapping instead
async updateRenamedFilePath(oldpath: string, newpath: string): Promise<void> {
const taskFileMapping = this.plugin.settings.taskFileMapping || {};
const fileMetadata = this.plugin.settings.fileMetadata || {};
for (const [taskId, mapping] of Object.entries(taskFileMapping)) {
if (mapping.filePath === oldpath) {
taskFileMapping[taskId] = { ...mapping, filePath: newpath };
}
const savedTasks = this.plugin.settings.todoistTasksData.tasks
this.plugin.settings.todoistTasksData.tasks.push(task);
this.plugin.logOperation?.log('CACHE_TASK_ADDED', `Added task to cache: ${task.content || task.id}`, task.path, task.id);
} catch (error) {
console.error(`Error appending task to Cache: ${error}`);
}
}
loadTaskFromCacheyID(taskId) {
try {
const savedTasks = this.plugin.settings.todoistTasksData.tasks
//console.log(savedTasks)
const savedTask = savedTasks.find((t) => t.id === taskId);
//console.log(savedTask)
return(savedTask)
} catch (error) {
console.error(`Error finding task from Cache: ${error}`);
return [];
this.plugin.settings.taskFileMapping = taskFileMapping;
if (fileMetadata[oldpath]) {
fileMetadata[newpath] = fileMetadata[oldpath];
delete fileMetadata[oldpath];
this.plugin.settings.fileMetadata = fileMetadata;
}
}
//覆盖update指定id的task
updateTaskToCacheByID(task) {
try {
//删除就的task
this.deleteTaskFromCache(task.id)
//添加新的task
this.appendTaskToCache(task)
this.plugin.logOperation?.log('CACHE_TASK_UPDATED', `Updated task in cache: ${task.content || task.id}`, task.path, task.id);
} catch (error) {
console.error(`Error updating task to Cache: ${error}`);
return [];
}
}
//due 的结构 {date: "2025-02-25",isRecurring: false,lang: "en",string: "2025-02-25"}
modifyTaskToCacheByID(taskId: string, { content, due }: { content?: string, due?: Due }): void {
try {
const savedTasks = this.plugin.settings.todoistTasksData.tasks;
const taskIndex = savedTasks.findIndex((task) => task.id === taskId);
if (taskIndex !== -1) {
const updatedTask = { ...savedTasks[taskIndex] };
if (content !== undefined) {
updatedTask.content = content;
}
if (due !== undefined) {
if (due === null) {
updatedTask.due = null;
} else {
updatedTask.due = due;
}
}
savedTasks[taskIndex] = updatedTask;
this.plugin.settings.todoistTasksData.tasks = savedTasks;
} else {
throw new Error(`Task with ID ${taskId} not found in cache.`);
}
} catch (error) {
// Handle the error appropriately, e.g. by logging it or re-throwing it.
}
}
//open a task status
reopenTaskToCacheByID(taskId:string) {
try {
const savedTasks = this.plugin.settings.todoistTasksData.tasks
// 遍历数组以查找具有指定 ID 的项
for (let i = 0; i < savedTasks.length; i++) {
if (savedTasks[i].id === taskId) {
// 修改对象的属性
savedTasks[i].isCompleted = false;
break; // 找到并修改了该项,跳出循环
}
}
this.plugin.settings.todoistTasksData.tasks = savedTasks
this.plugin.logOperation?.log('CACHE_TASK_REOPENED', `Reopened task in cache: ${taskId}`, undefined, taskId);
} catch (error) {
console.error(`Error open task to Cache file: ${error}`);
return [];
}
}
//close a task status
closeTaskToCacheByID(taskId:string):Promise<void> {
try {
const savedTasks = this.plugin.settings.todoistTasksData.tasks
// 遍历数组以查找具有指定 ID 的项
for (let i = 0; i < savedTasks.length; i++) {
if (savedTasks[i].id === taskId) {
// 修改对象的属性
savedTasks[i].isCompleted = true;
break; // 找到并修改了该项,跳出循环
}
}
this.plugin.settings.todoistTasksData.tasks = savedTasks
this.plugin.logOperation?.log('CACHE_TASK_COMPLETED', `Completed task in cache: ${taskId}`, undefined, taskId);
} catch (error) {
console.error(`Error close task to Cache file: ${error}`);
throw error; // 抛出错误使调用方能够捕获并处理它
}
}
// 通过 ID 删除任务
deleteTaskFromCache(taskId) {
try {
const savedTasks = this.plugin.settings.todoistTasksData.tasks
const newSavedTasks = savedTasks.filter((t) => t.id !== taskId);
this.plugin.settings.todoistTasksData.tasks = newSavedTasks
this.plugin.logOperation?.log('CACHE_TASK_DELETED', `Deleted task from cache: ${taskId}`, undefined, taskId);
} catch (error) {
console.error(`Error deleting task from Cache file: ${error}`);
}
}
// 通过 ID 数组 删除task
deleteTaskFromCacheByIDs(deletedTaskIds) {
try {
const savedTasks = this.plugin.settings.todoistTasksData.tasks
const newSavedTasks = savedTasks.filter((t) => !deletedTaskIds.includes(t.id))
this.plugin.settings.todoistTasksData.tasks = newSavedTasks
this.plugin.logOperation?.log('CACHE_TASK_DELETED', `Deleted ${deletedTaskIds.length} tasks from cache`, undefined, deletedTaskIds.join(', '));
} catch (error) {
console.error(`Error deleting task from Cache : ${error}`);
}
}
//通过 name 查找 project id
getProjectIdByNameFromCache(projectName:string) {
try {
const savedProjects = this.plugin.settings.todoistTasksData.projects
const targetProject = savedProjects.find(obj => obj.name === projectName);
const projectId = targetProject ? targetProject.id : null;
return(projectId)
} catch (error) {
console.error(`Error finding project from Cache file: ${error}`);
return(false)
}
}
getProjectNameByIdFromCache(projectId:string) {
try {
const savedProjects = this.plugin.settings.todoistTasksData.projects
const targetProject = savedProjects.find(obj => obj.id === projectId);
const projectName = targetProject ? targetProject.name : null;
return(projectName)
} catch (error) {
console.error(`Error finding project from Cache file: ${error}`);
return(false)
}
}
//save projects data to json file
async saveProjectsToCache() {
try{
//get projects
const projects = await this.plugin.todoistSyncAPI.GetAllProjects()
if(!projects){
return false
}
//save to json
this.plugin.settings.todoistTasksData.projects = projects
this.plugin.logOperation?.log('PROJECT_UPDATED', `Updated ${projects.length} projects in cache`);
return true
}catch(error){
return false
console.log(`error downloading projects: ${error}`)
}
}
async updateRenamedFilePath(oldpath:string,newpath:string){
try{
console.log(`oldpath is ${oldpath}`)
console.log(`newpath is ${newpath}`)
const savedTask = await this.loadTasksFromCache()
//console.log(savedTask)
const newTasks = savedTask.map(obj => {
if (obj.path === oldpath) {
return { ...obj, path: newpath };
}else {
return obj;
}
})
//console.log(newTasks)
await this.saveTasksToCache(newTasks)
//update filepath
const fileMetadatas = this.plugin.settings.fileMetadata
fileMetadatas[newpath] = fileMetadatas[oldpath]
delete fileMetadatas[oldpath]
this.plugin.settings.fileMetadata = fileMetadatas
this.plugin.logOperation?.log('CACHE_RENAMED', `Renamed file path from ${oldpath} to ${newpath}`, newpath);
}catch(error){
console.log(`Error updating renamed file path to cache: ${error}`)
}
this.plugin.logOperation?.log('CACHE_RENAMED', `Renamed file path from ${oldpath} to ${newpath}`, newpath);
}
async rebuildCache(noticeCallback?: (message: string) => void): Promise<{ success: boolean; tasksProcessed: number }> {

View file

@ -120,13 +120,13 @@ export class TaskParser {
//console.log(`缩进为 ${this.getTabIndentation(line)}`)
continue
}
if((this.getTabIndentation(line) < this.getTabIndentation(lineText))){
if((this.getTabIndentation(line) < this.getTabIndentation(lineText))){
//console.log(`缩进为 ${this.getTabIndentation(line)}`)
if(this.hasTodoistId(line)){
parentId = this.getTodoistIdFromLineText(line)
hasParent = true
//console.log(`parent id is ${parentId}`)
parentTaskObject = this.plugin.cacheOperation.loadTaskFromCacheyID(parentId)
parentTaskObject = await this.plugin.todoistSyncAPI.GetTaskById(parentId)
break
}
else{

View file

@ -12,19 +12,12 @@ export class TodoistToObsidianSync {
async syncCompletedTaskStatusToObsidian(unSynchronizedEvents: unknown[]): Promise<void> {
try {
const processedEvents = [];
for (const e of unSynchronizedEvents) {
const event = e as { object_id: string };
await this.plugin.fileOperation.completeTaskInTheFile(event.object_id);
await this.plugin.cacheOperation.closeTaskToCacheByID(event.object_id);
new Notice(`Task ${event.object_id} is closed.`);
this.plugin.logOperation?.log('TODOIST_TASK_COMPLETED', `Task completed in Todoist: ${event.object_id}`, undefined, event.object_id);
processedEvents.push(e);
}
await this.plugin.cacheOperation.appendEventsToCache(processedEvents);
this.plugin.saveSettings();
} catch (error) {
console.error('Error syncing task status:', error);
}
@ -32,18 +25,12 @@ export class TodoistToObsidianSync {
async syncUncompletedTaskStatusToObsidian(unSynchronizedEvents: unknown[]): Promise<void> {
try {
const processedEvents = [];
for (const e of unSynchronizedEvents) {
const event = e as { object_id: string };
await this.plugin.fileOperation.uncompleteTaskInTheFile(event.object_id);
await this.plugin.cacheOperation.reopenTaskToCacheByID(event.object_id);
new Notice(`Task ${event.object_id} is reopened.`);
this.plugin.logOperation?.log('TODOIST_TASK_REOPENED', `Task reopened in Todoist: ${event.object_id}`, undefined, event.object_id);
processedEvents.push(e);
}
await this.plugin.cacheOperation.appendEventsToCache(processedEvents);
this.plugin.saveSettings();
} catch (error) {
console.error('Error syncing task status:', error);
}
@ -51,8 +38,6 @@ export class TodoistToObsidianSync {
async syncUpdatedTaskToObsidian(unSynchronizedEvents: unknown[]): Promise<void> {
try {
const processedEvents = [];
for (const e of unSynchronizedEvents) {
const event = e as { object_id: string; event_type: string };
console.log(`Processing event: ${event.event_type} for task ${event.object_id}`);
@ -62,13 +47,7 @@ export class TodoistToObsidianSync {
} else if (event.event_type === 'due_date') {
await this.syncUpdatedTaskDueDateToObsidian(e);
}
processedEvents.push(e);
}
await this.plugin.cacheOperation.appendEventsToCache(processedEvents);
this.plugin.saveSettings();
} catch (error) {
console.error('Error syncing updated tasks:', error);
}
@ -88,19 +67,12 @@ export class TodoistToObsidianSync {
async syncAddedTaskNoteToObsidian(unSynchronizedEvents: unknown[]): Promise<void> {
try {
const processedEvents = [];
for (const e of unSynchronizedEvents) {
const event = e as { parent_item_id: string };
await this.plugin.fileOperation.syncAddedTaskNoteToTheFile(e);
new Notice(`Note added to task ${event.parent_item_id}`);
this.plugin.logOperation?.log('FILE_TASK_NOTE_ADDED', `Synced note from Todoist: ${event.parent_item_id}`, undefined, event.parent_item_id);
processedEvents.push(e);
}
await this.plugin.cacheOperation.appendEventsToCache(processedEvents);
this.plugin.saveSettings();
} catch (error) {
console.error('Error syncing task notes:', error);
}
@ -109,31 +81,25 @@ export class TodoistToObsidianSync {
async syncTodoistToObsidian(): Promise<void> {
try {
this.plugin.logOperation?.log('SYNC_START', 'Starting sync from Todoist to Obsidian');
const taskFileMapping = this.plugin.settings.taskFileMapping || {};
const knownTaskIds = new Set(Object.keys(taskFileMapping));
const all_activity_events = await this.plugin.todoistSyncAPI.getNonObsidianAllActivityEvents();
const savedEvents = await this.plugin.cacheOperation.loadEventsFromCache();
const result1 = all_activity_events.filter(
(objA: { id: string }) => !savedEvents.some((objB: { id: string }) => objB.id === objA.id)
(event: { object_id: string; parent_item_id: string }) =>
knownTaskIds.has(event.object_id) || knownTaskIds.has(event.parent_item_id)
);
const savedTasks = await this.plugin.cacheOperation.loadTasksFromCache();
const result2 = result1.filter(
(objA: { object_id: string }) => savedTasks.some((objB: { id: string }) => objB.id === objA.object_id)
);
const result3 = result1.filter(
(objA: { parent_item_id: string }) => savedTasks.some((objB: { id: string }) => objB.id === objA.parent_item_id)
);
const unsynchronized_item_completed_events = this.plugin.todoistSyncAPI.filterActivityEvents(result2, { event_type: 'completed', object_type: 'item' });
const unsynchronized_item_uncompleted_events = this.plugin.todoistSyncAPI.filterActivityEvents(result2, { event_type: 'uncompleted', object_type: 'item' });
const unsynchronized_item_updated_events = this.plugin.todoistSyncAPI.filterActivityEvents(result2, { event_type: 'updated', object_type: 'item' });
const unsynchronized_notes_added_events = this.plugin.todoistSyncAPI.filterActivityEvents(result3, { event_type: 'added', object_type: 'note' });
const unsynchronized_project_events = this.plugin.todoistSyncAPI.filterActivityEvents(result1, { object_type: 'project' });
const unsynchronized_item_completed_events = this.plugin.todoistSyncAPI.filterActivityEvents(result1, { event_type: 'completed', object_type: 'item' });
const unsynchronized_item_uncompleted_events = this.plugin.todoistSyncAPI.filterActivityEvents(result1, { event_type: 'uncompleted', object_type: 'item' });
const unsynchronized_item_updated_events = this.plugin.todoistSyncAPI.filterActivityEvents(result1, { event_type: 'updated', object_type: 'item' });
const unsynchronized_notes_added_events = this.plugin.todoistSyncAPI.filterActivityEvents(result1, { event_type: 'added', object_type: 'note' });
console.log(unsynchronized_item_completed_events);
console.log(unsynchronized_item_uncompleted_events);
console.log(unsynchronized_item_updated_events);
console.log(unsynchronized_project_events);
console.log(unsynchronized_notes_added_events);
await this.syncCompletedTaskStatusToObsidian(unsynchronized_item_completed_events);
@ -141,12 +107,6 @@ export class TodoistToObsidianSync {
await this.syncUpdatedTaskToObsidian(unsynchronized_item_updated_events);
await this.syncAddedTaskNoteToObsidian(unsynchronized_notes_added_events);
if (unsynchronized_project_events.length) {
console.log('New project event');
await this.plugin.cacheOperation.saveProjectsToCache();
await this.plugin.cacheOperation.appendEventsToCache(unsynchronized_project_events);
}
this.plugin.logOperation?.log('SYNC_COMPLETED', 'Sync from Todoist to Obsidian completed');
} catch (err) {
@ -166,7 +126,6 @@ export class TodoistToObsidianSync {
const fileName = `backup-${timeString}.json`;
const fullPath = `${backupFolder}/${fileName}`;
// Create backup folder if it doesn't exist
const folderExists = this.app.vault.getAbstractFileByPath(backupFolder);
if (!folderExists) {
await this.app.vault.createFolder(backupFolder);