Vanessa 2022-10-28 23:29:07 +08:00
parent 01ee358a61
commit ced6f0165d
2 changed files with 157 additions and 120 deletions

View file

@ -3,6 +3,7 @@ import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName} from "../
import {fetchSyncPost} from "../util/fetch";
import {hideTooltip, showTooltip} from "../dialog/tooltip";
let popoverTargetElement: HTMLElement
export const initBlockPopover = () => {
let timeout: number;
let timeoutHide: number;
@ -35,6 +36,17 @@ export const initBlockPopover = () => {
hideTooltip();
}
if (window.siyuan.config.editor.floatWindowMode === 1) {
if (!getTarget(event, aElement)) {
hidePopover(event);
return;
}
if (window.siyuan.ctrlIsPressed) {
showPopover()
}
return;
}
clearTimeout(timeout);
clearTimeout(timeoutHide);
timeoutHide = window.setTimeout(() => {
@ -45,9 +57,9 @@ export const initBlockPopover = () => {
) {
// b3-menu 需要处理,(( 后的 hint 上的图表移上去需显示预览
// gutter & mindmap & 文件树上的数字 & 关系图节点不处理
return;
return false;
}
let popoverTargetElement = hasClosestByAttribute(event.target, "data-type", "block-ref") as HTMLElement ||
popoverTargetElement = hasClosestByAttribute(event.target, "data-type", "block-ref") as HTMLElement ||
hasClosestByAttribute(event.target, "data-type", "virtual-block-ref") as HTMLElement;
if (popoverTargetElement && popoverTargetElement.classList.contains("b3-tooltips")) {
popoverTargetElement = undefined;
@ -60,133 +72,154 @@ export const initBlockPopover = () => {
popoverTargetElement = linkElement;
}
if (!popoverTargetElement) {
const blockElement = hasClosestByClassName(event.target, "block__popover", true);
const maxEditLevels: { [key: string]: number } = {oid: 0};
window.siyuan.blockPanels.forEach((item) => {
if (item.targetElement && item.element.getAttribute("data-pin") === "true") {
const level = parseInt(item.element.getAttribute("data-level"));
const oid = item.element.getAttribute("data-oid");
if (maxEditLevels[oid]) {
if (level > maxEditLevels[oid]) {
maxEditLevels[oid] = level;
}
} else {
maxEditLevels[oid] = level; // 不能为1否则 pin 住第三层,第二层会消失
}
}
});
if (blockElement) {
for (let i = 0; i < window.siyuan.blockPanels.length; i++) {
const item = window.siyuan.blockPanels[i];
if (item.targetElement &&
parseInt(item.element.getAttribute("data-level")) > (maxEditLevels[item.element.getAttribute("data-oid")] || 0) &&
item.element.getAttribute("data-pin") === "false" &&
parseInt(item.element.getAttribute("data-level")) > parseInt(blockElement.getAttribute("data-level"))) {
item.destroy();
i--;
}
}
} else {
for (let i = 0; i < window.siyuan.blockPanels.length; i++) {
const item = window.siyuan.blockPanels[i];
if (item.targetElement && item.element.getAttribute("data-pin") === "false" &&
parseInt(item.element.getAttribute("data-level")) > (maxEditLevels[item.element.getAttribute("data-oid")] || 0)) {
item.destroy();
i--;
}
}
}
hidePopover(event)
return;
}
if (!popoverTargetElement && !aElement) {
clearTimeout(timeout);
}
}, 200);
timeout = window.setTimeout(async () => {
if (hasClosestByClassName(event.target, "history__repo", true)) {
if (!getTarget(event, aElement)) {
return;
}
let popoverTargetElement = hasClosestByAttribute(event.target, "data-type", "block-ref") as HTMLElement ||
hasClosestByAttribute(event.target, "data-type", "virtual-block-ref") as HTMLElement;
if (popoverTargetElement && popoverTargetElement.classList.contains("b3-tooltips")) {
popoverTargetElement = undefined;
}
if (!popoverTargetElement) {
popoverTargetElement = hasClosestByClassName(event.target, "popover__block") as HTMLElement;
}
if (!popoverTargetElement && aElement && aElement.getAttribute("data-href")?.startsWith("siyuan://blocks") && aElement.getAttribute("prevent-popover") !== "true") {
popoverTargetElement = aElement;
}
if (!popoverTargetElement || window.siyuan.altIsPressed || window.siyuan.shiftIsPressed || window.siyuan.ctrlIsPressed ||
(popoverTargetElement && popoverTargetElement.getAttribute("prevent-popover") === "true")) {
return;
}
// https://github.com/siyuan-note/siyuan/issues/4314
if (popoverTargetElement && getSelection().rangeCount > 0) {
const range = getSelection().getRangeAt(0);
if (range.toString() !== "" && popoverTargetElement.contains(range.startContainer)) {
return;
}
}
clearTimeout(timeoutHide);
let ids: string[];
let defIds: string[];
const dataId = popoverTargetElement.getAttribute("data-id");
if (dataId) {
// backlink/util/hint/正文标题 上的弹层
if (dataId.startsWith("[")) {
ids = JSON.parse(dataId);
} else {
ids = [dataId];
}
defIds = JSON.parse(popoverTargetElement.getAttribute("data-defids") || "[]");
} else if (popoverTargetElement.getAttribute("data-type")?.indexOf("virtual-block-ref") > -1) {
const nodeElement = hasClosestBlock(popoverTargetElement);
if (nodeElement) {
const postResponse = await fetchSyncPost("/api/block/getBlockDefIDsByRefText", {
anchor: popoverTargetElement.textContent,
excludeIDs: [nodeElement.getAttribute("data-node-id")]
});
ids = postResponse.data;
}
} else if (popoverTargetElement.getAttribute("data-type")?.split(" ").includes("a")) {
// 以思源协议开头的链接
ids = [popoverTargetElement.getAttribute("data-href").substr(16, 22)];
} else {
// pdf
let targetId;
let url = "/api/block/getRefIDs";
if (popoverTargetElement.classList.contains("protyle-attr--refcount")) {
// 编辑器中的引用数
targetId = popoverTargetElement.parentElement.parentElement.getAttribute("data-node-id");
} else if (popoverTargetElement.classList.contains("pdf__rect")) {
targetId = popoverTargetElement.getAttribute("data-node-id");
url = "/api/block/getRefIDsByFileAnnotationID";
} else if (!targetId) {
// 文件树中的引用数
targetId = popoverTargetElement.parentElement.getAttribute("data-node-id");
}
const postResponse = await fetchSyncPost(url, {id: targetId});
ids = postResponse.data.refIDs;
defIds = postResponse.data.defIDs;
}
let hasPin = false;
window.siyuan.blockPanels.find((item) => {
if (item.targetElement && item.element.getAttribute("data-pin") === "true"
&& JSON.stringify(ids) === JSON.stringify(item.nodeIds)) {
hasPin = true;
return true;
}
});
if (!hasPin &&
popoverTargetElement.parentElement.style.opacity !== "0.1" // 反向面板图标拖拽时不应该弹层
) {
window.siyuan.blockPanels.push(new BlockPanel({
targetElement: popoverTargetElement,
nodeIds: ids,
defIds,
}));
}
showPopover()
}, 620);
});
};
const hidePopover = (event: MouseEvent & { target: HTMLElement }) => {
const blockElement = hasClosestByClassName(event.target, "block__popover", true);
const maxEditLevels: { [key: string]: number } = {oid: 0};
window.siyuan.blockPanels.forEach((item) => {
if (item.targetElement && item.element.getAttribute("data-pin") === "true") {
const level = parseInt(item.element.getAttribute("data-level"));
const oid = item.element.getAttribute("data-oid");
if (maxEditLevels[oid]) {
if (level > maxEditLevels[oid]) {
maxEditLevels[oid] = level;
}
} else {
maxEditLevels[oid] = level; // 不能为1否则 pin 住第三层,第二层会消失
}
}
});
if (blockElement) {
for (let i = 0; i < window.siyuan.blockPanels.length; i++) {
const item = window.siyuan.blockPanels[i];
if (item.targetElement &&
parseInt(item.element.getAttribute("data-level")) > (maxEditLevels[item.element.getAttribute("data-oid")] || 0) &&
item.element.getAttribute("data-pin") === "false" &&
parseInt(item.element.getAttribute("data-level")) > parseInt(blockElement.getAttribute("data-level"))) {
item.destroy();
i--;
}
}
} else {
for (let i = 0; i < window.siyuan.blockPanels.length; i++) {
const item = window.siyuan.blockPanels[i];
if (item.targetElement && item.element.getAttribute("data-pin") === "false" &&
parseInt(item.element.getAttribute("data-level")) > (maxEditLevels[item.element.getAttribute("data-oid")] || 0)) {
item.destroy();
i--;
}
}
}
}
const getTarget = (event: MouseEvent & { target: HTMLElement }, aElement: false | HTMLElement) => {
if (hasClosestByClassName(event.target, "history__repo", true)) {
return false;
}
popoverTargetElement = hasClosestByAttribute(event.target, "data-type", "block-ref") as HTMLElement ||
hasClosestByAttribute(event.target, "data-type", "virtual-block-ref") as HTMLElement;
if (popoverTargetElement && popoverTargetElement.classList.contains("b3-tooltips")) {
popoverTargetElement = undefined;
}
if (!popoverTargetElement) {
popoverTargetElement = hasClosestByClassName(event.target, "popover__block") as HTMLElement;
}
if (!popoverTargetElement && aElement && aElement.getAttribute("data-href")?.startsWith("siyuan://blocks") &&
aElement.getAttribute("prevent-popover") !== "true") {
popoverTargetElement = aElement;
}
if (!popoverTargetElement || window.siyuan.altIsPressed || window.siyuan.shiftIsPressed ||
(window.siyuan.config.editor.floatWindowMode === 0 && window.siyuan.ctrlIsPressed) ||
(popoverTargetElement && popoverTargetElement.getAttribute("prevent-popover") === "true")) {
return false;
}
// https://github.com/siyuan-note/siyuan/issues/4314
if (popoverTargetElement && getSelection().rangeCount > 0) {
const range = getSelection().getRangeAt(0);
if (range.toString() !== "" && popoverTargetElement.contains(range.startContainer)) {
return false;
}
}
return true
}
export const showPopover = async () => {
if (!popoverTargetElement) {
return;
}
let ids: string[];
let defIds: string[];
const dataId = popoverTargetElement.getAttribute("data-id");
if (dataId) {
// backlink/util/hint/正文标题 上的弹层
if (dataId.startsWith("[")) {
ids = JSON.parse(dataId);
} else {
ids = [dataId];
}
defIds = JSON.parse(popoverTargetElement.getAttribute("data-defids") || "[]");
} else if (popoverTargetElement.getAttribute("data-type")?.indexOf("virtual-block-ref") > -1) {
const nodeElement = hasClosestBlock(popoverTargetElement);
if (nodeElement) {
const postResponse = await fetchSyncPost("/api/block/getBlockDefIDsByRefText", {
anchor: popoverTargetElement.textContent,
excludeIDs: [nodeElement.getAttribute("data-node-id")]
});
ids = postResponse.data;
}
} else if (popoverTargetElement.getAttribute("data-type")?.split(" ").includes("a")) {
// 以思源协议开头的链接
ids = [popoverTargetElement.getAttribute("data-href").substr(16, 22)];
} else {
// pdf
let targetId;
let url = "/api/block/getRefIDs";
if (popoverTargetElement.classList.contains("protyle-attr--refcount")) {
// 编辑器中的引用数
targetId = popoverTargetElement.parentElement.parentElement.getAttribute("data-node-id");
} else if (popoverTargetElement.classList.contains("pdf__rect")) {
targetId = popoverTargetElement.getAttribute("data-node-id");
url = "/api/block/getRefIDsByFileAnnotationID";
} else if (!targetId) {
// 文件树中的引用数
targetId = popoverTargetElement.parentElement.getAttribute("data-node-id");
}
const postResponse = await fetchSyncPost(url, {id: targetId});
ids = postResponse.data.refIDs;
defIds = postResponse.data.defIDs;
}
let hasPin = false;
window.siyuan.blockPanels.find((item) => {
if (item.targetElement && item.element.getAttribute("data-pin") === "true"
&& JSON.stringify(ids) === JSON.stringify(item.nodeIds)) {
hasPin = true;
return true;
}
});
if (!hasPin &&
popoverTargetElement.parentElement.style.opacity !== "0.1" // 反向面板图标拖拽时不应该弹层
) {
window.siyuan.blockPanels.push(new BlockPanel({
targetElement: popoverTargetElement,
nodeIds: ids,
defIds,
}));
}
}

View file

@ -38,6 +38,7 @@ import {unicode2Emoji} from "../emoji";
import {deleteFile} from "../editor/deleteFile";
import {escapeHtml} from "./escape";
import {syncGuide} from "../sync/syncGuide";
import {showPopover} from "../block/popover";
const getRightBlock = (element: HTMLElement, x: number, y: number) => {
let index = 1;
@ -338,6 +339,9 @@ export const globalShortcut = () => {
if (!event.altKey && !event.shiftKey && isCtrl(event)) {
if (event.key === "Meta" || event.key === "Control" || event.ctrlKey || event.metaKey) {
window.siyuan.ctrlIsPressed = true;
if (window.siyuan.config.editor.floatWindowMode === 1) {
showPopover()
}
} else {
window.siyuan.ctrlIsPressed = false;
}