New version 1.7.0

This commit is contained in:
Andrea Alberti 2024-08-25 19:04:45 +02:00
parent f8e562f5a7
commit d71db186fa
11 changed files with 270 additions and 69 deletions

View file

@ -11,7 +11,7 @@ Obsidian Plugins Annotations is a plugin for [Obsidian](https://obsidian.md) tha
- Detailed instructions how to edit the annotations are provided in the _setting pane_ of the plugin.
- Possible to lock the annotations with the lock button next to the title "Installed plugins". This feature is useful in combination with the toggle hiding the annotations fields where there is no user annotation yet.
## Installation
## Installation
The preferred method to install the plugin is to use the Community Plugins Preference pane in Obsidian.
@ -32,7 +32,7 @@ The preferred method to install the plugin is to use the Community Plugins Prefe
## Screenshot
![Screenshot of the setting pane showing installed plugins with annotations by the user](docs/images/screenshot.jpg)
![Screenshot of the setting pane showing installed plugins with annotations by the user](docs/images/screenshot_dark.jpg)
## Development

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 KiB

View file

@ -1,7 +1,7 @@
{
"id": "plugins-annotations",
"name": "Plugins Annotations",
"version": "1.6.6",
"version": "1.7.0",
"minAppVersion": "1.5.0",
"description": "Allows adding personal comments to each installed plugin.",
"author": "Andrea Alberti",

View file

@ -4,14 +4,21 @@ import PluginsAnnotations from "main";
import { MarkdownRenderer, Platform } from "obsidian";
import { isPluginAnnotation } from "types";
export class annotationControl {
const github_prefix = "https://github.com/";
import { svg_github_dark, svg_github_light } from "graphics";
export class AnnotationControl {
static addGitHubIcon(controlDiv: Element) {
throw new Error('Method not implemented.');
}
private clickedLink: boolean;
private isPlaceholder: boolean;
private annotationDesc:string;
private placeholder:string;
private label:string;
private annotation_div: HTMLDivElement;
constructor(private plugin: PluginsAnnotations, private annotation_container:HTMLElement, private pluginId:string, private pluginName:string) {
this.clickedLink = false;
@ -183,4 +190,31 @@ export class annotationControl {
});
});
}
addGitHubIcon(controlDiv:Element, repo:string, isDarkMode:boolean) {
if (controlDiv) {
const GitHubDiv = document.createElement('div');
GitHubDiv.classList.add('clickable-icon', 'extra-setting-button', 'github-icon');
GitHubDiv.setAttribute('aria-label', 'Open plugin\'s GitHub page');
GitHubDiv.innerHTML = isDarkMode ? svg_github_dark : svg_github_light;
// Add click listener to open the repo URL
GitHubDiv.addEventListener('click', () => {
// Use Obsidian's native method to open external links
window.open(github_prefix + repo, '_blank');
});
// Get all elements with the class .clickable-icon inside controlDiv
const clickableIcons = controlDiv.querySelectorAll('.clickable-icon');
// Insert the new icon as the second last of all clickable icons
if (clickableIcons.length > 0) {
const lastIcon = clickableIcons[clickableIcons.length - 1];
controlDiv.insertBefore(GitHubDiv, lastIcon);
} else {
// If no clickable icons are found, append it as the first child
controlDiv.insertBefore(GitHubDiv, controlDiv.firstChild);
}
}
}
}

View file

@ -18,6 +18,7 @@ export const DEFAULT_SETTINGS: PluginsAnnotationsSettings = {
editable: true,
automatic_remove: false,
markdown_file_path: '',
show_github_icons: true,
backups: [],
compatibility: '1.6.0',
compatibility: '1.7.0',
}

View file

