mirror of
https://github.com/heroblackink/ultimate-todoist-sync-for-obsidian.git
synced 2026-07-22 07:40:27 +00:00
refactor(compare): unify sync and checker comparisons via task parser
This commit is contained in:
parent
04139499dd
commit
5199278550
3 changed files with 46 additions and 41 deletions
|
|
@ -197,22 +197,6 @@ export class DatabaseChecker {
|
|||
}
|
||||
}
|
||||
|
||||
private normalizeLabels(labels: string[] | undefined): string[] {
|
||||
if (!labels || labels.length === 0) return [];
|
||||
return labels
|
||||
.filter(label => label && label !== 'todoist')
|
||||
.map(label => label.trim())
|
||||
.filter(label => label.length > 0)
|
||||
.sort();
|
||||
}
|
||||
|
||||
private labelsEqual(a: string[] | undefined, b: string[] | undefined): boolean {
|
||||
const labelsA = this.normalizeLabels(a);
|
||||
const labelsB = this.normalizeLabels(b);
|
||||
if (labelsA.length !== labelsB.length) return false;
|
||||
return labelsA.every((label, index) => label === labelsB[index]);
|
||||
}
|
||||
|
||||
private async confirmTodoistTaskMissing(taskId: string): Promise<boolean> {
|
||||
const todoistSyncAPI = this.plugin.todoistSyncAPI;
|
||||
if (!todoistSyncAPI) return false;
|
||||
|
|
@ -273,7 +257,8 @@ export class DatabaseChecker {
|
|||
try {
|
||||
const fileOperation = this.plugin.fileOperation;
|
||||
const todoistSyncAPI = this.plugin.todoistSyncAPI;
|
||||
if (!fileOperation || !todoistSyncAPI) {
|
||||
const taskParser = this.plugin.taskParser;
|
||||
if (!fileOperation || !todoistSyncAPI || !taskParser) {
|
||||
throw new Error('Required modules are not initialized for database check');
|
||||
}
|
||||
|
||||
|
|
@ -438,6 +423,11 @@ export class DatabaseChecker {
|
|||
unknownIssueCount: number,
|
||||
caseStats: NonNullable<DatabaseCheckResult['caseStats']>
|
||||
}> {
|
||||
const taskParser = this.plugin.taskParser;
|
||||
if (!taskParser) {
|
||||
throw new Error('TaskParser is not initialized for database comparison');
|
||||
}
|
||||
|
||||
const issues: DatabaseCheckIssue[] = [];
|
||||
const summary = {
|
||||
mappingFileNotFound: 0,
|
||||
|
|
@ -594,7 +584,7 @@ export class DatabaseChecker {
|
|||
|
||||
let hasSemanticMismatch = false;
|
||||
|
||||
if (vaultTask.content.trim() !== todoistTask.content.trim()) {
|
||||
if (!taskParser.taskContentCompare(vaultTask, todoistTask)) {
|
||||
emitIssue({
|
||||
type: 'sync_content_mismatch',
|
||||
filePath: vaultTask.filePath,
|
||||
|
|
@ -607,8 +597,8 @@ export class DatabaseChecker {
|
|||
hasSemanticMismatch = true;
|
||||
}
|
||||
|
||||
const todoistChecked = !!(todoistTask as unknown as { checked?: boolean }).checked;
|
||||
if (vaultTask.isCompleted !== todoistChecked) {
|
||||
const todoistChecked = !!todoistTask.checked;
|
||||
if (!taskParser.taskStatusCompare(vaultTask, todoistTask)) {
|
||||
emitIssue({
|
||||
type: 'sync_completion_mismatch',
|
||||
filePath: vaultTask.filePath,
|
||||
|
|
@ -623,7 +613,7 @@ export class DatabaseChecker {
|
|||
|
||||
const vaultDueDate = vaultTask.dueDate || '';
|
||||
const todoistDueDate = todoistTask.dueDate || '';
|
||||
if (vaultDueDate !== todoistDueDate) {
|
||||
if (!taskParser.compareTaskDueDate(vaultTask, todoistTask)) {
|
||||
emitIssue({
|
||||
type: 'sync_due_mismatch',
|
||||
filePath: vaultTask.filePath,
|
||||
|
|
@ -638,7 +628,7 @@ export class DatabaseChecker {
|
|||
|
||||
const vaultPriority = vaultTask.priority || 1;
|
||||
const todoistPriority = todoistTask.priority || 1;
|
||||
if (vaultPriority !== todoistPriority) {
|
||||
if (!taskParser.taskPriorityCompare(vaultTask, todoistTask)) {
|
||||
emitIssue({
|
||||
type: 'sync_priority_mismatch',
|
||||
filePath: vaultTask.filePath,
|
||||
|
|
@ -651,9 +641,9 @@ export class DatabaseChecker {
|
|||
hasSemanticMismatch = true;
|
||||
}
|
||||
|
||||
const obsidianLabels = this.normalizeLabels(vaultTask.labels);
|
||||
const todoistLabels = this.normalizeLabels(todoistTask.labels);
|
||||
if (!this.labelsEqual(obsidianLabels, todoistLabels)) {
|
||||
const obsidianLabels = taskParser.normalizeLabelsForCompare(vaultTask.labels);
|
||||
const todoistLabels = taskParser.normalizeLabelsForCompare(todoistTask.labels);
|
||||
if (!taskParser.taskTagCompare(vaultTask, todoistTask)) {
|
||||
emitIssue({
|
||||
type: 'sync_labels_mismatch',
|
||||
filePath: vaultTask.filePath,
|
||||
|
|
@ -668,7 +658,7 @@ export class DatabaseChecker {
|
|||
|
||||
const fileMetadata = this.plugin.settings.fileMetadata?.[vaultTask.filePath];
|
||||
const expectedProjectId = fileMetadata?.defaultProjectId;
|
||||
if (expectedProjectId && expectedProjectId !== todoistTask.projectId) {
|
||||
if (expectedProjectId && !(await taskParser.taskProjectCompare({ projectId: expectedProjectId }, todoistTask))) {
|
||||
emitIssue({
|
||||
type: 'sync_project_mismatch',
|
||||
filePath: vaultTask.filePath,
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ type LineTaskComparable = {
|
|||
isCompleted?: boolean;
|
||||
dueDate?: string;
|
||||
projectId?: string;
|
||||
priority?: number;
|
||||
};
|
||||
|
||||
type TodoistTaskComparable = {
|
||||
|
|
@ -59,7 +60,9 @@ type TodoistTaskComparable = {
|
|||
labels?: string[];
|
||||
checked?: boolean;
|
||||
due?: { date?: string };
|
||||
dueDate?: string;
|
||||
projectId?: string;
|
||||
priority?: number;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -356,10 +359,10 @@ export class TaskParser {
|
|||
|
||||
//task content compare
|
||||
taskContentCompare(lineTask:LineTaskComparable,todoistTask:TodoistTaskComparable) {
|
||||
const lineTaskContent = lineTask.content
|
||||
const lineTaskContent = (lineTask.content || '').trim();
|
||||
//this.plugin.debugLog(dataviewTaskContent)
|
||||
|
||||
const todoistTaskContent = todoistTask.content
|
||||
const todoistTaskContent = (todoistTask.content || '').trim();
|
||||
//this.plugin.debugLog(todoistTask.content)
|
||||
|
||||
//content 是否修改
|
||||
|
|
@ -368,29 +371,41 @@ export class TaskParser {
|
|||
}
|
||||
|
||||
|
||||
taskTagCompare(lineTask:Object,todoistTask:Object) {
|
||||
const lineTaskTags = (lineTask as any).labels || [];
|
||||
const todoistTaskTags = (todoistTask as any).labels || [];
|
||||
const sortedLine = [...lineTaskTags].sort();
|
||||
const sortedTodoist = [...todoistTaskTags].sort();
|
||||
return sortedLine.length === sortedTodoist.length && sortedLine.every((val: string, index: number) => val === sortedTodoist[index]);
|
||||
normalizeLabelsForCompare(labels: string[] | undefined): string[] {
|
||||
if (!labels || labels.length === 0) return [];
|
||||
const normalized = labels
|
||||
.map(label => (label ?? '').trim())
|
||||
.filter(label => label.length > 0);
|
||||
const deduped = Array.from(new Set(normalized));
|
||||
return deduped.sort();
|
||||
}
|
||||
|
||||
taskTagCompare(lineTask:LineTaskComparable,todoistTask:TodoistTaskComparable) {
|
||||
const lineTaskTags = this.normalizeLabelsForCompare(lineTask.labels || []);
|
||||
const todoistTaskTags = this.normalizeLabelsForCompare(todoistTask.labels || []);
|
||||
return lineTaskTags.length === todoistTaskTags.length && lineTaskTags.every((val: string, index: number) => val === todoistTaskTags[index]);
|
||||
}
|
||||
|
||||
taskStatusCompare(lineTask:Object,todoistTask:Object) {
|
||||
return (lineTask as any).isCompleted === !!(todoistTask as any).checked;
|
||||
taskStatusCompare(lineTask:LineTaskComparable,todoistTask:TodoistTaskComparable) {
|
||||
return !!lineTask.isCompleted === !!todoistTask.checked;
|
||||
}
|
||||
|
||||
|
||||
compareTaskDueDate(lineTask: object, todoistTask: object): boolean {
|
||||
const lineTaskDue = (lineTask as any).dueDate || "";
|
||||
const todoistDue = (todoistTask as any).due;
|
||||
const todoistDueDate = todoistDue?.date || "";
|
||||
compareTaskDueDate(lineTask: LineTaskComparable, todoistTask: TodoistTaskComparable): boolean {
|
||||
const lineTaskDue = lineTask.dueDate || "";
|
||||
const todoistDueDate = todoistTask.due?.date || todoistTask.dueDate || "";
|
||||
|
||||
if (lineTaskDue === "" && todoistDueDate === "") return true;
|
||||
if (lineTaskDue === "" || todoistDueDate === "") return false;
|
||||
|
||||
return lineTaskDue === todoistDueDate;
|
||||
}
|
||||
|
||||
taskPriorityCompare(lineTask:LineTaskComparable, todoistTask:TodoistTaskComparable): boolean {
|
||||
const linePriority = lineTask.priority || 1;
|
||||
const todoistPriority = todoistTask.priority || 1;
|
||||
return linePriority === todoistPriority;
|
||||
}
|
||||
|
||||
|
||||
//task project id compare
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ export class ObsidianToTodoistSync {
|
|||
const tagsModified = !this.plugin.taskParser.taskTagCompare(lineTask, savedTask);
|
||||
const statusModified = !this.plugin.taskParser.taskStatusCompare(lineTask, savedTask);
|
||||
const dueDateModified = !this.plugin.taskParser.compareTaskDueDate(lineTask, savedTask);
|
||||
const priorityModified = !(lineTask.priority === savedTask.priority);
|
||||
const priorityModified = !this.plugin.taskParser.taskPriorityCompare(lineTask, savedTask);
|
||||
|
||||
try {
|
||||
let contentChanged = false;
|
||||
|
|
|
|||
Loading…
Reference in a new issue