diff --git a/src/public/app/widgets/type_widgets/options/other/note_erasure_timeout.ts b/src/public/app/widgets/type_widgets/options/other/note_erasure_timeout.ts
index 876cf36d3..6b187a825 100644
--- a/src/public/app/widgets/type_widgets/options/other/note_erasure_timeout.ts
+++ b/src/public/app/widgets/type_widgets/options/other/note_erasure_timeout.ts
@@ -11,26 +11,62 @@ const TPL = `
${t("note_erasure_timeout.note_erasure_description")}
${t("note_erasure_timeout.manual_erasing_description")}
-
+
`;
export default class NoteErasureTimeoutOptions extends OptionsWidget {
- private $eraseEntitiesAfterTimeInSeconds!: JQuery;
- private $eraseDeletedNotesButton!: JQuery;
+ private $eraseEntitiesAfterTime!: JQuery;
+ private $eraseEntitiesAfterTimeScale!: JQuery;
+ private $eraseDeletedNotesButton!: JQuery;
+ private eraseEntitiesAfterTimeInSeconds!: string | number;
doRender() {
this.$widget = $(TPL);
- this.$eraseEntitiesAfterTimeInSeconds = this.$widget.find(".erase-entities-after-time-in-seconds");
- this.$eraseEntitiesAfterTimeInSeconds.on("change", () => this.updateOption("eraseEntitiesAfterTimeInSeconds", this.$eraseEntitiesAfterTimeInSeconds.val()));
+ this.$eraseEntitiesAfterTime = this.$widget.find("#erase-entities-after-time");
+ this.$eraseEntitiesAfterTimeScale = this.$widget.find("#erase-entities-after-time-scale");
- this.$eraseDeletedNotesButton = this.$widget.find(".erase-deleted-notes-now-button");
+ this.$eraseEntitiesAfterTime.on("change", () => {
+ const time = this.$eraseEntitiesAfterTime.val();
+ const timeScale = this.$eraseEntitiesAfterTimeScale.val();
+
+ if (!this.handleTimeValidation() || typeof timeScale !== "string" || !time) return;
+
+ this.eraseEntitiesAfterTimeInSeconds = this.convertTime(time, timeScale).toOption();
+ this.updateOption("eraseEntitiesAfterTimeInSeconds", this.eraseEntitiesAfterTimeInSeconds);
+
+ });
+
+ this.$eraseEntitiesAfterTimeScale.on("change", () => {
+
+ const timeScale = this.$eraseEntitiesAfterTimeScale.val();
+
+ if (!this.handleTimeValidation() || typeof timeScale !== "string") return;
+
+ //calculate the new displayed value
+ const displayedTime = this.convertTime(this.eraseEntitiesAfterTimeInSeconds, timeScale).toDisplay();
+
+ this.updateOption("eraseEntitiesAfterTimeScale", timeScale);
+ this.$eraseEntitiesAfterTime.val(displayedTime).trigger("change");
+
+ });
+
+ this.$eraseDeletedNotesButton = this.$widget.find("#erase-deleted-notes-now-button");
this.$eraseDeletedNotesButton.on("click", () => {
server.post("notes/erase-deleted-notes-now").then(() => {
toastService.showMessage(t("note_erasure_timeout.deleted_notes_erased"));
@@ -39,6 +75,40 @@ export default class NoteErasureTimeoutOptions extends OptionsWidget {
}
async optionsLoaded(options: OptionMap) {
- this.$eraseEntitiesAfterTimeInSeconds.val(options.eraseEntitiesAfterTimeInSeconds);
+ this.eraseEntitiesAfterTimeInSeconds = options.eraseEntitiesAfterTimeInSeconds;
+
+ const displayedTime = this.convertTime(options.eraseEntitiesAfterTimeInSeconds, options.eraseEntitiesAfterTimeScale).toDisplay();
+ this.$eraseEntitiesAfterTime.val(displayedTime);
+ this.$eraseEntitiesAfterTimeScale.val(options.eraseEntitiesAfterTimeScale);
}
+
+
+ convertTime(time: string | number, timeScale: string | number) {
+
+ const value = typeof time === "number" ? time : parseInt(time);
+ if (Number.isNaN(value)) {
+ throw new Error(`Time needs to be a valid integer, but received: ${time}`);
+ }
+
+ const operand = typeof timeScale === "number" ? timeScale : parseInt(timeScale);
+ if (Number.isNaN(operand) || operand < 1) {
+ throw new Error(`TimeScale needs to be a valid integer >= 1, but received: ${timeScale}`);
+ }
+
+ return {
+ toOption: () => Math.ceil(value * operand),
+ toDisplay: () => Math.ceil(value / operand),
+ }
+
+ }
+
+ handleTimeValidation() {
+ if (this.$eraseEntitiesAfterTime.is(":invalid")) {
+ // TriliumNextTODO: i18n
+ toastService.showMessage("The entered time value is not a valid number.");
+ return false
+ }
+ return true;
+ }
+
}
diff --git a/src/routes/api/options.ts b/src/routes/api/options.ts
index 257344cab..14cb7ec42 100644
--- a/src/routes/api/options.ts
+++ b/src/routes/api/options.ts
@@ -12,6 +12,7 @@ import type { OptionNames } from "../../services/options_interface.js";
// options allowed to be updated directly in the Options dialog
const ALLOWED_OPTIONS = new Set([
"eraseEntitiesAfterTimeInSeconds",
+ "eraseEntitiesAfterTimeScale",
"protectedSessionTimeout",
"revisionSnapshotTimeInterval",
"revisionSnapshotNumberLimit",
diff --git a/src/services/options_init.ts b/src/services/options_init.ts
index dedd1a896..bb962835d 100644
--- a/src/services/options_init.ts
+++ b/src/services/options_init.ts
@@ -105,6 +105,7 @@ const defaultOptions: DefaultOption[] = [
{ name: "rightPaneVisible", value: "true", isSynced: false },
{ name: "nativeTitleBarVisible", value: "false", isSynced: false },
{ name: "eraseEntitiesAfterTimeInSeconds", value: "604800", isSynced: true }, // default is 7 days
+ { name: "eraseEntitiesAfterTimeScale", value: "86400", isSynced: true }, // default 86400 seconds = Day
{ name: "hideArchivedNotes_main", value: "false", isSynced: false },
{ name: "debugModeEnabled", value: "false", isSynced: false },
{ name: "headingStyle", value: "underline", isSynced: true },
diff --git a/src/services/options_interface.ts b/src/services/options_interface.ts
index 2632b7b2e..f3a92383b 100644
--- a/src/services/options_interface.ts
+++ b/src/services/options_interface.ts
@@ -61,6 +61,7 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions