mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-22 17:40:13 +01:00
This commit is contained in:
parent
d93bd7cfe5
commit
76b0617689
6 changed files with 159 additions and 145 deletions
|
|
@ -1259,12 +1259,6 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => {
|
|||
return;
|
||||
}
|
||||
|
||||
const avElement = document.querySelector(".av__panel");
|
||||
if (avElement) {
|
||||
avElement.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!window.siyuan.menus.menu.element.classList.contains("fn__none")) {
|
||||
if (window.siyuan.dialogs.length > 0 &&
|
||||
window.siyuan.menus.menu.element.style.zIndex < (window.siyuan.dialogs[0].element.querySelector(".b3-dialog") as HTMLElement).style.zIndex) {
|
||||
|
|
@ -1280,6 +1274,13 @@ export const windowKeyDown = (app: App, event: KeyboardEvent) => {
|
|||
return;
|
||||
}
|
||||
|
||||
// 需放在 menus 后,否则资源列中添加资源会先关闭菜单
|
||||
const avElement = document.querySelector(".av__panel");
|
||||
if (avElement) {
|
||||
avElement.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
// remove blockpopover
|
||||
const maxEditLevels: { [key: string]: number } = {oid: 0};
|
||||
window.siyuan.blockPanels.forEach((item) => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
import {hasClosestBlock, hasClosestByMatchTag} from "../protyle/util/hasClosest";
|
||||
import {
|
||||
hasClosestBlock,
|
||||
hasClosestByAttribute,
|
||||
hasClosestByClassName,
|
||||
hasClosestByMatchTag
|
||||
} from "../protyle/util/hasClosest";
|
||||
import {MenuItem} from "./Menu";
|
||||
import {focusBlock, focusByRange, focusByWbr, getEditorRange, selectAll,} from "../protyle/util/selection";
|
||||
import {
|
||||
|
|
@ -46,6 +51,142 @@ import {emitOpenMenu} from "../plugin/EventBus";
|
|||
import {openMobileFileById} from "../mobile/editor";
|
||||
import {openBacklink, openGraph} from "../layout/dock/util";
|
||||
import {updateHeader} from "../protyle/render/av/row";
|
||||
import {renderAssetsPreview} from "../asset/renderAssets";
|
||||
import {upDownHint} from "../util/upDownHint";
|
||||
import {hintRenderAssets} from "../protyle/hint/extend";
|
||||
import {Menu} from "../plugin/Menu";
|
||||
|
||||
const renderAssetList = (element: Element, k: string, position: IPosition, exts: string[] = []) => {
|
||||
fetchPost("/api/search/searchAsset", {
|
||||
k,
|
||||
exts
|
||||
}, (response) => {
|
||||
let searchHTML = "";
|
||||
response.data.forEach((item: { path: string, hName: string }, index: number) => {
|
||||
searchHTML += `<div data-value="${item.path}" class="b3-list-item${index === 0 ? " b3-list-item--focus" : ""}"><div class="b3-list-item__text">${item.hName}</div></div>`;
|
||||
});
|
||||
|
||||
const listElement = element.querySelector(".b3-list");
|
||||
const previewElement = element.querySelector("#preview");
|
||||
const inputElement = element.querySelector("input");
|
||||
listElement.innerHTML = searchHTML || `<li class="b3-list--empty">${window.siyuan.languages.emptyContent}</li>`;
|
||||
if (response.data.length > 0) {
|
||||
previewElement.innerHTML = renderAssetsPreview(response.data[0].path);
|
||||
} else {
|
||||
previewElement.innerHTML = window.siyuan.languages.emptyContent;
|
||||
}
|
||||
/// #if MOBILE
|
||||
window.siyuan.menus.menu.fullscreen();
|
||||
/// #else
|
||||
window.siyuan.menus.menu.popup(position);
|
||||
/// #endif
|
||||
if (!k) {
|
||||
inputElement.select();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export const assetMenu = (protyle: IProtyle, position: IPosition, callback?: (url: string) => void, exts?: string[]) => {
|
||||
window.siyuan.menus.menu.remove();
|
||||
const menu = new Menu()
|
||||
menu.addItem({
|
||||
iconHTML: "",
|
||||
type: "readonly",
|
||||
label: `<div class="fn__flex" style="max-height: 50vh">
|
||||
<div class="fn__flex-column" style="${isMobile() ? "width:100%" : "min-width: 260px;max-width:420px"}">
|
||||
<div class="fn__flex" style="margin: 0 8px 4px 8px">
|
||||
<input class="b3-text-field fn__flex-1"/>
|
||||
<span class="fn__space"></span>
|
||||
<span data-type="previous" class="block__icon block__icon--show"><svg><use xlink:href="#iconLeft"></use></svg></span>
|
||||
<span class="fn__space"></span>
|
||||
<span data-type="next" class="block__icon block__icon--show"><svg><use xlink:href="#iconRight"></use></svg></span>
|
||||
</div>
|
||||
<div class="b3-list fn__flex-1 b3-list--background" style="position: relative"><img style="margin: 0 auto;display: block;width: 64px;height: 64px" src="/stage/loading-pure.svg"></div>
|
||||
</div>
|
||||
<div id="preview" style="width: 360px;display: ${isMobile() || window.outerWidth < window.outerWidth / 2 + 260 ? "none" : "flex"};padding: 8px;overflow: auto;justify-content: center;align-items: center;word-break: break-all;"></div>
|
||||
</div>`,
|
||||
bind(element) {
|
||||
element.style.maxWidth = "none";
|
||||
const listElement = element.querySelector(".b3-list");
|
||||
const previewElement = element.querySelector("#preview");
|
||||
listElement.addEventListener("mouseover", (event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
const hoverItemElement = hasClosestByClassName(target, "b3-list-item");
|
||||
if (!hoverItemElement) {
|
||||
return;
|
||||
}
|
||||
previewElement.innerHTML = renderAssetsPreview(hoverItemElement.getAttribute("data-value"));
|
||||
});
|
||||
const inputElement = element.querySelector("input");
|
||||
inputElement.addEventListener("keydown", (event: KeyboardEvent) => {
|
||||
if (event.isComposing) {
|
||||
return;
|
||||
}
|
||||
const isEmpty = element.querySelector(".b3-list--empty");
|
||||
if (!isEmpty) {
|
||||
const currentElement = upDownHint(listElement, event);
|
||||
if (currentElement) {
|
||||
previewElement.innerHTML = renderAssetsPreview(currentElement.getAttribute("data-value"));
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
if (event.key === "Enter") {
|
||||
if (!isEmpty) {
|
||||
const currentURL = element.querySelector(".b3-list-item--focus").getAttribute("data-value");
|
||||
if (callback) {
|
||||
callback(currentURL);
|
||||
} else {
|
||||
hintRenderAssets(currentURL, protyle);
|
||||
window.siyuan.menus.menu.remove();
|
||||
}
|
||||
} else if (!callback) {
|
||||
window.siyuan.menus.menu.remove();
|
||||
focusByRange(protyle.toolbar.range);
|
||||
}
|
||||
// 空行处插入 mp3 会多一个空的 mp3 块
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
} else if (event.key === "Escape") {
|
||||
if (!callback) {
|
||||
focusByRange(protyle.toolbar.range);
|
||||
}
|
||||
}
|
||||
});
|
||||
inputElement.addEventListener("input", (event) => {
|
||||
event.stopPropagation();
|
||||
renderAssetList(element, inputElement.value, position, exts);
|
||||
});
|
||||
element.lastElementChild.addEventListener("click", (event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
const previousElement = hasClosestByAttribute(target, "data-type", "previous");
|
||||
if (previousElement) {
|
||||
inputElement.dispatchEvent(new KeyboardEvent("keydown", {key: "ArrowUp"}));
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
const nextElement = hasClosestByAttribute(target, "data-type", "next");
|
||||
if (nextElement) {
|
||||
inputElement.dispatchEvent(new KeyboardEvent("keydown", {key: "ArrowDown"}));
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
const listItemElement = hasClosestByClassName(target, "b3-list-item");
|
||||
if (listItemElement) {
|
||||
event.stopPropagation();
|
||||
const currentURL = listItemElement.getAttribute("data-value");
|
||||
if (callback) {
|
||||
callback(currentURL);
|
||||
} else {
|
||||
hintRenderAssets(currentURL, protyle);
|
||||
window.siyuan.menus.menu.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
renderAssetList(element, "", position, exts);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const fileAnnotationRefMenu = (protyle: IProtyle, refElement: HTMLElement) => {
|
||||
const nodeElement = hasClosestBlock(refElement);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {popSearch} from "../../mobile/menu/search";
|
|||
import {getEventName} from "../util/compatibility";
|
||||
import {Dialog} from "../../dialog";
|
||||
import {Constants} from "../../constants";
|
||||
import {assetMenu} from "../../menus/protyle";
|
||||
|
||||
const bgs = [
|
||||
"background:radial-gradient(black 3px, transparent 4px),radial-gradient(black 3px, transparent 4px),linear-gradient(#fff 4px, transparent 0),linear-gradient(45deg, transparent 74px, transparent 75px, #a4a4a4 75px, #a4a4a4 76px, transparent 77px, transparent 109px),linear-gradient(-45deg, transparent 75px, transparent 76px, #a4a4a4 76px, #a4a4a4 77px, transparent 78px, transparent 109px),#fff;background-size: 109px 109px, 109px 109px,100% 6px, 109px 109px, 109px 109px;background-position: 54px 55px, 0px 0px, 0px 0px, 0px 0px, 0px 0px;",
|
||||
|
|
@ -303,10 +304,10 @@ export class Background {
|
|||
break;
|
||||
} else if (type === "asset") {
|
||||
const rect = target.getBoundingClientRect();
|
||||
protyle.toolbar.showAssets(protyle, {
|
||||
x: rect.right - 798,
|
||||
assetMenu(protyle, {
|
||||
x: target.parentElement.getBoundingClientRect().right,
|
||||
y: rect.bottom + 8,
|
||||
isLeft: false,
|
||||
isLeft: true,
|
||||
}, (url) => {
|
||||
this.ial["title-img"] = `background-image:url("${url}")`;
|
||||
this.render(this.ial, protyle.block.rootID);
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import {getContenteditableElement, hasNextSibling, hasPreviousSibling} from "../
|
|||
import {transaction, updateTransaction} from "../wysiwyg/transaction";
|
||||
import {insertHTML} from "../util/insertHTML";
|
||||
import {highlightRender} from "../render/highlightRender";
|
||||
import {imgMenu} from "../../menus/protyle";
|
||||
import {assetMenu, imgMenu} from "../../menus/protyle";
|
||||
import {hideElements} from "../ui/hideElements";
|
||||
import {fetchPost} from "../../util/fetch";
|
||||
import {getDisplayName, pathPosix} from "../../util/pathName";
|
||||
|
|
@ -608,7 +608,7 @@ ${genHintItemHTML(item)}
|
|||
this.fixImageCursor(range);
|
||||
protyle.toolbar.range = range;
|
||||
const rangePosition = getSelectionPosition(nodeElement, range);
|
||||
protyle.toolbar.showAssets(protyle, {x: rangePosition.left, y: rangePosition.top + 26, w: 0, h: 26});
|
||||
assetMenu(protyle, {x: rangePosition.left, y: rangePosition.top + 26, w: 0, h: 26});
|
||||
updateTransaction(protyle, id, nodeElement.outerHTML, html);
|
||||
return;
|
||||
} else if (value === Constants.ZWSP + 3) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import {getSearch} from "../../../util/functions";
|
|||
import {openAsset} from "../../../editor/util";
|
||||
/// #endif
|
||||
import {previewImage} from "../../preview/image";
|
||||
import {assetMenu} from "../../../menus/protyle";
|
||||
|
||||
export const openMenuPanel = (options: {
|
||||
protyle: IProtyle,
|
||||
|
|
@ -613,7 +614,7 @@ export const openMenuPanel = (options: {
|
|||
id: options.colId,
|
||||
avID,
|
||||
name,
|
||||
type: target.dataset.oldType as TAVCol,
|
||||
type: target.dataset.oldType as TAVCol,
|
||||
}]);
|
||||
}
|
||||
avPanelElement.remove();
|
||||
|
|
@ -755,7 +756,7 @@ export const openMenuPanel = (options: {
|
|||
break;
|
||||
} else if (type === "addAssetExist") {
|
||||
const rect = target.getBoundingClientRect();
|
||||
options.protyle.toolbar.showAssets(options.protyle, {
|
||||
assetMenu(options.protyle, {
|
||||
x: rect.right,
|
||||
y: rect.bottom,
|
||||
w: target.parentElement.clientWidth + 8,
|
||||
|
|
@ -782,7 +783,7 @@ export const openMenuPanel = (options: {
|
|||
type: "addUpdate",
|
||||
addUpdateValue: [value]
|
||||
});
|
||||
hideElements(["util"], options.protyle);
|
||||
window.siyuan.menus.menu.remove();
|
||||
});
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
|
|
|||
|
|
@ -1522,136 +1522,6 @@ export class Toolbar {
|
|||
});
|
||||
}
|
||||
|
||||
private renderAssetList(listElement: Element, previewElement: Element, k: string, position: IPosition, exts: string[] = []) {
|
||||
fetchPost("/api/search/searchAsset", {
|
||||
k,
|
||||
exts
|
||||
}, (response) => {
|
||||
let searchHTML = "";
|
||||
response.data.forEach((item: { path: string, hName: string }, index: number) => {
|
||||
searchHTML += `<div data-value="${item.path}" class="b3-list-item${index === 0 ? " b3-list-item--focus" : ""}"><div class="b3-list-item__text">${item.hName}</div></div>`;
|
||||
});
|
||||
listElement.innerHTML = searchHTML || `<li class="b3-list--empty">${window.siyuan.languages.emptyContent}</li>`;
|
||||
if (response.data.length > 0) {
|
||||
previewElement.innerHTML = renderAssetsPreview(response.data[0].path);
|
||||
}
|
||||
/// #if !MOBILE
|
||||
setPosition(this.subElement, position.x, position.y, position.h, position.w);
|
||||
/// #endif
|
||||
});
|
||||
}
|
||||
|
||||
public showAssets(protyle: IProtyle, position: IPosition, callback?: (url: string) => void, exts: string[] = []) {
|
||||
hideElements(["hint"], protyle);
|
||||
window.siyuan.menus.menu.remove();
|
||||
this.subElement.style.width = "";
|
||||
this.subElement.style.padding = "";
|
||||
this.subElement.innerHTML = `<div style="max-height:50vh" class="fn__flex">
|
||||
<div class="fn__flex-column" style="${isMobile() ? "width:100%" : "min-width: 260px;max-width:420px"}">
|
||||
<div class="fn__flex" style="margin: 0 8px 4px 8px">
|
||||
<input class="b3-text-field fn__flex-1"/>
|
||||
<span class="fn__space"></span>
|
||||
<span data-type="previous" class="block__icon block__icon--show"><svg><use xlink:href="#iconLeft"></use></svg></span>
|
||||
<span class="fn__space"></span>
|
||||
<span data-type="next" class="block__icon block__icon--show"><svg><use xlink:href="#iconRight"></use></svg></span>
|
||||
</div>
|
||||
<div class="b3-list fn__flex-1 b3-list--background" style="position: relative"><img style="margin: 0 auto;display: block;width: 64px;height: 64px" src="/stage/loading-pure.svg"></div>
|
||||
</div>
|
||||
<div style="width: 360px;display: ${isMobile() || window.outerWidth < window.outerWidth / 2 + 260 ? "none" : "flex"};padding: 8px;overflow: auto;justify-content: center;align-items: center;word-break: break-all;"></div>
|
||||
</div>`;
|
||||
const listElement = this.subElement.querySelector(".b3-list");
|
||||
const previewElement = this.subElement.firstElementChild.lastElementChild;
|
||||
listElement.addEventListener("mouseover", (event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
const hoverItemElement = hasClosestByClassName(target, "b3-list-item");
|
||||
if (!hoverItemElement) {
|
||||
return;
|
||||
}
|
||||
previewElement.innerHTML = renderAssetsPreview(hoverItemElement.getAttribute("data-value"));
|
||||
});
|
||||
const inputElement = this.subElement.querySelector("input");
|
||||
inputElement.addEventListener("keydown", (event: KeyboardEvent) => {
|
||||
event.stopPropagation();
|
||||
if (event.isComposing) {
|
||||
return;
|
||||
}
|
||||
const isEmpty = this.subElement.querySelector(".b3-list--empty");
|
||||
if (!isEmpty) {
|
||||
const currentElement = upDownHint(listElement, event);
|
||||
if (currentElement) {
|
||||
previewElement.innerHTML = renderAssetsPreview(currentElement.getAttribute("data-value"));
|
||||
}
|
||||
}
|
||||
|
||||
if (event.key === "Enter") {
|
||||
if (!isEmpty) {
|
||||
const currentURL = this.subElement.querySelector(".b3-list-item--focus").getAttribute("data-value");
|
||||
if (callback) {
|
||||
callback(currentURL);
|
||||
} else {
|
||||
hintRenderAssets(currentURL, protyle);
|
||||
}
|
||||
} else if (!callback) {
|
||||
focusByRange(this.range);
|
||||
}
|
||||
this.subElement.classList.add("fn__none");
|
||||
// 空行处插入 mp3 会多一个空的 mp3 块
|
||||
event.preventDefault();
|
||||
} else if (event.key === "Escape") {
|
||||
this.subElement.classList.add("fn__none");
|
||||
if (!callback) {
|
||||
focusByRange(this.range);
|
||||
}
|
||||
}
|
||||
});
|
||||
inputElement.addEventListener("input", (event) => {
|
||||
event.stopPropagation();
|
||||
this.renderAssetList(listElement, previewElement, inputElement.value, position, exts);
|
||||
});
|
||||
this.subElement.lastElementChild.addEventListener("click", (event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
const previousElement = hasClosestByAttribute(target, "data-type", "previous");
|
||||
if (previousElement) {
|
||||
inputElement.dispatchEvent(new KeyboardEvent("keydown", {key: "ArrowUp"}));
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
const nextElement = hasClosestByAttribute(target, "data-type", "next");
|
||||
if (nextElement) {
|
||||
inputElement.dispatchEvent(new KeyboardEvent("keydown", {key: "ArrowDown"}));
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
if (target.classList.contains("b3-list--empty")) {
|
||||
this.subElement.classList.add("fn__none");
|
||||
if (!callback) {
|
||||
focusByRange(this.range);
|
||||
}
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
const listItemElement = hasClosestByClassName(target, "b3-list-item");
|
||||
if (listItemElement) {
|
||||
event.stopPropagation();
|
||||
const currentURL = listItemElement.getAttribute("data-value");
|
||||
if (callback) {
|
||||
callback(currentURL);
|
||||
} else {
|
||||
hintRenderAssets(currentURL, protyle);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.subElement.style.zIndex = (++window.siyuan.zIndex).toString();
|
||||
this.subElement.classList.remove("fn__none");
|
||||
this.subElementCloseCB = undefined;
|
||||
/// #if MOBILE
|
||||
setPosition(this.subElement, 0, 0);
|
||||
/// #endif
|
||||
this.element.classList.add("fn__none");
|
||||
inputElement.select();
|
||||
this.renderAssetList(listElement, previewElement, "", position, exts);
|
||||
}
|
||||
|
||||
public showContent(protyle: IProtyle, range: Range, nodeElement: Element) {
|
||||
this.range = range;
|
||||
hideElements(["hint"], protyle);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue