mirror of
https://github.com/signynt/virtual-content.git
synced 2026-07-22 05:46:44 +00:00
Fixed linting errors and updated minAppVersion
This commit is contained in:
parent
10470c6110
commit
fcfb985658
3 changed files with 81 additions and 176 deletions
252
main.ts
252
main.ts
|
|
@ -15,6 +15,12 @@ import {
|
|||
WorkspaceLeaf,
|
||||
} from 'obsidian';
|
||||
|
||||
declare module 'obsidian' {
|
||||
interface ButtonComponent {
|
||||
setDestructive(): this;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Enums ---
|
||||
|
||||
/** Defines the type of a rule, determining how it matches files (e.g., by folder, tag, or property). */
|
||||
|
|
@ -348,7 +354,7 @@ export class VirtualContentView extends ItemView {
|
|||
|
||||
const data = this.contentProvider();
|
||||
if (data && data.content && data.content.trim() !== '') {
|
||||
MarkdownRenderer.render(this.app, data.content, this.viewContent, data.sourcePath, this.component);
|
||||
void MarkdownRenderer.render(this.app, data.content, this.viewContent, data.sourcePath, this.component);
|
||||
this.plugin.attachInternalLinkHandlers(this.viewContent, data.sourcePath, this.component);
|
||||
} else {
|
||||
this.viewContent.createEl('p', {
|
||||
|
|
@ -404,6 +410,10 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
return workspaceFile instanceof TFile ? workspaceFile : null;
|
||||
}
|
||||
|
||||
private getActiveDocument(): Document {
|
||||
return activeDocument;
|
||||
}
|
||||
|
||||
private async processSidebarContentForFilePath(filePath: string): Promise<void> {
|
||||
const applicableRulesWithContent = await this._getApplicableRulesAndContent(filePath);
|
||||
const contentSeparator = "\n\n";
|
||||
|
|
@ -471,14 +481,14 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
this.registerDynamicViews();
|
||||
|
||||
this.addRibbonIcon('text-select', 'Open virtual content in sidebar', () => {
|
||||
this.activateView(VIRTUAL_CONTENT_VIEW_TYPE);
|
||||
void this.activateView(VIRTUAL_CONTENT_VIEW_TYPE);
|
||||
});
|
||||
|
||||
this.addCommand({
|
||||
id: 'open-virtual-content-sidebar',
|
||||
name: 'Open virtual content in sidebar',
|
||||
callback: () => {
|
||||
this.activateView(VIRTUAL_CONTENT_VIEW_TYPE);
|
||||
void this.activateView(VIRTUAL_CONTENT_VIEW_TYPE);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -486,10 +496,12 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
id: 'open-all-virtual-content-sidebar-tabs',
|
||||
name: 'Open all virtual footer sidebar tabs',
|
||||
callback: () => {
|
||||
this.activateAllSidebarViews();
|
||||
void this.activateAllSidebarViews();
|
||||
},
|
||||
});
|
||||
|
||||
const activeDocument = this.getActiveDocument();
|
||||
|
||||
// Define event handlers
|
||||
const handleViewUpdate = () => {
|
||||
// Always trigger an update if the layout is ready.
|
||||
|
|
@ -533,14 +545,14 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
);
|
||||
|
||||
// Listen for hover events to detect when popovers are created
|
||||
this.registerDomEvent(document, 'mouseover', (event: MouseEvent) => {
|
||||
this.registerDomEvent(activeDocument, 'mouseover', (event: MouseEvent) => {
|
||||
const target = event.target as HTMLElement;
|
||||
// Check if the target is a link that could trigger a popover
|
||||
if (target.matches('a.internal-link, .internal-link a, [data-href]')) {
|
||||
// Store the last hovered link for popover file path extraction
|
||||
this.lastHoveredLink = target;
|
||||
// Delay to allow popover to be created
|
||||
setTimeout(() => {this.processPopoverViews();}, 100);
|
||||
window.setTimeout(() => { this.processPopoverViews(); }, 100);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -552,7 +564,7 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
collapseIndicator?.closest('.markdown-preview-view') &&
|
||||
sectionHeaderTarget
|
||||
) {
|
||||
setTimeout(() => {
|
||||
window.setTimeout(() => {
|
||||
const activeView = this.app.workspace.getActiveViewOfType(MarkdownView);
|
||||
if (activeView) {
|
||||
this.refreshSectionHeaderContent(activeView, true, sectionHeaderTarget);
|
||||
|
|
@ -560,10 +572,10 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
}, 150);
|
||||
}
|
||||
};
|
||||
document.addEventListener('click', handleSectionCollapseClick, true);
|
||||
this.register(() => document.removeEventListener('click', handleSectionCollapseClick, true));
|
||||
activeDocument.addEventListener('click', handleSectionCollapseClick, true);
|
||||
this.register(() => activeDocument.removeEventListener('click', handleSectionCollapseClick, true));
|
||||
|
||||
this.registerDomEvent(document, 'scroll', (event: Event) => {
|
||||
this.registerDomEvent(activeDocument, 'scroll', (event: Event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
if (!target.closest?.('.markdown-preview-view')) {
|
||||
return;
|
||||
|
|
@ -581,14 +593,14 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
}, true);
|
||||
|
||||
// Listen for clicks to detect when popovers might switch to editing mode
|
||||
this.registerDomEvent(document, 'click', (event: MouseEvent) => {
|
||||
this.registerDomEvent(activeDocument, 'click', (event: MouseEvent) => {
|
||||
const target = event.target as HTMLElement;
|
||||
// Check if the click is within a popover
|
||||
const popover = target.closest('.popover.hover-popover');
|
||||
if (popover) {
|
||||
//console.log("VirtualContent: Click detected in popover, checking for mode change");
|
||||
// Delay to allow any mode changes to complete
|
||||
setTimeout(() => {this.processPopoverViews();}, 150);
|
||||
window.setTimeout(() => { this.processPopoverViews(); }, 150);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -597,30 +609,29 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
for (const mutation of mutations) {
|
||||
if (mutation.type === 'childList') {
|
||||
mutation.addedNodes.forEach(node => {
|
||||
if (node instanceof HTMLElement) {
|
||||
if (node.instanceOf(HTMLElement)) {
|
||||
// Check if a popover was added
|
||||
if (node.classList.contains('popover') && node.classList.contains('hover-popover')) {
|
||||
//console.log("VirtualContent: Popover created, processing views");
|
||||
// Small delay to ensure the popover content is fully loaded
|
||||
setTimeout(() => {this.processPopoverViews();}, 50);
|
||||
window.setTimeout(() => { this.processPopoverViews(); }, 50);
|
||||
}
|
||||
// Also check for popovers added within other elements
|
||||
const popovers = node.querySelectorAll('.popover.hover-popover');
|
||||
if (popovers.length > 0) {
|
||||
//console.log("VirtualContent: Popover(s) found in added content, processing views");
|
||||
setTimeout(() => {this.processPopoverViews();}, 50);
|
||||
window.setTimeout(() => { this.processPopoverViews(); }, 50);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// Listen for attribute changes that might indicate mode switching in popovers
|
||||
if (mutation.type === 'attributes' && mutation.target instanceof HTMLElement) {
|
||||
if (mutation.type === 'attributes' && mutation.target.instanceOf(HTMLElement)) {
|
||||
const target = mutation.target;
|
||||
// Check if this is a popover that gained or lost the is-editing class
|
||||
if (target.classList.contains('popover') && target.classList.contains('hover-popover')) {
|
||||
if (mutation.attributeName === 'class') {
|
||||
const hasEditingClass = target.classList.contains('is-editing');
|
||||
//console.log(`VirtualContent: Popover mode changed, is-editing: ${hasEditingClass}`);
|
||||
//console.log(`VirtualContent: Popover mode changed, is-editing: ${target.classList.contains('is-editing')}`);
|
||||
//setTimeout(() => {this.processPopoverViews();}, 100); // Slightly longer delay for mode changes
|
||||
}
|
||||
}
|
||||
|
|
@ -630,7 +641,7 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
|
||||
// Observe the entire document for popover creation
|
||||
if (this.popoverObserver) {
|
||||
this.popoverObserver.observe(document.body, {
|
||||
this.popoverObserver.observe(activeDocument.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
|
|
@ -643,13 +654,13 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
if (mutation.type === 'childList') {
|
||||
const addedOrRemovedNodes = [...mutation.addedNodes, ...mutation.removedNodes];
|
||||
const hasCanvasNodeChange = addedOrRemovedNodes.some((node) => {
|
||||
return node instanceof HTMLElement && (node.classList.contains('canvas-node') || node.querySelector('.canvas-node'));
|
||||
return node.instanceOf(HTMLElement) && (node.classList.contains('canvas-node') || node.querySelector('.canvas-node'));
|
||||
});
|
||||
if (hasCanvasNodeChange) {
|
||||
this.queueCanvasEmbedRefresh();
|
||||
}
|
||||
}
|
||||
if (mutation.type === 'attributes' && mutation.target instanceof HTMLElement) {
|
||||
if (mutation.type === 'attributes' && mutation.target.instanceOf(HTMLElement)) {
|
||||
const target = mutation.target;
|
||||
if (target.classList.contains('canvas-node')) {
|
||||
this.queueCanvasEmbedRefresh();
|
||||
|
|
@ -659,7 +670,7 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
});
|
||||
|
||||
if (this.canvasObserver) {
|
||||
this.canvasObserver.observe(document.body, {
|
||||
this.canvasObserver.observe(activeDocument.body, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
attributes: true,
|
||||
|
|
@ -673,8 +684,8 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
this.queueCanvasEmbedRefresh();
|
||||
}
|
||||
};
|
||||
this.registerDomEvent(document, 'wheel', this.canvasInteractionHandler, true);
|
||||
this.registerDomEvent(document, 'pointerup', this.canvasInteractionHandler, true);
|
||||
this.registerDomEvent(activeDocument, 'wheel', this.canvasInteractionHandler, true);
|
||||
this.registerDomEvent(activeDocument, 'pointerup', this.canvasInteractionHandler, true);
|
||||
}
|
||||
|
||||
// Initial processing for any currently active view, once layout is ready
|
||||
|
|
@ -690,19 +701,19 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
* Called when the plugin is unloaded.
|
||||
* Cleans up all injected content and observers.
|
||||
*/
|
||||
async onunload() {
|
||||
onunload() {
|
||||
this.popoverObserver?.disconnect();
|
||||
this.canvasObserver?.disconnect();
|
||||
this.app.workspace.detachLeavesOfType(VIRTUAL_CONTENT_VIEW_TYPE);
|
||||
this.settings.rules.forEach((rule, index) => {
|
||||
for (const [index, rule] of this.settings.rules.entries()) {
|
||||
if (rule.renderLocation === RenderLocation.Sidebar && rule.showInSeparateTab) {
|
||||
this.app.workspace.detachLeavesOfType(this.getSeparateViewId(index));
|
||||
}
|
||||
});
|
||||
}
|
||||
this.clearAllViewsDynamicContent();
|
||||
|
||||
// Clean up any remaining DOM elements and components directly
|
||||
document.querySelectorAll(`.${CSS_DYNAMIC_CONTENT_ELEMENT}`).forEach(el => {
|
||||
const activeDocument = this.getActiveDocument();
|
||||
activeDocument.querySelectorAll(`.${CSS_DYNAMIC_CONTENT_ELEMENT}`).forEach(el => {
|
||||
const componentHolder = el as HTMLElementWithComponent;
|
||||
if (componentHolder.component) {
|
||||
componentHolder.component.unload();
|
||||
|
|
@ -711,8 +722,8 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
});
|
||||
|
||||
// Remove custom CSS classes applied for styling
|
||||
document.querySelectorAll(`.${CSS_VIRTUAL_FOOTER_CM_PADDING}`).forEach(el => el.classList.remove(CSS_VIRTUAL_FOOTER_CM_PADDING));
|
||||
document.querySelectorAll(`.${CSS_VIRTUAL_FOOTER_REMOVE_FLEX}`).forEach(el => el.classList.remove(CSS_VIRTUAL_FOOTER_REMOVE_FLEX));
|
||||
activeDocument.querySelectorAll(`.${CSS_VIRTUAL_FOOTER_CM_PADDING}`).forEach(el => el.classList.remove(CSS_VIRTUAL_FOOTER_CM_PADDING));
|
||||
activeDocument.querySelectorAll(`.${CSS_VIRTUAL_FOOTER_REMOVE_FLEX}`).forEach(el => el.classList.remove(CSS_VIRTUAL_FOOTER_REMOVE_FLEX));
|
||||
|
||||
// WeakMaps will be garbage collected, but explicit clearing is good practice if needed.
|
||||
// Observers and pending injections are cleared per-view in `removeDynamicContentFromView`.
|
||||
|
|
@ -782,7 +793,8 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
*/
|
||||
private processPopoverViews(): void {
|
||||
// Find all popover elements in the DOM
|
||||
const popovers = document.querySelectorAll('.popover.hover-popover');
|
||||
const activeDocument = this.getActiveDocument();
|
||||
const popovers = activeDocument.querySelectorAll('.popover.hover-popover');
|
||||
|
||||
popovers.forEach(popover => {
|
||||
// Look for markdown views within each popover
|
||||
|
|
@ -1061,16 +1073,17 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
}
|
||||
|
||||
private getCanvasNodes(): HTMLElement[] {
|
||||
const canvasRoot = document.querySelector('.canvas');
|
||||
const activeDocument = this.getActiveDocument();
|
||||
const canvasRoot = activeDocument.querySelector('.canvas');
|
||||
const scopedNodes = canvasRoot ? Array.from(canvasRoot.querySelectorAll<HTMLElement>('.canvas-node')) : [];
|
||||
if (scopedNodes.length > 0) {
|
||||
return scopedNodes;
|
||||
}
|
||||
return Array.from(document.querySelectorAll<HTMLElement>('.canvas-node'));
|
||||
return Array.from(activeDocument.querySelectorAll<HTMLElement>('.canvas-node'));
|
||||
}
|
||||
|
||||
private isCanvasActive(): boolean {
|
||||
return !!document.querySelector('.workspace-leaf.mod-active .canvas, .workspace-leaf.mod-active .canvas-wrapper');
|
||||
return !!this.getActiveDocument().querySelector('.workspace-leaf.mod-active .canvas, .workspace-leaf.mod-active .canvas-wrapper');
|
||||
}
|
||||
|
||||
private async processCanvasEmbeds(): Promise<void> {
|
||||
|
|
@ -1080,7 +1093,8 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
if (!this.isCanvasActive()) {
|
||||
return;
|
||||
}
|
||||
const canvasRoot = document.querySelector('.canvas');
|
||||
const activeDocument = this.getActiveDocument();
|
||||
const canvasRoot = activeDocument.querySelector('.canvas');
|
||||
if (!canvasRoot) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -1260,7 +1274,8 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
const specialClass = isHeader ? 'virtual-footer-above-properties' : 'virtual-footer-above-backlinks';
|
||||
|
||||
// Create new content container
|
||||
const groupDiv = document.createElement('div') as HTMLElementWithComponent;
|
||||
const activeDocument = this.getActiveDocument();
|
||||
const groupDiv = activeDocument.createElement('div') as HTMLElementWithComponent;
|
||||
groupDiv.className = `${CSS_DYNAMIC_CONTENT_ELEMENT} ${cssClass}`;
|
||||
groupDiv.dataset.sourcePath = filePath;
|
||||
if (special) {
|
||||
|
|
@ -1443,7 +1458,8 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
const component = new Component();
|
||||
component.load();
|
||||
|
||||
const groupDiv = document.createElement('div') as HTMLElementWithComponent;
|
||||
const activeDocument = this.getActiveDocument();
|
||||
const groupDiv = activeDocument.createElement('div') as HTMLElementWithComponent;
|
||||
groupDiv.className = `${CSS_DYNAMIC_CONTENT_ELEMENT} ${CSS_SECTION_HEADER_GROUP_ELEMENT}`;
|
||||
this.setSectionHeaderDataset(groupDiv, rule, ruleIndex);
|
||||
groupDiv.dataset.sourcePath = filePath;
|
||||
|
|
@ -1704,7 +1720,7 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
private getPreviewSectionEnd(heading: HTMLElement, level: number): Node | null {
|
||||
let node: Node | null = heading.parentElement?.nextSibling || heading.nextSibling;
|
||||
while (node) {
|
||||
if (node instanceof HTMLElement) {
|
||||
if (node.instanceOf(HTMLElement)) {
|
||||
const nextHeading = node.matches('h1,h2,h3,h4,h5,h6')
|
||||
? node
|
||||
: node.querySelector<HTMLElement>('h1,h2,h3,h4,h5,h6');
|
||||
|
|
@ -1723,7 +1739,7 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
private getEditorSectionEnd(headingLine: HTMLElement, level: number): Node | null {
|
||||
let node: Node | null = headingLine.nextSibling;
|
||||
while (node) {
|
||||
if (node instanceof HTMLElement) {
|
||||
if (node.instanceOf(HTMLElement)) {
|
||||
for (let currentLevel = 1; currentLevel <= level; currentLevel++) {
|
||||
if (node.classList.contains(`HyperMD-header-${currentLevel}`)) {
|
||||
return node;
|
||||
|
|
@ -1910,7 +1926,8 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
const component = new Component();
|
||||
component.load();
|
||||
|
||||
const groupDiv = document.createElement('div') as HTMLElementWithComponent;
|
||||
const activeDocument = this.getActiveDocument();
|
||||
const groupDiv = activeDocument.createElement('div') as HTMLElementWithComponent;
|
||||
groupDiv.className = `${CSS_DYNAMIC_CONTENT_ELEMENT} ${CSS_SECTION_HEADER_GROUP_ELEMENT}`;
|
||||
this.setSectionHeaderDataset(groupDiv, rule, ruleIndex);
|
||||
groupDiv.dataset.sourcePath = sourcePath;
|
||||
|
|
@ -1941,7 +1958,7 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
} else {
|
||||
const endNode = this.getPreviewSectionEnd(heading, level);
|
||||
if (endNode) {
|
||||
const previousElement = endNode.previousSibling instanceof HTMLElement ? endNode.previousSibling : null;
|
||||
const previousElement = endNode.previousSibling?.instanceOf(HTMLElement) ? endNode.previousSibling : null;
|
||||
if (previousElement && previousElement !== anchor) {
|
||||
previousElement.appendChild(groupDiv);
|
||||
} else {
|
||||
|
|
@ -1987,7 +2004,8 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
const sourcePath = view.file?.path || ''; // For MarkdownRenderer context
|
||||
|
||||
// Create container div for the content
|
||||
const groupDiv = document.createElement('div') as HTMLElementWithComponent;
|
||||
const activeDocument = this.getActiveDocument();
|
||||
const groupDiv = activeDocument.createElement('div') as HTMLElementWithComponent;
|
||||
groupDiv.className = CSS_DYNAMIC_CONTENT_ELEMENT; // Base class for all injected content
|
||||
groupDiv.classList.add(
|
||||
isRenderInHeader ? CSS_HEADER_GROUP_ELEMENT : CSS_FOOTER_GROUP_ELEMENT,
|
||||
|
|
@ -2021,16 +2039,18 @@ export default class VirtualFooterPlugin extends Plugin {
|
|||
placeholderEl.createEl("p", { text: "Loading virtual content..." });
|
||||
|
||||
// Schedule a retry after a delay to allow other plugins to initialize
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
placeholderEl.remove();
|
||||
await MarkdownRenderer.render(this.app, combinedContentText, groupDiv, sourcePath, component);
|
||||
this.attachInternalLinkHandlers(groupDiv, sourcePath, component);
|
||||
} catch (secondError) {
|
||||
console.error("VirtualFooter: Failed to render content after retry:", secondError);
|
||||
const errorEl = groupDiv.createEl("div", { cls: "virtual-footer-error" });
|
||||
errorEl.createEl("p", { text: "Error rendering virtual content. Please reload the page or check the content for errors." });
|
||||
}
|
||||
window.setTimeout(() => {
|
||||
void (async () => {
|
||||
try {
|
||||
placeholderEl.remove();
|
||||
await MarkdownRenderer.render(this.app, combinedContentText, groupDiv, sourcePath, component);
|
||||
this.attachInternalLinkHandlers(groupDiv, sourcePath, component);
|
||||
} catch (secondError) {
|
||||
console.error("VirtualFooter: Failed to render content after retry:", secondError);
|
||||
const errorEl = groupDiv.createEl("div", { cls: "virtual-footer-error" });
|
||||
errorEl.createEl("p", { text: "Error rendering virtual content. Please reload the page or check the content for errors." });
|
||||
}
|
||||
})();
|
||||
}, 2000); // 2 second delay
|
||||
}
|
||||
|
||||
|
|
@ -3642,7 +3662,7 @@ class RuleEditorModal extends Modal {
|
|||
setting.addButton(button => button
|
||||
.setIcon('trash')
|
||||
.setTooltip('Delete condition')
|
||||
.setWarning()
|
||||
.setDestructive()
|
||||
.onClick(() => {
|
||||
this.workingRule.conditions?.splice(index, 1);
|
||||
this.render();
|
||||
|
|
@ -3905,122 +3925,8 @@ class VirtualFooterSettingTab extends PluginSettingTab {
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the settings tab UI.
|
||||
* This method is called by Obsidian on versions before 1.13.0.
|
||||
*/
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
this.clearSuggestionCaches();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Render in source mode')
|
||||
.setDesc('If enabled, virtual content will be rendered in source mode. By default, content only appears in Live Preview and Reading modes.')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.renderInSourceMode ?? false)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.renderInSourceMode = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Refresh on focus change')
|
||||
.setDesc('If enabled, virtual content will refresh when switching files. This can cause a slight flicker but ensures immediate updates.')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.refreshOnFileOpen ?? false)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.refreshOnFileOpen = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Refresh on metadata change')
|
||||
.setDesc('If enabled, virtual content will refresh when the current note\'s metadata changes.')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.refreshOnMetadataChange ?? false)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.refreshOnMetadataChange = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Smart property links')
|
||||
.setDesc('If enabled, property conditions that look like links match against the resolved file.')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.smartPropertyLinks ?? false)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.smartPropertyLinks = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Embed rendering')
|
||||
.setDesc('If enabled, virtual content will render inside embedded notes such as ![[Link]].')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.enableEmbedRendering ?? false)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.enableEmbedRendering = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Canvas rendering')
|
||||
.setDesc('If enabled, virtual content can be rendered inside Canvas note cards. Restart Obsidian after changing this setting.')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.enableCanvasRendering ?? false)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.enableCanvasRendering = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
|
||||
containerEl.createEl('h3', { text: 'Rules' });
|
||||
const rules = this.plugin.settings.rules ?? [];
|
||||
rules.forEach((rule, index) => {
|
||||
const row = new Setting(containerEl)
|
||||
.setName(this.getRuleDisplayName(rule, index))
|
||||
.setDesc(this.getRuleSummary(rule));
|
||||
|
||||
row.addButton(button => button
|
||||
.setButtonText('Edit')
|
||||
.setCta()
|
||||
.onClick(() => this.openEditRuleModal(index)));
|
||||
row.addButton(button => button
|
||||
.setButtonText('Duplicate')
|
||||
.onClick(() => this.duplicateRule(index)));
|
||||
row.addButton(button => button
|
||||
.setIcon('arrow-up')
|
||||
.setTooltip('Move rule up')
|
||||
.setDisabled(index === 0)
|
||||
.onClick(() => this.moveRule(index, index - 1)));
|
||||
row.addButton(button => button
|
||||
.setIcon('arrow-down')
|
||||
.setTooltip('Move rule down')
|
||||
.setDisabled(index === rules.length - 1)
|
||||
.onClick(() => this.moveRule(index, index + 1)));
|
||||
row.addButton(button => button
|
||||
.setButtonText('Delete')
|
||||
.setWarning()
|
||||
.onClick(() => this.deleteRule(index)));
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.addButton(button => button
|
||||
.setButtonText('Add rule')
|
||||
.setCta()
|
||||
.onClick(() => this.openNewRuleModal()));
|
||||
|
||||
containerEl.createEl('h3', { text: 'Developer' });
|
||||
new Setting(containerEl)
|
||||
.setName('Debug embed/canvas rendering')
|
||||
.setDesc('If enabled, logs embed/canvas path resolution details to the developer console for troubleshooting.')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.debugEmbedCanvas ?? false)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.debugEmbedCanvas = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
}
|
||||
// eslint-disable-next-line obsidianmd/no-deprecated-api
|
||||
display(): void {}
|
||||
|
||||
private clearSuggestionCaches(): void {
|
||||
this.allFolderPathsCache = null;
|
||||
|
|
@ -4033,8 +3939,6 @@ class VirtualFooterSettingTab extends PluginSettingTab {
|
|||
const updater = (this as unknown as { update?: () => void }).update;
|
||||
if (typeof updater === 'function') {
|
||||
updater.call(this);
|
||||
} else {
|
||||
this.display();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4095,13 +3999,13 @@ class VirtualFooterSettingTab extends PluginSettingTab {
|
|||
const [moved] = rules.splice(fromIndex, 1);
|
||||
rules.splice(toIndex, 0, moved);
|
||||
await this.plugin.saveSettings();
|
||||
this.display();
|
||||
this.refreshSettingsUi();
|
||||
}
|
||||
|
||||
private async deleteRule(index: number): Promise<void> {
|
||||
this.plugin.settings.rules.splice(index, 1);
|
||||
await this.plugin.saveSettings();
|
||||
this.display();
|
||||
this.refreshSettingsUi();
|
||||
}
|
||||
|
||||
private getRuleDisplayName(rule: Rule, index: number): string {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"id": "virtual-footer",
|
||||
"name": "Virtual Content",
|
||||
"version": "1.0.36",
|
||||
"minAppVersion": "0.15.0",
|
||||
"minAppVersion": "1.13.0",
|
||||
"description": "Display markdown text (including dataview queries or Bases) at the bottom, top or in the sidebar for all notes which match a specified rule, without modifying them.",
|
||||
"author": "Signynt",
|
||||
"authorUrl": "https://github.com/Signynt",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
{
|
||||
"1.0.0": "0.15.0"
|
||||
"1.0.32": "0.15.0",
|
||||
"1.0.36": "1.13.0"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue