add: dblclick to preview images

This commit is contained in:
xiangyu 2022-11-17 17:26:57 +08:00
parent 5e0050b855
commit a28ade9f2a
4 changed files with 276 additions and 0 deletions

View File

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Image Preview</title>
</head>
<body>
<style>
html,
body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
#image {
position: relative;
/* top: 50%;
transform: translateY(-50%); */
vertical-align: middle;
}
.container {
height: calc(100% - 50px);
overflow: auto;
text-align: center;
}
.toolbar {
position: absolute;
bottom: 0px;
height: 50px;
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-evenly;
align-items: center;
}
</style>
<link rel="stylesheet" href="chrome://__addonRef__/skin/workspace.css" />
<script>
window.addEventListener("DOMContentLoaded", (e) => {
document.querySelector(".container").style["line-height"] = `${
window.innerHeight - 50
}px`;
window.addEventListener("resize", (_e) => {
document.querySelector(".container").style["line-height"] = `${
window.innerHeight - 50
}px`;
});
});
</script>
<div class="container">
<img id="image" src="" alt="" />
</div>
<div class="toolbar">
<div class="tooltip" id="left-container">
<button id="left" class="tool-button">
<svg
t="1668665847719"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="6765"
width="18"
height="18"
>
<path
d="M641.28 278.613333l-45.226667-45.226666-278.634666 278.762666 278.613333 278.485334 45.248-45.269334-233.365333-233.237333z"
p-id="6766"
></path>
</svg>
</button>
<span class="tooltiptext">Previous</span>
</div>
<div class="tooltip" id="right-container">
<button id="right" class="tool-button">
<svg
t="1668665870223"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="6907"
width="18"
height="18"
>
<path
d="M593.450667 512.128L360.064 278.613333l45.290667-45.226666 278.613333 278.762666L405.333333 790.613333l-45.226666-45.269333z"
p-id="6908"
></path>
</svg>
</button>
<span class="tooltiptext">Next</span>
</div>
</div>
</body>
</html>

View File

