From 5ab0bdaa6917a8d9d658a597e68f83cc0a21697b Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Fri, 21 Jan 2022 13:53:24 +0100 Subject: [PATCH] #233 - Partial dashboard update on file change --- src/listeners/PagesListener.ts | 168 ++++++++++++++++++++------------- 1 file changed, 104 insertions(+), 64 deletions(-) diff --git a/src/listeners/PagesListener.ts b/src/listeners/PagesListener.ts index 94e71b07..f77ddc85 100644 --- a/src/listeners/PagesListener.ts +++ b/src/listeners/PagesListener.ts @@ -1,6 +1,6 @@ import { isValidFile } from './../helpers/isValidFile'; import { existsSync } from "fs"; -import { dirname, join } from "path"; +import { basename, dirname, join } from "path"; import { commands, FileSystemWatcher, RelativePattern, Uri, workspace } from "vscode"; import { Dashboard } from "../commands/Dashboard"; import { Folders } from "../commands/Folders"; @@ -8,7 +8,7 @@ import { COMMAND_NAME, DefaultFields, SETTINGS_CONTENT_STATIC_FOLDER, SETTING_DA import { DashboardCommand } from "../dashboardWebView/DashboardCommand"; import { DashboardMessage } from "../dashboardWebView/DashboardMessage"; import { Page } from "../dashboardWebView/models"; -import { ArticleHelper, Settings } from "../helpers"; +import { ArticleHelper, Logger, Settings } from "../helpers"; import { ContentType } from "../helpers/ContentType"; import { DateHelper } from "../helpers/DateHelper"; import { Notifications } from "../helpers/Notifications"; @@ -17,6 +17,7 @@ import { BaseListener } from "./BaseListener"; export class PagesListener extends BaseListener { private static watchers: { [path: string]: FileSystemWatcher } = {}; + private static lastPages: Page[] = []; /** * Start watching the folders in the current workspace for content changes @@ -39,9 +40,10 @@ export class PagesListener extends BaseListener { // Recreate all the watchers for (const folder of folders) { const folderUri = Uri.parse(folder.path); - let watcher = workspace.createFileSystemWatcher(new RelativePattern(folderUri, "*")); - watcher.onDidCreate(async (uri: Uri) => this.getPagesData); - watcher.onDidDelete(async (uri: Uri) => this.getPagesData); + let watcher = workspace.createFileSystemWatcher(new RelativePattern(folderUri, "*"), false, false, false); + watcher.onDidCreate(async (uri: Uri) => this.watcherExec(uri)); + watcher.onDidChange(async (uri: Uri) => this.watcherExec(uri)); + watcher.onDidDelete(async (uri: Uri) => this.watcherExec(uri)); this.watchers[folderUri.fsPath] = watcher; } } @@ -69,16 +71,29 @@ export class PagesListener extends BaseListener { } } + private static async watcherExec(file: Uri) { + if (Dashboard.isOpen) { + Logger.info(`File watcher execution for: ${file.fsPath}`) + + const pageIdx = this.lastPages.findIndex(p => p.fmFilePath === file.fsPath); + if (pageIdx !== -1) { + const stats = await workspace.fs.stat(file); + const crntPage = this.lastPages[pageIdx]; + const updatedPage = this.processPageContent(file.fsPath, stats.mtime, basename(file.fsPath), crntPage.fmFolder); + if (updatedPage) { + this.lastPages[pageIdx] = updatedPage; + this.sendMsg(DashboardCommand.pages, this.lastPages); + } + } else { + this.getPagesData(); + } + } + } + /** * Retrieve all the markdown pages */ private static async getPagesData() { - const wsFolder = Folders.getWorkspaceFolder(); - - const descriptionField = Settings.get(SETTING_SEO_DESCRIPTION_FIELD) as string || DefaultFields.Description; - const dateField = Settings.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate; - const staticFolder = Settings.get(SETTINGS_CONTENT_STATIC_FOLDER); - const folderInfo = await Folders.getInfo(); const pages: Page[] = []; @@ -87,62 +102,12 @@ export class PagesListener extends BaseListener { for (const file of folder.lastModified) { if (isValidFile(file.fileName)) { try { - const article = ArticleHelper.getFrontMatterByPath(file.filePath); + const page = this.processPageContent(file.filePath, file.mtime, file.fileName, folder.title); - if (article?.data.title) { - const page: Page = { - ...article.data, - // FrontMatter properties - fmFolder: folder.title, - fmModified: file.mtime, - fmFilePath: file.filePath, - fmFileName: file.fileName, - fmDraft: ContentType.getDraftStatus(article?.data), - fmYear: article?.data[dateField] ? DateHelper.tryParse(article?.data[dateField])?.getFullYear() : null, - // Make sure these are always set - title: article?.data.title, - slug: article?.data.slug, - date: article?.data[dateField] || "", - draft: article?.data.draft, - description: article?.data[descriptionField] || "", - }; - - const contentType = ArticleHelper.getContentType(article.data); - const previewField = contentType.fields.find(field => field.isPreviewImage && field.type === "image")?.name || "preview"; - - if (article?.data[previewField] && wsFolder) { - let fieldValue = article?.data[previewField]; - if (fieldValue && Array.isArray(fieldValue)) { - if (fieldValue.length > 0) { - fieldValue = fieldValue[0]; - } else { - fieldValue = undefined; - } - } - - // Revalidate as the array could have been empty - if (fieldValue) { - const staticPath = join(wsFolder.fsPath, staticFolder || "", fieldValue); - const contentFolderPath = join(dirname(file.filePath), fieldValue); - - let previewUri = null; - if (existsSync(staticPath)) { - previewUri = Uri.file(staticPath); - } else if (existsSync(contentFolderPath)) { - previewUri = Uri.file(contentFolderPath); - } - - if (previewUri) { - const preview = Dashboard.getWebview()?.asWebviewUri(previewUri); - page[previewField] = preview?.toString() || ""; - } else { - page[previewField] = ""; - } - } - } - + if (page) { pages.push(page); } + } catch (error: any) { Notifications.error(`File error: ${file.filePath} - ${error?.message || error}`); } @@ -151,10 +116,85 @@ export class PagesListener extends BaseListener { } } + this.lastPages = pages; this.sendMsg(DashboardCommand.pages, pages); } public static refresh() { this.getPagesData(); } + + /** + * Process the page content + * @param filePath + * @param fileMtime + * @param fileName + * @param folderTitle + * @returns + */ + private static processPageContent(filePath: string, fileMtime: number, fileName: string, folderTitle: string): Page | undefined { + const article = ArticleHelper.getFrontMatterByPath(filePath); + + if (article?.data.title) { + const wsFolder = Folders.getWorkspaceFolder(); + const descriptionField = Settings.get(SETTING_SEO_DESCRIPTION_FIELD) as string || DefaultFields.Description; + const dateField = Settings.get(SETTING_DATE_FIELD) as string || DefaultFields.PublishingDate; + const staticFolder = Settings.get(SETTINGS_CONTENT_STATIC_FOLDER); + + const page: Page = { + ...article.data, + // FrontMatter properties + fmFolder: folderTitle, + fmModified: fileMtime, + fmFilePath: filePath, + fmFileName: fileName, + fmDraft: ContentType.getDraftStatus(article?.data), + fmYear: article?.data[dateField] ? DateHelper.tryParse(article?.data[dateField])?.getFullYear() : null, + // Make sure these are always set + title: article?.data.title, + slug: article?.data.slug, + date: article?.data[dateField] || "", + draft: article?.data.draft, + description: article?.data[descriptionField] || "", + }; + + const contentType = ArticleHelper.getContentType(article.data); + const previewField = contentType.fields.find(field => field.isPreviewImage && field.type === "image")?.name || "preview"; + + if (article?.data[previewField] && wsFolder) { + let fieldValue = article?.data[previewField]; + if (fieldValue && Array.isArray(fieldValue)) { + if (fieldValue.length > 0) { + fieldValue = fieldValue[0]; + } else { + fieldValue = undefined; + } + } + + // Revalidate as the array could have been empty + if (fieldValue) { + const staticPath = join(wsFolder.fsPath, staticFolder || "", fieldValue); + const contentFolderPath = join(dirname(filePath), fieldValue); + + let previewUri = null; + if (existsSync(staticPath)) { + previewUri = Uri.file(staticPath); + } else if (existsSync(contentFolderPath)) { + previewUri = Uri.file(contentFolderPath); + } + + if (previewUri) { + const preview = Dashboard.getWebview()?.asWebviewUri(previewUri); + page[previewField] = preview?.toString() || ""; + } else { + page[previewField] = ""; + } + } + } + + return page; + } + + return; + } } \ No newline at end of file