mirror of
https://github.com/4source/favorites-obsidian-plugin.git
synced 2026-07-22 06:44:46 +00:00
297 lines
11 KiB
TypeScript
297 lines
11 KiB
TypeScript
import { CommunityItem, CommunityModal, Modal, Plugin } from 'obsidian';
|
|
|
|
export default class FavoritesPlugin extends Plugin {
|
|
favoritePlugins?: string[];
|
|
favoriteThemes?: string[];
|
|
communityPluginModalPrototype?: CommunityModal;
|
|
communityThemesModalPrototype?: CommunityModal;
|
|
|
|
async onload() {
|
|
await this.loadSettings();
|
|
|
|
if (!Modal.prototype.originalOpen) {
|
|
Modal.prototype.originalOpen = Modal.prototype.open;
|
|
const originalModalOpen = Modal.prototype.open;
|
|
|
|
Modal.prototype.open = (function (originalModalOpen, plugin) {
|
|
return function () {
|
|
originalModalOpen?.apply(this);
|
|
|
|
// Check the opened Modal is the Community plugin browse modal
|
|
if (this.containerEl?.querySelector('.mod-community-plugin')) {
|
|
// Store the Community Plugin Browse Modal prototype to be able to reset to the original
|
|
plugin.communityPluginModalPrototype = this.constructor.prototype;
|
|
|
|
// Check the plugin updateItems is already overwritten
|
|
if (!this.constructor.prototype.originalUpdateItems) {
|
|
// Save original method
|
|
this.constructor.prototype.originalUpdateItems = this.constructor.prototype.updateItems;
|
|
const originalUpdateItems = this.constructor.prototype.updateItems;
|
|
if (!this.constructor.prototype.originalUpdateItems) {
|
|
console.error('Favorites plugin: Failed to access original updateItems method!');
|
|
return;
|
|
}
|
|
|
|
// Overwrite method with additional functionality
|
|
this.constructor.prototype.updateItems = (function (originalUpdateItems, plugin) {
|
|
return function () {
|
|
// Load the favorite plugins
|
|
plugin.favoritePlugins = JSON.parse(localStorage.getItem('favorite-plugins') || '[]');
|
|
|
|
const result = originalUpdateItems.apply(this);
|
|
|
|
// Add to the favorite plugins a tag to visualize it for the user
|
|
if (plugin.favoritePlugins) {
|
|
plugin.favoritePlugins.forEach(id => {
|
|
if (this.items && this.items[id]?.nameEl) {
|
|
this.items[id].nameEl.createSpan({
|
|
cls: 'flair',
|
|
text: 'favorite',
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
return result;
|
|
};
|
|
})(originalUpdateItems, plugin);
|
|
}
|
|
|
|
// Check the plugin showItem is already overwritten
|
|
if (!this.constructor.prototype.originalShowItem) {
|
|
// Save original method
|
|
this.constructor.prototype.originalShowItem = this.constructor.prototype.showItem;
|
|
const originalShowItem = this.constructor.prototype.showItem;
|
|
if (!this.constructor.prototype.originalShowItem) {
|
|
console.error('Favorites: Failed to access original showItem method!');
|
|
return;
|
|
}
|
|
|
|
// Overwrite method with additional functionality
|
|
this.constructor.prototype.showItem = (function (originalShowItem, plugin) {
|
|
return function (...args: CommunityItem[]) {
|
|
// Load the favorite plugins
|
|
plugin.favoritePlugins = JSON.parse(localStorage.getItem('favorite-plugins') || '[]');
|
|
|
|
return originalShowItem.apply(this, args).then(async (r: void) => {
|
|
const infoEl = await this.detailsEl.getElementsByClassName('community-modal-info')[0];
|
|
const infoNameEl = await infoEl?.getElementsByClassName('community-modal-info-name')[0];
|
|
const buttonContainerEl = await infoEl?.getElementsByClassName('community-modal-button-container')[0];
|
|
|
|
const isFavorite = plugin.favoritePlugins?.contains(this.selectedItemId);
|
|
|
|
// Add to the favorite plugins a tag to visualize it for the user
|
|
if (isFavorite) {
|
|
if (infoNameEl) {
|
|
infoNameEl.createSpan({
|
|
cls: 'flair',
|
|
text: 'favorite',
|
|
});
|
|
}
|
|
}
|
|
|
|
plugin.registerEvent(buttonContainerEl?.createEl('button', { text: isFavorite ? 'Unfavorite' : 'Favorite' }).addEventListener('click', () => {
|
|
if (isFavorite) {
|
|
plugin.favoritePlugins?.remove(this.selectedItemId);
|
|
}
|
|
else {
|
|
plugin.favoritePlugins?.push(this.selectedItemId);
|
|
}
|
|
|
|
plugin.saveSettings();
|
|
|
|
// Redraw
|
|
infoEl.detach();
|
|
this.showItem(this.items[this.selectedItemId]);
|
|
this.update();
|
|
}));
|
|
|
|
return r;
|
|
});
|
|
};
|
|
})(originalShowItem, plugin);
|
|
}
|
|
}
|
|
|
|
// Check the opened Modal is the Community themes browse modal
|
|
if (this.containerEl?.querySelector('.mod-community-theme')) {
|
|
// Store the Community Theme Browse Modal prototype to be able to reset to the original
|
|
plugin.communityThemesModalPrototype = this.constructor.prototype;
|
|
|
|
// Check the theme updateItems is already overwritten
|
|
if (!this.constructor.prototype.originalUpdateItems) {
|
|
// Save original method
|
|
this.constructor.prototype.originalUpdateItems = this.constructor.prototype.updateItems;
|
|
const originalUpdateItems = this.constructor.prototype.updateItems;
|
|
if (!this.constructor.prototype.originalUpdateItems) {
|
|
console.error('Favorites: Failed to access original updateItems method!');
|
|
return;
|
|
}
|
|
|
|
// Overwrite method with additional functionality
|
|
this.constructor.prototype.updateItems = (function (originalUpdateItems, plugin) {
|
|
return function () {
|
|
// Load the favorite themes
|
|
plugin.favoriteThemes = JSON.parse(localStorage.getItem('favorite-themes') || '[]');
|
|
|
|
const result = originalUpdateItems.apply(this);
|
|
|
|
// Ignore the default theme
|
|
if (this.selectedItemId === '') {
|
|
return;
|
|
}
|
|
|
|
// Add to the favorite themes a tag to visualize it for the user
|
|
if (plugin.favoriteThemes) {
|
|
plugin.favoriteThemes.forEach(id => {
|
|
if (this.items && this.items[id]?.nameEl) {
|
|
this.items[id].nameEl.createSpan({
|
|
cls: 'flair',
|
|
text: 'favorite',
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
return result;
|
|
};
|
|
})(originalUpdateItems, plugin);
|
|
}
|
|
|
|
// Check the theme showItem is already overwritten
|
|
if (!this.constructor.prototype.originalShowItem) {
|
|
// Save original method
|
|
this.constructor.prototype.originalShowItem = this.constructor.prototype.showItem;
|
|
const originalShowItem = this.constructor.prototype.showItem;
|
|
if (!this.constructor.prototype.originalShowItem) {
|
|
console.error('Favorites: Failed to access original showItem method!');
|
|
return;
|
|
}
|
|
|
|
// Overwrite method with additional functionality
|
|
this.constructor.prototype.showItem = (function (originalShowItem, plugin) {
|
|
// Load the favorite themes
|
|
plugin.favoriteThemes = JSON.parse(localStorage.getItem('favorite-themes') || '[]');
|
|
|
|
return function (...args: CommunityItem[]) {
|
|
return originalShowItem.apply(this, args).then(async (r: void) => {
|
|
// Ignore the default theme
|
|
if (this.selectedItemId === '') {
|
|
return;
|
|
}
|
|
|
|
const infoEl = await this.detailsEl.getElementsByClassName('community-modal-info')[0];
|
|
const infoNameEl = await infoEl?.getElementsByClassName('community-modal-info-name')[0];
|
|
const buttonContainerEl = await infoEl?.getElementsByClassName('community-modal-button-container')[0];
|
|
|
|
const isFavorite = plugin.favoriteThemes?.contains(this.selectedItemId);
|
|
|
|
// Add to the favorite themes a tag to visualize it for the user
|
|
if (isFavorite) {
|
|
if (infoNameEl) {
|
|
infoNameEl.createSpan({
|
|
cls: 'flair',
|
|
text: 'favorite',
|
|
});
|
|
}
|
|
}
|
|
|
|
plugin.registerEvent(buttonContainerEl?.createEl('button', { text: isFavorite ? 'Unfavorite' : 'Favorite' }).addEventListener('click', () => {
|
|
if (isFavorite) {
|
|
plugin.favoriteThemes?.remove(this.selectedItemId);
|
|
}
|
|
else {
|
|
plugin.favoriteThemes?.push(this.selectedItemId);
|
|
}
|
|
|
|
plugin.saveSettings();
|
|
|
|
// Redraw
|
|
infoEl.detach();
|
|
this.showItem(this.items[this.selectedItemId]);
|
|
this.update();
|
|
}));
|
|
|
|
return r;
|
|
});
|
|
};
|
|
})(originalShowItem, plugin);
|
|
}
|
|
}
|
|
|
|
// Restore the original Modal open function as soon as the CommunityPluginModal and CommunityThemesModal is opened once
|
|
if (Modal.prototype.originalOpen && plugin.communityPluginModalPrototype && plugin.communityThemesModalPrototype) {
|
|
Modal.prototype.open = Modal.prototype.originalOpen;
|
|
delete Modal.prototype.originalOpen;
|
|
}
|
|
};
|
|
})(originalModalOpen, this);
|
|
}
|
|
else {
|
|
console.warn('Favorites plugin: Modal prototype already has originalOpen, this is not intended!');
|
|
}
|
|
|
|
/*
|
|
* TODO: Add command to save and reload the favorites list
|
|
* TODO: Add command to remove all favorites from list
|
|
* TODO: Add command to search for plugin to add to favorites list
|
|
*/
|
|
}
|
|
|
|
async onunload() {
|
|
// Restore the original Modal open function
|
|
|
|
if (Modal.prototype.originalOpen) {
|
|
Modal.prototype.open = Modal.prototype.originalOpen;
|
|
delete Modal.prototype.originalOpen;
|
|
}
|
|
|
|
// Restore the original plugin updateItems function
|
|
if (this.communityPluginModalPrototype && this.communityPluginModalPrototype.originalUpdateItems) {
|
|
this.communityPluginModalPrototype.updateItems = this.communityPluginModalPrototype.originalUpdateItems;
|
|
delete this.communityPluginModalPrototype.originalUpdateItems;
|
|
}
|
|
|
|
// Restore the original plugin showItem function
|
|
if (this.communityPluginModalPrototype && this.communityPluginModalPrototype.originalShowItem) {
|
|
this.communityPluginModalPrototype.showItem = this.communityPluginModalPrototype.originalShowItem;
|
|
delete this.communityPluginModalPrototype.originalShowItem;
|
|
}
|
|
|
|
// Restore the original theme updateItems function
|
|
if (this.communityThemesModalPrototype && this.communityThemesModalPrototype.originalUpdateItems) {
|
|
this.communityThemesModalPrototype.updateItems = this.communityThemesModalPrototype.originalUpdateItems;
|
|
delete this.communityThemesModalPrototype.originalUpdateItems;
|
|
}
|
|
|
|
// Restore the original theme showItem function
|
|
if (this.communityThemesModalPrototype && this.communityThemesModalPrototype.originalShowItem) {
|
|
this.communityThemesModalPrototype.showItem = this.communityThemesModalPrototype.originalShowItem;
|
|
delete this.communityThemesModalPrototype.originalShowItem;
|
|
}
|
|
}
|
|
|
|
async loadSettings() {
|
|
|
|
}
|
|
|
|
async saveSettings() {
|
|
if (this.favoritePlugins) {
|
|
if (this.favoritePlugins.length > 0) {
|
|
localStorage.setItem('favorite-plugins', JSON.stringify(this.favoritePlugins));
|
|
}
|
|
else {
|
|
localStorage.removeItem('favorite-plugins');
|
|
}
|
|
}
|
|
|
|
if (this.favoriteThemes) {
|
|
if (this.favoriteThemes.length > 0) {
|
|
localStorage.setItem('favorite-themes', JSON.stringify(this.favoriteThemes));
|
|
}
|
|
else {
|
|
localStorage.removeItem('favorite-themes');
|
|
}
|
|
}
|
|
}
|
|
}
|