@ -19,6 +19,7 @@ import NoteExportWindow from "./note/noteExportWindow";
import NoteExport from "./note/noteExportController";
import EditorViews from "./editor/editorViews";
import EditorController from "./editor/editorController";
import EditorImageViewer from "./editor/imageViewerWindow";
import TemplateWindow from "./template/templateWindow";
class Knowledge4Zotero {
@ -49,6 +50,7 @@ class Knowledge4Zotero {
public NoteParse: NoteParse;
public EditorViews: EditorViews;
public EditorController: EditorController;
public EditorImageViewer: EditorImageViewer;
constructor() {
this.ZoteroEvents = new ZoteroEvents(this);
@ -59,6 +61,7 @@ class Knowledge4Zotero {
this.WorkspaceMenu = new WorkspaceMenu(this);
this.EditorViews = new EditorViews(this);
this.EditorController = new EditorController(this);
this.EditorImageViewer = new EditorImageViewer(this);
this.WizardWindow = new WizardWindow(this);
this.SyncInfoWindow = new SyncInfoWindow(this);
this.SyncListWindow = new SyncListWindow(this);

View File

@ -0,0 +1,164 @@
/*
* This file contains image viewer for note editor.
*/
import Knowledge4Zotero from "../addon";
import AddonBase from "../module";
class EditorImageViewer extends AddonBase {
_window: Window;
scaling: number;
srcList: string[];
idx: number;
title: string;
anchorPosition: {
left: number;
top: number;
};
constructor(parent: Knowledge4Zotero) {
super(parent);
this.scaling = 1;
this.title = "Note";
}
async onInit(srcs: string[], idx: number, title: string) {
if (!this._window || this._window.closed) {
this._window = window.open(
"chrome://Knowledge4Zotero/content/imageViewer.html",
"",
"chrome,centerscreen,resizable,status,width=400,height=450"
);
let t = 0;
console.log(this._window.document?.readyState);
// Wait for window
while (t < 500 && this._window.document.readyState !== "complete") {
console.log(this._window.document?.readyState);
await Zotero.Promise.delay(10);
t += 1;
}
this._window.document
.querySelector("#left")
.addEventListener("click", (e) => {
this.setIndex("left");
});
this._window.document
.querySelector("#right")
.addEventListener("click", (e) => {
this.setIndex("right");
});
const container = this._window.document.querySelector(
".container"
) as HTMLDivElement;
const img = this._window.document.querySelector(
"#image"
) as HTMLImageElement;
this._window.addEventListener("keydown", (e) => {
// ctrl+w or esc
if ((e.key === "w" && e.ctrlKey) || e.keyCode === 27) {
this._window.close();
}
this.anchorPosition = {
left: img.scrollWidth / 2 - container.scrollLeft / 2,
top: img.scrollHeight / 2 - container.scrollLeft / 2,
};
if (e.keyCode === 37 || e.keyCode === 40) {
this.setIndex("left");
}
if (e.keyCode === 38 || e.keyCode === 39) {
this.setIndex("right");
}
if (e.key === "0") {
this.setScale(1);
} else if (e.keyCode === 107 || e.keyCode === 187 || e.key === "=") {
this.setScale(this.scaling * 1.1);
} else if (e.key === "-") {
this.setScale(this.scaling / 1.1);
}
});
this._window.addEventListener("wheel", async (e) => {
this.anchorPosition = {
left: e.pageX - container.offsetLeft,
top: e.pageY - container.offsetTop,
};
function normalizeWheelEventDirection(evt) {
let delta = Math.hypot(evt.deltaX, evt.deltaY);
const angle = Math.atan2(evt.deltaY, evt.deltaX);
if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) {
// All that is left-up oriented has to change the sign.
delta = -delta;
}
return delta;
}
if (e.ctrlKey) {
const delta = normalizeWheelEventDirection(e);
this.setScale(
this.scaling *
Math.pow(delta > 0 ? 1.1 : 1 / 1.1, Math.round(Math.abs(delta)))
);
}
});
}
this.srcList = srcs;
this.idx = idx;
this.title = title || "Note";
this.setImage();
this.setScale(1);
this._window.focus();
}
private setImage() {
(this._window.document.querySelector("#image") as HTMLImageElement).src =
this.srcList[this.idx];
this.setTitle();
(
this._window.document.querySelector("#left-container") as HTMLButtonElement
).style.visibility = this.idx === 0 ? "hidden" : "visible";
(
this._window.document.querySelector("#right-container") as HTMLButtonElement
).style.visibility =
this.idx === this.srcList.length - 1 ? "hidden" : "visible";
}
private setIndex(type: "left" | "right") {
if (type === "left") {
this.idx > 0 ? (this.idx -= 1) : undefined;
}
if (type === "right") {
this.idx < this.srcList.length - 1 ? (this.idx += 1) : undefined;
}
this.setImage();
}
private setScale(scaling: number) {
const oldScale = this.scaling;
this.scaling = scaling;
if (this.scaling > 10) {
this.scaling = 10;
}
if (this.scaling < 0.1) {
this.scaling = 0.1;
}
const container = this._window.document.querySelector(
".container"
) as HTMLDivElement;
(
this._window.document.querySelector("#image") as HTMLImageElement
).style.width = `calc(100% * ${this.scaling})`;
if (this.scaling > 1) {
container.scrollLeft +=
this.anchorPosition.left * (this.scaling - oldScale);
container.scrollTop +=
this.anchorPosition.top * (this.scaling - oldScale);
}
}
private setTitle() {
this._window.document.querySelector("title").innerText = `${this.idx + 1}/${
this.srcList.length
}:${this.title}`;
}
}
export default EditorImageViewer;

View File

@ -319,6 +319,7 @@ class ZoteroEvents extends AddonBase {
Zotero.debug(`Knowledge4Zotero: note editor initialized.`);
if (!instance._knowledgeSelectionInitialized) {
// Put event listeners here to access Zotero instance
instance._iframeWindow.document.addEventListener(
"selectionchange",
async (e) => {
@ -412,6 +413,18 @@ class ZoteroEvents extends AddonBase {
}
}
);
instance._iframeWindow.document.addEventListener("dblclick", (e) => {
if ((e.target as HTMLElement).tagName === "IMG") {
const imgs = instance._iframeWindow.document
.querySelector(".primary-editor")
?.querySelectorAll("img");
this._Addon.EditorImageViewer.onInit(
Array.prototype.map.call(imgs, (e: HTMLImageElement) => e.src),
Array.prototype.indexOf.call(imgs, e.target),
instance._item.getNoteTitle()
);
}
});
instance._knowledgeSelectionInitialized = true;
}