diff --git a/src/main.ts b/src/main.ts index 6548e11..70c1c36 100644 --- a/src/main.ts +++ b/src/main.ts @@ -47,6 +47,7 @@ interface ReadwisePluginSettings { booksToRefresh: Array; booksIDsMap: { [key: string]: string; }; reimportShowConfirmation: boolean; + frontmatterBookIdKey?: string; } // define our initial settings @@ -65,6 +66,114 @@ const DEFAULT_SETTINGS: ReadwisePluginSettings = { reimportShowConfirmation: true, }; +class AdvancedModal extends Modal { + plugin: ReadwisePlugin; + + constructor(app: App, plugin: ReadwisePlugin) { + super(app); + this.plugin = plugin; + } + + /** helper to extract all book IDs from frontmatter in the readwiseDir ("base folder"), + perfectly matching them to the document they came from */ + async extractBookIDs() { + console.log('Readwise Official plugin: extracting book IDs from frontmatter...'); + const files = this.plugin.app.vault.getMarkdownFiles(); + const bookIDs: { [bookID: string]: string } = {}; + for (const file of files) { + if (file.path.startsWith(this.plugin.settings.readwiseDir)) { + const cache = this.app.metadataCache.getFileCache(file); + // skip if there's no cache + if (!cache) continue; + + const frontmatter = cache.frontmatter; + // skip if there's no frontmatter + if (!frontmatter) continue; + + const bookID = frontmatter[this.plugin.settings.frontmatterBookIdKey]; + if (bookID) bookIDs[file.path] = bookID; + } + } + + return bookIDs; + } + + onOpen() { + const { titleEl, contentEl } = this; + + titleEl.setText('Advanced settings'); + + // add new setting that allows text input + new Setting(contentEl) + .setName('Book ID frontmatter key') + .setDesc('The frontmatter key used to store the Readwise book_id. If set, will be used to identify the export for syncs.') + .addText(text => text + .setPlaceholder('readwise-book-id') + .setValue(this.plugin.settings.frontmatterBookIdKey) + .onChange(async value => { + console.log('Readwise Official plugin: setting frontmatter book ID key to', value); + this.plugin.settings.frontmatterBookIdKey = value; + this.plugin.saveSettings(); + + // enable/disable populate button depending on whether the key is set + const populateButton = contentEl.querySelector('.rw-setting-populate-book-id'); + if (populateButton instanceof HTMLButtonElement) { + populateButton.disabled = !value; + } + })); + + // button to populate the frontmatter with using + // the frontmatterBookIdKey and matching it + // with whatever's saved in booksIDsMap + return new Setting(contentEl) + .setName('Populate frontmatter key') + .setDesc('If the book ID frontmatter key is configured above, this will populate the frontmatter key setting with the first key found in the booksIDsMap. This will not overwrite existing keys.') + .addButton(button => button + .setButtonText('Populate') + .setClass('rw-setting-populate-book-id') + .setDisabled(!this.plugin.settings.frontmatterBookIdKey) + .onClick(async () => { + this.plugin.notice("Populating frontmatter with book IDs...", true); + console.log(`Readwise Official plugin: populating frontmatter key ${this.plugin.settings.frontmatterBookIdKey} with matching value from booksIDsMap...`); + + const readwiseExports = this.plugin.app.vault.getMarkdownFiles(); + for (const file of readwiseExports) { + console.log('Readwise Official plugin: checking file for frontmatter', file.path); + + const cache = this.app.metadataCache.getFileCache(file); + if (!cache) continue; + + const frontmatter = cache.frontmatter; + if (!frontmatter) continue; + + const existingBookId = frontmatter[this.plugin.settings.frontmatterBookIdKey]; + if (existingBookId) continue; + + const bookId = this.plugin.settings.booksIDsMap[file.path]; + if (!bookId) continue; + + // set the book ID in the frontmatter + await this.app.fileManager.processFrontMatter(file, frontmatter => { + // only set if it's not already set + const keyAlreadySet = frontmatter[this.plugin.settings.frontmatterBookIdKey]; + if (!keyAlreadySet) { + console.log(`Readwise Official plugin: setting frontmatter key for "${file.path}" to ${bookId}`); + frontmatter[this.plugin.settings.frontmatterBookIdKey] = bookId; + } + }) + } + + this.plugin.notice("Frontmatter populated with book IDs", true); + }) + ); + } + + onClose() { + const { contentEl } = this; + contentEl.empty(); + } +} + export default class ReadwisePlugin extends Plugin { settings: ReadwisePluginSettings; fs: DataAdapter; @@ -732,6 +841,17 @@ class ReadwiseSettingTab extends PluginSettingTab { } ); + new Setting(containerEl) + .setName('Advanced settings') + .setDesc('Customize additional settings for the Readwise plugin') + .addButton(button => { + button + .setButtonText('Open') + .onClick(() => { + new AdvancedModal(this.app, this.plugin).open(); + }); + }); + if (this.plugin.settings.lastSyncFailed) { this.plugin.showInfoStatus(containerEl.find(".rw-setting-sync .rw-info-container").parentElement, "Last sync failed", "rw-error"); }