feat: persistent recent files history + fix limit enforcement + fix settings data loss
- Recent files are now persisted to disk and survive restarts - Max items limit is applied on load (in case setting was reduced) - Omitted paths regex filtering is now wired up in addToRecentFiles - Fixed saveAndRefresh() overwriting entire plugin data on settings change - Debounced disk writes (300ms) to avoid excessive saves on rapid opens
This commit is contained in:
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "waypoint-sidebar",
|
"id": "waypoint-sidebar",
|
||||||
"name": "Waypoint Sidebar",
|
"name": "Waypoint Sidebar",
|
||||||
"version": "1.3.0",
|
"version": "1.4.0",
|
||||||
"minAppVersion": "0.16.3",
|
"minAppVersion": "0.16.3",
|
||||||
"description": "Calendar, recent files, and custom bookmarks sidebar.",
|
"description": "Calendar, recent files, and custom bookmarks sidebar.",
|
||||||
"author": "Olivier",
|
"author": "Olivier",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "waypoint",
|
"name": "waypoint",
|
||||||
"version": "1.3.0",
|
"version": "1.4.0",
|
||||||
"description": "Calendar, recent files, and custom bookmarks sidebar.",
|
"description": "Calendar, recent files, and custom bookmarks sidebar.",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
+38
-1
@@ -16,12 +16,14 @@ import { BookmarkItem, WaypointData } from 'src/models/bookmark';
|
|||||||
|
|
||||||
const DEFAULT_DATA: WaypointData = {
|
const DEFAULT_DATA: WaypointData = {
|
||||||
bookmarks: [],
|
bookmarks: [],
|
||||||
|
recentFiles: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class WaypointPlugin extends Plugin {
|
export default class WaypointPlugin extends Plugin {
|
||||||
public settings: WaypointSettings;
|
public settings: WaypointSettings;
|
||||||
public waypointData: WaypointData;
|
public waypointData: WaypointData;
|
||||||
public recentFiles: { path: string; basename: string }[] = [];
|
public recentFiles: { path: string; basename: string }[] = [];
|
||||||
|
private recentFilesSaveTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
async onload(): Promise<void> {
|
async onload(): Promise<void> {
|
||||||
console.debug('Waypoint: loading plugin v' + this.manifest.version);
|
console.debug('Waypoint: loading plugin v' + this.manifest.version);
|
||||||
@@ -206,14 +208,36 @@ export default class WaypointPlugin extends Plugin {
|
|||||||
const saved = await this.loadData() as Record<string, unknown> | null;
|
const saved = await this.loadData() as Record<string, unknown> | null;
|
||||||
const d = (saved?.waypointData || {}) as Partial<WaypointData>;
|
const d = (saved?.waypointData || {}) as Partial<WaypointData>;
|
||||||
this.waypointData = Object.assign({}, DEFAULT_DATA, d);
|
this.waypointData = Object.assign({}, DEFAULT_DATA, d);
|
||||||
|
|
||||||
|
// Load persisted recent files
|
||||||
|
this.recentFiles = this.waypointData.recentFiles || [];
|
||||||
|
|
||||||
|
// Apply current limit (in case maxItems was reduced since last save)
|
||||||
|
if (this.recentFiles.length > this.settings.recentFiles.maxItems) {
|
||||||
|
this.recentFiles = this.recentFiles.slice(0, this.settings.recentFiles.maxItems);
|
||||||
|
this.waypointData.recentFiles = this.recentFiles;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveWaypointData(): Promise<void> {
|
async saveWaypointData(): Promise<void> {
|
||||||
|
// Sync recentFiles into waypointData before saving
|
||||||
|
this.waypointData.recentFiles = this.recentFiles;
|
||||||
const all = (await this.loadData()) as Record<string, unknown> || {};
|
const all = (await this.loadData()) as Record<string, unknown> || {};
|
||||||
all.waypointData = this.waypointData;
|
all.waypointData = this.waypointData;
|
||||||
await this.saveData(all);
|
await this.saveData(all);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persist recent files to disk (debounced to avoid excessive writes on rapid opens).
|
||||||
|
*/
|
||||||
|
persistRecentFiles(): void {
|
||||||
|
this.waypointData.recentFiles = this.recentFiles;
|
||||||
|
if (this.recentFilesSaveTimer) clearTimeout(this.recentFilesSaveTimer);
|
||||||
|
this.recentFilesSaveTimer = setTimeout(() => {
|
||||||
|
this.saveWaypointData();
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Recent Files ──
|
// ── Recent Files ──
|
||||||
|
|
||||||
private onFileOpen(file: TFile): void {
|
private onFileOpen(file: TFile): void {
|
||||||
@@ -225,14 +249,26 @@ export default class WaypointPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addToRecentFiles(file: TFile): void {
|
addToRecentFiles(file: TFile): void {
|
||||||
|
// Apply omitted paths filter
|
||||||
|
if (this.settings.recentFiles.omittedPaths.length > 0) {
|
||||||
|
for (const pattern of this.settings.recentFiles.omittedPaths) {
|
||||||
|
try {
|
||||||
|
if (new RegExp(pattern).test(file.path)) return;
|
||||||
|
} catch {
|
||||||
|
// Invalid regex, skip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.recentFiles = this.recentFiles.filter(f => f.path !== file.path);
|
this.recentFiles = this.recentFiles.filter(f => f.path !== file.path);
|
||||||
this.recentFiles.unshift({ path: file.path, basename: file.basename });
|
this.recentFiles.unshift({ path: file.path, basename: file.basename });
|
||||||
|
|
||||||
// Prune
|
// Apply max items limit
|
||||||
if (this.recentFiles.length > this.settings.recentFiles.maxItems) {
|
if (this.recentFiles.length > this.settings.recentFiles.maxItems) {
|
||||||
this.recentFiles = this.recentFiles.slice(0, this.settings.recentFiles.maxItems);
|
this.recentFiles = this.recentFiles.slice(0, this.settings.recentFiles.maxItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.persistRecentFiles();
|
||||||
this.broadcastRedraw();
|
this.broadcastRedraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,6 +277,7 @@ export default class WaypointPlugin extends Plugin {
|
|||||||
if (entry) {
|
if (entry) {
|
||||||
entry.path = file.path;
|
entry.path = file.path;
|
||||||
entry.basename = (file as TFile).basename || file.name.replace(/\.[^/.]+$/, '');
|
entry.basename = (file as TFile).basename || file.name.replace(/\.[^/.]+$/, '');
|
||||||
|
this.persistRecentFiles();
|
||||||
this.broadcastRedraw();
|
this.broadcastRedraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ export interface BookmarkItem {
|
|||||||
|
|
||||||
export interface WaypointData {
|
export interface WaypointData {
|
||||||
bookmarks: BookmarkItem[];
|
bookmarks: BookmarkItem[];
|
||||||
|
recentFiles: { path: string; basename: string }[];
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -294,7 +294,7 @@ export class WaypointSettingTab extends PluginSettingTab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async saveAndRefresh(): Promise<void> {
|
private async saveAndRefresh(): Promise<void> {
|
||||||
await this.plugin.saveData(this.settings);
|
await (this.plugin as any).saveSettings();
|
||||||
this.onSettingsChange();
|
this.onSettingsChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -304,7 +304,7 @@ export class WaypointView extends ItemView {
|
|||||||
removeBtn.addEventListener('click', (e) => {
|
removeBtn.addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
this.plugin.recentFiles = this.plugin.recentFiles.filter(f => f.path !== file.path);
|
this.plugin.recentFiles = this.plugin.recentFiles.filter(f => f.path !== file.path);
|
||||||
this.plugin.saveSettings();
|
this.plugin.persistRecentFiles();
|
||||||
this.redraw();
|
this.redraw();
|
||||||
});
|
});
|
||||||
setTooltip(navFile, file.path);
|
setTooltip(navFile, file.path);
|
||||||
@@ -384,7 +384,7 @@ export class WaypointView extends ItemView {
|
|||||||
} else {
|
} else {
|
||||||
new Notice('Cannot find file');
|
new Notice('Cannot find file');
|
||||||
this.plugin.recentFiles = this.plugin.recentFiles.filter(f => f.path !== file.path);
|
this.plugin.recentFiles = this.plugin.recentFiles.filter(f => f.path !== file.path);
|
||||||
this.plugin.saveSettings();
|
this.plugin.persistRecentFiles();
|
||||||
this.redraw();
|
this.redraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user