From c751add5fee379ae5cc5143be3afb988ae8c6df6 Mon Sep 17 00:00:00 2001 From: Grol Grol Date: Fri, 11 Apr 2025 18:42:49 +0300 Subject: [PATCH] ref events. add delete action. optimize loadAndSyncActiveFiles --- src/FileStateHolder.ts | 5 +++ src/events/FileChangeEventHandler.ts | 15 ++++++- src/events/FileLoadEventHandler.ts | 60 +++++++++++++++++++--------- src/main.ts | 2 +- 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/src/FileStateHolder.ts b/src/FileStateHolder.ts index a488d11..1ccd252 100644 --- a/src/FileStateHolder.ts +++ b/src/FileStateHolder.ts @@ -58,4 +58,9 @@ export default class FileStateHolder { const keysArray = Array.from(keysIterator); return keysArray; } + + delete(file: TFile): boolean { + const existed = this.map.delete(file); + return existed; + } } \ No newline at end of file diff --git a/src/events/FileChangeEventHandler.ts b/src/events/FileChangeEventHandler.ts index 65622f7..93cb5e3 100644 --- a/src/events/FileChangeEventHandler.ts +++ b/src/events/FileChangeEventHandler.ts @@ -1,4 +1,5 @@ -import { App, TFile } from "obsidian"; +import { App, TAbstractFile, TFile } from "obsidian"; +import FileStateHolder from "src/FileStateHolder"; import CheckboxSyncPlugin from "src/main"; import SyncController from "src/SyncController"; @@ -6,11 +7,13 @@ export class FileChangeEventHandler { private plugin: CheckboxSyncPlugin; private app: App; private syncController: SyncController; + private fileStateHolder: FileStateHolder; - constructor(plugin: CheckboxSyncPlugin, app: App, syncController: SyncController) { + constructor(plugin: CheckboxSyncPlugin, app: App, syncController: SyncController, fileStateHolder: FileStateHolder) { this.plugin = plugin; this.app = app; this.syncController = syncController; + this.fileStateHolder = fileStateHolder; } registerEvents() { @@ -30,5 +33,13 @@ export class FileChangeEventHandler { await this.syncController.syncEditor(editor, info); }) ); + + this.plugin.registerEvent( + this.app.vault.on("delete", (file: TAbstractFile) => { + if (file instanceof TFile && file.extension === "md") { + this.fileStateHolder.delete(file); + } + }) + ); } } \ No newline at end of file diff --git a/src/events/FileLoadEventHandler.ts b/src/events/FileLoadEventHandler.ts index 947cf24..d7f44f6 100644 --- a/src/events/FileLoadEventHandler.ts +++ b/src/events/FileLoadEventHandler.ts @@ -64,30 +64,54 @@ export class FileLoadEventHandler { //загрузка в кеш и синхронизация открытых файлов async loadAndSyncActiveFiles() { const markdownLeaves = this.app.workspace.getLeavesOfType('markdown'); - await Promise.all(markdownLeaves.map(async (leaf) => await this.loadAndSyncActiveFile(leaf))); + await Promise.all(markdownLeaves.map(async (leaf) => await this.initializeStateForLeaf(leaf))); } - private async loadAndSyncActiveFile(leaf: WorkspaceLeaf) { + private async initializeStateForLeaf(leaf: WorkspaceLeaf) { const view = leaf.view as MarkdownView; if (!view.file) return; - //вызов ререндера, для кеширования через MarkdownPostProcessor - await this.rerenderView(view); - } - // вызывает рендеринг view - private async rerenderView(view: MarkdownView) { - if (!view.file) return; + const file = view.file; + console.log(`Initializing state for active file and its embeds: ${file.path}`); - if (view.getMode() === 'preview') { - view.previewMode.rerender(); - } else { - await MarkdownRenderer.render( - this.plugin.app, - view.editor.getValue(), - document.createElement('div'), - view.file.path, - this.plugin - ); + const filesToInitialize: Set = new Set([file]); + await this.findEmbedsRecursive(file, filesToInitialize); + + for (const fileToInit of filesToInitialize) { + try { + const isUpdateNeeded = await this.fileStateHolder.initIfNeeded(fileToInit); + // Синхронизируем только если инициализация это потребовала, + // ИЛИ если это основной файл, открытый в редакторе (на всякий случай) + if (isUpdateNeeded || (fileToInit === file && view.getMode() === 'source')) { + // Если основной файл в редакторе, лучше вызвать syncEditor для него + if (fileToInit === file && view.getMode() === 'source') { + await this.syncController.syncEditor(view.editor, view); + } else { + await this.syncController.syncFile(fileToInit); + } + } + } catch (error) { + console.error(`Error processing file ${fileToInit.path} during initial load:`, error); + } } } + + // Вспомогательная рекурсивная функция для поиска всех вложенных embeds + private async findEmbedsRecursive(file: TFile, visited: Set) { + const cache = this.app.metadataCache.getFileCache(file); + if (!cache?.embeds) return; + + for (const embed of cache.embeds) { + const embedFile = this.app.metadataCache.getFirstLinkpathDest(embed.link, file.path); + if (!embedFile) continue; + + if (embedFile instanceof TFile && embedFile.extension === 'md') { + // Если файл еще не посещали, добавляем и ищем его внедрения + if (!visited.has(embedFile)) { + visited.add(embedFile); + await this.findEmbedsRecursive(embedFile, visited); + } + } + } +} } \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 1f706ee..7a0afc5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -27,7 +27,7 @@ export default class CheckboxSyncPlugin extends Plugin { this.checkboxUtils = new CheckboxUtils(this.settings); this.syncController = new SyncController(this.app.vault, this.checkboxUtils, this.fileStateHolder); this.fileLoadEventHandler = new FileLoadEventHandler(this, this.app, this.syncController, this.fileStateHolder); - this.fileChangeEventHandler = new FileChangeEventHandler(this, this.app, this.syncController); + this.fileChangeEventHandler = new FileChangeEventHandler(this, this.app, this.syncController, this.fileStateHolder); this.addSettingTab(new CheckboxSyncPluginSettingTab(this.app, this)); this.fileLoadEventHandler.registerEvents();