Skip to content

Commit

Permalink
release: 0.37.12
Browse files Browse the repository at this point in the history
  • Loading branch information
RyotaUshio committed Mar 8, 2024
1 parent 4b0229d commit 754e949
Show file tree
Hide file tree
Showing 16 changed files with 485 additions and 126 deletions.
33 changes: 30 additions & 3 deletions src/backlink-visualizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,8 @@ export class BacklinkDomManager extends PDFPlusComponent {
for (const el of cacheToDoms.get(cache)) {
this.hookBacklinkOpeners(el, cache);
this.hookBacklinkViewEventHandlers(el, cache);
this.registerDomEvent(el, 'contextmenu', (evt) => {
onBacklinkVisualizerContextMenu(evt, this.visualizer, cache);
});
this.hookContextMenuHandler(el, cache);
this.hookClassAdderOnMouseOver(el, cache);

if (color?.type === 'name') {
el.dataset.highlightColor = color.name.toLowerCase();
Expand Down Expand Up @@ -178,6 +177,34 @@ export class BacklinkDomManager extends PDFPlusComponent {
}
});
}

hookContextMenuHandler(el: HTMLElement, cache: PDFBacklinkCache) {
this.registerDomEvent(el, 'contextmenu', (evt) => {
onBacklinkVisualizerContextMenu(evt, this.visualizer, cache);
});
}

hookClassAdderOnMouseOver(el: HTMLElement, cache: PDFBacklinkCache) {
const pageNumber = cache.page;

if (typeof pageNumber === 'number') {
const className = 'is-hovered';

el.addEventListener('mouseover', () => {
for (const otherEl of this.getCacheToDomsMap(pageNumber).get(cache)) {
otherEl.addClass(className);
}

const onMouseOut = () => {
for (const otherEl of this.getCacheToDomsMap(pageNumber).get(cache)) {
otherEl.removeClass(className);
}
el.removeEventListener('mouseout', onMouseOut);
};
el.addEventListener('mouseout', onMouseOut);
});
}
}
}


Expand Down
22 changes: 21 additions & 1 deletion src/color-palette.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export class ColorPalette extends Component {
});
}

addDropdown(paletteEl: HTMLElement, itemNames: string[], checkedIndexKey: KeysOfType<ColorPalette, number>, tooltip: string, onItemClick?: () => void) {
addDropdown(paletteEl: HTMLElement, itemNames: string[], checkedIndexKey: KeysOfType<ColorPalette, number>, tooltip: string, onItemClick?: () => void, beforeShowMenu?: (menu: Menu) => void) {
return paletteEl.createDiv('clickable-icon', (buttonEl) => {
setIcon(buttonEl, 'lucide-chevron-down');
setTooltip(buttonEl, tooltip);
Expand Down Expand Up @@ -169,6 +169,8 @@ export class ColorPalette extends Component {
});
}

beforeShowMenu?.(menu);

const { x, bottom, width } = buttonEl.getBoundingClientRect();
menu.setParentElement(buttonEl).showAtPosition({
x,
Expand Down Expand Up @@ -215,6 +217,15 @@ export class ColorPalette extends Component {
if (this.plugin.settings.syncColorPaletteAction && this.plugin.settings.syncDefaultColorPaletteAction) {
this.plugin.settings.defaultColorPaletteActionIndex = this.actionIndex;
}
},
(menu) => {
menu.addItem((item) => {
item.setTitle('Customize...')
.onClick(() => {
this.plugin.openSettingTab()
.scrollTo('copyCommands');
});
});
}
);
buttonEl.addClass('pdf-plus-action-menu');
Expand All @@ -231,6 +242,15 @@ export class ColorPalette extends Component {
if (this.plugin.settings.syncDisplayTextFormat && this.plugin.settings.syncDefaultDisplayTextFormat) {
this.plugin.settings.defaultDisplayTextFormatIndex = this.displayTextFormatIndex;
}
},
(menu) => {
menu.addItem((item) => {
item.setTitle('Customize...')
.onClick(() => {
this.plugin.openSettingTab()
.scrollTo('displayTextFormats');
});
});
}
);
buttonEl.addClass('pdf-plus-display-text-format-menu');
Expand Down
15 changes: 13 additions & 2 deletions src/context-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ export const onOutlineItemContextMenu = (plugin: PDFPlus, child: PDFViewerChild,
if (settings.openAfterExtractPages) {
const leaf = lib.workspace.getLeaf(settings.howToOpenExtractedPDF);
await leaf.openFile(file);
app.workspace.revealLeaf(leaf);
lib.workspace.revealLeaf(leaf);
}
});
});
Expand Down Expand Up @@ -380,7 +380,7 @@ export class PDFPlusContextMenu extends Menu {

static async fromMouseEvent(plugin: PDFPlus, child: PDFViewerChild, evt: MouseEvent) {
const menu = new PDFPlusContextMenu(plugin, child);
menu.addSections(['action', 'selection', 'selection-canvas', 'write-file', 'annotation', 'annotation-canvas', 'modify-annotation', 'link']);
menu.addSections(['action', 'selection', 'selection-canvas', 'write-file', 'annotation', 'annotation-canvas', 'modify-annotation', 'link', 'search']);
await menu.addItems(evt);
return menu;
}
Expand Down Expand Up @@ -628,6 +628,17 @@ export class PDFPlusContextMenu extends Menu {
}
}

