mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-05-17 09:30:48 +08:00
This commit is contained in:
parent
17067c4d49
commit
aa677abb62
@ -11,30 +11,31 @@ import {getCurrentWindow} from "@electron/remote";
|
|||||||
import {focusByRange} from "../protyle/util/selection";
|
import {focusByRange} from "../protyle/util/selection";
|
||||||
import {Constants} from "../constants";
|
import {Constants} from "../constants";
|
||||||
|
|
||||||
const rectAnno = (config: any, pdf: any, element: HTMLElement) => {
|
export const initAnno = (file: string, element: HTMLElement, annoId: string, pdf: any, pdfConfig: any) => {
|
||||||
const rectAnnoElement = config.toolbar.rectAnno;
|
getConfig(pdf);
|
||||||
|
const rectAnnoElement = pdfConfig.toolbar.rectAnno;
|
||||||
rectAnnoElement.addEventListener("click", () => {
|
rectAnnoElement.addEventListener("click", () => {
|
||||||
if (rectAnnoElement.classList.contains("toggled")) {
|
if (rectAnnoElement.classList.contains("toggled")) {
|
||||||
rectAnnoElement.classList.remove("toggled");
|
rectAnnoElement.classList.remove("toggled");
|
||||||
config.mainContainer.classList.remove("rect-to-annotation");
|
pdfConfig.mainContainer.classList.remove("rect-to-annotation");
|
||||||
} else {
|
} else {
|
||||||
pdf.pdfCursorTools.switchTool(0);
|
pdf.pdfCursorTools.switchTool(0);
|
||||||
rectAnnoElement.classList.add("toggled");
|
rectAnnoElement.classList.add("toggled");
|
||||||
config.mainContainer.classList.add("rect-to-annotation");
|
pdfConfig.mainContainer.classList.add("rect-to-annotation");
|
||||||
if (getSelection().rangeCount > 0) {
|
if (getSelection().rangeCount > 0) {
|
||||||
getSelection().getRangeAt(0).collapse(true);
|
getSelection().getRangeAt(0).collapse(true);
|
||||||
}
|
}
|
||||||
hideToolbar(element);
|
hideToolbar(element);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const rectResizeElement = config.mainContainer.lastElementChild;
|
const rectResizeElement = pdfConfig.mainContainer.lastElementChild;
|
||||||
config.mainContainer.addEventListener("mousedown", (event: MouseEvent) => {
|
pdfConfig.mainContainer.addEventListener("mousedown", (event: MouseEvent) => {
|
||||||
if (event.button === 2 || !rectAnnoElement.classList.contains("toggled")) {
|
if (event.button === 2 || !rectAnnoElement.classList.contains("toggled")) {
|
||||||
// 右键
|
// 右键
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const canvasRect = pdf.pdfViewer._getVisiblePages().first.view.canvas.getBoundingClientRect();
|
const canvasRect = pdf.pdfViewer._getVisiblePages().first.view.canvas.getBoundingClientRect();
|
||||||
const containerRet = config.mainContainer.getBoundingClientRect();
|
const containerRet = pdfConfig.mainContainer.getBoundingClientRect();
|
||||||
const mostLeft = canvasRect.left;
|
const mostLeft = canvasRect.left;
|
||||||
const mostRight = canvasRect.right;
|
const mostRight = canvasRect.right;
|
||||||
const mostBottom = containerRet.bottom;
|
const mostBottom = containerRet.bottom;
|
||||||
@ -104,22 +105,18 @@ const rectAnno = (config: any, pdf: any, element: HTMLElement) => {
|
|||||||
documentSelf.onselectstart = null;
|
documentSelf.onselectstart = null;
|
||||||
documentSelf.onselect = null;
|
documentSelf.onselect = null;
|
||||||
rectAnnoElement.classList.remove("toggled");
|
rectAnnoElement.classList.remove("toggled");
|
||||||
config.mainContainer.classList.remove("rect-to-annotation");
|
pdfConfig.mainContainer.classList.remove("rect-to-annotation");
|
||||||
rectResizeElement.setAttribute("data-render", "true");
|
rectResizeElement.setAttribute("data-render", "true");
|
||||||
const utilElement = element.querySelector(".pdf__util") as HTMLElement;
|
const utilElement = element.querySelector(".pdf__util") as HTMLElement;
|
||||||
utilElement.classList.remove("pdf__util--hide", "fn__none");
|
utilElement.classList.remove("pdf__util--hide", "fn__none");
|
||||||
|
utilElement.setAttribute("data-mode", "rect");
|
||||||
const targetRect = rectResizeElement.getBoundingClientRect();
|
const targetRect = rectResizeElement.getBoundingClientRect();
|
||||||
setPosition(utilElement, targetRect.left,
|
setPosition(utilElement, targetRect.left,
|
||||||
targetRect.top + targetRect.height + 4);
|
targetRect.top + targetRect.height + 4);
|
||||||
rectElement = null;
|
rectElement = null;
|
||||||
element.querySelector(".pdf__util").classList.add("pdf__util--hide");
|
utilElement.classList.add("pdf__util--hide");
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
export const initAnno = (file: string, element: HTMLElement, annoId: string, pdf: any, pdfConfig: any) => {
|
|
||||||
getConfig(pdf);
|
|
||||||
rectAnno(pdfConfig, pdf, element);
|
|
||||||
|
|
||||||
element.addEventListener("click", (event) => {
|
element.addEventListener("click", (event) => {
|
||||||
let processed = false;
|
let processed = false;
|
||||||
@ -129,20 +126,37 @@ export const initAnno = (file: string, element: HTMLElement, annoId: string, pdf
|
|||||||
if (target.classList.contains("b3-color__square")) {
|
if (target.classList.contains("b3-color__square")) {
|
||||||
const color = target.style.backgroundColor;
|
const color = target.style.backgroundColor;
|
||||||
if (rectElement) {
|
if (rectElement) {
|
||||||
updateColor(pdf, color);
|
const config = getConfig(pdf);
|
||||||
|
const annoItem = config[rectElement.getAttribute("data-node-id")];
|
||||||
|
annoItem.color = color;
|
||||||
|
Array.from(rectElement.children).forEach((item: HTMLElement) => {
|
||||||
|
item.style.border = "2px solid " + color;
|
||||||
|
if (annoItem.type === "text") {
|
||||||
|
item.style.backgroundColor = color;
|
||||||
|
} else {
|
||||||
|
item.style.backgroundColor = "transparent";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fetchPost("/api/asset/setFileAnnotation", {
|
||||||
|
path: pdf.appConfig.file.replace(location.origin, "").substr(1) + ".sya",
|
||||||
|
data: JSON.stringify(config),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
let coords;
|
let coords;
|
||||||
if (pdfConfig.mainContainer.lastElementChild.classList.contains(
|
if (pdfConfig.mainContainer.lastElementChild.classList.contains("fn__none")) {
|
||||||
"fn__none")) {
|
|
||||||
coords = getHightlightCoordsByRange(pdf, color);
|
coords = getHightlightCoordsByRange(pdf, color);
|
||||||
} else {
|
} else {
|
||||||
coords = getHightlightCoordsByRect(pdf, color,
|
coords = getHightlightCoordsByRect(pdf, color, pdfConfig.mainContainer.lastElementChild);
|
||||||
pdfConfig.mainContainer.lastElementChild);
|
|
||||||
pdfConfig.mainContainer.lastElementChild.classList.add("fn__none");
|
pdfConfig.mainContainer.lastElementChild.classList.add("fn__none");
|
||||||
}
|
}
|
||||||
if (coords) {
|
if (coords) {
|
||||||
coords.forEach(item => {
|
coords.forEach((item, index) => {
|
||||||
showHighlight(item, pdf);
|
const newElement = showHighlight(item, pdf);
|
||||||
|
if (index === 0) {
|
||||||
|
rectElement = newElement;
|
||||||
|
copyAnno(`${pdf.appConfig.file.replace(location.origin, "").substr(1)}/${rectElement.getAttribute("data-node-id")}`,
|
||||||
|
pdf.appConfig.file.replace(location.origin, "").substr(8).replace(/-\d{14}-\w{7}.pdf$/, ""))
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,49 +173,46 @@ export const initAnno = (file: string, element: HTMLElement, annoId: string, pdf
|
|||||||
processed = true;
|
processed = true;
|
||||||
break;
|
break;
|
||||||
} else if (type === "remove") {
|
} else if (type === "remove") {
|
||||||
removeConfig(pdf, rectElement.getAttribute("data-node-id"));
|
const urlPath = pdf.appConfig.file.replace(location.origin, "").substr(1);
|
||||||
|
const config = getConfig(pdf);
|
||||||
|
delete config[rectElement.getAttribute("data-node-id")];
|
||||||
|
rectElement.remove();
|
||||||
|
fetchPost("/api/asset/setFileAnnotation", {
|
||||||
|
path: urlPath + ".sya",
|
||||||
|
data: JSON.stringify(config),
|
||||||
|
});
|
||||||
hideToolbar(element);
|
hideToolbar(element);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
processed = true;
|
processed = true;
|
||||||
break;
|
break;
|
||||||
} else if (type === "copy") {
|
} else if (type === "copy") {
|
||||||
const id = rectElement.getAttribute("data-node-id");
|
|
||||||
const text = rectElement.getAttribute("data-content");
|
|
||||||
if (rectElement.childElementCount === 1) {
|
|
||||||
/// #if !BROWSER
|
|
||||||
const rect = rectElement.firstElementChild.getBoundingClientRect();
|
|
||||||
getCurrentWindow().webContents.capturePage({
|
|
||||||
x: Math.floor(rect.x),
|
|
||||||
y: Math.floor(rect.y),
|
|
||||||
width: Math.floor(rect.width) + 2,
|
|
||||||
height: Math.floor(rect.height) + 2
|
|
||||||
}).then((image: NativeImage) => {
|
|
||||||
fetch(image.toDataURL()).then((response) => {
|
|
||||||
return response.blob();
|
|
||||||
}).then((blob) => {
|
|
||||||
const formData = new FormData();
|
|
||||||
const imageName = text + ".png";
|
|
||||||
formData.append("file[]", blob, imageName);
|
|
||||||
fetchPost(Constants.UPLOAD_ADDRESS, formData, (response) => {
|
|
||||||
writeText(`<<${pdf.appConfig.file.replace(location.origin, "").substr(1)}/${id} "${text}">>
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
/// #else
|
|
||||||
writeText(`<<${pdf.appConfig.file.replace(location.origin, "").substr(1)}/${id} "${text}">>`);
|
|
||||||
/// #endif
|
|
||||||
} else {
|
|
||||||
writeText(`<<${pdf.appConfig.file.replace(location.origin, "").substr(1)}/${id} "${text}">>`);
|
|
||||||
}
|
|
||||||
hideToolbar(element);
|
hideToolbar(element);
|
||||||
|
copyAnno(`${pdf.appConfig.file.replace(location.origin, "").substr(1)}/${rectElement.getAttribute("data-node-id")}`,
|
||||||
|
pdf.appConfig.file.replace(location.origin, "").substr(8).replace(/-\d{14}-\w{7}.pdf$/, ""))
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
processed = true;
|
processed = true;
|
||||||
break;
|
break;
|
||||||
} else if (type === "toggle") {
|
} else if (type === "toggle") {
|
||||||
updateType(pdf);
|
const config = getConfig(pdf);
|
||||||
|
const annoItem = config[rectElement.getAttribute("data-node-id")];
|
||||||
|
if (annoItem.type === "border") {
|
||||||
|
annoItem.type = "text";
|
||||||
|
} else {
|
||||||
|
annoItem.type = "border";
|
||||||
|
}
|
||||||
|
Array.from(rectElement.children).forEach((item: HTMLElement) => {
|
||||||
|
if (annoItem.type === "text") {
|
||||||
|
item.style.backgroundColor = item.style.border.replace("2px solid ", "");
|
||||||
|
} else {
|
||||||
|
item.style.backgroundColor = "";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fetchPost("/api/asset/setFileAnnotation", {
|
||||||
|
path: pdf.appConfig.file.replace(location.origin, "").substr(1) + ".sya",
|
||||||
|
data: JSON.stringify(config),
|
||||||
|
});
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
processed = true;
|
processed = true;
|
||||||
@ -252,47 +263,10 @@ export const initAnno = (file: string, element: HTMLElement, annoId: string, pdf
|
|||||||
return pdf;
|
return pdf;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateType = (pdf: any) => {
|
|
||||||
const config = getConfig(pdf);
|
|
||||||
const annoItem = config[rectElement.getAttribute("data-node-id")];
|
|
||||||
if (annoItem.type === "border") {
|
|
||||||
annoItem.type = "text";
|
|
||||||
} else {
|
|
||||||
annoItem.type = "border";
|
|
||||||
}
|
|
||||||
Array.from(rectElement.children).forEach((item: HTMLElement) => {
|
|
||||||
if (annoItem.type === "text") {
|
|
||||||
item.style.backgroundColor = item.style.border.replace("2px solid ", "");
|
|
||||||
} else {
|
|
||||||
item.style.backgroundColor = "";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fetchPost("/api/asset/setFileAnnotation", {
|
|
||||||
path: pdf.appConfig.file.replace(location.origin, "").substr(1) + ".sya",
|
|
||||||
data: JSON.stringify(config),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateColor = (pdf: any, color: string) => {
|
|
||||||
const config = getConfig(pdf);
|
|
||||||
const annoItem = config[rectElement.getAttribute("data-node-id")];
|
|
||||||
annoItem.color = color;
|
|
||||||
Array.from(rectElement.children).forEach((item: HTMLElement) => {
|
|
||||||
item.style.border = "2px solid " + color;
|
|
||||||
if (annoItem.type === "text") {
|
|
||||||
item.style.backgroundColor = color;
|
|
||||||
} else {
|
|
||||||
item.style.backgroundColor = "transparent";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
fetchPost("/api/asset/setFileAnnotation", {
|
|
||||||
path: pdf.appConfig.file.replace(location.origin, "").substr(1) + ".sya",
|
|
||||||
data: JSON.stringify(config),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const hideToolbar = (element: HTMLElement) => {
|
const hideToolbar = (element: HTMLElement) => {
|
||||||
element.querySelector(".pdf__util").classList.add("fn__none");
|
const utilElement = element.querySelector(".pdf__util")
|
||||||
|
utilElement.classList.add("fn__none");
|
||||||
|
utilElement.removeAttribute("data-mode");
|
||||||
};
|
};
|
||||||
|
|
||||||
let rectElement: HTMLElement;
|
let rectElement: HTMLElement;
|
||||||
@ -309,6 +283,7 @@ const showToolbar = (element: HTMLElement, range: Range, target?: HTMLElement) =
|
|||||||
utilElement.classList.remove("fn__none");
|
utilElement.classList.remove("fn__none");
|
||||||
|
|
||||||
if (range) {
|
if (range) {
|
||||||
|
utilElement.setAttribute("data-mode", "text");
|
||||||
utilElement.classList.add("pdf__util--hide");
|
utilElement.classList.add("pdf__util--hide");
|
||||||
const rects = range.getClientRects();
|
const rects = range.getClientRects();
|
||||||
const rect = rects[rects.length - 1];
|
const rect = rects[rects.length - 1];
|
||||||
@ -322,103 +297,6 @@ const showToolbar = (element: HTMLElement, range: Range, target?: HTMLElement) =
|
|||||||
setPosition(utilElement, targetRect.left, targetRect.top + targetRect.height + 4);
|
setPosition(utilElement, targetRect.left, targetRect.top + targetRect.height + 4);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getHightlightCoordsByRect = (pdf: any, color: string, rectResizeElement: HTMLElement) => {
|
|
||||||
const rect = rectResizeElement.getBoundingClientRect();
|
|
||||||
|
|
||||||
const startPageElement = hasClosestByClassName(document.elementFromPoint(rect.left, rect.top - 1), "page");
|
|
||||||
if (!startPageElement) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const startIndex = parseInt(
|
|
||||||
startPageElement.getAttribute("data-page-number")) - 1;
|
|
||||||
|
|
||||||
const startPage = pdf.pdfViewer.getPageView(startIndex);
|
|
||||||
const startPageRect = startPage.canvas.getClientRects()[0];
|
|
||||||
const startViewport = startPage.viewport;
|
|
||||||
|
|
||||||
const startSelected = startViewport.convertToPdfPoint(
|
|
||||||
rect.left - startPageRect.x,
|
|
||||||
rect.top - startPageRect.y).concat(startViewport.convertToPdfPoint(rect.right - startPageRect.x,
|
|
||||||
rect.bottom - startPageRect.y));
|
|
||||||
|
|
||||||
const pages: {
|
|
||||||
index: number
|
|
||||||
positions: number[]
|
|
||||||
}[] = [
|
|
||||||
{
|
|
||||||
index: startPage.id - 1,
|
|
||||||
positions: [startSelected],
|
|
||||||
}];
|
|
||||||
|
|
||||||
const id = Lute.NewNodeID();
|
|
||||||
const content = pdf.appConfig.file.replace(location.origin, "").substr(8).replace(/-\d{14}-\w{7}.pdf$/, "") +
|
|
||||||
`-P${startPage.id}-${dayjs().format("YYYYMMDDHHmmss")}`;
|
|
||||||
const result = [
|
|
||||||
{
|
|
||||||
index: startPage.id - 1,
|
|
||||||
coords: [startSelected],
|
|
||||||
id,
|
|
||||||
color,
|
|
||||||
content,
|
|
||||||
type: "border",
|
|
||||||
}];
|
|
||||||
|
|
||||||
let endPageElement = document.elementFromPoint(rect.right, rect.bottom + 1);
|
|
||||||
endPageElement = hasClosestByClassName(endPageElement, "page") as HTMLElement;
|
|
||||||
if (endPageElement) {
|
|
||||||
const endIndex = parseInt(
|
|
||||||
endPageElement.getAttribute("data-page-number")) - 1;
|
|
||||||
if (endIndex !== startIndex) {
|
|
||||||
const endPage = pdf.pdfViewer.getPageView(endIndex);
|
|
||||||
const endPageRect = endPage.canvas.getClientRects()[0];
|
|
||||||
const endViewport = endPage.viewport;
|
|
||||||
|
|
||||||
const endSelected = endViewport.convertToPdfPoint(
|
|
||||||
rect.left - endPageRect.x,
|
|
||||||
rect.top - endPageRect.y).concat(endViewport.convertToPdfPoint(rect.right - endPageRect.x,
|
|
||||||
rect.bottom - endPageRect.y));
|
|
||||||
pages.push({
|
|
||||||
index: endPage.id - 1,
|
|
||||||
positions: [endSelected],
|
|
||||||
});
|
|
||||||
result.push({
|
|
||||||
index: endPage.id - 1,
|
|
||||||
coords: [endSelected],
|
|
||||||
id,
|
|
||||||
color,
|
|
||||||
content,
|
|
||||||
type: "border",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setConfig(pdf, id, {
|
|
||||||
pages,
|
|
||||||
content,
|
|
||||||
color,
|
|
||||||
type: "border",
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
const mergeRects = (range: Range) => {
|
|
||||||
const rects = range.getClientRects();
|
|
||||||
const mergedRects: { left: number, top: number, right: number, bottom: number }[] = [];
|
|
||||||
let lastTop: number = undefined;
|
|
||||||
Array.from(rects).forEach(item => {
|
|
||||||
if (item.height === 0 || item.width === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof lastTop === "undefined" || Math.abs(lastTop - item.top) > 4) {
|
|
||||||
mergedRects.push({left: item.left, top: item.top, right: item.right, bottom: item.bottom});
|
|
||||||
lastTop = item.top;
|
|
||||||
} else {
|
|
||||||
mergedRects[mergedRects.length - 1].right = item.right;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return mergedRects;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getHightlightCoordsByRange = (pdf: any, color: string) => {
|
const getHightlightCoordsByRange = (pdf: any, color: string) => {
|
||||||
const range = window.getSelection().getRangeAt(0);
|
const range = window.getSelection().getRangeAt(0);
|
||||||
const startPageElement = hasClosestByClassName(range.startContainer, "page");
|
const startPageElement = hasClosestByClassName(range.startContainer, "page");
|
||||||
@ -503,6 +381,7 @@ const getHightlightCoordsByRange = (pdf: any, color: string) => {
|
|||||||
color,
|
color,
|
||||||
content,
|
content,
|
||||||
type: "text",
|
type: "text",
|
||||||
|
mode: "text",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (endSelected.length > 0) {
|
if (endSelected.length > 0) {
|
||||||
@ -510,8 +389,7 @@ const getHightlightCoordsByRange = (pdf: any, color: string) => {
|
|||||||
index: endIndex,
|
index: endIndex,
|
||||||
positions: endSelected,
|
positions: endSelected,
|
||||||
});
|
});
|
||||||
results.push(
|
results.push({index: endIndex, coords: endSelected, id, color, content, type: "text", mode: "text"});
|
||||||
{index: endIndex, coords: endSelected, id, color, content, type: "text"});
|
|
||||||
}
|
}
|
||||||
if (pages.length === 0) {
|
if (pages.length === 0) {
|
||||||
return;
|
return;
|
||||||
@ -521,10 +399,109 @@ const getHightlightCoordsByRange = (pdf: any, color: string) => {
|
|||||||
content,
|
content,
|
||||||
color,
|
color,
|
||||||
type: "text",
|
type: "text",
|
||||||
|
mode: "text",
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getHightlightCoordsByRect = (pdf: any, color: string, rectResizeElement: HTMLElement) => {
|
||||||
|
const rect = rectResizeElement.getBoundingClientRect();
|
||||||
|
|
||||||
|
const startPageElement = hasClosestByClassName(document.elementFromPoint(rect.left, rect.top - 1), "page");
|
||||||
|
if (!startPageElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const startIndex = parseInt(
|
||||||
|
startPageElement.getAttribute("data-page-number")) - 1;
|
||||||
|
|
||||||
|
const startPage = pdf.pdfViewer.getPageView(startIndex);
|
||||||
|
const startPageRect = startPage.canvas.getClientRects()[0];
|
||||||
|
const startViewport = startPage.viewport;
|
||||||
|
|
||||||
|
const startSelected = startViewport.convertToPdfPoint(
|
||||||
|
rect.left - startPageRect.x,
|
||||||
|
rect.top - startPageRect.y).concat(startViewport.convertToPdfPoint(rect.right - startPageRect.x,
|
||||||
|
rect.bottom - startPageRect.y));
|
||||||
|
|
||||||
|
const pages: {
|
||||||
|
index: number
|
||||||
|
positions: number[]
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
index: startPage.id - 1,
|
||||||
|
positions: [startSelected],
|
||||||
|
}];
|
||||||
|
|
||||||
|
const id = Lute.NewNodeID();
|
||||||
|
const content = pdf.appConfig.file.replace(location.origin, "").substr(8).replace(/-\d{14}-\w{7}.pdf$/, "") +
|
||||||
|
`-P${startPage.id}-${dayjs().format("YYYYMMDDHHmmss")}`;
|
||||||
|
const result = [{
|
||||||
|
index: startPage.id - 1,
|
||||||
|
coords: [startSelected],
|
||||||
|
id,
|
||||||
|
color,
|
||||||
|
content,
|
||||||
|
type: "border",
|
||||||
|
mode: "rect",
|
||||||
|
}];
|
||||||
|
|
||||||
|
let endPageElement = document.elementFromPoint(rect.right, rect.bottom + 1);
|
||||||
|
endPageElement = hasClosestByClassName(endPageElement, "page") as HTMLElement;
|
||||||
|
if (endPageElement) {
|
||||||
|
const endIndex = parseInt(
|
||||||
|
endPageElement.getAttribute("data-page-number")) - 1;
|
||||||
|
if (endIndex !== startIndex) {
|
||||||
|
const endPage = pdf.pdfViewer.getPageView(endIndex);
|
||||||
|
const endPageRect = endPage.canvas.getClientRects()[0];
|
||||||
|
const endViewport = endPage.viewport;
|
||||||
|
|
||||||
|
const endSelected = endViewport.convertToPdfPoint(
|
||||||
|
rect.left - endPageRect.x,
|
||||||
|
rect.top - endPageRect.y).concat(endViewport.convertToPdfPoint(rect.right - endPageRect.x,
|
||||||
|
rect.bottom - endPageRect.y));
|
||||||
|
pages.push({
|
||||||
|
index: endPage.id - 1,
|
||||||
|
positions: [endSelected],
|
||||||
|
});
|
||||||
|
result.push({
|
||||||
|
index: endPage.id - 1,
|
||||||
|
coords: [endSelected],
|
||||||
|
id,
|
||||||
|
color,
|
||||||
|
content,
|
||||||
|
type: "border",
|
||||||
|
mode: "rect",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfig(pdf, id, {
|
||||||
|
pages,
|
||||||
|
content,
|
||||||
|
color,
|
||||||
|
type: "border",
|
||||||
|
mode: "rect",
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
const mergeRects = (range: Range) => {
|
||||||
|
const rects = range.getClientRects();
|
||||||
|
const mergedRects: { left: number, top: number, right: number, bottom: number }[] = [];
|
||||||
|
let lastTop: number = undefined;
|
||||||
|
Array.from(rects).forEach(item => {
|
||||||
|
if (item.height === 0 || item.width === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof lastTop === "undefined" || Math.abs(lastTop - item.top) > 4) {
|
||||||
|
mergedRects.push({left: item.left, top: item.top, right: item.right, bottom: item.bottom});
|
||||||
|
lastTop = item.top;
|
||||||
|
} else {
|
||||||
|
mergedRects[mergedRects.length - 1].right = item.right;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return mergedRects;
|
||||||
|
};
|
||||||
|
|
||||||
export const getPdfInstance = (element: HTMLElement) => {
|
export const getPdfInstance = (element: HTMLElement) => {
|
||||||
let pdfInstance;
|
let pdfInstance;
|
||||||
@ -537,7 +514,6 @@ export const getPdfInstance = (element: HTMLElement) => {
|
|||||||
return pdfInstance;
|
return pdfInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const getHighlight = (element: HTMLElement) => {
|
export const getHighlight = (element: HTMLElement) => {
|
||||||
const pdfInstance: any = getPdfInstance(element);
|
const pdfInstance: any = getPdfInstance(element);
|
||||||
if (!pdfInstance) {
|
if (!pdfInstance) {
|
||||||
@ -562,8 +538,8 @@ export const getHighlight = (element: HTMLElement) => {
|
|||||||
color: item.color,
|
color: item.color,
|
||||||
content: item.content,
|
content: item.content,
|
||||||
type: item.type,
|
type: item.type,
|
||||||
},
|
mode: item.mode || ""
|
||||||
pdfInstance, pdfInstance.annoId === key);
|
}, pdfInstance, pdfInstance.annoId === key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -581,7 +557,7 @@ const showHighlight = (selected: IPdfAnno, pdf: any, hl?: boolean) => {
|
|||||||
}
|
}
|
||||||
textLayerElement = textLayerElement.lastElementChild;
|
textLayerElement = textLayerElement.lastElementChild;
|
||||||
|
|
||||||
let html = `<div class="pdf__rect popover__block" data-node-id="${selected.id}">`;
|
let html = `<div class="pdf__rect popover__block" data-node-id="${selected.id}" data-mode="${selected.mode}">`;
|
||||||
selected.coords.forEach((rect) => {
|
selected.coords.forEach((rect) => {
|
||||||
const bounds = viewport.convertToViewportRectangle(rect);
|
const bounds = viewport.convertToViewportRectangle(rect);
|
||||||
const width = Math.abs(bounds[0] - bounds[2]);
|
const width = Math.abs(bounds[0] - bounds[2]);
|
||||||
@ -599,11 +575,11 @@ const showHighlight = (selected: IPdfAnno, pdf: any, hl?: boolean) => {
|
|||||||
height: ${Math.abs(bounds[1] - bounds[3])}px"></div>`;
|
height: ${Math.abs(bounds[1] - bounds[3])}px"></div>`;
|
||||||
});
|
});
|
||||||
textLayerElement.insertAdjacentHTML("beforeend", html + "</div>");
|
textLayerElement.insertAdjacentHTML("beforeend", html + "</div>");
|
||||||
textLayerElement.lastElementChild.setAttribute("data-content",
|
textLayerElement.lastElementChild.setAttribute("data-content", selected.content);
|
||||||
selected.content);
|
|
||||||
if (hl) {
|
if (hl) {
|
||||||
hlPDFRect(textLayerElement, selected.id);
|
hlPDFRect(textLayerElement, selected.id);
|
||||||
}
|
}
|
||||||
|
return textLayerElement.lastElementChild;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hlPDFRect = (element: HTMLElement, id: string) => {
|
export const hlPDFRect = (element: HTMLElement, id: string) => {
|
||||||
@ -632,23 +608,46 @@ export const hlPDFRect = (element: HTMLElement, id: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const copyAnno = (idPath: string, fileName: string) => {
|
||||||
|
const mode = rectElement.getAttribute("data-mode")
|
||||||
|
const content = rectElement.getAttribute("data-content")
|
||||||
|
setTimeout(() => {
|
||||||
|
/// #if !BROWSER
|
||||||
|
if (mode === "rect" ||
|
||||||
|
(mode === "" && rectElement.childElementCount === 1 && content.startsWith(fileName)) // 兼容历史,以前没有 mode
|
||||||
|
) {
|
||||||
|
const rect = rectElement.firstElementChild.getBoundingClientRect();
|
||||||
|
getCurrentWindow().webContents.capturePage({
|
||||||
|
x: Math.floor(rect.x),
|
||||||
|
y: Math.floor(rect.y),
|
||||||
|
width: Math.floor(rect.width),
|
||||||
|
height: Math.floor(rect.height)
|
||||||
|
}).then((image: NativeImage) => {
|
||||||
|
fetch(image.toDataURL()).then((response) => {
|
||||||
|
return response.blob();
|
||||||
|
}).then((blob) => {
|
||||||
|
const formData = new FormData();
|
||||||
|
const imageName = content + ".png";
|
||||||
|
formData.append("file[]", blob, imageName);
|
||||||
|
fetchPost(Constants.UPLOAD_ADDRESS, formData, (response) => {
|
||||||
|
writeText(`<<${idPath} "${content}">>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
writeText(`<<${idPath} "${content}">>`);
|
||||||
|
}
|
||||||
|
/// #else
|
||||||
|
writeText(`<<${idPath} "${content}">>`);
|
||||||
|
/// #endif
|
||||||
|
}, Constants.TIMEOUT_DBLCLICK);
|
||||||
|
}
|
||||||
|
|
||||||
const setConfig = (pdf: any, id: string, data: IPdfAnno) => {
|
const setConfig = (pdf: any, id: string, data: IPdfAnno) => {
|
||||||
const urlPath = pdf.appConfig.file.replace(location.origin, "").substr(1);
|
const urlPath = pdf.appConfig.file.replace(location.origin, "").substr(1);
|
||||||
const config = getConfig(pdf);
|
const config = getConfig(pdf);
|
||||||
config[id] = data;
|
config[id] = data;
|
||||||
fetchPost("/api/asset/setFileAnnotation", {
|
|
||||||
path: urlPath + ".sya",
|
|
||||||
data: JSON.stringify(config),
|
|
||||||
}, () => {
|
|
||||||
writeText(`<<${urlPath}/${id} "${data.content}">>`);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeConfig = (pdf: any, id: string) => {
|
|
||||||
const urlPath = pdf.appConfig.file.replace(location.origin, "").substr(1);
|
|
||||||
const config = getConfig(pdf);
|
|
||||||
delete config[id];
|
|
||||||
rectElement.remove();
|
|
||||||
fetchPost("/api/asset/setFileAnnotation", {
|
fetchPost("/api/asset/setFileAnnotation", {
|
||||||
path: urlPath + ".sya",
|
path: urlPath + ".sya",
|
||||||
data: JSON.stringify(config),
|
data: JSON.stringify(config),
|
||||||
|
5
app/src/types/index.d.ts
vendored
5
app/src/types/index.d.ts
vendored
@ -113,8 +113,9 @@ interface IPdfAnno {
|
|||||||
}[]
|
}[]
|
||||||
index?: number,
|
index?: number,
|
||||||
color: string,
|
color: string,
|
||||||
type: string,
|
type: string, // border, text
|
||||||
content: string,
|
content: string, // rect, text
|
||||||
|
mode: string,
|
||||||
id?: string,
|
id?: string,
|
||||||
coords?: number[]
|
coords?: number[]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user