@ -1,8 +1,29 @@
// defaults.ts
import { AnnotationType_1_5_0, PluginsAnnotationsSettings_1_3_0, PluginsAnnotationsSettings_1_4_0, PluginsAnnotationsSettings_1_5_0 } from './types_legacy';
import { AnnotationType_1_5_0, PluginsAnnotationsSettings_1_3_0, PluginsAnnotationsSettings_1_4_0, PluginsAnnotationsSettings_1_5_0, PluginsAnnotationsSettings_1_6_0 } from './types_legacy';
export const DEFAULT_SETTINGS_1_6_0: PluginsAnnotationsSettings_1_6_0 = {
annotations: {
"plugins-annotations": {
"name": "Plugins Annotations",
"desc": "Allows writing annotations (just like this one) about the community plugins installed in the vault.",
}
},
plugins_annotations_uuid: 'BC56AB7B-A46F-4ACF-9BA1-3A4461F74C79',
hide_placeholders: false,
delete_placeholder_string_on_insertion: false,
label_mobile: '<b>Annotation:&nbsp;</b>',
label_desktop: '<b>Personal annotation:&nbsp;</b>',
label_placeholder : "<em>Add your personal comment about <strong>${plugin_name}</strong> here...</em>",
editable: true,
automatic_remove: false,
markdown_file_path: '',
backups: [],
compatibility: '1.6.0',
}
/* ===== Version 1.5.0 ===== */
export const DEFAULT_SETTINGS_1_5_0: PluginsAnnotationsSettings_1_5_0 = {
"annotations": {
"plugins-annotations": {

7
src/graphics.ts Normal file
View file

@ -0,0 +1,7 @@
// graphics.ts
export const svg_unlocked = atob('PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgdmlld0JveD0iMCAwIDI0IDI0IiBcCiAgICAgICAgICAgICAgICAgICAgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0ibHVjaWRlIGx1Y2lkZS1sb2NrLW9wZW4iPlwKICAgICAgICAgICAgICAgICAgICA8cmVjdCB3aWR0aD0iMTgiIGhlaWdodD0iMTEiIHg9IjMiIHk9IjExIiByeD0iMiIgcnk9IjIiLz5cCiAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik03IDExdi00YzAtMi44IDIuMi01IDUtNSAxLjYgMCAzLjEuOCA0IDIiLz4gXAogICAgICAgICAgICAgICAgPC9zdmc+');
export const svg_locked = atob('PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxOCIgaGVpZ2h0PSIxOCIgdmlld0JveD0iMCAwIDI0IDI0IiBcCiAgICAgICAgICAgICAgICAgICAgZmlsbD0ibm9uZSIgc3Ryb2tlPSJjdXJyZW50Q29sb3IiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0ibHVjaWRlIGx1Y2lkZS1sb2NrIj5cCiAgICAgICAgICAgICAgICAgICAgPHJlY3Qgd2lkdGg9IjE4IiBoZWlnaHQ9IjExIiB4PSIzIiB5PSIxMSIgcng9IjIiIHJ5PSIyIi8+XAogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik03IDExVjdhNSA1IDAgMCAxIDEwIDB2NCIvPlwKICAgICAgICAgICAgICAgIDwvc3ZnPg==');
export const svg_github_light=atob('PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9InN2Zy1pY29uIGx1Y2lkZS1zZXR0aW5ncyI+CiAgPGRlZnM+CiAgICA8c3R5bGU+CiAgICAgIC5jbHMtMSB7CiAgICAgICAgZmlsbDogIzI0MjkyZjsKICAgICAgICBmaWxsLXJ1bGU6IGV2ZW5vZGQ7CiAgICAgICAgc3Ryb2tlLXdpZHRoOiAwcHg7CiAgICAgIH0KICAgIDwvc3R5bGU+CiAgPC9kZWZzPgogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTEyLC4zQzUuNC4zLjEsNS43LjEsMTIuM3MzLjQsOS44LDguMSwxMS40Yy42LjEuOC0uMy44LS42czAtMS4yLDAtMi4yYy0zLjMuNy00LTEuNC00LTEuNC0uNS0xLjQtMS4zLTEuNy0xLjMtMS43LTEuMS0uNywwLS43LDAtLjcsMS4yLDAsMS44LDEuMiwxLjgsMS4yLDEuMSwxLjgsMi44LDEuMywzLjUsMSwwLS44LjQtMS4zLjctMS42LTIuNi0uMy01LjQtMS4zLTUuNC01LjlzLjUtMi40LDEuMi0zLjJjLS4xLS4zLS41LTEuNS4xLTMuMiwwLDAsMS0uMywzLjMsMS4yLDEtLjMsMi0uNCwzLS40LDEsMCwyLC4xLDMsLjQsMi4zLTEuNSwzLjMtMS4yLDMuMy0xLjIuNywxLjYuMiwyLjkuMSwzLjIuOC44LDEuMiwxLjksMS4yLDMuMiwwLDQuNi0yLjgsNS42LTUuNCw1LjkuNC40LjgsMS4xLjgsMi4yLDAsMS42LDAsMi45LDAsMy4zcy4yLjcuOC42YzQuNy0xLjYsOC4xLTYuMSw4LjEtMTEuNCwwLTYuNi01LjMtMTItMTEuOS0xMloiLz4KPC9zdmc+');
export const svg_github_dark=atob('PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9InN2Zy1pY29uIGx1Y2lkZS1zZXR0aW5ncyI+CiAgPGRlZnM+CiAgICA8c3R5bGU+CiAgICAgIC5jbHMtMSB7CiAgICAgICAgZmlsbDogI2ZmZjsKICAgICAgICBmaWxsLXJ1bGU6IGV2ZW5vZGQ7CiAgICAgICAgc3Ryb2tlLXdpZHRoOiAwcHg7CiAgICAgIH0KICAgIDwvc3R5bGU+CiAgPC9kZWZzPgogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTEyLC4zQzUuNC4zLjEsNS43LjEsMTIuM3MzLjQsOS44LDguMSwxMS40Yy42LjEuOC0uMy44LS42czAtMS4yLDAtMi4yYy0zLjMuNy00LTEuNC00LTEuNC0uNS0xLjQtMS4zLTEuNy0xLjMtMS43LTEuMS0uNywwLS43LDAtLjcsMS4yLDAsMS44LDEuMiwxLjgsMS4yLDEuMSwxLjgsMi44LDEuMywzLjUsMSwwLS44LjQtMS4zLjctMS42LTIuNi0uMy01LjQtMS4zLTUuNC01LjlzLjUtMi40LDEuMi0zLjJjLS4xLS4zLS41LTEuNS4xLTMuMiwwLDAsMS0uMywzLjMsMS4yLDEtLjMsMi0uNCwzLS40LDEsMCwyLC4xLDMsLjQsMi4zLTEuNSwzLjMtMS4yLDMuMy0xLjIuNiwxLjYuMiwyLjkuMSwzLjIuOC44LDEuMiwxLjksMS4yLDMuMiwwLDQuNi0yLjgsNS42LTUuNCw1LjkuNC40LjgsMS4xLjgsMi4yLDAsMS42LDAsMi45LDAsMy4zcy4yLjcuOC42YzQuNy0xLjYsOC4xLTYuMSw4LjEtMTEuNCwwLTYuNi01LjMtMTItMTEuOS0xMloiLz4KPC9zdmc+');

View file

@ -14,36 +14,24 @@ import {
// App,
} from 'obsidian';
import { around } from 'monkey-around';
import { isPluginAnnotation, isPluginsAnnotationsSettings, PluginAnnotation, PluginAnnotationDict, PluginBackup, PluginsAnnotationsSettings } from './types';
import { PluginAnnotationDict_1_4_0, PluginsAnnotationsSettings_1_4_0, PluginsAnnotationsSettings_1_3_0, isPluginAnnotationDictFormat_1_3_0, isSettingsFormat_1_3_0, isSettingsFormat_1_4_0, parseAnnotation_1_4_0, PluginsAnnotationsSettings_1_5_0, PluginAnnotationDict_1_5_0, isPluginsAnnotationsSettings_1_5_0, } from 'types_legacy'
import { DEFAULT_SETTINGS_1_3_0, DEFAULT_SETTINGS_1_4_0, DEFAULT_SETTINGS_1_5_0 } from './defaults_legacy';
import { CommunityPluginInfo, CommunityPluginInfoDict, isPluginAnnotation, isPluginsAnnotationsSettings, PluginAnnotation, PluginAnnotationDict, PluginBackup, PluginsAnnotationsSettings } from './types';
import { PluginAnnotationDict_1_4_0, PluginsAnnotationsSettings_1_4_0, PluginsAnnotationsSettings_1_3_0, isPluginAnnotationDictFormat_1_3_0, isSettingsFormat_1_3_0, isSettingsFormat_1_4_0, parseAnnotation_1_4_0, PluginsAnnotationsSettings_1_5_0, PluginAnnotationDict_1_5_0, isPluginsAnnotationsSettings_1_5_0, PluginsAnnotationsSettings_1_6_0, isPluginsAnnotationsSettings_1_6_0, } from 'types_legacy'
import { DEFAULT_SETTINGS_1_3_0, DEFAULT_SETTINGS_1_4_0, DEFAULT_SETTINGS_1_5_0, DEFAULT_SETTINGS_1_6_0 } from './defaults_legacy';
import { DEFAULT_SETTINGS } from 'defaults';
import { PluginsAnnotationsSettingTab } from 'settings_tab'
import * as path from 'path';
import { readAnnotationsFromMdFile, writeAnnotationsToMdFile } from 'manageAnnotations';
import { backupSettings, debounceFactoryWithWaitMechanism, delay, sortAnnotations } from 'utils';
import { annotationControl } from 'annotation_control';
import { AnnotationControl } from 'annotation_control';
import { svg_locked, svg_unlocked, svg_github_dark, svg_github_light } from "graphics";
export default class PluginsAnnotations extends Plugin {
settings: PluginsAnnotationsSettings = structuredClone(DEFAULT_SETTINGS);
pluginNameToIdMap: Record<string,string> = {};
pluginIdToNameMap: Record<string,string> = {};
sortedPluginIds: string[] = [];
svg_unlocked ='<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" \
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-lock-open">\
<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/>\
<path d="M7 11v-4c0-2.8 2.2-5 5-5 1.6 0 3.1.8 4 2"/> \
</svg>';
svg_locked ='<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" \
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-lock">\
<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/>\
<path d="M7 11V7a5 5 0 0 1 10 0v4"/>\
</svg>';
svg_github_light=atob('PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9InN2Zy1pY29uIGx1Y2lkZS1zZXR0aW5ncyI+CiAgPGRlZnM+CiAgICA8c3R5bGU+CiAgICAgIC5jbHMtMSB7CiAgICAgICAgZmlsbDogIzI0MjkyZjsKICAgICAgICBmaWxsLXJ1bGU6IGV2ZW5vZGQ7CiAgICAgICAgc3Ryb2tlLXdpZHRoOiAwcHg7CiAgICAgIH0KICAgIDwvc3R5bGU+CiAgPC9kZWZzPgogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTEyLC4zQzUuNC4zLjEsNS43LjEsMTIuM3MzLjQsOS44LDguMSwxMS40Yy42LjEuOC0uMy44LS42czAtMS4yLDAtMi4yYy0zLjMuNy00LTEuNC00LTEuNC0uNS0xLjQtMS4zLTEuNy0xLjMtMS43LTEuMS0uNywwLS43LDAtLjcsMS4yLDAsMS44LDEuMiwxLjgsMS4yLDEuMSwxLjgsMi44LDEuMywzLjUsMSwwLS44LjQtMS4zLjctMS42LTIuNi0uMy01LjQtMS4zLTUuNC01LjlzLjUtMi40LDEuMi0zLjJjLS4xLS4zLS41LTEuNS4xLTMuMiwwLDAsMS0uMywzLjMsMS4yLDEtLjMsMi0uNCwzLS40LDEsMCwyLC4xLDMsLjQsMi4zLTEuNSwzLjMtMS4yLDMuMy0xLjIuNywxLjYuMiwyLjkuMSwzLjIuOC44LDEuMiwxLjksMS4yLDMuMiwwLDQuNi0yLjgsNS42LTUuNCw1LjkuNC40LjgsMS4xLjgsMi4yLDAsMS42LDAsMi45LDAsMy4zcy4yLjcuOC42YzQuNy0xLjYsOC4xLTYuMSw4LjEtMTEuNCwwLTYuNi01LjMtMTItMTEuOS0xMloiLz4KPC9zdmc+');
svg_github_dark=atob('PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIGZpbGw9Im5vbmUiIHN0cm9rZT0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgY2xhc3M9InN2Zy1pY29uIGx1Y2lkZS1zZXR0aW5ncyI+CiAgPGRlZnM+CiAgICA8c3R5bGU+CiAgICAgIC5jbHMtMSB7CiAgICAgICAgZmlsbDogI2ZmZjsKICAgICAgICBmaWxsLXJ1bGU6IGV2ZW5vZGQ7CiAgICAgICAgc3Ryb2tlLXdpZHRoOiAwcHg7CiAgICAgIH0KICAgIDwvc3R5bGU+CiAgPC9kZWZzPgogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTEyLC4zQzUuNC4zLjEsNS43LjEsMTIuM3MzLjQsOS44LDguMSwxMS40Yy42LjEuOC0uMy44LS42czAtMS4yLDAtMi4yYy0zLjMuNy00LTEuNC00LTEuNC0uNS0xLjQtMS4zLTEuNy0xLjMtMS43LTEuMS0uNywwLS43LDAtLjcsMS4yLDAsMS44LDEuMiwxLjgsMS4yLDEuMSwxLjgsMi44LDEuMywzLjUsMSwwLS44LjQtMS4zLjctMS42LTIuNi0uMy01LjQtMS4zLTUuNC01LjlzLjUtMi40LDEuMi0zLjJjLS4xLS4zLS41LTEuNS4xLTMuMiwwLDAsMS0uMywzLjMsMS4yLDEtLjMsMi0uNCwzLS40LDEsMCwyLC4xLDMsLjQsMi4zLTEuNSwzLjMtMS4yLDMuMy0xLjIuNiwxLjYuMiwyLjkuMSwzLjIuOC44LDEuMiwxLjksMS4yLDMuMiwwLDQuNi0yLjgsNS42LTUuNCw1LjkuNC40LjgsMS4xLjgsMi4yLDAsMS42LDAsMi45LDAsMy4zcy4yLjcuOC42YzQuNy0xLjYsOC4xLTYuMSw4LjEtMTEuNCwwLTYuNi01LjMtMTItMTEuOS0xMloiLz4KPC9zdmc+');
private lockIcon: HTMLDivElement | null = null;
private mutationObserver: MutationObserver | null = null;
@ -55,6 +43,11 @@ export default class PluginsAnnotations extends Plugin {
private savePromise: Promise<void> | null = null;
private resolveSavePromise: (() => void) | null = null;
private community_plugins = {} as CommunityPluginInfoDict;
private handleThemeChange: ((event: MediaQueryListEvent) => void) | null = null;
private colorSchemeMedia: MediaQueryList | null = null;
// Declare class methods that will be initialized in the constructor
debouncedSaveAnnotations: (callback?: () => void) => void;
waitForSaveToComplete: () => Promise<void>;
@ -69,7 +62,6 @@ export default class PluginsAnnotations extends Plugin {
async (callback: () => void = (): void => {}) => {
await this.saveSettings();
if(callback) callback();
console.log("FINISHED SAVING ANNOTATIONS");
}, timeout_debounced_saving_ms);
this.debouncedSaveAnnotations = debouncedFct;
this.waitForSaveToComplete = waitFnc;
@ -77,8 +69,6 @@ export default class PluginsAnnotations extends Plugin {
async onload() {
// console.clear();
// console.log('Loading Plugins Annotations');
// Add settings tab. It avoids loading the setting at this stage
@ -101,6 +91,14 @@ export default class PluginsAnnotations extends Plugin {
}
}
});
this.app.workspace.onLayoutReady(async () => {
// Wait for all plugins to be loaded
this.colorSchemeMedia = matchMedia('(prefers-color-scheme: dark)');
});
// Call this function in your plugin initialization or where appropriate
this.loadCommunityPluginsJson();
}
/* Load settings for different versions */
@ -114,7 +112,17 @@ export default class PluginsAnnotations extends Plugin {
// Nested function to handle different versions of settings
const getSettingsFromData = async (data: unknown): Promise<unknown> => {
if (isPluginsAnnotationsSettings(data)) {
const settings: PluginsAnnotationsSettings = data;
return data as PluginsAnnotationsSettings;
} else if (isPluginsAnnotationsSettings_1_6_0(data)) {
// Make a backup
await backupSettings('Settings before upgrade from 1.5 to 1.6',data,importBackups);
await delay(10); // add a small delay to shift the timestamp of the backup
const settings: PluginsAnnotationsSettings = {
...data,
"compatibility":"1.7.0",
show_github_icons:DEFAULT_SETTINGS.show_github_icons
};
return settings as PluginsAnnotationsSettings;
} else if (isPluginsAnnotationsSettings_1_5_0(data)) {
// Make a backup
@ -132,8 +140,8 @@ export default class PluginsAnnotations extends Plugin {
const oldSettings: PluginsAnnotationsSettings_1_5_0 = data;
// Update the data with the new format
const default_new_settings = DEFAULT_SETTINGS;
const newSettings: PluginsAnnotationsSettings = {
const default_new_settings = DEFAULT_SETTINGS_1_6_0;
const newSettings: PluginsAnnotationsSettings_1_6_0 = {
...oldSettings,
annotations: upgradedAnnotations,
plugins_annotations_uuid: default_new_settings.plugins_annotations_uuid,
@ -393,8 +401,48 @@ export default class PluginsAnnotations extends Plugin {
this.sortedPluginIds = sortAnnotations(this.settings.annotations);
}
listenForThemeChange(tabContainer: HTMLElement) {
const pluginsContainer = tabContainer.querySelector('.installed-plugins-container');
// Remove previous event listener if it exists
if (this.handleThemeChange) {
if (this.colorSchemeMedia) {
this.colorSchemeMedia.removeEventListener("change", this.handleThemeChange);
}
}
// Create the event listener with the correct signature
this.handleThemeChange = (event: MediaQueryListEvent): void => {
const isDarkMode = event.matches; // true means dark mode is active
if (pluginsContainer) {
const githubIcons = pluginsContainer.querySelectorAll(
'div.setting-item > div.setting-item-control > div.github-icon'
);
// Iterate over each github icon and set the appropriate SVG
githubIcons.forEach((icon) => {
if (isDarkMode) {
icon.innerHTML = svg_github_dark;
} else {
icon.innerHTML = svg_github_light;
}
});
}
}
// Add an event listener for changes to the appearance mode
if (this.colorSchemeMedia) {
this.colorSchemeMedia.addEventListener("change", this.handleThemeChange);
}
}
async observeTab(tab: SettingTab) {
// just in case, remove previous observers if there are any
this.disconnectObservers();
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this;
@ -437,13 +485,16 @@ export default class PluginsAnnotations extends Plugin {
// there could be changes in the settings due to synchronization among devices
// which only happens after the plugin is loaded
await this.loadSettings();
await this.loadCommunityPluginsJson();
this.addIcon(tab);
this.addAnnotations(tab);
});
observer.observe(tab.containerEl, { childList: true, subtree: false });
this.mutationObserver = observer;
this.listenForThemeChange(tab.containerEl);
}
// force reload - this is convenient because since the loading of the plugin
@ -479,10 +530,10 @@ export default class PluginsAnnotations extends Plugin {
if(this.settings.editable) {
lockIcon.setAttribute('aria-label', 'Click to lock personal annotations');
lockIcon.innerHTML = this.svg_unlocked;
lockIcon.innerHTML = svg_unlocked;
} else {
lockIcon.setAttribute('aria-label', 'Click to be able to edit personal annotations');
lockIcon.innerHTML = this.svg_locked;
lockIcon.innerHTML = svg_locked;
}
lockIcon.addEventListener('click', (event:MouseEvent) => {
@ -491,10 +542,10 @@ export default class PluginsAnnotations extends Plugin {
this.debouncedSaveAnnotations();
if(this.settings.editable) {
lockIcon.setAttribute('aria-label', 'Click to lock personal annotations');
lockIcon.innerHTML = this.svg_unlocked;
lockIcon.innerHTML = svg_unlocked;
} else {
lockIcon.setAttribute('aria-label', 'Click to unlock personal annotations');
lockIcon.innerHTML = this.svg_locked;
lockIcon.innerHTML = svg_locked;
}
const plugins = tab.containerEl.querySelectorAll('.plugin-comment-annotation');
@ -526,7 +577,6 @@ export default class PluginsAnnotations extends Plugin {
// Remove the 'plugin-comment-placeholder' class
el.classList.remove('plugin-comment-placeholder');
}
});
});
@ -541,11 +591,38 @@ export default class PluginsAnnotations extends Plugin {
}
}
async loadCommunityPluginsJson() {
const url = 'https://raw.githubusercontent.com/obsidianmd/obsidian-releases/master/community-plugins.json';
try {
// Fetch the JSON data from the URL
const response = await fetch(url);
// Check if the response is OK (status code 200-299)
if (!response.ok) {
// throw new Error(`Failed to fetch: ${response.status} ${response.statusText}`);
return;
}
// Parse the JSON data
const pluginsData = (await response.json()) as CommunityPluginInfo[];
this.community_plugins = pluginsData.reduce((acc:CommunityPluginInfoDict, plugin:CommunityPluginInfo) => {
acc[plugin.id] = plugin;
return acc;
}, {} as CommunityPluginInfoDict);
} catch (error) {
console.error('Error loading community plugins JSON:', error);
}
}
addAnnotation(pluginDOMElement: Element) {
const pluginNameDiv = pluginDOMElement.querySelector('.setting-item-name');
const pluginName = pluginNameDiv ? pluginNameDiv.textContent : null;
if (!pluginName) {
console.log(pluginNameDiv);
console.warn('Plugin name not found');
return;
}
@ -556,8 +633,6 @@ export default class PluginsAnnotations extends Plugin {
return;
}
const manifest = this.app.plugins.manifests[pluginId];
const settingItemInfo = pluginDOMElement.querySelector('.setting-item-info');
if (settingItemInfo) {
const descriptionDiv = settingItemInfo.querySelector('.setting-item-description');
@ -567,29 +642,24 @@ export default class PluginsAnnotations extends Plugin {
const annotation_container = document.createElement('div');
annotation_container.className = 'plugin-comment';
new annotationControl(this,annotation_container,pluginId,pluginName);
const annotationControl = new AnnotationControl(this,annotation_container,pluginId,pluginName);
descriptionDiv.appendChild(annotation_container);
}
}
}
const controlDiv = pluginDOMElement.querySelector('.setting-item-control');
if (controlDiv) {
const GitHubDiv = document.createElement('div');
GitHubDiv.classList.add('clickable-icon', 'extra-setting-button');
GitHubDiv.setAttribute('aria-label', 'Open plugin\'s GitHub page');
GitHubDiv.innerHTML = this.svg_github_light;
// Get all elements with the class .clickable-icon inside controlDiv
const clickableIcons = controlDiv.querySelectorAll('.clickable-icon');
console.log(manifest);
// Insert the new icon as the second last of all clickable icons
if (clickableIcons.length > 0) {
const lastIcon = clickableIcons[clickableIcons.length - 1];
controlDiv.insertBefore(GitHubDiv, lastIcon);
} else {
// If no clickable icons are found, append it as the first child
controlDiv.insertBefore(GitHubDiv, controlDiv.firstChild);
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) {
annotationControl.addGitHubIcon(controlDiv,repo, this.colorSchemeMedia.matches);
}
}
}
}
}
}
}
}

View file

@ -6,7 +6,9 @@ import { App, normalizePath, Notice, Platform, PluginSettingTab, Setting, TextCo
import { PluginAnnotationDict } from "types";
import { parseFilePath, FileSuggestion, downloadJson, showConfirmationDialog, backupSettings, sortAnnotations } from "utils";
import { DEFAULT_SETTINGS } from 'defaults';
import { annotationControl } from "annotation_control";
import { AnnotationControl } from "annotation_control";
import { svg_locked, svg_unlocked } from "graphics";
declare const moment: typeof import('moment');
@ -110,13 +112,13 @@ export class PluginsAnnotationsSettingTab extends PluginSettingTab {
div.classList.add('plugin-comment-icon-container')
const unlock_icon = document.createElement('div');
unlock_icon.classList.add('clickable-icon');
unlock_icon.innerHTML = this.plugin.svg_unlocked;
unlock_icon.innerHTML = svg_unlocked;
unlock_icon.addEventListener('click', (event:MouseEvent) => {
editable_toggle.setValue(true);
});
const lock_icon = document.createElement('div');
lock_icon.classList.add('clickable-icon');
lock_icon.innerHTML = this.plugin.svg_locked;
lock_icon.innerHTML = svg_locked;
lock_icon.addEventListener('click', (event:MouseEvent) => {
editable_toggle.setValue(false);
});
@ -446,6 +448,32 @@ export class PluginsAnnotationsSettingTab extends PluginSettingTab {
});
});
const show_github_icons_setting = new Setting(containerEl)
.setName('Show GitHub links')
.setDesc("If this option is enabled, a clickable icon linking to the plugin's GitHub page will be displayed.");
let show_github_icons_toggle: ToggleComponent;
show_github_icons_setting.addToggle(toggle => {
show_github_icons_toggle = toggle;
toggle
.setValue(this.plugin.settings.show_github_icons)
.onChange(async (value: boolean) => {
this.plugin.settings.show_github_icons = value;
this.plugin.debouncedSaveAnnotations();
});
});
show_github_icons_setting.addExtraButton((button) => {
button
.setIcon("reset")
.setTooltip("Reset to default value")
.onClick(() => {
const value = DEFAULT_SETTINGS.show_github_icons
show_github_icons_toggle.setValue(value);
});
});
/* ====== Backups ====== */
this.backupManager = new BackupManager(this.plugin, containerEl);
@ -722,7 +750,7 @@ class UninstalledPluginsManager {
pluginSetting.descEl.dataset.plugin=pluginId;
// Render the annotation
new annotationControl(this.plugin,pluginSetting.descEl,pluginId,this.uninstalledPlugins[pluginId].name);
new AnnotationControl(this.plugin,pluginSetting.descEl,pluginId,this.uninstalledPlugins[pluginId].name);
// Set the attributes by applying the correct classes
pluginSetting.descEl.classList.add('plugin-comment-annotation');
@ -737,7 +765,7 @@ class UninstalledPluginsManager {
const pluginId = descEl.dataset.plugin;
if(pluginId) {
descEl.innerHTML = '';
new annotationControl(this.plugin,descEl,pluginId,this.uninstalledPlugins[pluginId].name);
new AnnotationControl(this.plugin,descEl,pluginId,this.uninstalledPlugins[pluginId].name);
}
}
});

