diff --git a/app/src/assets/scss/component/_menu.scss b/app/src/assets/scss/component/_menu.scss index bec14a135..60de8f4a0 100644 --- a/app/src/assets/scss/component/_menu.scss +++ b/app/src/assets/scss/component/_menu.scss @@ -169,7 +169,7 @@ } &__items { - max-height: min(80vh, calc(100vh - 20px - var(--b3-menu-position-top, 0px))); // 20px 是 .b3-menu 的上下 padding + max-height: 80vh; overflow: auto; padding: 0 8px; } diff --git a/app/src/boot/onGetConfig.ts b/app/src/boot/onGetConfig.ts index decd7a88e..37a6ad8e1 100644 --- a/app/src/boot/onGetConfig.ts +++ b/app/src/boot/onGetConfig.ts @@ -84,6 +84,7 @@ export const onGetConfig = (isStart: boolean, app: App) => { adjustLayout(); resizeTabs(); resizeTopBar(); + window.siyuan.menus.menu.resetPosition(); firstResize = true; }, 200); }); diff --git a/app/src/menus/Menu.ts b/app/src/menus/Menu.ts index 556644ad1..3f6ce4b06 100644 --- a/app/src/menus/Menu.ts +++ b/app/src/menus/Menu.ts @@ -146,7 +146,25 @@ export class Menu { this.element.style.zIndex = (++window.siyuan.zIndex).toString(); this.element.classList.remove("fn__none"); setPosition(this.element, options.x - (options.isLeft ? this.element.clientWidth : 0), options.y, options.h, options.w); - this.element.style.setProperty("--b3-menu-position-top", this.element.style.top); + const menuTop = parseInt(this.element.style.top) || options.y; + const availableHeight = window.innerHeight - menuTop - Constants.SIZE_TOOLBAR_HEIGHT; + (this.element.lastElementChild as HTMLElement).style.maxHeight = Math.max(availableHeight, 0) + "px"; + } + + public resetPosition() { + if (this.element.classList.contains("fn__none")) { + return; + } + + setPosition(this.element, parseInt(this.element.style.left) || 0, parseInt(this.element.style.top) || 0, 0, 0); + const menuTop = parseInt(this.element.style.top) || 0; + const availableHeight = window.innerHeight - menuTop - Constants.SIZE_TOOLBAR_HEIGHT; + (this.element.lastElementChild as HTMLElement).style.maxHeight = Math.max(availableHeight, 0) + "px"; + + const showSubMenus = this.element.querySelectorAll(".b3-menu__item--show .b3-menu__submenu"); + showSubMenus.forEach((subMenuElement) => { + this.showSubMenu(subMenuElement as HTMLElement); + }); } public fullscreen(position: "bottom" | "all" = "all") { diff --git a/app/src/util/setPosition.ts b/app/src/util/setPosition.ts index e0871fd5f..9c584dec6 100644 --- a/app/src/util/setPosition.ts +++ b/app/src/util/setPosition.ts @@ -4,20 +4,26 @@ export const setPosition = (element: HTMLElement, x: number, y: number, targetHe element.style.top = y + "px"; element.style.left = x + "px"; const rect = element.getBoundingClientRect(); - // 上下超出屏幕 + + // 垂直方向调整 if (rect.bottom > window.innerHeight || rect.top < Constants.SIZE_TOOLBAR_HEIGHT) { - const top = y - rect.height - targetHeight; - if (top > Constants.SIZE_TOOLBAR_HEIGHT && (top + rect.height) < window.innerHeight) { - // 上部 - element.style.top = top + "px"; - } else if (top <= Constants.SIZE_TOOLBAR_HEIGHT) { - // 位置超越到屏幕上方外时,需移动到屏幕顶部。eg:光标在第一个块,然后滚动到上方看不见的位置,按 ctrl+a - element.style.top = Constants.SIZE_TOOLBAR_HEIGHT + "px"; + const bottomSpace = window.innerHeight - y; + const topSpace = y - Constants.SIZE_TOOLBAR_HEIGHT; + + if (bottomSpace >= rect.height) { + // 如果下方空间足够,直接使用原位置 + element.style.top = y + "px"; + } else if (topSpace >= rect.height) { + // 如果上方空间足够,向上调整 + element.style.top = (y - rect.height - targetHeight) + "px"; } else { - // 依旧展现在下部,只是位置上移 - element.style.top = Math.max(Constants.SIZE_TOOLBAR_HEIGHT, window.innerHeight - rect.height) + "px"; + // 如果上下空间都不够,优先展现在下部 + const maxTop = Math.max(Constants.SIZE_TOOLBAR_HEIGHT, window.innerHeight - rect.height); + element.style.top = maxTop + "px"; } } + + // 水平方向调整 if (rect.right > window.innerWidth) { // 展现在左侧 element.style.left = `${window.innerWidth - rect.width - targetLeft}px`; diff --git a/app/src/window/init.ts b/app/src/window/init.ts index 442a24b7d..7e92d8d06 100644 --- a/app/src/window/init.ts +++ b/app/src/window/init.ts @@ -61,6 +61,7 @@ export const init = (app: App) => { resizeTimeout = window.setTimeout(() => { adjustLayout(window.siyuan.layout.centerLayout); resizeTabs(); + window.siyuan.menus.menu.resetPosition(); }, 200); }); };