#233 - Partial dashboard update on file change

This commit is contained in:
Elio Struyf
2022-01-21 13:53:24 +01:00
parent 1c74df0266
commit 5ab0bdaa69
+104 -64
View File
@@ -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<string>(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<string>(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;
}
}