From 9ff1c0cedf8a07e99d9b3305bf58abbbbe42f87c Mon Sep 17 00:00:00 2001 From: Andrea Alberti Date: Wed, 14 Aug 2024 14:44:41 +0200 Subject: [PATCH] Backup manager --- src/defaults.ts | 1 + src/defaults_legacy.ts | 18 ++++++----- src/main.ts | 23 ++++++++++---- src/settings_tab.ts | 68 +++++++++++++++++++++++++++++++++++++++--- src/types.ts | 9 ++++++ src/types_legacy.ts | 2 +- src/utils.ts | 3 +- 7 files changed, 104 insertions(+), 20 deletions(-) diff --git a/src/defaults.ts b/src/defaults.ts index f479c6e..002e5d0 100644 --- a/src/defaults.ts +++ b/src/defaults.ts @@ -19,5 +19,6 @@ export const DEFAULT_SETTINGS: PluginsAnnotationsSettings = { editable: true, automatic_remove: false, markdown_file_path: '', + backups: [], compatibility: '1.5.0', } diff --git a/src/defaults_legacy.ts b/src/defaults_legacy.ts index e7fe04a..c96363d 100644 --- a/src/defaults_legacy.ts +++ b/src/defaults_legacy.ts @@ -1,19 +1,23 @@ // defaults.ts +import { DEFAULT_SETTINGS } from 'defaults'; import { PluginsAnnotationsSettings_1_3_0, PluginsAnnotationsSettings_1_4_0 } from './types_legacy'; +/* ===== Version 1.4.0 ===== */ + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const { annotations:_, markdown_file_path:__, compatibility:___, backups:____, ...theRestingSettings_1_4_0} = DEFAULT_SETTINGS; + + export const DEFAULT_SETTINGS_1_4_0: PluginsAnnotationsSettings_1_4_0 = { + ...theRestingSettings_1_4_0, annotations: {}, plugins_annotations_uuid: 'B265C5B2-A6AD-4194-9E4C-C1327DB1EA18', - hide_placeholders: false, - delete_placeholder_string_on_insertion: false, - label_mobile: 'Annotation: ', - label_desktop: 'Personal annotation: ', - label_placeholder : "Add your personal comment about ${plugin_name} here...", - editable: true, - automatic_remove: false, } + +/* ===== Version 1.3.0 ===== */ + export const DEFAULT_SETTINGS_1_3_0: PluginsAnnotationsSettings_1_3_0 = { ...DEFAULT_SETTINGS_1_4_0, annotations: {}, // Override the annotations property with the appropriate type diff --git a/src/main.ts b/src/main.ts index 9203fe4..8d2ed76 100644 --- a/src/main.ts +++ b/src/main.ts @@ -60,11 +60,9 @@ export default class PluginsAnnotations extends Plugin { }); } - async loadSettings(): Promise { - // Create a mapping of names to IDs for the installed plugins - this.pluginNameToIdMap = this.constructPluginNameToIdMap(); - this.pluginIdToNameMap = this.generateInvertedMap(this.pluginNameToIdMap); - + /* Load settings for different versions */ + importSettings(data: unknown): {importedSettings: unknown, wasUpdated: boolean} { + // Set to true when the settings are updated to the new format let wasUpdated = false; @@ -95,6 +93,7 @@ export default class PluginsAnnotations extends Plugin { ...oldSettings, annotations: upgradedAnnotations, plugins_annotations_uuid: DEFAULT_SETTINGS.plugins_annotations_uuid, + backups: DEFAULT_SETTINGS.backups, compatibility: DEFAULT_SETTINGS.compatibility, markdown_file_path: DEFAULT_SETTINGS.markdown_file_path }; @@ -131,8 +130,20 @@ export default class PluginsAnnotations extends Plugin { } }; + const importedSettings = getSettingsFromData(data); + + return {importedSettings, wasUpdated}; + } + + async loadSettings(): Promise { + // Create a mapping of names to IDs for the installed plugins + this.pluginNameToIdMap = this.constructPluginNameToIdMap(); + this.pluginIdToNameMap = this.generateInvertedMap(this.pluginNameToIdMap); + + const {importedSettings, wasUpdated} = this.importSettings(await this.loadData()); + // Merge loaded settings with default settings - this.settings = Object.assign({}, DEFAULT_SETTINGS, getSettingsFromData(await this.loadData())); + this.settings = Object.assign({}, DEFAULT_SETTINGS, importedSettings); if(wasUpdated) { this.debouncedSaveAnnotations(); diff --git a/src/settings_tab.ts b/src/settings_tab.ts index 78bd4f6..7492542 100644 --- a/src/settings_tab.ts +++ b/src/settings_tab.ts @@ -290,13 +290,73 @@ export class PluginsAnnotationsSettingTab extends PluginSettingTab { /* ====== Backups ====== */ - - - + this.createBackupManager(containerEl); /* ====== Personal annotations of no longer installed community plugins ====== */ - this.createUninstalledPluginSettings(containerEl); } + + createBackupManager(containerEl: HTMLElement) { + new Setting(containerEl) + .setName('Backup Annotations') + .setHeading(); + + // Create Backup Button + new Setting(containerEl) + .setName('Create Backup') + .setDesc('Create a new backup of your current annotations.') + .addButton(button => button + .setButtonText('Create Backup') + .setCta() + .onClick(async () => { + const backupName = prompt('Enter a name for this backup:'); + if (backupName) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const {backups:_,...currentSettings} = this.plugin.settings; + this.plugin.settings.backups.push({ + name: backupName, + date: new Date(), + settings: { ...currentSettings } + }); + this.plugin.debouncedSaveAnnotations(); + this.display(); // Refresh the display to show the new backup + } + }) + ); + + // List Existing Backups + if (this.plugin.settings.backups.length > 0) { + new Setting(containerEl) + .setName('Restore Backup') + .setDesc('Select a backup to restore your annotations.'); + + this.plugin.settings.backups.forEach((backup, index) => { + new Setting(containerEl) + .setName(backup.name) + .setDesc(`Created on: ${backup.date.toLocaleString()}`) + .addButton(button => button + .setButtonText('Restore') + .setCta() + .onClick(async () => { + this.plugin.settings = { backups: this.plugin.settings.backups, ...backup.settings }; + this.plugin.debouncedSaveAnnotations(); + alert(`Annotations restored from backup: ${backup.name}`); + this.display(); // Refresh the display to reflect the restored annotations + }) + ) + .addButton(button => button + .setButtonText('Delete') + .setCta() + .onClick(async () => { + this.plugin.settings.backups.splice(index, 1); + this.plugin.debouncedSaveAnnotations(); + this.display(); // Refresh the display to remove the deleted backup + }) + ); + }); + } + + + } } diff --git a/src/types.ts b/src/types.ts index b7a0dd1..b5b098f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -12,6 +12,12 @@ export interface PluginAnnotationDict { [pluginId: string]: PluginAnnotation; } +export interface PluginBackup { + name: string; + date: Date; + settings: PluginsAnnotationsSettingsWithoutBackups; +} + export interface PluginsAnnotationsSettings { annotations: PluginAnnotationDict; plugins_annotations_uuid: string; @@ -24,8 +30,11 @@ export interface PluginsAnnotationsSettings { automatic_remove: boolean; markdown_file_path: string; compatibility: string; + backups: PluginBackup[]; } +type PluginsAnnotationsSettingsWithoutBackups = Omit; + export function isPluginsAnnotationsSettings(s:unknown): s is PluginsAnnotationsSettings { if (typeof s !== 'object' || s === null) { return false; diff --git a/src/types_legacy.ts b/src/types_legacy.ts index 613849c..acff747 100644 --- a/src/types_legacy.ts +++ b/src/types_legacy.ts @@ -14,7 +14,7 @@ export type PluginAnnotationDict_1_4_0 = { } // Extend the original interface and override the annotations property -export interface PluginsAnnotationsSettings_1_4_0 extends Omit { +export interface PluginsAnnotationsSettings_1_4_0 extends Omit { annotations: PluginAnnotationDict_1_4_0; } diff --git a/src/utils.ts b/src/utils.ts index e90b4a5..6c8bf46 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,5 @@ // utils.ts -import PluginsAnnotations from "main"; import { App, Modal, normalizePath, TAbstractFile, TFile, TFolder, Vault, AbstractInputSuggest, prepareFuzzySearch, SearchResult } from "obsidian"; import * as path from "path"; @@ -135,4 +134,4 @@ export function sortPluginAnnotationsByName(annotations: PluginAnnotationDict): pluginArray.sort((a, b) => a.name.localeCompare(b.name)); return pluginArray.map(item => item.pluginId); -} \ No newline at end of file +}