Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
6 changes: 6 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
// https://github.com/st3v3nmw/obsidian-spaced-repetition/issues/776
export const SCHEDULING_INFO_REGEX =
/^---\r?\n((?:.*\r?\n)*)sr-due: (.+)\r?\nsr-interval: (\d+)\r?\nsr-ease: (\d+)\r?\n((?:.*\r?\n)?)---/;

export const SCHEDULING_INFO_BLOCK = /---\s(sr-due:[^>\n]+)\s(sr-interval:[^>\n]+)\s(sr-ease:[^>\n]+)\s---/g;
export const SCHEDULING_INFO_TEXT = /(sr-due:[^>\n]+)\s(sr-interval:[^>\n]+)\s(sr-ease:[^>\n]+)\s/g

export const YAML_FRONT_MATTER_REGEX = /^---\r?\n((?:.*\r?\n)*?)---/;

export const MULTI_SCHEDULING_EXTRACTOR = /!([\d-]+),(\d+),(\d+)/gm;
export const LEGACY_SCHEDULING_EXTRACTOR = /<!--SR:([\d-]+),(\d+),(\d+)-->/gm;
export const SCHEDULING_EXTRACTOR = /[\s]*<!--SR:[^>]+-->/g;

export const OBSIDIAN_TAG_AT_STARTOFLINE_REGEX = /^#[^\s#]+/gi;

// https://help.obsidian.md/Linking+notes+and+files/Internal+links#Link+to+a+block+in+a+note
Expand Down
26 changes: 26 additions & 0 deletions src/delete-scheduling-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { TFile, Vault } from "obsidian";

import { SCHEDULING_EXTRACTOR, SCHEDULING_INFO_BLOCK, SCHEDULING_INFO_TEXT } from "src/constants";

/**
* Modifies a file to remove scheduling data.
* @param vault - The Obsidian vault instance.
* @param file - The file to modify.
* @returns - A promise that resolves to the modified file content.
*/
function modifyFile(vault: Vault, file: TFile): Promise<string> {
return vault.process(file, (data) => {
return data.replace(SCHEDULING_INFO_BLOCK, "").replace(SCHEDULING_INFO_TEXT, "").replace(SCHEDULING_EXTRACTOR, "").trim();
});
}

/**
* Deletes all scheduling data from all markdown files in the vault.
*/
export function deleteSchedulingData() {
const files = this.app.vault.getMarkdownFiles();

for (const file of files) {
modifyFile(this.app.vault, file);
}
}
54 changes: 54 additions & 0 deletions src/gui/confirmation-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { App, Modal, Notice, Setting } from "obsidian";

import { t } from "src/lang/helpers";

/**
* A reusable confirmation modal.
*/
export class ConfirmationModal extends Modal {
/**
* Creates a confirmation modal.
* @param app - The Obsidian app instance.
* @param title - Title of the modal.
* @param message - Body message of the modal.
* @param confirmationMessage - Notice message to display upon confirmation.
* @param onConfirm - Callback function to execute upon confirmation.
*/
constructor(
app: App,
title: string,
message: string,
confirmationMessage?: string,
onConfirm?: () => void,
) {
super(app);

this.setTitle(title);
this.titleEl.addClass("modal-header");

this.setContent(message);
this.contentEl.addClass("modal-content");

new Setting(this.contentEl)
.setClass("modal-button-container")
.addButton((button) =>
button
.setButtonText(t("CONFIRM"))
.setClass("mod-warning")
.onClick(() => {
if (onConfirm) {
onConfirm();
}
if (confirmationMessage) {
new Notice(confirmationMessage);
}
this.close();
}),
)
.addButton((button) =>
button.setButtonText(t("CANCEL")).onClick(() => {
this.close();
}),
);
}
}
21 changes: 21 additions & 0 deletions src/gui/settings.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { App, Notice, PluginSettingTab, Setting } from "obsidian";

import { deleteSchedulingData } from "src/delete-scheduling-data";
import { ConfirmationModal } from "src/gui/confirmation-modal";
import { StatisticsView } from "src/gui/statistics";
import { createTabs, TabStructure } from "src/gui/tabs";
import { t } from "src/lang/helpers";
Expand Down Expand Up @@ -1040,6 +1042,25 @@ export class SRSettingTab extends PluginSettingTab {
await this.plugin.savePluginData();
}),
);

containerEl.createEl("h3", { text: t("DELETE_SCHEDULING_DATA") });
new Setting(containerEl)
.setName(t("DELETE_SCHEDULING_DATA"))
.setDesc(t("DELETE_SCHEDULING_DATA_IN_NOTES_AND_FLASHCARDS"))
.addButton((button) =>
button
.setButtonText(t("DELETE"))
.setClass("mod-warning")
.onClick(async () => {
new ConfirmationModal(
this.plugin.app,
t("DELETE_SCHEDULING_DATA"),
t("CONFIRM_SCHEDULING_DATA_DELETION"),
t("SCHEDULING_DATA_HAS_BEEN_DELETED"),
deleteSchedulingData,
).open();
}),
);
}

private async tabHelp(containerEl: HTMLElement): Promise<void> {
Expand Down
9 changes: 9 additions & 0 deletions src/lang/locale/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,15 @@ export default {
EXPERIMENTAL: "Experimental",
HELP: "Help",
STORE_IN_NOTES: "In the notes",
DELETE_SCHEDULING_DATA: "Delete Scheduling Data",
DELETE_SCHEDULING_DATA_IN_NOTES_AND_FLASHCARDS:
"Delete scheduling data from all notes and flashcards.",
DELETE: "Delete",
CONFIRM_SCHEDULING_DATA_DELETION:
"Are you sure you want to delete all scheduling data from your notes and flashcards? This action cannot be undone.",
CONFIRM: "Confirm",
SCHEDULING_DATA_HAS_BEEN_DELETED:
"Scheduling data has been deleted from all notes and flashcards.",

// sidebar.ts
NOTES_REVIEW_QUEUE: "Notes Review Queue",
Expand Down