if (plugin.settings.showCopyLinkToSearchInContextMenu) {
this.addItem((item) => {
item.setSection('search')
.setTitle('Copy link to search')
.setIcon('lucide-copy')
.onClick(() => {
lib.copyLink.copyLinkToSearch(false, child, pageNumber, selectedText.trim());
});
});
}

app.workspace.trigger('pdf-menu', this, {
pageNumber,
selection: selectedText,
Expand Down
6 changes: 3 additions & 3 deletions src/lib/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ export class PDFPlusCommands extends PDFPlusLibSubmodule {
if (this.settings.openAfterExtractPages) {
const leaf = this.lib.workspace.getLeaf(this.settings.howToOpenExtractedPDF);
await leaf.openFile(file);
this.app.workspace.revealLeaf(leaf);
this.lib.workspace.revealLeaf(leaf);
}
});
});
Expand Down Expand Up @@ -623,7 +623,7 @@ export class PDFPlusCommands extends PDFPlusLibSubmodule {
if (this.settings.openAfterExtractPages) {
const leaf = this.lib.workspace.getLeaf(this.settings.howToOpenExtractedPDF);
await leaf.openFile(file);
this.app.workspace.revealLeaf(leaf);
this.lib.workspace.revealLeaf(leaf);
}
});
});
Expand Down Expand Up @@ -783,7 +783,7 @@ export class PDFPlusCommands extends PDFPlusLibSubmodule {
const openFile = async () => {
const { leaf, isExistingLeaf } = await this.lib.copyLink.prepareMarkdownLeafForPaste(file);
if (leaf) {
this.app.workspace.revealLeaf(leaf);
this.lib.workspace.revealLeaf(leaf);
this.app.workspace.setActiveLeaf(leaf);
const view = leaf.view;
if (view instanceof MarkdownView) {
Expand Down
99 changes: 67 additions & 32 deletions src/lib/copy-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ export type AutoFocusTarget =
export class copyLinkLib extends PDFPlusLibSubmodule {
statusDurationMs = 2000;

getPageAndTextRangeFromSelection(selection?: Selection | null): { page: number, selection?: { beginIndex: number, beginOffset: number, endIndex: number, endOffset: number } } | null{
getPageAndTextRangeFromSelection(selection?: Selection | null): { page: number, selection?: { beginIndex: number, beginOffset: number, endIndex: number, endOffset: number } } | null {
selection = selection ?? activeWindow.getSelection();
if (!selection) return null;

const pageEl = this.lib.getPageElFromSelection(selection);
if (!pageEl || pageEl.dataset.pageNumber === undefined) return null;

const pageNumber = +pageEl.dataset.pageNumber;

const range = selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
Expand All @@ -38,7 +38,7 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
return { page: pageNumber };
}

// The same of getTextSelectionRangeStr in app.js, but returns an object instead of a string.
// The same as getTextSelectionRangeStr in Obsidian's app.js, but returns an object instead of a string.
getTextSelectionRange(pageEl: HTMLElement, range: Range) {
if (range && !range.collapsed) {
const startTextLayerNode = getTextLayerNode(pageEl, range.startContainer);
Expand Down Expand Up @@ -238,26 +238,31 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
}

if (!checking) {
const evaluated = this.getTextToCopy(child, template, undefined, file, page, subpath, text, colorName?.toLowerCase() ?? '');
navigator.clipboard.writeText(evaluated);
this.onCopyFinish(evaluated);
(async () => {
const evaluated = this.getTextToCopy(child, template, undefined, file, page, subpath, text, colorName?.toLowerCase() ?? '');
// Without await, the focus can move to a different document before `writeText` is completed
// if auto-focus is on and the PDF is opened in a secondary window, which causes the copy to fail.
// https://github.com/RyotaUshio/obsidian-pdf-plus/issues/93
await navigator.clipboard.writeText(evaluated);
this.onCopyFinish(evaluated);

const palette = this.lib.getColorPaletteFromChild(child);
palette?.setStatus('Link copied', this.statusDurationMs);
this.afterCopy(evaluated, autoPaste, palette ?? undefined);
const palette = this.lib.getColorPaletteFromChild(child);
palette?.setStatus('Link copied', this.statusDurationMs);
this.afterCopy(evaluated, autoPaste, palette ?? undefined);

// TODO: Needs refactor
const result = parsePDFSubpath(subpath);
if (result && 'beginIndex' in result) {
const item = child.getPage(page).textLayer?.textContentItems[result.beginIndex];
if (item) {
const left = item.transform[4];
const top = item.transform[5] + item.height;
if (typeof left === 'number' && typeof top === 'number') {
this.plugin.lastCopiedDestInfo = { file, destArray: [page - 1, 'XYZ', left, top, null] };
// TODO: Needs refactor
const result = parsePDFSubpath(subpath);
if (result && 'beginIndex' in result) {
const item = child.getPage(page).textLayer?.textContentItems[result.beginIndex];
if (item) {
const left = item.transform[4];
const top = item.transform[5] + item.height;
if (typeof left === 'number' && typeof top === 'number') {
this.plugin.lastCopiedDestInfo = { file, destArray: [page - 1, 'XYZ', left, top, null] };
}
}
}
}
})()
}

return true;
Expand All @@ -282,7 +287,7 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
subpath += `&rect=${rect[0]},${rect[1]},${rect[2]},${rect[3]}`;
}
const evaluated = this.getTextToCopy(child, template, undefined, file, page, subpath, text ?? '', color);
navigator.clipboard.writeText(evaluated);
await navigator.clipboard.writeText(evaluated);
this.onCopyFinish(evaluated);

const palette = this.lib.getColorPaletteFromChild(child);
Expand All @@ -305,13 +310,15 @@ export class copyLinkLib extends PDFPlusLibSubmodule {

copyLinkToAnnotationWithGivenTextAndFile(text: string, file: TFile, child: PDFViewerChild, checking: boolean, template: string, page: number, id: string, colorName: string, autoPaste?: boolean) {
if (!checking) {
const evaluated = this.getTextToCopy(child, template, undefined, file, page, `#page=${page}&annotation=${id}`, text, colorName)
navigator.clipboard.writeText(evaluated);
this.onCopyFinish(evaluated);
(async () => {
const evaluated = this.getTextToCopy(child, template, undefined, file, page, `#page=${page}&annotation=${id}`, text, colorName)
await navigator.clipboard.writeText(evaluated);
this.onCopyFinish(evaluated);

const palette = this.lib.getColorPaletteFromChild(child);
palette?.setStatus('Link copied', this.statusDurationMs);
this.afterCopy(evaluated, autoPaste, palette ?? undefined);
const palette = this.lib.getColorPaletteFromChild(child);
palette?.setStatus('Link copied', this.statusDurationMs);
this.afterCopy(evaluated, autoPaste, palette ?? undefined);
})();
}

return true;
Expand Down Expand Up @@ -386,7 +393,7 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
const extension = this.settings.rectImageExtension;

if (!this.settings.rectEmbedStaticImage) {
navigator.clipboard.writeText(text);
await navigator.clipboard.writeText(text);

this.onCopyFinish(text);
} else if (this.settings.rectImageFormat === 'file') {
Expand All @@ -395,7 +402,7 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
const imageEmbedLink = useWikilinks ? `![[${imagePath}]]` : `![](${encodeLinktext(imagePath)})`;
text = imageEmbedLink + '\n\n' + embedLink.slice(1);

navigator.clipboard.writeText(text);
await navigator.clipboard.writeText(text);

const createImageFile = async () => {
const buffer = await this.lib.pdfPageToImageArrayBuffer(page, { type: `image/${extension}`, cropRect: rect });
Expand All @@ -412,7 +419,7 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
const imageEmbedLink = `![](${dataUrl})`;
text = imageEmbedLink + '\n\n' + embedLink.slice(1);

navigator.clipboard.writeText(text);
await navigator.clipboard.writeText(text);

this.onCopyFinish(text);
}
Expand All @@ -427,6 +434,27 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
return true;
}

copyLinkToSearch(checking: boolean, child: PDFViewerChild, pageNumber: number, query: string, autoPaste?: boolean, sourcePath?: string): boolean {
if (!child.file) return false;
const file = child.file;

const palette = this.lib.getColorPaletteFromChild(child);

if (!checking) {
const display = this.lib.copyLink.getDisplayText(child, undefined, file, pageNumber, query);
const link = this.lib.generateMarkdownLink(file, '', `#search=${query}`, display).slice(1);

(async () => {
await navigator.clipboard.writeText(link);
this.onCopyFinish(link);
palette?.setStatus('Link copied', this.statusDurationMs);
await this.afterCopy(link, autoPaste, palette ?? undefined);
})();
}

return true;
}

makeCanvasTextNodeFromSelection(checking: boolean, canvas: Canvas, template: string, colorName?: string): boolean {
const variables = this.getTemplateVariables(colorName ? { color: colorName.toLowerCase() } : {});

Expand Down Expand Up @@ -538,7 +566,7 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
if (file) { // auto-focus target found
const { leaf, isExistingLeaf } = await this.prepareMarkdownLeafForPaste(file);
if (leaf) {
this.app.workspace.revealLeaf(leaf);
this.lib.workspace.revealLeaf(leaf);
this.app.workspace.setActiveLeaf(leaf);
const view = leaf.view;
if (view instanceof MarkdownView) {
Expand Down Expand Up @@ -646,7 +674,8 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
if (leaf && isExistingLeaf && leaf.view instanceof MarkdownView) {
// If the file is already opened in some tab, use the editor interface to respect the current cursor position
// https://github.com/RyotaUshio/obsidian-pdf-plus/issues/71
const editor = leaf.view.editor;
const view = leaf.view;
const editor = view.editor;

if (this.settings.respectCursorPositionWhenAutoPaste) {
editor.replaceSelection(text);
Expand All @@ -658,8 +687,14 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
editor.setValue(data);
}

// MarkdownView's file saving is debounced, so we need to
// explicitly save the new data right after pasting so that
// the backlink highlight will be visibile as soon as possible.
view.save();

if (this.settings.focusEditorAfterAutoPaste) {
editor.focus();
this.lib.workspace.revealLeaf(leaf);
}
} else {
// Otherwise we just use the vault interface
Expand All @@ -680,7 +715,7 @@ export class copyLinkLib extends PDFPlusLibSubmodule {
this.app.workspace.offref(eventRef);

if (info instanceof MarkdownView) {
this.app.workspace.revealLeaf(info.leaf);
this.lib.workspace.revealLeaf(info.leaf);
}

if (!editor.hasFocus()) editor.focus();
Expand Down
8 changes: 6 additions & 2 deletions src/lib/highlights/viewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,12 @@ export class ViewerHighlightLib extends PDFPlusLibSubmodule {
return rectEl;
}

highlightSubpath(child: PDFViewerChild, subpath: string, duration: number) {
child.applySubpath(subpath);
/**
*
* @param child
* @param duration The duration in seconds to highlight the subpath. If it's 0, the highlight will not be removed until the user clicks on the page.
*/
highlightSubpath(child: PDFViewerChild, duration: number) {
if (child.subpathHighlight?.type === 'text') {
const component = new Component();
component.load();
Expand Down
Loading

0 comments on commit 754e949

Please sign in to comment.