Skip to content

Commit

Permalink
Implement suggestions and edit README
Browse files Browse the repository at this point in the history
  • Loading branch information
felipetappata committed Nov 19, 2024
1 parent e49b850 commit 2b0fda0
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 26 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

A plugin for [Obsidian](https://obsidian.md) that shows a preview of external links when hovering over them.

![Demo of Link Preview](demo.gif)

## Features

- Instantly preview external links without leaving Obsidian
Expand All @@ -18,7 +20,6 @@ A plugin for [Obsidian](https://obsidian.md) that shows a preview of external li

## Settings

- **Enable Preview**: Toggle the preview functionality on/off
- **Preview Delay**: Set how long to wait before showing the preview (in milliseconds)
- **Maximum Preview Height**: Set the maximum height of the preview window (in pixels)
- **Maximum Preview Width**: Set the maximum width of the preview window (in pixels)
Expand Down
Binary file added demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 26 additions & 24 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import { App, Plugin, PluginSettingTab, Setting } from 'obsidian';
interface LinkPreviewSettings {
previewDelay: number;
maxPreviewHeight: number;
enablePreview: boolean;
maxPreviewWidth: number;
}

// Default settings values
const DEFAULT_SETTINGS: LinkPreviewSettings = {
previewDelay: 300,
enablePreview: true,
maxPreviewHeight: 400,
maxPreviewWidth: 600
}
Expand All @@ -29,20 +27,31 @@ export default class LinkPreviewPlugin extends Plugin {
async onload() {
await this.loadSettings();

// Register the hover handler with cleanup
this.registerDomEvent(document, 'mouseover', (evt: MouseEvent) => {
// Register hover handler for main window
this.registerHoverHandler(document);

// Register for pop-out windows
this.registerEvent(
this.app.workspace.on('window-open', ({win}) => {
this.registerHoverHandler(win.document);
})
);

this.addSettingTab(new LinkPreviewSettingTab(this.app, this));
}

private registerHoverHandler(doc: Document) {
this.registerDomEvent(doc, 'mouseover', (evt: MouseEvent) => {
const target = evt.target as HTMLElement;
const linkEl = target.closest('a');

if (!linkEl || !this.settings.enablePreview) return;
if (!linkEl) return;

if (linkEl.hasClass('external-link')) {
const rect = linkEl.getBoundingClientRect();
this.showPreview(linkEl, rect);
this.showPreview(linkEl, rect, doc);
}
});

this.addSettingTab(new LinkPreviewSettingTab(this.app, this));
}

/**
Expand All @@ -61,22 +70,24 @@ export default class LinkPreviewPlugin extends Plugin {
* @param linkEl - The link element for which to create a preview
* @param rect - The bounding rectangle of the link element
*/
private showPreview(linkEl: HTMLElement, rect: DOMRect) {
private showPreview(linkEl: HTMLElement, rect: DOMRect, doc: Document) {
const url = linkEl.getAttribute('href');
if (!url) return;

const linkId = `preview-${url}`;
if (this.activeLinks.has(linkId)) return;

let hideTimeout: NodeJS.Timeout;
let hideTimeout: number;
const win = doc.defaultView;
if (!win) return;

const handleLinkLeave = () => {
hideTimeout = setTimeout(cleanupPreview, 300);
hideTimeout = win.setTimeout(cleanupPreview, 300);
};

const handlePreviewEnter = () => {
if (hideTimeout) {
clearTimeout(hideTimeout);
win.clearTimeout(hideTimeout);
}
};

Expand Down Expand Up @@ -128,7 +139,7 @@ export default class LinkPreviewPlugin extends Plugin {
hoverEl.addEventListener('mouseenter', handlePreviewEnter);
hoverEl.addEventListener('mouseleave', handlePreviewLeave);

document.body.appendChild(hoverEl);
doc.body.appendChild(hoverEl);
}, this.settings.previewDelay);
}

Expand All @@ -142,8 +153,9 @@ export default class LinkPreviewPlugin extends Plugin {
cls: 'hover-popup'
});

// Set dynamic positioning via cssText to avoid !important conflicts
// Use viewport-relative positioning - this will be relative to whatever window contains the element
el.style.cssText = `
position: fixed;
left: ${rect.left}px;
top: ${rect.bottom + 5}px;
width: ${this.settings.maxPreviewWidth}px;
Expand Down Expand Up @@ -178,16 +190,6 @@ class LinkPreviewSettingTab extends PluginSettingTab {

containerEl.empty();

new Setting(containerEl)
.setName('Enable preview')
.setDesc('Toggle link preview functionality')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enablePreview)
.onChange(async (value) => {
this.plugin.settings.enablePreview = value;
await this.plugin.saveSettings();
}));

new Setting(containerEl)
.setName('Preview delay')
.setDesc('How long to wait before showing the preview (in milliseconds)')
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"description": "Show a preview of external links on hover",
"author": "Felipe Tappata",
"authorUrl": "https://github.com/felipetappata",
"isDesktopOnly": true
"isDesktopOnly": false
}

0 comments on commit 2b0fda0

Please sign in to comment.