mirror of
https://github.com/alberti42/obsidian-plugins-annotations.git
synced 2026-07-22 10:10:24 +00:00
Merge branch 'main' into testing_annotation_control
This commit is contained in:
commit
3ba82f30c8
6 changed files with 140 additions and 98 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
|
@ -18,3 +18,12 @@ data.json
|
|||
|
||||
# Exclude macOS Finder (System Explorer) View States
|
||||
.DS_Store
|
||||
|
||||
# iCLoud
|
||||
*.nosync
|
||||
|
||||
# Sublime
|
||||
*sublime-workspace
|
||||
|
||||
# Markdown
|
||||
*.md
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "plugins-annotations",
|
||||
"name": "Plugins Annotations",
|
||||
"version": "1.7.8",
|
||||
"version": "1.7.10",
|
||||
"minAppVersion": "1.5.0",
|
||||
"description": "Allows adding personal comments to each installed plugin.",
|
||||
"author": "Andrea Alberti",
|
||||
|
|
|
|||
29
obsidian-plugin-annotations.sublime-project
Normal file
29
obsidian-plugin-annotations.sublime-project
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": ".",
|
||||
"folder_exclude_patterns": [".git", "node_modules", "dist"]
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"tab_size": 4,
|
||||
"translate_tabs_to_spaces": true,
|
||||
"typescript_tsdk": "./node_modules/typescript/lib"
|
||||
},
|
||||
"build_systems": [
|
||||
{
|
||||
"name": "TypeScript Build",
|
||||
"shell_cmd": "npm run build",
|
||||
"working_dir": "${folder}", // Use ${folder} to point to the project root
|
||||
"file_regex": "^\\s*(.+?\\.ts)\\((\\d+),(\\d+)\\):\\s*(.*)$",
|
||||
"selector": "source.ts"
|
||||
},
|
||||
{
|
||||
"name": "TypeScript Dev",
|
||||
"shell_cmd": "npm run dev",
|
||||
"working_dir": "${folder}", // Use ${folder} to point to the project root
|
||||
"file_regex": "^\\s*(.+?\\.ts):(\\d+):(\\d+):\\s*(.*)$",
|
||||
"selector": "source.ts"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -56,7 +56,10 @@ export class AnnotationControl {
|
|||
|
||||
addEventListeners() {
|
||||
const linkInteractionHandler = (event: MouseEvent | TouchEvent) => {
|
||||
if (event.target && (event.target as HTMLElement).tagName === 'A') {
|
||||
const target = event.target as HTMLElement | null;
|
||||
// Use closest('a') so clicks on nested elements (e.g., spans inside links) still register as link clicks.
|
||||
// This scenario is likely never occurring, but closest('a') keeps link detection reliable (just in case).
|
||||
if (target && target.closest('a')) {
|
||||
this.clickedLink = true;
|
||||
} else {
|
||||
this.clickedLink = false;
|
||||
|
|
@ -73,8 +76,10 @@ export class AnnotationControl {
|
|||
return;
|
||||
} else {
|
||||
event.stopPropagation();
|
||||
// Explicitly focus to help mobile keyboards appear, especially on Android.
|
||||
this.annotation_div.focus();
|
||||
if (!this.clickedLink) {
|
||||
// Explicitly focus to help mobile keyboards appear, especially on Android.
|
||||
this.annotation_div.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
172
src/main.ts
172
src/main.ts
|
|
@ -45,7 +45,7 @@ export default class PluginsAnnotations extends Plugin {
|
|||
debouncedSaveAnnotations: (callback?: () => void) => void;
|
||||
waitForSaveToComplete: () => Promise<void>;
|
||||
|
||||
private communityPluginSettingTabPatched = false;
|
||||
private communityPluginSettingTabPatched = false;
|
||||
|
||||
private listGitHubIcons:HTMLDivElement[] = [];
|
||||
|
||||
|
|
@ -104,18 +104,22 @@ export default class PluginsAnnotations extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
async onLayoutReady() {
|
||||
// Load settings
|
||||
const loadSettingsPromise = this.loadSettings();
|
||||
|
||||
// Load the big json file containing the GitHub address of all community plugins
|
||||
const loadCommunityPluginsJsonPromise = this.loadCommunityPluginsJson();
|
||||
async onLayoutReady() {
|
||||
// Load settings
|
||||
const loadSettingsPromise = this.loadSettings();
|
||||
|
||||
// Load the big json file containing the GitHub address of all community plugins
|
||||
const loadCommunityPluginsJsonPromise = this.loadCommunityPluginsJson();
|
||||
|
||||
// Store a reference to the community plugin tab
|
||||
this.communityPluginTab = this.app.setting.settingTabs.find((tab:SettingTab):boolean => tab.id === "community-plugins");
|
||||
// Store a reference to the community plugin tab
|
||||
this.communityPluginTab = this.app.setting.settingTabs.find((tab:SettingTab):boolean => tab.id === "community-plugins");
|
||||
|
||||
// Patch the rendering function of the community plugin preference pane
|
||||
if(this.communityPluginTab) this.patchCommunityPluginSettingTab(this.communityPluginTab);
|
||||
// Patch the rendering function of the community plugin preference pane
|
||||
if(this.communityPluginTab) {
|
||||
this.patchCommunityPluginSettingTab(this.communityPluginTab);
|
||||
} else {
|
||||
console.warn('[Plugins Annotations] Community plugins tab not found; hook not installed.');
|
||||
}
|
||||
|
||||
// Monkey-patch functions to detect when community plugins are installed and uninstalled.
|
||||
this.hookOnInstallAndUninstallPlugins();
|
||||
|
|
@ -406,49 +410,46 @@ export default class PluginsAnnotations extends Plugin {
|
|||
return invertedMap;
|
||||
}
|
||||
|
||||
patchCommunityPluginSettingTab(tab:SettingTab) {
|
||||
if(this.communityPluginSettingTabPatched) return;
|
||||
patchCommunityPluginSettingTab(tab:SettingTab) {
|
||||
if(this.communityPluginSettingTabPatched) return;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const self = this;
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
const self = this;
|
||||
|
||||
// Monkey patch for uninstallPlugin
|
||||
const removeMonkeyPatchForRender = around(tab, {
|
||||
renderInstalledPlugin: (next: (
|
||||
pluginManifest: PluginManifest,
|
||||
containerEl:HTMLElement,
|
||||
nameMatch: boolean | null,
|
||||
authorMatch: boolean | null,
|
||||
descriptionMatch: boolean | null
|
||||
) => void ) => {
|
||||
const removeMonkeyPatchForRender = around(tab, {
|
||||
renderInstalledPlugin: (next: SettingTab['renderInstalledPlugin']) => {
|
||||
|
||||
return function (this: SettingTab,
|
||||
pluginManifest: PluginManifest,
|
||||
containerEl: HTMLElement,
|
||||
nameMatch: boolean | null,
|
||||
authorMatch: boolean | null,
|
||||
descriptionMatch: boolean | null
|
||||
): void {
|
||||
next.call(this, pluginManifest, containerEl, nameMatch, authorMatch, descriptionMatch);
|
||||
return function (this: SettingTab,
|
||||
pluginManifest: PluginManifest,
|
||||
nameMatch: boolean | null,
|
||||
authorMatch: boolean | null,
|
||||
descriptionMatch: boolean | null
|
||||
): void {
|
||||
next.call(this, pluginManifest, nameMatch, authorMatch, descriptionMatch);
|
||||
|
||||
// Custom code for personal annotations here
|
||||
if(containerEl && containerEl.lastElementChild) self.addAnnotation(containerEl.lastElementChild);
|
||||
};
|
||||
},
|
||||
// Custom code for personal annotations here
|
||||
const listEl = (this as SettingTab & { installedPlugins?: { listEl?: HTMLElement } }).installedPlugins?.listEl;
|
||||
const targetElement = listEl?.lastElementChild;
|
||||
if (targetElement instanceof HTMLElement) {
|
||||
self.addAnnotation(targetElement);
|
||||
}
|
||||
};
|
||||
},
|
||||
// Patch for `render` method
|
||||
render: (next: (
|
||||
isInitialRender: boolean
|
||||
) => void) => {
|
||||
render: (next: (
|
||||
isInitialRender: boolean
|
||||
) => void) => {
|
||||
|
||||
return function (this: SettingTab, isInitialRender: boolean): void {
|
||||
self.listGitHubIcons = [];
|
||||
return function (this: SettingTab, isInitialRender: boolean): void {
|
||||
self.listGitHubIcons = [];
|
||||
|
||||
// Call the original `render` function
|
||||
next.call(this, isInitialRender);
|
||||
self.addLockIcon(this.containerEl);
|
||||
};
|
||||
}
|
||||
});
|
||||
// Call the original `render` function
|
||||
next.call(this, isInitialRender);
|
||||
self.addLockIcon(this.containerEl);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Register the patch to ensure it gets cleaned up
|
||||
this.register(removeMonkeyPatchForRender);
|
||||
|
|
@ -645,53 +646,53 @@ export default class PluginsAnnotations extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
addAnnotation(pluginDOMElement: Element) {
|
||||
const pluginNameDiv = pluginDOMElement.querySelector('.setting-item-name');
|
||||
const pluginName = pluginNameDiv ? pluginNameDiv.textContent : null;
|
||||
addAnnotation(pluginDOMElement: Element) {
|
||||
const pluginNameDiv = pluginDOMElement.querySelector('.setting-item-name');
|
||||
const pluginName = pluginNameDiv ? pluginNameDiv.textContent : null;
|
||||
|
||||
if (!pluginName) {
|
||||
console.warn('Plugin name not found');
|
||||
return;
|
||||
}
|
||||
if (!pluginName) {
|
||||
console.warn('Plugin name not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const pluginId = this.pluginNameToIdMap[pluginName];
|
||||
if (!pluginId) {
|
||||
console.warn(`Plugin ID not found for plugin name: ${pluginName}`);
|
||||
return;
|
||||
}
|
||||
const pluginId = this.pluginNameToIdMap[pluginName];
|
||||
if (!pluginId) {
|
||||
console.warn(`Plugin ID not found for plugin name: ${pluginName}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const settingItemInfo = pluginDOMElement.querySelector('.setting-item-info');
|
||||
if (settingItemInfo) {
|
||||
const descriptionDiv = settingItemInfo.querySelector('.setting-item-description');
|
||||
if (descriptionDiv) {
|
||||
const commentDiv = descriptionDiv.querySelector('.plugin-comment');
|
||||
if (!commentDiv) {
|
||||
const annotation_container = document.createElement('div');
|
||||
annotation_container.className = 'plugin-comment';
|
||||
const settingItemInfo = pluginDOMElement.querySelector('.setting-item-info');
|
||||
if (settingItemInfo) {
|
||||
const descriptionDiv = settingItemInfo.querySelector('.setting-item-description');
|
||||
if (descriptionDiv) {
|
||||
const commentDiv = descriptionDiv.querySelector('.plugin-comment');
|
||||
if (!commentDiv) {
|
||||
const annotation_container = document.createElement('div');
|
||||
annotation_container.className = 'plugin-comment';
|
||||
|
||||
const annotationControl = new AnnotationControl(this,annotation_container,pluginId,pluginName);
|
||||
|
||||
descriptionDiv.appendChild(annotation_container);
|
||||
|
||||
if(this.settings.show_github_icons) {
|
||||
// Get the repository of the plugin
|
||||
const community_plugins = this.community_plugins[pluginId];
|
||||
const repo = community_plugins ? community_plugins.repo : undefined;
|
||||
if (repo) {
|
||||
const controlDiv = pluginDOMElement.querySelector('.setting-item-control');
|
||||
if(controlDiv) {
|
||||
if(this.colorSchemeMedia) {
|
||||
const isDarkMode = this.colorSchemeMedia.matches;
|
||||
const gitHubIcon = annotationControl.addGitHubIcon(controlDiv,repo, isDarkMode);
|
||||
if(gitHubIcon) this.listGitHubIcons.push(gitHubIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(this.settings.show_github_icons) {
|
||||
// Get the repository of the plugin
|
||||
const community_plugins = this.community_plugins[pluginId];
|
||||
const repo = community_plugins ? community_plugins.repo : undefined;
|
||||
if (repo) {
|
||||
const controlDiv = pluginDOMElement.querySelector('.setting-item-control');
|
||||
if(controlDiv) {
|
||||
if(this.colorSchemeMedia) {
|
||||
const isDarkMode = this.colorSchemeMedia.matches;
|
||||
const gitHubIcon = annotationControl.addGitHubIcon(controlDiv,repo, isDarkMode);
|
||||
if(gitHubIcon) this.listGitHubIcons.push(gitHubIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addAnnotations() {
|
||||
if(this.communityPluginTab===undefined) {
|
||||
|
|
@ -760,4 +761,3 @@ export default class PluginsAnnotations extends Plugin {
|
|||
return uninstalledPlugins;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
15
src/types/obsidian-augment.d.ts
vendored
15
src/types/obsidian-augment.d.ts
vendored
|
|
@ -20,13 +20,12 @@ declare module "obsidian" {
|
|||
navEl: HTMLElement;
|
||||
// updateSearch(e: string): void;
|
||||
render(isInitialRender:boolean):void;
|
||||
renderInstalledPlugin(
|
||||
pluginManifest: PluginManifest,
|
||||
containerEl: HTMLElement,
|
||||
nameMatch: boolean | null,
|
||||
authorMatch: boolean | null,
|
||||
descriptionMatch: boolean | null
|
||||
): void;
|
||||
renderInstalledPlugin(
|
||||
pluginManifest: PluginManifest,
|
||||
nameMatch: boolean | null,
|
||||
authorMatch: boolean | null,
|
||||
descriptionMatch: boolean | null
|
||||
): void;
|
||||
}
|
||||
interface Setting {
|
||||
onOpen(): void;
|
||||
|
|
@ -70,4 +69,4 @@ declare module "obsidian" {
|
|||
textInputEl: HTMLInputElement;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue