Skip to content

Commit fb85901

Browse files
committed
Add new functionality to allow users to onboard all notes in their vault (optionally skipping directories via provided list) to the Spaced Everything plugin
1 parent e644b6b commit fb85901

File tree

3 files changed

+119
-2
lines changed

3 files changed

+119
-2
lines changed

manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "spaced-everything",
33
"name": "Spaced everything",
4-
"version": "1.1.1",
4+
"version": "1.2.0",
55
"minAppVersion": "1.6.7",
66
"description": "Apply spaced repetition algorithms to everything in your vault.",
77
"author": "Zach Mueller",

src/main.ts

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const DEFAULT_SETTINGS: SpacedEverythingPluginSettings = {
3131
includeShortThoughtInAlias: true,
3232
shortCapturedThoughtThreshold: 200,
3333
openCapturedThoughtInNewTab: false,
34+
onboardingExcludedFolders: []
3435
}
3536

3637
export default class SpacedEverythingPlugin extends Plugin {

src/settings.ts

+117-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { App, Notice, PluginSettingTab, Setting, normalizePath } from 'obsidian';
1+
import { App, Notice, PluginSettingTab, Setting, normalizePath, Modal, TAbstractFile, TFile, TFolder } from 'obsidian';
22
import { Context, ReviewOption, SpacingMethod } from './types';
33
import SpacedEverythingPlugin from './main';
44

@@ -16,6 +16,7 @@ interface SpacedEverythingPluginSettings {
1616
includeShortThoughtInAlias: boolean;
1717
shortCapturedThoughtThreshold: number;
1818
openCapturedThoughtInNewTab: boolean;
19+
onboardingExcludedFolders: string[];
1920
}
2021

2122
export type { SpacedEverythingPluginSettings };
@@ -262,8 +263,81 @@ export class SpacedEverythingSettingTab extends PluginSettingTab {
262263
await this.plugin.saveSettings();
263264
})
264265
);
266+
267+
268+
// Onboard all notes
269+
new Setting(containerEl).setName('Onboard all notes (beta)')
270+
.setHeading()
271+
.setDesc('This provides an optional means of onboarding every note in your vault to the Spaced Everything system. Importantly, the plugin uses frontmatter properties on notes to track relevant metadata to perform the spacing algorithm actions. So it is recommended to use the "Excluded folders" setting below to filter out subsets of notes that you wish to avoid onboarding. Performing this action will not change any existing Spaced Everything frontmatter if you already have some notes oboarded.\n\nThis is still a beta feature. Currently, it asusmes to only apply the settings from the first Spacing Method (defined above) and assumes to not set any context for notes onboarded in this manner.');
272+
273+
new Setting(containerEl)
274+
.setName('Excluded folders')
275+
.setDesc('Enter the paths of any folders you want to exclude from the onboarding process (one per line). Consider adding folders that contain things like templates or scripts that may not work if frontmatter properties are added to them.')
276+
.addTextArea((textArea) => {
277+
textArea.setValue(this.plugin.settings.onboardingExcludedFolders.join('\n')).onChange(async (value) => {
278+
this.plugin.settings.onboardingExcludedFolders = value.trim().split('\n').filter((v) => v);
279+
await this.plugin.saveSettings();
280+
});
281+
});
282+
283+
new Setting(containerEl)
284+
.setName('Onboard all notes')
285+
.setDesc('Click the button to add the required frontmatter properties to all notes in your vault, excluding the folders specified above.')
286+
.addButton((button) =>
287+
button
288+
.setButtonText('Onboard all notes')
289+
.onClick(async () => this.showConfirmationModal())
290+
);
291+
}
292+
293+
294+
// functions for onboarding all notes
295+
async showConfirmationModal() {
296+
const modal = new ConfirmationModal(this.app, this.plugin);
297+
modal.open();
298+
}
299+
300+
async addFrontMatterPropertiesToAllNotes() {
301+
const files = this.app.vault.getMarkdownFiles();
302+
303+
for (const file of files) {
304+
if (!this.isFileExcluded(file)) {
305+
await this.addFrontMatterPropertiesToNote(file);
306+
}
307+
}
308+
}
309+
310+
isFileExcluded(file: TAbstractFile): boolean {
311+
const excludedFolders = this.plugin.settings.onboardingExcludedFolders;
312+
let parent: TFolder | null = file.parent;
313+
314+
while (parent) {
315+
if (excludedFolders.includes(parent.path)) {
316+
return true;
317+
}
318+
parent = parent.parent;
319+
}
320+
321+
return false;
265322
}
266323

324+
async addFrontMatterPropertiesToNote(file: TFile) {
325+
const frontMatter = this.app.metadataCache.getCache(file.path)?.frontmatter;
326+
const modifiedFrontMatter = {
327+
'se-interval': frontMatter?.['se-interval'] || this.plugin.settings.spacingMethods[0].defaultInterval,
328+
'se-last-reviewed': frontMatter?.['se-last-reviewed'] || new Date().toISOString().split('.')[0],
329+
'se-ease': frontMatter?.['se-ease'] || this.plugin.settings.spacingMethods[0].defaultEaseFactor,
330+
};
331+
332+
await this.app.fileManager.processFrontMatter(file, async (frontmatter: any) => {
333+
frontmatter["se-interval"] = modifiedFrontMatter["se-interval"];
334+
frontmatter["se-last-reviewed"] = modifiedFrontMatter["se-last-reviewed"];
335+
frontmatter["se-ease"] = modifiedFrontMatter["se-ease"];
336+
});
337+
}
338+
339+
340+
// Functions for rendering subsets of the settings
267341
renderSpacingMethodSetting(containerEl: HTMLElement, spacingMethod: SpacingMethod, index: number) {
268342
const settingEl = containerEl.createDiv('spacing-method-settings-items');
269343
const settingHeader = settingEl.createDiv('spacing-method-header');
@@ -517,3 +591,45 @@ export class SpacedEverythingSettingTab extends PluginSettingTab {
517591
});
518592
}
519593
}
594+
595+
class ConfirmationModal extends Modal {
596+
plugin: SpacedEverythingPlugin;
597+
settingsTab: SpacedEverythingSettingTab;
598+
599+
constructor(app: App, plugin: SpacedEverythingPlugin) {
600+
super(app);
601+
this.plugin = plugin;
602+
this.settingsTab = new SpacedEverythingSettingTab(app, plugin);
603+
}
604+
605+
onOpen() {
606+
const { contentEl } = this;
607+
contentEl.createEl('h2', { text: 'Confirm Action' });
608+
contentEl.createEl('p', { text: 'Are you sure you want to onboard to all notes in your vault? This action cannot be undone. It is highly recommended you create a full backup of your vault prior to running this vault-wide action, in case any unexpected changes result.' });
609+
610+
const confirmButton = new Setting(contentEl)
611+
.addButton((button) => {
612+
button
613+
.setButtonText('Confirm')
614+
.setCta()
615+
.onClick(async () => {
616+
await this.settingsTab.addFrontMatterPropertiesToAllNotes();
617+
this.close();
618+
new Notice('All notes onboarded');
619+
});
620+
});
621+
622+
const cancelButton = new Setting(contentEl)
623+
.addButton((button) => {
624+
button
625+
.setButtonText('Cancel')
626+
.onClick(() => {
627+
this.close();
628+
});
629+
});
630+
}
631+
632+
onClose() {
633+
this.contentEl.empty();
634+
}
635+
}

0 commit comments

Comments
 (0)