mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-07 09:23:00 +02:00
#178 - macOS and Linux support for date retrieval
This commit is contained in:
+36
-13
@@ -4,7 +4,7 @@ import { basename, dirname, extname, join, parse } from "path";
|
||||
import { existsSync, readdirSync, statSync, unlinkSync, writeFileSync } from "fs";
|
||||
import { commands, Uri, ViewColumn, Webview, WebviewPanel, window, workspace, env, Position } from "vscode";
|
||||
import { Settings as SettingsHelper } from '../helpers';
|
||||
import { DraftField, Framework, SortingSetting, SortOrder, TaxonomyType } from '../models';
|
||||
import { DraftField, Framework, SortingSetting, SortOrder, SortType, TaxonomyType } from '../models';
|
||||
import { Folders } from './Folders';
|
||||
import { DashboardCommand } from '../dashboardWebView/DashboardCommand';
|
||||
import { DashboardMessage } from '../dashboardWebView/DashboardMessage';
|
||||
@@ -27,6 +27,7 @@ import { DateHelper } from '../helpers/DateHelper';
|
||||
import { FrameworkDetector } from '../helpers/FrameworkDetector';
|
||||
import { ContentType } from '../helpers/ContentType';
|
||||
import { SortingOption } from '../dashboardWebView/models';
|
||||
import { Sorting } from '../helpers/Sorting';
|
||||
|
||||
export class Dashboard {
|
||||
private static webview: WebviewPanel | null = null;
|
||||
@@ -384,13 +385,16 @@ export class Dashboard {
|
||||
|
||||
if (relSelectedFolderPath) {
|
||||
const files = await workspace.findFiles(join(relSelectedFolderPath, '/*'));
|
||||
const media = Dashboard.filterMedia(files);
|
||||
const media = await Dashboard.updateMediaData(selectedFolder, Dashboard.filterMedia(files));
|
||||
|
||||
allMedia = [...media];
|
||||
} else {
|
||||
if (staticFolder) {
|
||||
const folderSearch = join(staticFolder || "", '/*');
|
||||
const absFolderSearch = join(wsFolder?.fsPath || "", folderSearch);
|
||||
|
||||
const files = await workspace.findFiles(folderSearch);
|
||||
const media = Dashboard.filterMedia(files);
|
||||
const media = await Dashboard.updateMediaData(absFolderSearch, Dashboard.filterMedia(files));
|
||||
|
||||
allMedia = [...media];
|
||||
}
|
||||
@@ -401,22 +405,20 @@ export class Dashboard {
|
||||
const relFolderPath = contentFolder.path.substring(wsFolder.fsPath.length + 1);
|
||||
const folderSearch = relSelectedFolderPath ? join(relSelectedFolderPath, '/*') : join(relFolderPath, '/*');
|
||||
const files = await workspace.findFiles(folderSearch);
|
||||
const media = Dashboard.filterMedia(files);
|
||||
const media = await Dashboard.updateMediaData(join(wsFolder.fsPath || "", folderSearch), Dashboard.filterMedia(files));
|
||||
|
||||
allMedia = [...allMedia, ...media];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
allMedia = allMedia.sort((a, b) => {
|
||||
if (a.fsPath.toLowerCase() < b.fsPath.toLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.fsPath.toLowerCase() > b.fsPath.toLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
if (crntSort?.type === SortType.string) {
|
||||
allMedia = allMedia.sort(Sorting.alphabetically("fsPath"));
|
||||
} else if (crntSort?.type === SortType.date) {
|
||||
allMedia = allMedia.sort(Sorting.date("modified"));
|
||||
} else {
|
||||
allMedia = allMedia.sort(Sorting.alphabetically("fsPath"));
|
||||
}
|
||||
|
||||
if (crntSort?.order === SortOrder.desc) {
|
||||
allMedia = allMedia.reverse();
|
||||
@@ -499,6 +501,27 @@ export class Dashboard {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the metadata of the retrieved files
|
||||
* @param folder
|
||||
* @param files
|
||||
*/
|
||||
private static async updateMediaData(folder: string, files: MediaInfo[]) {
|
||||
const fileMetadata = await MediaLibrary.getMetadata(folder);
|
||||
|
||||
if (fileMetadata && fileMetadata.length > 0) {
|
||||
files = files.map((m: MediaInfo) => {
|
||||
const metadata = fileMetadata.find((f) => m.fsPath.endsWith(f.fileName));
|
||||
if (metadata) {
|
||||
m.modified = metadata.date;
|
||||
}
|
||||
return m;
|
||||
});
|
||||
}
|
||||
|
||||
return Object.assign([], files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all the markdown pages
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,8 @@ export interface ISortingProps {
|
||||
}
|
||||
|
||||
export const sortOptions: SortingOption[] = [
|
||||
{ name: "Last modified", id: SortOption.LastModified, order: SortOrder.desc, type: SortType.string },
|
||||
{ name: "Last modified (asc)", id: SortOption.LastModifiedAsc, order: SortOrder.asc, type: SortType.date },
|
||||
{ name: "Last modified (desc)", id: SortOption.LastModifiedDesc, order: SortOrder.desc, type: SortType.date },
|
||||
{ name: "By filename (asc)", id: SortOption.FileNameAsc, order: SortOrder.asc, type: SortType.string },
|
||||
{ name: "By filename (desc)", id: SortOption.FileNameDesc, order: SortOrder.desc, type: SortType.string },
|
||||
];
|
||||
@@ -36,7 +37,7 @@ export const Sorting: React.FunctionComponent<ISortingProps> = ({disableCustomSo
|
||||
setCrntSorting(value)
|
||||
};
|
||||
|
||||
let allOptions = view === ViewType.Contents ? [...sortOptions] : [...sortOptions.slice(1)];
|
||||
let allOptions = [...sortOptions];
|
||||
if (settings?.customSorting && !disableCustomSorting) {
|
||||
allOptions = [...allOptions, ...settings.customSorting.map((s) => ({
|
||||
title: s.title || s.name,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export enum SortOption {
|
||||
LastModified = "LastModified",
|
||||
LastModifiedAsc = "LastModifiedAsc",
|
||||
LastModifiedDesc = "LastModifiedDesc",
|
||||
FileNameAsc = "FileNameAsc",
|
||||
FileNameDesc = "FileNameDesc"
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import Fuse from 'fuse.js';
|
||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||
import { CategorySelector, FolderSelector, SearchSelector, SettingsSelector, SortingAtom, TabSelector, TagSelector } from '../state';
|
||||
import { SortOrder, SortType } from '../../models';
|
||||
import { DateHelper } from '../../helpers/DateHelper';
|
||||
import { Sorting } from '../../helpers/Sorting';
|
||||
|
||||
const fuseOptions: Fuse.IFuseOptions<Page> = {
|
||||
keys: [
|
||||
@@ -26,29 +26,6 @@ export default function usePages(pages: Page[]) {
|
||||
const tag = useRecoilValue(TagSelector);
|
||||
const category = useRecoilValue(CategorySelector);
|
||||
|
||||
// Sort field value alphabetically
|
||||
const sortAlphabetically = (property: string) => {
|
||||
return (a: Page, b: Page) => {
|
||||
if (a[property] < b[property]) {
|
||||
return -1;
|
||||
}
|
||||
if (a[property] > b[property]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
};
|
||||
|
||||
// Sort by date
|
||||
const sortByDate = (property: string) => {
|
||||
return (a: Page, b: Page) => {
|
||||
const dateA = DateHelper.tryParse(a[property]);
|
||||
const dateB = DateHelper.tryParse(b[property]);
|
||||
|
||||
return (dateA || new Date(0)).getTime() - (dateB || new Date(0)).getTime();
|
||||
};
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const draftField = settings?.draftField;
|
||||
let usedSorting = sorting;
|
||||
@@ -91,27 +68,30 @@ export default function usePages(pages: Page[]) {
|
||||
|
||||
// Sort the pages
|
||||
let pagesSorted: Page[] = Object.assign([], pagesToShow);
|
||||
debugger;
|
||||
if (!search) {
|
||||
if (sorting && sorting.id === SortOption.FileNameAsc) {
|
||||
pagesSorted = pagesSorted.sort(sortAlphabetically("fmFileName"));
|
||||
pagesSorted = pagesSorted.sort(Sorting.alphabetically("fmFileName"));
|
||||
} else if (sorting && sorting.id === SortOption.FileNameDesc) {
|
||||
pagesSorted = pagesSorted.sort(sortAlphabetically("fmFileName")).reverse();
|
||||
} else if (sorting && sorting.id === SortOption.LastModified) {
|
||||
pagesSorted = pagesSorted.sort((a, b) => b.fmModified - a.fmModified);
|
||||
pagesSorted = pagesSorted.sort(Sorting.alphabetically("fmFileName")).reverse();
|
||||
} else if (sorting && sorting.id === SortOption.LastModifiedAsc) {
|
||||
pagesSorted = pagesSorted.sort(Sorting.number("fmModified"));
|
||||
} else if (sorting && sorting.id === SortOption.LastModifiedDesc) {
|
||||
pagesSorted = pagesSorted.sort(Sorting.number("fmModified")).reverse();
|
||||
} else if (sorting && sorting.id && sorting.name) {
|
||||
const { order, name, type } = sorting;
|
||||
|
||||
if (type === SortType.string) {
|
||||
pagesSorted = pagesSorted.sort(sortAlphabetically(name));
|
||||
pagesSorted = pagesSorted.sort(Sorting.alphabetically(name));
|
||||
} else if (type === SortType.date) {
|
||||
pagesSorted = pagesSorted.sort(sortByDate(name));
|
||||
pagesSorted = pagesSorted.sort(Sorting.date(name));
|
||||
}
|
||||
|
||||
if (order === SortOrder.desc) {
|
||||
pagesSorted = pagesSorted.reverse();
|
||||
}
|
||||
} else {
|
||||
pagesSorted = pagesSorted.sort((a, b) => b.fmModified - a.fmModified);
|
||||
pagesSorted = pagesSorted.sort(Sorting.number("fmModified")).reverse();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { atom } from 'recoil';
|
||||
import { SortOption } from '../../constants/SortOption';
|
||||
import { SortingOption } from '../../models/SortingOption';
|
||||
|
||||
export const DEFAULT_SORTING_OPTION = SortOption.LastModified;
|
||||
export const DEFAULT_SORTING_OPTION = SortOption.LastModifiedDesc;
|
||||
|
||||
export const SortingAtom = atom<SortingOption | null>({
|
||||
key: 'SortingAtom',
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import * as os from 'os';
|
||||
import { DateHelper } from './DateHelper';
|
||||
import { Dashboard } from '../commands/Dashboard';
|
||||
import { workspace } from 'vscode';
|
||||
import { workspace, env as vscodeEnv } from 'vscode';
|
||||
import { JsonDB } from 'node-json-db/dist/JsonDB';
|
||||
import { basename, dirname, join, parse } from 'path';
|
||||
import { Folders, WORKSPACE_PLACEHOLDER } from '../commands/Folders';
|
||||
@@ -7,6 +9,7 @@ import { existsSync, renameSync } from 'fs';
|
||||
import { Notifications } from './Notifications';
|
||||
import { parseWinPath } from './parseWinPath';
|
||||
import { LocalStore } from '../constants';
|
||||
import { exec } from 'child_process';
|
||||
|
||||
interface MediaRecord {
|
||||
description: string;
|
||||
@@ -47,6 +50,54 @@ export class MediaLibrary {
|
||||
return MediaLibrary.instance;
|
||||
}
|
||||
|
||||
public static async getMetadata(path: string): Promise<{ date: Date, fileName: string }[] | null> {
|
||||
return new Promise((resolve) => {
|
||||
let command: string = "";
|
||||
|
||||
// Run bash scripts to retrieve metadata faster
|
||||
if (os.type() === "Darwin") {
|
||||
command = `for file in *; do
|
||||
fdate=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M" "$file")
|
||||
echo "$file,$fdate"
|
||||
done`;
|
||||
} else if (os.type() === "Windows_NT") {
|
||||
resolve(null);
|
||||
return;
|
||||
} else if (os.type() === "Linux" && vscodeEnv.remoteName?.toLowerCase() === "wsl") {
|
||||
command = `for file in *; do
|
||||
fdate=$(stat -c "%y" "$file")
|
||||
echo "$file,$fdate"
|
||||
done`;
|
||||
} else {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
exec(`cd ${path} && ${command}`, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const lines = stdout.split('\n');
|
||||
const metadata: any[] = [];
|
||||
|
||||
let lineData: any = {};
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
const parts = line.split(',');
|
||||
metadata.push({
|
||||
fileName: parts[0],
|
||||
date: DateHelper.tryParse(parts[1])
|
||||
});
|
||||
}
|
||||
|
||||
resolve(metadata);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public get(id: string): MediaRecord | undefined {
|
||||
try {
|
||||
const fileId = this.parsePath(id);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { DateHelper } from "./DateHelper";
|
||||
|
||||
|
||||
export class Sorting {
|
||||
|
||||
/**
|
||||
* Sort field value alphabetically
|
||||
* @param property
|
||||
* @returns
|
||||
*/
|
||||
public static alphabetically = (property: string) => {
|
||||
return (a: any, b: any) => {
|
||||
if (a[property] < b[property]) {
|
||||
return -1;
|
||||
}
|
||||
if (a[property] > b[property]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort by date
|
||||
* @param property
|
||||
* @returns
|
||||
*/
|
||||
public static date = (property: string) => {
|
||||
return (a: any, b: any) => {
|
||||
const dateA = DateHelper.tryParse(a[property]);
|
||||
const dateB = DateHelper.tryParse(b[property]);
|
||||
|
||||
return (dateA || new Date(0)).getTime() - (dateB || new Date(0)).getTime();
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort by number
|
||||
* @param property
|
||||
* @returns
|
||||
*/
|
||||
public static number = (property: string) => {
|
||||
return (a: any, b: any) => {
|
||||
return a[property] - b[property];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -15,4 +15,5 @@ export interface MediaInfo {
|
||||
dimensions: ISizeCalculationResult | undefined;
|
||||
caption?: string | undefined;
|
||||
alt?: string | undefined;
|
||||
modified?: Date | undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user