| 39 | * - Keep index updates field-aware so ordinary note edits do not invalidate filter work |
| 40 | */ |
| 41 | export class TaskManager extends Events { |
| 42 | private app: App; |
| 43 | private settings: TaskNotesSettings; |
| 44 | private taskTag: string; |
| 45 | private excludedFolders: string[]; |
| 46 | private fieldMapper?: FieldMapper; |
| 47 | private disableNoteIndexing: boolean; |
| 48 | private storeTitleInFilename: boolean; |
| 49 | |
| 50 | // Initialization state |
| 51 | private initialized = false; |
| 52 | |
| 53 | // Event listeners for cleanup |
| 54 | private eventListeners: EventRef[] = []; |
| 55 | |
| 56 | // Debouncing for file changes to prevent excessive updates during typing |
| 57 | private debouncedHandlers: Map<string, number> = new Map(); |
| 58 | private readonly DEBOUNCE_DELAY = 300; // 300ms delay after user stops typing |
| 59 | |
| 60 | // Write-through fallback for files TaskNotes just wrote before Obsidian metadata is ready. |
| 61 | private pendingTaskInfoByPath = new Map<string, TaskInfo>(); |
| 62 | |
| 63 | // Filter/query indexes, built lazily and maintained incrementally after first use. |
| 64 | private filterIndexesBuilt = false; |
| 65 | private indexedTaskPaths: Set<string> = new Set(); |
| 66 | private taskFilterEntries: Map<string, TaskFilterIndexEntry> = new Map(); |
| 67 | private statusIndex: Map<string, Set<string>> = new Map(); |
| 68 | private priorityIndex: Map<string, Set<string>> = new Map(); |
| 69 | private dueDateIndex: Map<string, Set<string>> = new Map(); |
| 70 | private scheduledDateIndex: Map<string, Set<string>> = new Map(); |
| 71 | private tagCounts: Map<string, number> = new Map(); |
| 72 | private contextCounts: Map<string, number> = new Map(); |
| 73 | private projectCounts: Map<string, number> = new Map(); |
| 74 | |
| 75 | constructor(app: App, settings: TaskNotesSettings, fieldMapper?: FieldMapper) { |
| 76 | super(); |
| 77 | this.app = app; |
| 78 | this.settings = settings; |
| 79 | this.taskTag = settings.taskTag; |
| 80 | this.excludedFolders = parseExcludedFolders(settings.excludedFolders); |
| 81 | this.fieldMapper = fieldMapper; |
| 82 | this.disableNoteIndexing = settings.disableNoteIndexing; |
| 83 | this.storeTitleInFilename = settings.storeTitleInFilename; |
| 84 | } |
| 85 | |
| 86 | /** |
| 87 | * Initialize by setting up native event listeners |
| 88 | */ |
| 89 | initialize(): void { |
| 90 | if (this.initialized) { |
| 91 | return; |
| 92 | } |
| 93 | |
| 94 | this.setupNativeEventListeners(); |
| 95 | this.initialized = true; |
| 96 | this.trigger("cache-initialized", { message: "Task manager ready" }); |
| 97 | } |
| 98 |
nothing calls this directly
no outgoing calls
no test coverage detected