mirror of
https://github.com/zadam/trilium.git
synced 2025-11-11 00:49:00 +01:00
chore(react/type_widget): add code block & image integration
This commit is contained in:
parent
fb46e09428
commit
2947682783
@ -11,11 +11,12 @@ import "@triliumnext/ckeditor5";
|
||||
import FNote from "../../../entities/fnote";
|
||||
import { getLocaleById } from "../../../services/i18n";
|
||||
import { getMermaidConfig } from "../../../services/mermaid";
|
||||
import { loadIncludedNote, refreshIncludedNote } from "./utils";
|
||||
import { loadIncludedNote, refreshIncludedNote, setupImageOpening } from "./utils";
|
||||
import { renderMathInElement } from "../../../services/math";
|
||||
import link from "../../../services/link";
|
||||
import { formatCodeBlocks } from "../../../services/syntax_highlight";
|
||||
|
||||
export default function ReadOnlyText({ note }: TypeWidgetProps) {
|
||||
export default function ReadOnlyText({ note, ntxId }: TypeWidgetProps) {
|
||||
const blob = useNoteBlob(note);
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const { isRtl } = useNoteLanguage(note);
|
||||
@ -29,6 +30,8 @@ export default function ReadOnlyText({ note }: TypeWidgetProps) {
|
||||
applyIncludedNotes(container);
|
||||
applyMath(container);
|
||||
applyReferenceLinks(container);
|
||||
formatCodeBlocks($(container));
|
||||
setupImageOpening(container, true);
|
||||
}, [ blob ]);
|
||||
|
||||
// React to included note changes.
|
||||
@ -37,6 +40,12 @@ export default function ReadOnlyText({ note }: TypeWidgetProps) {
|
||||
refreshIncludedNote(contentRef.current, noteId);
|
||||
});
|
||||
|
||||
// Search integration.
|
||||
useTriliumEvent("executeWithContentElement", ({ resolve, ntxId: eventNtxId }) => {
|
||||
if (eventNtxId !== ntxId || !contentRef.current) return;
|
||||
resolve($(contentRef.current));
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className="note-detail-readonly-text note-detail-printable"
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import appContext from "../../../components/app_context";
|
||||
import content_renderer from "../../../services/content_renderer";
|
||||
import froca from "../../../services/froca";
|
||||
import link from "../../../services/link";
|
||||
import utils from "../../../services/utils";
|
||||
|
||||
export async function loadIncludedNote(noteId: string, $el: JQuery<HTMLElement>) {
|
||||
const note = await froca.getNote(noteId);
|
||||
@ -25,3 +27,69 @@ export function refreshIncludedNote(container: HTMLDivElement, noteId: string) {
|
||||
loadIncludedNote(noteId, $(includedNote as HTMLElement));
|
||||
}
|
||||
}
|
||||
|
||||
export function setupImageOpening(container: HTMLDivElement, singleClickOpens: boolean) {
|
||||
const $container = $(container);
|
||||
$container.on("dblclick", "img", (e) => openImageInCurrentTab($(e.target)));
|
||||
$container.on("click", "img", (e) => {
|
||||
e.stopPropagation();
|
||||
const isLeftClick = e.which === 1;
|
||||
const isMiddleClick = e.which === 2;
|
||||
const ctrlKey = utils.isCtrlKey(e);
|
||||
const activate = (isLeftClick && ctrlKey && e.shiftKey) || (isMiddleClick && e.shiftKey);
|
||||
|
||||
if ((isLeftClick && ctrlKey) || isMiddleClick) {
|
||||
openImageInNewTab($(e.target), activate);
|
||||
} else if (isLeftClick && singleClickOpens) {
|
||||
openImageInCurrentTab($(e.target));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function openImageInCurrentTab($img: JQuery<HTMLElement>) {
|
||||
const parsedImage = await parseFromImage($img);
|
||||
|
||||
if (parsedImage) {
|
||||
appContext.tabManager.getActiveContext()?.setNote(parsedImage.noteId, { viewScope: parsedImage.viewScope });
|
||||
} else {
|
||||
window.open($img.prop("src"), "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
async function openImageInNewTab($img: JQuery<HTMLElement>, activate: boolean = false) {
|
||||
const parsedImage = await parseFromImage($img);
|
||||
|
||||
if (parsedImage) {
|
||||
appContext.tabManager.openTabWithNoteWithHoisting(parsedImage.noteId, { activate, viewScope: parsedImage.viewScope });
|
||||
} else {
|
||||
window.open($img.prop("src"), "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
async function parseFromImage($img: JQuery<HTMLElement>) {
|
||||
const imgSrc = $img.prop("src");
|
||||
|
||||
const imageNoteMatch = imgSrc.match(/\/api\/images\/([A-Za-z0-9_]+)\//);
|
||||
if (imageNoteMatch) {
|
||||
return {
|
||||
noteId: imageNoteMatch[1],
|
||||
viewScope: {}
|
||||
};
|
||||
}
|
||||
|
||||
const attachmentMatch = imgSrc.match(/\/api\/attachments\/([A-Za-z0-9_]+)\/image\//);
|
||||
if (attachmentMatch) {
|
||||
const attachmentId = attachmentMatch[1];
|
||||
const attachment = await froca.getAttachment(attachmentId);
|
||||
|
||||
return {
|
||||
noteId: attachment?.ownerId,
|
||||
viewScope: {
|
||||
viewMode: "attachments",
|
||||
attachmentId: attachmentId
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -13,71 +13,6 @@ export default class AbstractTextTypeWidget extends TypeWidget {
|
||||
this.refreshCodeBlockOptions();
|
||||
}
|
||||
|
||||
setupImageOpening(singleClickOpens: boolean) {
|
||||
this.$widget.on("dblclick", "img", (e) => this.openImageInCurrentTab($(e.target)));
|
||||
|
||||
this.$widget.on("click", "img", (e) => {
|
||||
e.stopPropagation();
|
||||
const isLeftClick = e.which === 1;
|
||||
const isMiddleClick = e.which === 2;
|
||||
const ctrlKey = utils.isCtrlKey(e);
|
||||
const activate = (isLeftClick && ctrlKey && e.shiftKey) || (isMiddleClick && e.shiftKey);
|
||||
|
||||
if ((isLeftClick && ctrlKey) || isMiddleClick) {
|
||||
this.openImageInNewTab($(e.target), activate);
|
||||
} else if (isLeftClick && singleClickOpens) {
|
||||
this.openImageInCurrentTab($(e.target));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async openImageInCurrentTab($img: JQuery<HTMLElement>) {
|
||||
const parsedImage = await this.parseFromImage($img);
|
||||
|
||||
if (parsedImage) {
|
||||
appContext.tabManager.getActiveContext()?.setNote(parsedImage.noteId, { viewScope: parsedImage.viewScope });
|
||||
} else {
|
||||
window.open($img.prop("src"), "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
async openImageInNewTab($img: JQuery<HTMLElement>, activate: boolean = false) {
|
||||
const parsedImage = await this.parseFromImage($img);
|
||||
|
||||
if (parsedImage) {
|
||||
appContext.tabManager.openTabWithNoteWithHoisting(parsedImage.noteId, { activate, viewScope: parsedImage.viewScope });
|
||||
} else {
|
||||
window.open($img.prop("src"), "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
async parseFromImage($img: JQuery<HTMLElement>) {
|
||||
const imgSrc = $img.prop("src");
|
||||
|
||||
const imageNoteMatch = imgSrc.match(/\/api\/images\/([A-Za-z0-9_]+)\//);
|
||||
if (imageNoteMatch) {
|
||||
return {
|
||||
noteId: imageNoteMatch[1],
|
||||
viewScope: {}
|
||||
};
|
||||
}
|
||||
|
||||
const attachmentMatch = imgSrc.match(/\/api\/attachments\/([A-Za-z0-9_]+)\/image\//);
|
||||
if (attachmentMatch) {
|
||||
const attachmentId = attachmentMatch[1];
|
||||
const attachment = await froca.getAttachment(attachmentId);
|
||||
|
||||
return {
|
||||
noteId: attachment?.ownerId,
|
||||
viewScope: {
|
||||
viewMode: "attachments",
|
||||
attachmentId: attachmentId
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async loadReferenceLinkTitle($el: JQuery<HTMLElement>, href: string | null = null) {
|
||||
await linkService.loadReferenceLinkTitle($el, href);
|
||||
|
||||
@ -5,39 +5,6 @@ import type { CommandListenerData, EventData } from "../../components/app_contex
|
||||
import appContext from "../../components/app_context.js";
|
||||
|
||||
export default class ReadOnlyTextTypeWidget extends AbstractTextTypeWidget {
|
||||
|
||||
private $content!: JQuery<HTMLElement>;
|
||||
|
||||
static getType() {
|
||||
return "readOnlyText";
|
||||
}
|
||||
|
||||
doRender() {
|
||||
this.$content = this.$widget.find(".note-detail-readonly-text-content");
|
||||
|
||||
this.setupImageOpening(true);
|
||||
|
||||
super.doRender();
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
this.$content.html("");
|
||||
}
|
||||
|
||||
async doRefresh(note: FNote) {
|
||||
await formatCodeBlocks(this.$content);
|
||||
}
|
||||
|
||||
async executeWithContentElementEvent({ resolve, ntxId }: EventData<"executeWithContentElement">) {
|
||||
if (!this.isNoteContext(ntxId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.initialized;
|
||||
|
||||
resolve(this.$content);
|
||||
}
|
||||
|
||||
buildTouchBarCommand({ TouchBar, buildIcon }: CommandListenerData<"buildTouchBar">) {
|
||||
return [
|
||||
new TouchBar.TouchBarSpacer({ size: "flexible" }),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user