From 40c4930ba1bc8afa8e8dcb96b376007612470055 Mon Sep 17 00:00:00 2001 From: 4Source <38220764+4Source@users.noreply.github.com> Date: Sun, 1 Mar 2026 22:30:15 +0100 Subject: [PATCH] [FEAT] Favorite/Unfavorite for installed plugins (#8) * Fix favorite themes loading logic * Validate environment variables for favorite plugins and themes on load * Add community plugins settings tab favorite icon * Enhance README with usage details and screenshots Updated the README to clarify ease of use and added additional screenshots. * Security Audit fix --- README.md | 19 +++++--- package-lock.json | 99 +++++++++++++++++++++++----------------- src/constants.ts | 4 +- src/main.ts | 112 ++++++++++++++++++++++++++++++++++++++++++---- src/types.d.ts | 48 +++++++++++--------- 5 files changed, 204 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 99fdc2c..a2655cd 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,12 @@ Stop re-searching the same plugins or themes in every vault. With one central li # Features - **Global Favorites for Plugins & Themes** - Mark your go to plugins and themes once and use them in all vaults -- **Ease of Use** - Favorite/unfavorite directly from the Obsidian's plugin and theme details browser +- **Ease of Use** - Favorite/unfavorite directly inside the Obsidian's + - Plugin browser + - Community plugins tab + - Theme browser - **Vault Independence** - Favorites are stored globally on your device, not tied to a single vault -# Screenshots -image - -image - # How It Works 1. Install and enable ***Favorites***. 2. Open Obsidian's plugin or theme browser. @@ -19,6 +17,15 @@ Stop re-searching the same plugins or themes in every vault. With one central li 4. Use the Favorite button. 5. Your favorites are saved globally and appear in every vault. +For plugins you can also favorite already installed plugins directly from the Community plugins tab. + +# Screenshots +image + +image + +image + # Contribution Feel free to contribute. diff --git a/package-lock.json b/package-lock.json index ac88723..48f48f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "favorites", - "version": "1.1.1", + "version": "1.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "favorites", - "version": "1.1.1", + "version": "1.1.2", "license": "MIT", "devDependencies": { "@stylistic/eslint-plugin": "^3.1.0", @@ -68,6 +68,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -1059,10 +1060,11 @@ } }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1105,10 +1107,11 @@ } }, "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1175,10 +1178,11 @@ } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -1574,8 +1578,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", - "dev": true, - "peer": true + "dev": true }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", @@ -1979,6 +1982,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", "dev": true, + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", @@ -2156,6 +2160,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2207,10 +2212,11 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2490,6 +2496,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -3108,6 +3115,7 @@ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -3226,10 +3234,11 @@ } }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3443,10 +3452,11 @@ } }, "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -3667,10 +3677,11 @@ } }, "node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4118,10 +4129,11 @@ } }, "node_modules/jake/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4134,6 +4146,7 @@ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, + "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -4730,10 +4743,11 @@ "dev": true }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -5026,12 +5040,13 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -5806,8 +5821,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/supports-color": { "version": "7.2.0", @@ -5864,10 +5878,11 @@ } }, "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6030,6 +6045,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6120,8 +6136,7 @@ "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", - "dev": true, - "peer": true + "dev": true }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", diff --git a/src/constants.ts b/src/constants.ts index d673d01..20ab87b 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,6 +1,8 @@ export const PLUGIN_ID = 'favorite'; export const MONKEY_KEY_MODAL_OPEN = `${PLUGIN_ID}-Modal-open`; +export const MONKEY_KEY_SETTINGS_MODAL_OPEN_TAB = `${PLUGIN_ID}-SettingsModal-openTab`; export const MONKEY_KEY_PLUGIN_BROWSER_MODAL_UPDATE_ITEMS = `${PLUGIN_ID}-CommunityPluginModal-updateItems`; export const MONKEY_KEY_PLUGIN_BROWSER_MODAL_SHOW_ITEMS = `${PLUGIN_ID}-CommunityPluginModal-showItems`; export const MONKEY_KEY_THEME_BROWSER_MODAL_UPDATE_ITEMS = `${PLUGIN_ID}-ThemePluginModal-updateItems`; -export const MONKEY_KEY_THEME_BROWSER_MODAL_SHOW_ITEMS = `${PLUGIN_ID}-ThemePluginModal-showItems`; \ No newline at end of file +export const MONKEY_KEY_THEME_BROWSER_MODAL_SHOW_ITEMS = `${PLUGIN_ID}-ThemePluginModal-showItems`; +export const MONKEY_KEY_COMMUNITY_PLUGIN_SETTINGS_TAB_RENDER_INSTALLED_PLUGIN = `${PLUGIN_ID}-CommunityPluginsSettingTab-renderInstalledPlugin`; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 4f44317..251dbca 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ -import { CommunityItem, CommunityModal, Modal, Plugin } from 'obsidian'; +import { CommunityItem, CommunityModal, CommunityPluginsSettingTab, Modal, Plugin, setIcon, SettingsModal, SettingTab, setTooltip } from 'obsidian'; import { dedupe, around } from 'monkey-around'; -import { MONKEY_KEY_PLUGIN_BROWSER_MODAL_UPDATE_ITEMS, MONKEY_KEY_MODAL_OPEN, MONKEY_KEY_THEME_BROWSER_MODAL_UPDATE_ITEMS, MONKEY_KEY_THEME_BROWSER_MODAL_SHOW_ITEMS, MONKEY_KEY_PLUGIN_BROWSER_MODAL_SHOW_ITEMS } from './constants'; +import { MONKEY_KEY_PLUGIN_BROWSER_MODAL_UPDATE_ITEMS, MONKEY_KEY_MODAL_OPEN, MONKEY_KEY_THEME_BROWSER_MODAL_UPDATE_ITEMS, MONKEY_KEY_THEME_BROWSER_MODAL_SHOW_ITEMS, MONKEY_KEY_PLUGIN_BROWSER_MODAL_SHOW_ITEMS, MONKEY_KEY_SETTINGS_MODAL_OPEN_TAB, MONKEY_KEY_COMMUNITY_PLUGIN_SETTINGS_TAB_RENDER_INSTALLED_PLUGIN } from './constants'; export default class FavoritesPlugin extends Plugin { pluginsKey: string; @@ -10,19 +10,103 @@ export default class FavoritesPlugin extends Plugin { communityPluginModalPrototype?: CommunityModal; communityThemesModalPrototype?: CommunityModal; uninstallModalOpen?: () => void; + uninstallSettingsModalOpenTab?: () => void; uninstallPluginBrowserModalUpdateItems?: () => void; uninstallPluginBrowserModalShowItem?: () => void; uninstallThemeBrowserModalUpdateItems?: () => void; uninstallThemeBrowserModalShowItem?: () => void; + uninstallCommunityPluginsSettingTabRenderInstalledPlugin?: () => void; onload() { - this.pluginsKey = process.env.FAVORITE_PLUGINS_KEY || ''; - this.themesKey = process.env.FAVORITE_THEMES_KEY || ''; + if (process.env.FAVORITE_PLUGINS_KEY) { + this.pluginsKey = process.env.FAVORITE_PLUGINS_KEY; + } + else { + throw Error('Missing environment variable \'FAVORITE_PLUGINS_KEY\''); + } + if (process.env.FAVORITE_THEMES_KEY) { + this.themesKey = process.env.FAVORITE_THEMES_KEY; + } + else { + throw Error('Missing environment variable \'FAVORITE_THEMES_KEY\''); + } console.debug(`Plugins key: ${this.pluginsKey} Themes key: ${this.themesKey}`); // eslint-disable-next-line @typescript-eslint/no-this-alias -- Is required because the this context wil change inside the 'monkey-around' functions but the plugin is required to be accessible const plugin = this; + // Patch the opening of SettingsModal + if (!this.uninstallSettingsModalOpenTab) { + console.debug('Patch SettingsModal.openTab'); + this.uninstallSettingsModalOpenTab = around(this.app.setting as SettingsModal, { + openTab(oldMethod) { + return dedupe(MONKEY_KEY_SETTINGS_MODAL_OPEN_TAB, oldMethod, function (...args) { + console.debug('Call SettingsModal.openTab'); + + const tab = args[0] as SettingTab; + if (tab.id === 'community-plugins') { + if (!plugin.uninstallCommunityPluginsSettingTabRenderInstalledPlugin) { + console.debug('Patch CommunityPluginsSettingTab.renderInstalledPlugin'); + plugin.uninstallCommunityPluginsSettingTabRenderInstalledPlugin = around((tab as CommunityPluginsSettingTab), { + renderInstalledPlugin(oldMethod) { + return dedupe(MONKEY_KEY_COMMUNITY_PLUGIN_SETTINGS_TAB_RENDER_INSTALLED_PLUGIN, oldMethod, function (...args) { + console.debug('Call CommunityPluginsSettingTab.renderInstalledPlugin'); + oldMethod && oldMethod.apply(this, args); + + // Load the favorite plugins + plugin.loadFavoritePlugins(); + + const selectedPluginID = args[0].id; + const isFavorite = plugin.favoritePlugins?.contains(selectedPluginID); + + const favEl = createDiv('clickable-icon extra-setting-button'); + + plugin.registerDomEvent(favEl, 'click', () => { + if (isFavorite) { + plugin.favoritePlugins?.remove(selectedPluginID); + } + else { + plugin.favoritePlugins?.push(selectedPluginID); + } + + plugin.saveFavorites(); + + // Redraw + (tab as CommunityPluginsSettingTab).render(false); + }); + + if (isFavorite) { + setIcon(favEl, 'star-off'); + setTooltip(favEl, 'Unfavorite'); + } + else { + setIcon(favEl, 'star'); + setTooltip(favEl, 'Favorite'); + } + + // Add Favorite Icon to plugin control + const controlEl: HTMLElement = this.installedPlugins.listEl.lastChild?.getElementsByClassName('setting-item-control')[0]; + controlEl.insertBefore(favEl, controlEl.children[0]); + }); + }, + }); + } + else { + console.debug('CommunityPluginsSettingTab.renderInstalledPlugin already patched!'); + } + } + + if (plugin.uninstallSettingsModalOpenTab && plugin.uninstallCommunityPluginsSettingTabRenderInstalledPlugin) { + console.debug('Uninstall SettingsModal.openTab'); + plugin.uninstallSettingsModalOpenTab(); + plugin.uninstallSettingsModalOpenTab = undefined; + } + return oldMethod && oldMethod.apply(this, args); + }); + }, + }); + } + if (!this.uninstallModalOpen) { console.debug('Patch Modal.open'); this.uninstallModalOpen = around(Modal.prototype, { @@ -64,7 +148,7 @@ export default class FavoritesPlugin extends Plugin { }); } else { - console.warn('PluginBrowserModal.updateItems already patched!'); + console.debug('PluginBrowserModal.updateItems already patched!'); } // Patch showItem method @@ -118,7 +202,7 @@ export default class FavoritesPlugin extends Plugin { }); } else { - console.warn('PluginBrowserModal.showItem already patched!'); + console.debug('PluginBrowserModal.showItem already patched!'); } } @@ -160,7 +244,7 @@ export default class FavoritesPlugin extends Plugin { }); } else { - console.warn('ThemeBrowserModal.updateItems already patched!'); + console.debug('ThemeBrowserModal.updateItems already patched!'); } // Patch showItems method @@ -219,7 +303,7 @@ export default class FavoritesPlugin extends Plugin { }); } else { - console.warn('ThemeBrowserModal.showItem already patched!'); + console.debug('ThemeBrowserModal.showItem already patched!'); } } @@ -254,6 +338,11 @@ export default class FavoritesPlugin extends Plugin { this.uninstallModalOpen(); this.uninstallModalOpen = undefined; } + if (this.uninstallSettingsModalOpenTab) { + console.debug('Uninstall SettingsModal.openTab'); + this.uninstallSettingsModalOpenTab(); + this.uninstallSettingsModalOpenTab = undefined; + } if (this.uninstallPluginBrowserModalUpdateItems) { console.debug('Uninstall PluginBrowserModal.updateItem'); this.uninstallPluginBrowserModalUpdateItems(); @@ -274,6 +363,11 @@ export default class FavoritesPlugin extends Plugin { this.uninstallThemeBrowserModalShowItem(); this.uninstallThemeBrowserModalShowItem = undefined; } + if (this.uninstallCommunityPluginsSettingTabRenderInstalledPlugin) { + console.debug('Uninstall CommunityPluginsSettingTab.renderInstalledPlugin'); + this.uninstallCommunityPluginsSettingTabRenderInstalledPlugin(); + this.uninstallCommunityPluginsSettingTabRenderInstalledPlugin = undefined; + } } catch (e) { console.error(e); @@ -287,7 +381,7 @@ export default class FavoritesPlugin extends Plugin { loadFavoriteThemes() { // Load the favorite plugins - this.favoritePlugins = JSON.parse(localStorage.getItem(this.themesKey) || '[]'); + this.favoriteThemes = JSON.parse(localStorage.getItem(this.themesKey) || '[]'); } saveFavorites() { diff --git a/src/types.d.ts b/src/types.d.ts index bfa7dff..fa845a4 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,37 +1,45 @@ import { } from 'obsidian'; declare module 'obsidian' { + interface App { + setting: SettingsModal + } + interface CommunityItem { id: string; - - // ... } interface CommunityModal { update(): void; updateItems(): CommunityItem[]; showItem(item: CommunityItem): void; - - // ... - - // Additional from this plugin - /** - * This is the backup of the original ``updateItems()`` function. Do not use otherwise than restoring! - */ - originalUpdateItems?(): CommunityItem[]; - - /** - * This is the backup of the original ``showItem()`` function. Do not use otherwise than restoring! - */ - originalShowItem?(item: CommunityItem): void; } interface Modal { - // Additional form this plugin - /** - * This is the backup of the original ``open()`` function. Do not use otherwise than restoring! - */ - originalOpen?(): void; + } + + interface SettingsModal { + openTab(settingTab: SettingTab): unknown; + } + + interface SettingTab { + id: string; + setting: unknown; + containerEl: HTMLElement; + navEl: HTMLElement; + app: App; + } + + interface CommunityPluginsSettingTab extends SettingTab { + id: 'community-plugins'; + installedPlugins: { + listEl: HTMLElement + }; + + display(): void; + render(e: boolean): void; + renderInstalledPlugin(plugin: CommunityItem, t: unknown, n: unknown, i: unknown, r: unknown): void; + updateSearch(e: unknown): void } } \ No newline at end of file