2022-05-26 15:18:53 +08:00
|
|
|
|
import {BlockPanel} from "./Panel";
|
2024-04-03 15:05:32 +08:00
|
|
|
|
import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName,} from "../protyle/util/hasClosest";
|
2024-03-25 10:50:23 +08:00
|
|
|
|
import {fetchPost, fetchSyncPost} from "../util/fetch";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
import {hideTooltip, showTooltip} from "../dialog/tooltip";
|
2024-03-25 10:50:23 +08:00
|
|
|
|
import {getIdFromSYProtocol, isLocalPath} from "../util/pathName";
|
2023-05-18 19:27:21 +08:00
|
|
|
|
import {App} from "../index";
|
2023-11-17 21:57:08 +08:00
|
|
|
|
import {Constants} from "../constants";
|
2024-01-14 12:09:42 +08:00
|
|
|
|
import {getCellText} from "../protyle/render/av/cell";
|
2024-06-21 23:44:40 +08:00
|
|
|
|
import {isTouchDevice} from "../util/functions";
|
2025-12-09 11:13:37 +08:00
|
|
|
|
import {escapeAriaLabel, escapeHtml} from "../util/escape";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
2022-10-30 00:16:48 +08:00
|
|
|
|
let popoverTargetElement: HTMLElement;
|
2024-09-28 17:14:54 +08:00
|
|
|
|
let notebookItemElement: HTMLElement | false;
|
2023-05-18 19:27:21 +08:00
|
|
|
|
export const initBlockPopover = (app: App) => {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
let timeout: number;
|
|
|
|
|
|
let timeoutHide: number;
|
|
|
|
|
|
// 编辑器内容块引用/backlinks/tag/bookmark/套娃中使用
|
2023-01-15 23:16:48 +08:00
|
|
|
|
document.addEventListener("mouseover", (event: MouseEvent & { target: HTMLElement, path: HTMLElement[] }) => {
|
2025-07-14 18:03:03 +08:00
|
|
|
|
if (!window.siyuan.config || !window.siyuan.menus ||
|
|
|
|
|
|
// 拖拽时禁止
|
|
|
|
|
|
window.siyuan.dragElement || document.onmousemove) {
|
|
|
|
|
|
hideTooltip();
|
2022-10-29 21:58:09 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-08-31 01:14:45 +08:00
|
|
|
|
const aElement = hasClosestByAttribute(event.target, "data-type", "a", true) ||
|
2023-07-12 11:46:58 +08:00
|
|
|
|
hasClosestByClassName(event.target, "ariaLabel") ||
|
2024-01-14 15:31:54 +08:00
|
|
|
|
hasClosestByAttribute(event.target, "data-type", "tab-header") ||
|
|
|
|
|
|
hasClosestByAttribute(event.target, "data-type", "inline-memo") ||
|
2024-06-17 10:42:06 +08:00
|
|
|
|
hasClosestByClassName(event.target, "av__calc--ashow") ||
|
2025-02-27 01:02:49 +08:00
|
|
|
|
hasClosestByClassName(event.target, "av__cell");
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (aElement) {
|
2024-10-11 11:45:24 +08:00
|
|
|
|
let tooltipClass = "";
|
2025-02-26 09:54:59 +08:00
|
|
|
|
let tip = aElement.getAttribute("aria-label") || "";
|
2025-08-22 10:46:14 +08:00
|
|
|
|
if (aElement.classList.contains("av__cell") && !aElement.classList.contains("ariaLabel")) {
|
2024-12-05 11:45:59 +08:00
|
|
|
|
if (aElement.classList.contains("av__cell--header")) {
|
|
|
|
|
|
const textElement = aElement.querySelector(".av__celltext");
|
2024-12-09 10:20:40 +08:00
|
|
|
|
const desc = aElement.getAttribute("data-desc");
|
2025-03-10 16:41:07 +08:00
|
|
|
|
if (textElement.scrollWidth > textElement.clientWidth + 0.5 || desc) {
|
2024-12-05 11:45:59 +08:00
|
|
|
|
if (desc) {
|
|
|
|
|
|
tip = `${getCellText(aElement)}<div class='ft__on-surface'>${escapeAriaLabel(desc)}</div>`;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
tip = getCellText(aElement);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2024-03-28 23:34:11 +08:00
|
|
|
|
if (aElement.firstElementChild?.getAttribute("data-type") === "url") {
|
2024-03-28 18:26:35 +08:00
|
|
|
|
if (aElement.firstElementChild.textContent.indexOf("...") > -1) {
|
2024-05-22 22:56:06 +08:00
|
|
|
|
tip = Lute.EscapeHTMLStr(aElement.firstElementChild.getAttribute("data-href"));
|
2024-11-01 08:31:07 +08:00
|
|
|
|
tooltipClass = "href";
|
2024-03-28 18:26:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-22 10:46:14 +08:00
|
|
|
|
tip = "";
|
2024-03-28 18:26:35 +08:00
|
|
|
|
if (!tip && aElement.dataset.wrap !== "true" && event.target.dataset.type !== "block-more" && !hasClosestByClassName(event.target, "block__icon")) {
|
|
|
|
|
|
aElement.style.overflow = "auto";
|
|
|
|
|
|
if (aElement.scrollWidth > aElement.clientWidth + 2) {
|
2024-05-22 22:56:06 +08:00
|
|
|
|
tip = Lute.EscapeHTMLStr(getCellText(aElement));
|
2024-03-28 18:26:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
aElement.style.overflow = "";
|
2024-01-14 12:09:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-12-13 11:09:03 +08:00
|
|
|
|
} else if (aElement.parentElement.parentElement.classList.contains("av__views") && aElement.parentElement.classList.contains("layout-tab-bar")) {
|
2024-12-05 11:45:59 +08:00
|
|
|
|
const textElement = aElement.querySelector(".item__text");
|
2024-12-09 10:20:40 +08:00
|
|
|
|
const desc = aElement.getAttribute("data-desc");
|
2025-03-10 16:41:07 +08:00
|
|
|
|
if (textElement.scrollWidth > textElement.clientWidth + 0.5 || desc) {
|
2024-12-05 11:45:59 +08:00
|
|
|
|
if (desc) {
|
|
|
|
|
|
tip = `${textElement.textContent}<div class='ft__on-surface'>${escapeAriaLabel(desc)}</div>`;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
tip = textElement.textContent;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-06-16 17:26:11 +08:00
|
|
|
|
} else if (aElement.classList.contains("av__celltext--url")) {
|
2025-02-26 09:54:59 +08:00
|
|
|
|
const title = aElement.getAttribute("data-name") || "";
|
|
|
|
|
|
tip = tip ? `<span style="word-break: break-all">${tip.substring(0, Constants.SIZE_TITLE)}</span>${title ? '<div class="fn__hr"></div><span>' + title + "</span>" : ""}` : title;
|
2024-11-01 08:31:07 +08:00
|
|
|
|
tooltipClass = "href";
|
2024-06-17 10:42:06 +08:00
|
|
|
|
} else if (aElement.classList.contains("av__calc--ashow") && aElement.clientWidth + 2 < aElement.scrollWidth) {
|
|
|
|
|
|
tip = aElement.lastChild.textContent + " " + aElement.firstElementChild.textContent;
|
2025-02-26 09:54:59 +08:00
|
|
|
|
} else if (aElement.getAttribute("data-type") === "setRelationCell") {
|
|
|
|
|
|
const childElement = aElement.querySelector(".b3-menu__label");
|
|
|
|
|
|
if (childElement && childElement.clientWidth < childElement.scrollWidth) {
|
|
|
|
|
|
tip = childElement.textContent;
|
|
|
|
|
|
}
|
2023-08-09 22:55:34 +08:00
|
|
|
|
}
|
2025-12-16 10:53:10 +08:00
|
|
|
|
let tooltipSpace: number | undefined;
|
2025-12-19 11:07:02 +08:00
|
|
|
|
if (!tip && aElement.getAttribute("data-type")?.includes("inline-memo")) {
|
2025-12-09 11:13:37 +08:00
|
|
|
|
tip = escapeHtml(aElement.getAttribute("data-inline-memo-content"));
|
2025-12-16 11:14:04 +08:00
|
|
|
|
tooltipClass = "memo"; // 为行级备注添加 class https://github.com/siyuan-note/siyuan/issues/6161
|
|
|
|
|
|
tooltipSpace = 0; // tooltip 和备注元素之间不能有空隙 https://github.com/siyuan-note/siyuan/issues/14796#issuecomment-3649757267
|
2024-10-11 11:45:24 +08:00
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
if (!tip) {
|
2025-12-19 11:07:02 +08:00
|
|
|
|
if (aElement.getAttribute("data-type")?.includes("a")) {
|
2025-12-16 11:14:04 +08:00
|
|
|
|
tooltipClass = "href"; // 为超链接添加 class https://github.com/siyuan-note/siyuan/issues/11440#issuecomment-2119080691
|
|
|
|
|
|
tooltipSpace = 0;
|
|
|
|
|
|
}
|
2024-03-25 10:50:23 +08:00
|
|
|
|
const href = aElement.getAttribute("data-href") || "";
|
2024-05-27 09:36:14 +08:00
|
|
|
|
// 链接地址强制换行 https://github.com/siyuan-note/siyuan/issues/11539
|
2024-05-27 16:43:56 +08:00
|
|
|
|
if (href) {
|
|
|
|
|
|
tip = `<span style="word-break: break-all">${href.substring(0, Constants.SIZE_TITLE)}</span>`;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
const title = aElement.getAttribute("data-title");
|
2024-03-25 10:50:23 +08:00
|
|
|
|
if (tip && isLocalPath(href) && !aElement.classList.contains("b3-tooltips")) {
|
|
|
|
|
|
let assetTip = tip;
|
|
|
|
|
|
fetchPost("/api/asset/statAsset", {path: href}, (response) => {
|
2024-03-25 10:52:34 +08:00
|
|
|
|
if (response.code === 1) {
|
|
|
|
|
|
if (title) {
|
2025-02-26 09:54:59 +08:00
|
|
|
|
assetTip += '<div class="fn__hr"></div><span>' + title + "</span>";
|
2024-03-25 10:52:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2025-02-26 09:54:59 +08:00
|
|
|
|
assetTip += ` ${response.data.hSize}${title ? '<div class="fn__hr"></div><span>' + title + "</span>" : ""}<br>${window.siyuan.languages.modifiedAt} ${response.data.hUpdated}<br>${window.siyuan.languages.createdAt} ${response.data.hCreated}`;
|
2024-03-25 10:52:34 +08:00
|
|
|
|
}
|
2025-12-16 11:14:04 +08:00
|
|
|
|
showTooltip(assetTip, aElement, tooltipClass, event, tooltipSpace);
|
2024-03-25 10:50:23 +08:00
|
|
|
|
});
|
|
|
|
|
|
tip = "";
|
|
|
|
|
|
} else if (title) {
|
2025-03-10 10:47:31 +08:00
|
|
|
|
tip = (tip ? (tip + '<div class="fn__hr"></div>') : "") + "<span>" + title + "</span>";
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-02-28 11:45:04 +08:00
|
|
|
|
|
2024-09-28 17:14:54 +08:00
|
|
|
|
notebookItemElement = hasClosestByClassName(event.target, "b3-list-item__text");
|
2024-09-28 16:45:07 +08:00
|
|
|
|
if (notebookItemElement && notebookItemElement.parentElement.getAttribute("data-type") === "navigation-root") {
|
|
|
|
|
|
fetchPost("/api/notebook/getNotebookInfo", {notebook: notebookItemElement.parentElement.parentElement.getAttribute("data-url")}, (response) => {
|
|
|
|
|
|
const boxData = response.data.boxInfo;
|
2024-09-29 10:55:24 +08:00
|
|
|
|
const tip = `${boxData.name} <small class='ft__on-surface'>${boxData.hSize}</small>${boxData.docCount !== 0 ? window.siyuan.languages.includeSubFile.replace("x", boxData.docCount) : ""}<br>${window.siyuan.languages.modifiedAt} ${boxData.hMtime}<br>${window.siyuan.languages.createdAt} ${boxData.hCtime}`;
|
2024-09-28 17:17:09 +08:00
|
|
|
|
const scopeNotebookItemElement = hasClosestByClassName(event.target, "b3-list-item__text");
|
2025-07-23 12:21:59 +08:00
|
|
|
|
if (notebookItemElement && scopeNotebookItemElement && (notebookItemElement === scopeNotebookItemElement)) {
|
2024-09-28 17:14:54 +08:00
|
|
|
|
showTooltip(tip, notebookItemElement);
|
|
|
|
|
|
}
|
2024-09-28 17:17:09 +08:00
|
|
|
|
if (scopeNotebookItemElement &&
|
|
|
|
|
|
scopeNotebookItemElement.parentElement.getAttribute("data-type") === "navigation-root" &&
|
|
|
|
|
|
scopeNotebookItemElement.parentElement.parentElement.getAttribute("data-url") === boxData.id) {
|
|
|
|
|
|
scopeNotebookItemElement.setAttribute("aria-label", tip);
|
2024-09-28 17:14:54 +08:00
|
|
|
|
}
|
2024-09-29 10:55:24 +08:00
|
|
|
|
});
|
2025-02-28 11:45:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tip && !aElement.classList.contains("b3-tooltips")) {
|
|
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/11294
|
|
|
|
|
|
try {
|
2025-12-16 10:53:10 +08:00
|
|
|
|
showTooltip(decodeURIComponent(tip), aElement, tooltipClass, event, tooltipSpace);
|
2025-02-28 11:45:04 +08:00
|
|
|
|
} catch (e) {
|
|
|
|
|
|
// https://ld246.com/article/1718235737991
|
2025-12-16 10:53:10 +08:00
|
|
|
|
showTooltip(tip, aElement, tooltipClass, event, tooltipSpace);
|
2024-09-28 16:45:07 +08:00
|
|
|
|
}
|
2025-02-28 11:45:04 +08:00
|
|
|
|
event.stopPropagation();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
hideTooltip();
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (!aElement) {
|
|
|
|
|
|
const tipElement = hasClosestByAttribute(event.target, "id", "tooltip", true);
|
|
|
|
|
|
if (!tipElement || (
|
|
|
|
|
|
tipElement && (tipElement.clientHeight >= tipElement.scrollHeight && tipElement.clientWidth >= tipElement.scrollWidth)
|
|
|
|
|
|
)) {
|
|
|
|
|
|
hideTooltip();
|
2023-09-16 14:53:26 +08:00
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
2023-05-17 18:48:42 +08:00
|
|
|
|
if (window.siyuan.config.editor.floatWindowMode === 1 || window.siyuan.shiftIsPressed) {
|
2022-10-29 00:10:08 +08:00
|
|
|
|
clearTimeout(timeoutHide);
|
|
|
|
|
|
timeoutHide = window.setTimeout(() => {
|
2022-10-30 00:16:48 +08:00
|
|
|
|
hidePopover(event);
|
2023-11-17 21:57:08 +08:00
|
|
|
|
}, Constants.TIMEOUT_INPUT);
|
2022-10-29 00:10:08 +08:00
|
|
|
|
|
2022-10-28 23:29:07 +08:00
|
|
|
|
if (!getTarget(event, aElement)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-08-23 11:32:25 +08:00
|
|
|
|
// https://github.com/siyuan-note/siyuan/issues/9007
|
|
|
|
|
|
if (event.relatedTarget && !document.contains(event.relatedTarget as Node)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2022-10-28 23:29:07 +08:00
|
|
|
|
if (window.siyuan.ctrlIsPressed) {
|
2022-10-29 00:10:08 +08:00
|
|
|
|
clearTimeout(timeoutHide);
|
2023-05-18 19:27:21 +08:00
|
|
|
|
showPopover(app);
|
2023-05-17 18:48:42 +08:00
|
|
|
|
} else if (window.siyuan.shiftIsPressed) {
|
|
|
|
|
|
clearTimeout(timeoutHide);
|
2023-05-18 19:27:21 +08:00
|
|
|
|
showPopover(app, true);
|
2022-10-28 23:29:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-05-26 15:18:53 +08:00
|
|
|
|
clearTimeout(timeout);
|
|
|
|
|
|
clearTimeout(timeoutHide);
|
|
|
|
|
|
timeoutHide = window.setTimeout(() => {
|
2022-10-29 00:10:08 +08:00
|
|
|
|
if (!hidePopover(event)) {
|
2022-10-28 23:29:07 +08:00
|
|
|
|
return;
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (!popoverTargetElement && !aElement) {
|
|
|
|
|
|
clearTimeout(timeout);
|
|
|
|
|
|
}
|
2023-11-17 21:57:08 +08:00
|
|
|
|
}, Constants.TIMEOUT_INPUT);
|
2023-05-17 18:48:42 +08:00
|
|
|
|
timeout = window.setTimeout(() => {
|
2025-01-12 17:24:54 +08:00
|
|
|
|
if (!getTarget(event, aElement) || isTouchDevice()) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
clearTimeout(timeoutHide);
|
2023-05-18 19:27:21 +08:00
|
|
|
|
showPopover(app);
|
2026-03-02 23:13:02 +08:00
|
|
|
|
}, window.siyuan.config.editor.floatWindowDelay);
|
2022-10-28 23:29:07 +08:00
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2023-11-17 21:57:08 +08:00
|
|
|
|
const hidePopover = (event: MouseEvent & { path: HTMLElement[] }) => {
|
|
|
|
|
|
// pad 端点击后 event.target 不会更新。
|
2024-07-06 09:57:00 +08:00
|
|
|
|
const target = isTouchDevice() ? document.elementFromPoint(event.clientX, event.clientY) : event.target as HTMLElement;
|
2023-11-27 17:27:19 +08:00
|
|
|
|
if (!target) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2024-01-11 21:44:05 +08:00
|
|
|
|
if ((target.id && target.tagName !== "svg" && (target.id.startsWith("minder_node") || target.id.startsWith("kity_") || target.id.startsWith("node_")))
|
2023-11-17 21:57:08 +08:00
|
|
|
|
|| target.classList.contains("counter")
|
|
|
|
|
|
|| target.tagName === "circle"
|
2022-10-29 00:10:08 +08:00
|
|
|
|
) {
|
|
|
|
|
|
// gutter & mindmap & 文件树上的数字 & 关系图节点不处理
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2024-01-11 21:44:05 +08:00
|
|
|
|
|
2024-04-16 09:27:35 +08:00
|
|
|
|
const avPanelElement = hasClosestByClassName(target, "av__panel") || hasClosestByClassName(target, "av__mask");
|
2024-01-11 21:44:05 +08:00
|
|
|
|
if (avPanelElement) {
|
|
|
|
|
|
// 浮窗上点击 av 操作,浮窗不能消失
|
|
|
|
|
|
const blockPanel = window.siyuan.blockPanels.find((item) => {
|
|
|
|
|
|
if (item.element.style.zIndex < avPanelElement.style.zIndex) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (blockPanel) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 浮窗上点击菜单,浮窗不能消失 https://ld246.com/article/1632668091023
|
2024-01-14 16:38:45 +08:00
|
|
|
|
const menuElement = hasClosestByClassName(target, "b3-menu");
|
2025-10-18 10:41:11 +08:00
|
|
|
|
if (menuElement && menuElement.getAttribute("data-name") !== Constants.MENU_DOC_TREE_MORE) {
|
2024-01-11 21:44:05 +08:00
|
|
|
|
const blockPanel = window.siyuan.blockPanels.find((item) => {
|
|
|
|
|
|
if (item.element.style.zIndex < menuElement.style.zIndex) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (blockPanel) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-11-17 21:57:08 +08:00
|
|
|
|
popoverTargetElement = hasClosestByAttribute(target, "data-type", "block-ref") as HTMLElement ||
|
|
|
|
|
|
hasClosestByAttribute(target, "data-type", "virtual-block-ref") as HTMLElement;
|
2022-10-29 00:10:08 +08:00
|
|
|
|
if (popoverTargetElement && popoverTargetElement.classList.contains("b3-tooltips")) {
|
|
|
|
|
|
popoverTargetElement = undefined;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!popoverTargetElement) {
|
2023-11-17 21:57:08 +08:00
|
|
|
|
popoverTargetElement = hasClosestByClassName(target, "popover__block") as HTMLElement;
|
2022-10-29 00:10:08 +08:00
|
|
|
|
}
|
2023-11-17 21:57:08 +08:00
|
|
|
|
const linkElement = hasClosestByAttribute(target, "data-type", "a", true);
|
2022-10-29 00:10:08 +08:00
|
|
|
|
if (!popoverTargetElement && linkElement && linkElement.getAttribute("data-href")?.startsWith("siyuan://blocks")) {
|
|
|
|
|
|
popoverTargetElement = linkElement;
|
|
|
|
|
|
}
|
2025-07-23 13:08:38 +08:00
|
|
|
|
if (!popoverTargetElement || (popoverTargetElement && window.siyuan.menus.menu.data && window.siyuan.menus.menu.data === popoverTargetElement)) {
|
2023-01-15 23:16:48 +08:00
|
|
|
|
// 移动到弹窗的 loading 元素上,但经过 settimeout 后 loading 已经被移除了
|
|
|
|
|
|
// https://ld246.com/article/1673596577519/comment/1673767749885#comments
|
2023-11-17 21:57:08 +08:00
|
|
|
|
let targetElement = target;
|
2023-02-11 12:33:09 +08:00
|
|
|
|
if (!targetElement.parentElement && event.path && event.path[1]) {
|
2023-01-16 00:00:53 +08:00
|
|
|
|
targetElement = event.path[1];
|
2023-01-15 23:16:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
const blockElement = hasClosestByClassName(targetElement, "block__popover", true);
|
2022-10-29 00:10:08 +08:00
|
|
|
|
const maxEditLevels: { [key: string]: number } = {oid: 0};
|
|
|
|
|
|
window.siyuan.blockPanels.forEach((item) => {
|
2023-05-19 20:39:32 +08:00
|
|
|
|
if ((item.targetElement || typeof item.x === "number") && item.element.getAttribute("data-pin") === "true") {
|
2022-10-29 00:10:08 +08:00
|
|
|
|
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 住第三层,第二层会消失
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-10-29 00:10:08 +08:00
|
|
|
|
});
|
2024-02-24 21:38:25 +08:00
|
|
|
|
const menuLevel = parseInt(window.siyuan.menus.menu.element.dataset.from);
|
2022-10-29 00:10:08 +08:00
|
|
|
|
if (blockElement) {
|
2024-02-24 21:38:25 +08:00
|
|
|
|
for (let i = window.siyuan.blockPanels.length - 1; i >= 0; i--) {
|
2022-10-29 00:10:08 +08:00
|
|
|
|
const item = window.siyuan.blockPanels[i];
|
2024-02-25 22:28:35 +08:00
|
|
|
|
const itemLevel = parseInt(item.element.getAttribute("data-level"));
|
2023-05-19 20:39:32 +08:00
|
|
|
|
if ((item.targetElement || typeof item.x === "number") &&
|
2024-02-24 21:38:25 +08:00
|
|
|
|
itemLevel > (maxEditLevels[item.element.getAttribute("data-oid")] || 0) &&
|
2022-10-29 00:10:08 +08:00
|
|
|
|
item.element.getAttribute("data-pin") === "false" &&
|
2024-02-24 21:38:25 +08:00
|
|
|
|
itemLevel > parseInt(blockElement.getAttribute("data-level"))) {
|
|
|
|
|
|
if (menuLevel && menuLevel >= itemLevel) {
|
|
|
|
|
|
// 有 gutter 菜单时不隐藏
|
2025-05-05 11:43:57 +08:00
|
|
|
|
break;
|
2024-02-24 21:38:25 +08:00
|
|
|
|
} else {
|
2025-05-05 11:43:57 +08:00
|
|
|
|
const hasToolbar = item.editors.find(editItem => {
|
|
|
|
|
|
if (!editItem.protyle.toolbar.subElement.classList.contains("fn__none")) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (hasToolbar) {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2024-02-24 21:38:25 +08:00
|
|
|
|
item.destroy();
|
|
|
|
|
|
}
|
2022-10-29 00:10:08 +08:00
|
|
|
|
}
|
2022-10-28 23:29:07 +08:00
|
|
|
|
}
|
2022-10-29 00:10:08 +08:00
|
|
|
|
} else {
|
2024-02-24 21:38:25 +08:00
|
|
|
|
for (let i = window.siyuan.blockPanels.length - 1; i >= 0; i--) {
|
2022-10-29 00:10:08 +08:00
|
|
|
|
const item = window.siyuan.blockPanels[i];
|
2024-02-24 21:38:25 +08:00
|
|
|
|
const itemLevel = parseInt(item.element.getAttribute("data-level"));
|
2023-11-03 23:09:18 +08:00
|
|
|
|
if ((item.targetElement || typeof item.x === "number") && item.element.getAttribute("data-pin") === "false") {
|
2024-02-24 21:38:25 +08:00
|
|
|
|
if (menuLevel && menuLevel >= itemLevel) {
|
|
|
|
|
|
// 有 gutter 菜单时不隐藏
|
2025-05-05 11:43:57 +08:00
|
|
|
|
break;
|
2024-09-19 17:12:47 +08:00
|
|
|
|
} else if (item.targetElement && item.targetElement.classList.contains("protyle-wysiwyg__embed") &&
|
|
|
|
|
|
item.targetElement.contains(targetElement)) {
|
2024-09-19 17:31:37 +08:00
|
|
|
|
// 点击嵌入块后浮窗消失后再快速点击嵌入块无法弹出浮窗 https://github.com/siyuan-note/siyuan/issues/12511
|
2025-05-05 11:43:57 +08:00
|
|
|
|
break;
|
2024-02-24 21:38:25 +08:00
|
|
|
|
} else {
|
2025-05-05 11:43:57 +08:00
|
|
|
|
const hasToolbar = item.editors.find(editItem => {
|
|
|
|
|
|
if (!editItem.protyle.toolbar.subElement.classList.contains("fn__none")) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
if (hasToolbar) {
|
2025-08-22 10:46:14 +08:00
|
|
|
|
break;
|
2025-05-05 11:43:57 +08:00
|
|
|
|
}
|
2024-02-24 21:38:25 +08:00
|
|
|
|
item.destroy();
|
|
|
|
|
|
}
|
2022-10-29 00:10:08 +08:00
|
|
|
|
}
|
2022-10-28 23:29:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-10-30 00:16:48 +08:00
|
|
|
|
};
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
2022-10-28 23:29:07 +08:00
|
|
|
|
const getTarget = (event: MouseEvent & { target: HTMLElement }, aElement: false | HTMLElement) => {
|
2024-02-09 15:09:26 +08:00
|
|
|
|
if (window.siyuan.config.editor.floatWindowMode === 2 || hasClosestByClassName(event.target, "history__repo", true)) {
|
2022-10-28 23:29:07 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2024-01-14 15:31:54 +08:00
|
|
|
|
if (!popoverTargetElement && aElement) {
|
|
|
|
|
|
if (aElement.getAttribute("data-href")?.startsWith("siyuan://blocks") && aElement.getAttribute("prevent-popover") !== "true") {
|
|
|
|
|
|
popoverTargetElement = aElement;
|
|
|
|
|
|
} else if (aElement.classList.contains("av__cell")) {
|
2024-01-14 16:38:45 +08:00
|
|
|
|
const textElement = aElement.querySelector(".av__celltext--url") as HTMLElement;
|
2024-01-14 15:31:54 +08:00
|
|
|
|
if (textElement && textElement.dataset.type === "url" && textElement.dataset.href?.startsWith("siyuan://blocks")) {
|
|
|
|
|
|
popoverTargetElement = textElement;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-10-28 23:29:07 +08:00
|
|
|
|
}
|
2023-05-17 18:48:42 +08:00
|
|
|
|
if (!popoverTargetElement || window.siyuan.altIsPressed ||
|
2022-10-28 23:29:07 +08:00
|
|
|
|
(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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-10-30 00:16:48 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
};
|
2022-10-28 23:29:07 +08:00
|
|
|
|
|
2023-05-18 19:27:21 +08:00
|
|
|
|
export const showPopover = async (app: App, showRef = false) => {
|
2025-07-23 13:08:38 +08:00
|
|
|
|
if (!popoverTargetElement || (window.siyuan.menus.menu.data && window.siyuan.menus.menu.data === popoverTargetElement)) {
|
2022-10-28 23:29:07 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-02-01 20:43:47 +08:00
|
|
|
|
let refDefs: IRefDefs[] = [];
|
2025-01-16 10:00:30 +08:00
|
|
|
|
let originalRefBlockIDs: IObject;
|
2022-10-28 23:29:07 +08:00
|
|
|
|
const dataId = popoverTargetElement.getAttribute("data-id");
|
|
|
|
|
|
if (dataId) {
|
2025-01-13 13:44:05 +08:00
|
|
|
|
// backlink/util/hint 上的弹层
|
2023-05-17 18:48:42 +08:00
|
|
|
|
if (showRef) {
|
|
|
|
|
|
const postResponse = await fetchSyncPost("/api/block/getRefIDs", {id: dataId});
|
2025-01-13 13:25:31 +08:00
|
|
|
|
refDefs = postResponse.data.refDefs;
|
2025-01-12 00:47:26 +08:00
|
|
|
|
originalRefBlockIDs = postResponse.data.originalRefBlockIDs;
|
2022-10-28 23:29:07 +08:00
|
|
|
|
} else {
|
2023-05-17 18:48:42 +08:00
|
|
|
|
if (dataId.startsWith("[")) {
|
2025-01-13 12:47:28 +08:00
|
|
|
|
JSON.parse(dataId).forEach((item: string) => {
|
|
|
|
|
|
refDefs.push({refID: item});
|
|
|
|
|
|
});
|
2023-05-17 18:48:42 +08:00
|
|
|
|
} else {
|
2025-01-13 12:47:28 +08:00
|
|
|
|
refDefs = [{refID: dataId}];
|
2023-05-17 18:48:42 +08:00
|
|
|
|
}
|
2022-10-28 23:29:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
} 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")]
|
2022-05-26 15:18:53 +08:00
|
|
|
|
});
|
2025-01-13 12:47:28 +08:00
|
|
|
|
refDefs = postResponse.data.refDefs;
|
2022-10-28 23:29:07 +08:00
|
|
|
|
}
|
2023-08-09 22:55:34 +08:00
|
|
|
|
} else if (popoverTargetElement.getAttribute("data-type")?.split(" ").includes("a")) {
|
2022-10-28 23:29:07 +08:00
|
|
|
|
// 以思源协议开头的链接
|
2025-01-13 12:47:28 +08:00
|
|
|
|
refDefs = [{refID: getIdFromSYProtocol(popoverTargetElement.getAttribute("data-href"))}];
|
2023-08-09 22:55:34 +08:00
|
|
|
|
} else if (popoverTargetElement.dataset.type === "url") {
|
|
|
|
|
|
// 在 database 的 url 列中以思源协议开头的链接
|
2025-01-13 12:47:28 +08:00
|
|
|
|
refDefs = [{refID: getIdFromSYProtocol(popoverTargetElement.textContent.trim())}];
|
2024-03-08 11:15:23 +08:00
|
|
|
|
} else if (popoverTargetElement.dataset.popoverUrl) {
|
|
|
|
|
|
// 镜像数据库
|
2024-03-08 11:19:39 +08:00
|
|
|
|
const postResponse = await fetchSyncPost(popoverTargetElement.dataset.popoverUrl, {avID: popoverTargetElement.dataset.avId});
|
2025-01-13 12:47:28 +08:00
|
|
|
|
refDefs = postResponse.data.refDefs;
|
2022-10-28 23:29:07 +08:00
|
|
|
|
} 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")) {
|
2024-02-09 16:02:21 +08:00
|
|
|
|
const relationIds = popoverTargetElement.getAttribute("data-relations");
|
2024-02-09 14:55:54 +08:00
|
|
|
|
if (relationIds) {
|
2025-01-13 12:47:28 +08:00
|
|
|
|
relationIds.split(",").forEach((item: string) => {
|
|
|
|
|
|
refDefs.push({refID: item});
|
|
|
|
|
|
});
|
2024-02-09 14:55:54 +08:00
|
|
|
|
url = "";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
targetId = popoverTargetElement.getAttribute("data-node-id");
|
|
|
|
|
|
url = "/api/block/getRefIDsByFileAnnotationID";
|
|
|
|
|
|
}
|
2022-10-28 23:29:07 +08:00
|
|
|
|
} else if (!targetId) {
|
|
|
|
|
|
// 文件树中的引用数
|
|
|
|
|
|
targetId = popoverTargetElement.parentElement.getAttribute("data-node-id");
|
|
|
|
|
|
}
|
2024-02-09 14:55:54 +08:00
|
|
|
|
if (url) {
|
|
|
|
|
|
const postResponse = await fetchSyncPost(url, {id: targetId});
|
2025-01-13 13:25:31 +08:00
|
|
|
|
refDefs = postResponse.data.refDefs;
|
2025-01-12 00:47:26 +08:00
|
|
|
|
originalRefBlockIDs = postResponse.data.originalRefBlockIDs;
|
2024-02-09 14:55:54 +08:00
|
|
|
|
}
|
2022-10-28 23:29:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-13 17:55:42 +08:00
|
|
|
|
if (refDefs.length === 0) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-10-28 23:29:07 +08:00
|
|
|
|
let hasPin = false;
|
|
|
|
|
|
window.siyuan.blockPanels.find((item) => {
|
2023-05-19 20:39:32 +08:00
|
|
|
|
if ((item.targetElement || typeof item.x === "number") && item.element.getAttribute("data-pin") === "true"
|
2025-01-13 12:47:28 +08:00
|
|
|
|
&& JSON.stringify(refDefs) === JSON.stringify(item.refDefs)) {
|
2022-10-28 23:29:07 +08:00
|
|
|
|
hasPin = true;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2022-05-26 15:18:53 +08:00
|
|
|
|
});
|
2023-02-08 14:58:53 +08:00
|
|
|
|
if (!hasPin && popoverTargetElement.parentElement &&
|
2025-03-31 16:15:44 +08:00
|
|
|
|
popoverTargetElement.parentElement.style.opacity !== "0.38" // 反向面板图标拖拽时不应该弹层
|
2022-10-28 23:29:07 +08:00
|
|
|
|
) {
|
|
|
|
|
|
window.siyuan.blockPanels.push(new BlockPanel({
|
2023-05-18 19:27:21 +08:00
|
|
|
|
app,
|
2022-10-28 23:29:07 +08:00
|
|
|
|
targetElement: popoverTargetElement,
|
2023-05-19 20:27:14 +08:00
|
|
|
|
isBacklink: showRef || popoverTargetElement.classList.contains("protyle-attr--refcount") || popoverTargetElement.classList.contains("counter"),
|
2025-01-13 12:47:28 +08:00
|
|
|
|
refDefs,
|
2025-01-12 00:47:26 +08:00
|
|
|
|
originalRefBlockIDs,
|
2022-10-28 23:29:07 +08:00
|
|
|
|
}));
|
|
|
|
|
|
}
|
2023-05-17 18:48:42 +08:00
|
|
|
|
// 不能清除,否则ctrl 后 shift 就 无效 popoverTargetElement = undefined;
|
2022-10-30 00:16:48 +08:00
|
|
|
|
};
|