diff --git a/apps/client/src/widgets/NoteDetail.tsx b/apps/client/src/widgets/NoteDetail.tsx index d0eb6530a..06270a59a 100644 --- a/apps/client/src/widgets/NoteDetail.tsx +++ b/apps/client/src/widgets/NoteDetail.tsx @@ -14,6 +14,7 @@ import ContentWidget from "./type_widgets/ContentWidget"; import WebView from "./type_widgets/WebView"; import "./NoteDetail.css"; import File from "./type_widgets/File"; +import Image from "./type_widgets/Image"; /** * A `NoteType` altered by the note detail widget, taking into consideration whether the note is editable or not and adding special note types such as an empty one, @@ -70,6 +71,7 @@ function getCorrespondingWidget(noteType: ExtendedNoteType | undefined, props: T case "contentWidget": return case "webView": return case "file": return + case "image": return default: break; } } diff --git a/apps/client/src/widgets/type_widgets/Image.css b/apps/client/src/widgets/type_widgets/Image.css new file mode 100644 index 000000000..1e638f86b --- /dev/null +++ b/apps/client/src/widgets/type_widgets/Image.css @@ -0,0 +1,24 @@ +.type-image .note-detail { + height: 100%; +} + +.note-detail-image { + height: 100%; +} + +.note-detail-image-wrapper { + position: relative; + display: flex; + align-items: center; + overflow: hidden; + justify-content: center; + height: 100%; +} + +.note-detail-image-view { + display: block; + width: auto; + height: auto; + align-self: center; + flex-shrink: 0; +} \ No newline at end of file diff --git a/apps/client/src/widgets/type_widgets/Image.tsx b/apps/client/src/widgets/type_widgets/Image.tsx new file mode 100644 index 000000000..956a461bd --- /dev/null +++ b/apps/client/src/widgets/type_widgets/Image.tsx @@ -0,0 +1,46 @@ +import { useEffect, useRef, useState } from "preact/hooks"; +import { createImageSrcUrl } from "../../services/utils"; +import { useTriliumEvent, useUniqueName } from "../react/hooks"; +import "./Image.css"; +import { TypeWidgetProps } from "./type_widget"; +import WheelZoom from 'vanilla-js-wheel-zoom'; +import image_context_menu from "../../menus/image_context_menu"; +import { refToJQuerySelector } from "../react/react_utils"; +import { copyImageReferenceToClipboard } from "../../services/image"; + +export default function Image({ note, ntxId }: TypeWidgetProps) { + const uniqueId = useUniqueName("image"); + const containerRef = useRef(null); + + // Set up pan & zoom + useEffect(() => { + const zoomInstance = WheelZoom.create(`#${uniqueId}`, { + maxScale: 50, + speed: 1.3, + zoomOnClick: false + }); + + return () => zoomInstance.destroy(); + }, [ note ]); + + // Set up context menu + useEffect(() => image_context_menu.setupContextMenu(refToJQuerySelector(containerRef)), []); + + // Copy reference events + useTriliumEvent("copyImageReferenceToClipboard", ({ ntxId: eventNtxId }) => { + if (eventNtxId !== ntxId) return; + copyImageReferenceToClipboard(refToJQuerySelector(containerRef)); + }); + + return ( +
+
+ +
+
+ ) +} diff --git a/apps/client/src/widgets/type_widgets_old/image.ts b/apps/client/src/widgets/type_widgets_old/image.ts index e4afcbe1e..f5e337b7b 100644 --- a/apps/client/src/widgets/type_widgets_old/image.ts +++ b/apps/client/src/widgets/type_widgets_old/image.ts @@ -4,41 +4,6 @@ import imageContextMenuService from "../../menus/image_context_menu.js"; import imageService from "../../services/image.js"; import type FNote from "../../entities/fnote.js"; import type { EventData } from "../../components/app_context.js"; -import WheelZoom from 'vanilla-js-wheel-zoom'; - -const TPL = /*html*/` -
- - -
- -
-
`; class ImageTypeWidget extends TypeWidget { @@ -49,40 +14,7 @@ class ImageTypeWidget extends TypeWidget { return "image"; } - doRender() { - this.$widget = $(TPL); - this.$imageWrapper = this.$widget.find(".note-detail-image-wrapper"); - this.$imageView = this.$widget.find(".note-detail-image-view").attr("id", `image-view-${utils.randomString(10)}`); - - const initZoom = async () => { - const element = document.querySelector(`#${this.$imageView.attr("id")}`); - if (element) { - WheelZoom.create(`#${this.$imageView.attr("id")}`, { - maxScale: 50, - speed: 1.3, - zoomOnClick: false - }); - } else { - requestAnimationFrame(initZoom); - } - }; - initZoom(); - - imageContextMenuService.setupContextMenu(this.$imageView); - - super.doRender(); - } - - async doRefresh(note: FNote) { - this.$imageView.prop("src", utils.createImageSrcUrl(note)); - } - copyImageReferenceToClipboardEvent({ ntxId }: EventData<"copyImageReferenceToClipboard">) { - if (!this.isNoteContext(ntxId)) { - return; - } - - imageService.copyImageReferenceToClipboard(this.$imageWrapper); } async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {