This commit is contained in:
Vanessa 2023-11-02 11:20:02 +08:00
parent d93bd7cfe5
commit 76b0617689
6 changed files with 159 additions and 145 deletions

View file

@ -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) => {

View file

@ -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);

View file

@ -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);

View file

@ -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) {

View file

@ -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();

View file

@ -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);