View file

@ -28,7 +28,8 @@ export interface PluginsAnnotationsSettings {
editable: boolean;
automatic_remove: boolean;
markdown_file_path: string;
compatibility: string;
show_github_icons: boolean;
compatibility: "1.7.0";
backups: PluginBackup[];
}
@ -37,11 +38,12 @@ export function isPluginsAnnotationsSettings(s:unknown): s is PluginsAnnotations
return false;
}
return 'annotations' in s
&& 'compatibility' in s && (s as PluginsAnnotationsSettings).compatibility === '1.6.0'
&& 'compatibility' in s && (s as PluginsAnnotationsSettings).compatibility === '1.7.0'
&& 'plugins_annotations_uuid' in s
&& (s as PluginsAnnotationsSettings).plugins_annotations_uuid === DEFAULT_SETTINGS.plugins_annotations_uuid;
}
export function isPluginAnnotation(anno:unknown): anno is PluginAnnotation {
if (typeof anno !== 'object' || anno === null) {
return false;
@ -61,3 +63,13 @@ export interface ParsedPath {
ext: string,
path: string
}
export type CommunityPluginInfoDict = {[key:string]:CommunityPluginInfo};
export interface CommunityPluginInfo {
author: string,
description: string,
id: string,
name: string,
repo: string,
}

View file

@ -1,7 +1,34 @@
// types_legacy.ts
import { DEFAULT_SETTINGS_1_3_0, DEFAULT_SETTINGS_1_4_0, DEFAULT_SETTINGS_1_5_0 } from "defaults_legacy";
import { PluginAnnotation, PluginsAnnotationsSettings } from "types";
import { DEFAULT_SETTINGS_1_3_0, DEFAULT_SETTINGS_1_4_0, DEFAULT_SETTINGS_1_5_0, DEFAULT_SETTINGS_1_6_0 } from "defaults_legacy";
import { PluginAnnotation, PluginAnnotationDict, PluginBackup } from "types";
/* VERSION 1.6 */
export interface PluginsAnnotationsSettings_1_6_0 {
annotations: PluginAnnotationDict;
plugins_annotations_uuid: string;
hide_placeholders: boolean;
delete_placeholder_string_on_insertion: boolean;
label_mobile: string;
label_desktop: string;
label_placeholder: string;
editable: boolean;
automatic_remove: boolean;
markdown_file_path: string;
compatibility: "1.6.0";
backups: PluginBackup[];
}
export function isPluginsAnnotationsSettings_1_6_0(s:unknown): s is PluginsAnnotationsSettings_1_6_0 {
if (typeof s !== 'object' || s === null) {
return false;
}
return 'annotations' in s
&& 'compatibility' in s && (s as PluginsAnnotationsSettings_1_6_0).compatibility === '1.6.0'
&& 'plugins_annotations_uuid' in s
&& (s as PluginsAnnotationsSettings_1_6_0).plugins_annotations_uuid === DEFAULT_SETTINGS_1_6_0.plugins_annotations_uuid;
}
/* VERSION 1.5 */
@ -13,8 +40,9 @@ export interface PluginAnnotationDict_1_5_0 {
[pluginId: string]: PluginAnnotation_1_5_0;
}
export interface PluginsAnnotationsSettings_1_5_0 extends Omit<PluginsAnnotationsSettings, 'annotations' >{
export interface PluginsAnnotationsSettings_1_5_0 extends Omit<PluginsAnnotationsSettings_1_6_0, 'annotations' | 'compatibility' >{
annotations: PluginAnnotationDict_1_5_0;
compatibility: "1.5.0";
}
export function isPluginsAnnotationsSettings_1_5_0(s:unknown): s is PluginsAnnotationsSettings_1_5_0 {