From 48cacbc5dc8a862afb2a1d073c0e20d0c37fc3ca Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Wed, 4 Feb 2026 23:08:55 +0800 Subject: [PATCH] :art: Improve soft keyboard toolbar pop-up https://github.com/siyuan-note/siyuan/issues/16548 Signed-off-by: Daniel <845765@qq.com> --- app/src/mobile/index.ts | 108 ++++++++++++++++++++--------------- app/src/mobile/util/touch.ts | 15 +---- 2 files changed, 63 insertions(+), 60 deletions(-) diff --git a/app/src/mobile/index.ts b/app/src/mobile/index.ts index e58b01b9b..6d8dd9b1a 100644 --- a/app/src/mobile/index.ts +++ b/app/src/mobile/index.ts @@ -2,7 +2,12 @@ import {addScript, addScriptSync} from "../protyle/util/addScript"; import {Constants} from "../constants"; import {onMessage} from "./util/onMessage"; import {genUUID} from "../util/genID"; -import {hasClosestBlock, hasClosestByAttribute, hasTopClosestByClassName} from "../protyle/util/hasClosest"; +import { + hasClosestBlock, + hasClosestByAttribute, + hasClosestByClassName, + hasTopClosestByClassName +} from "../protyle/util/hasClosest"; import {Model} from "../layout/Model"; import "../assets/scss/mobile.scss"; import {Menus} from "../menus"; @@ -14,7 +19,7 @@ import {initAssets, loadAssets} from "../util/assets"; import {bootSync} from "../dialog/processSystem"; import {initMessage, showMessage} from "../dialog/message"; import {goBack} from "./util/MobileBackFoward"; -import {hideKeyboardToolbar, showKeyboardToolbar} from "./util/keyboardToolbar"; +import {activeBlur, hideKeyboardToolbar, showKeyboardToolbar} from "./util/keyboardToolbar"; import {getLocalStorage, writeText} from "../protyle/util/compatibility"; import {getCurrentEditor, openMobileFileById} from "./editor"; import {getSearch} from "../util/functions"; @@ -88,6 +93,17 @@ class App { showMessage(window.siyuan.languages.copied, 2000); event.preventDefault(); } + + const wysisygElement = hasClosestByClassName(event.target, "protyle-wysiwyg", true); + let editElement: HTMLElement; + if (["INPUT", "TEXTAREA"].includes(event.target.tagName) && event.target.getAttribute("readonly") !== "readonly") { + editElement = event.target; + } else if (wysisygElement && wysisygElement.getAttribute("data-readonly") === "false") { + editElement = hasClosestByAttribute(event.target, "contenteditable", "true") as HTMLElement; + } + if (editElement) { + window.JSAndroid?.showKeyboard(); + } }); window.addEventListener("beforeunload", () => { saveScroll(window.siyuan.mobile.editor.protyle); @@ -98,6 +114,50 @@ class App { // 判断手机横竖屏状态 window.matchMedia("(orientation:portrait)").addEventListener("change", () => { updateCardHV(); + activeBlur(); + }); + window.siyuan.mobile.size.isLandscape = window.matchMedia && window.matchMedia("(orientation: landscape)").matches; + if (window.siyuan.mobile.size.isLandscape) { + window.siyuan.mobile.size.landscape = { + height1: window.innerHeight, + height2: window.innerHeight, + } + } else { + window.siyuan.mobile.size.portrait = { + height1: window.innerHeight, + height2: window.innerHeight, + } + } + window.addEventListener("resize", () => { + // 获取键盘高度 + window.siyuan.mobile.size.isLandscape = window.matchMedia && window.matchMedia("(orientation: landscape)").matches; + if (window.siyuan.mobile.size.isLandscape) { + if (!window.siyuan.mobile.size.landscape) { + window.siyuan.mobile.size.landscape = { + height1: window.innerHeight, + height2: window.innerHeight, + } + } + if (window.innerHeight < window.siyuan.mobile.size.landscape.height1) { + window.siyuan.mobile.size.landscape.height2 = window.innerHeight; + } + if (window.innerHeight > window.siyuan.mobile.size.landscape.height1) { + window.siyuan.mobile.size.landscape.height1 = window.innerHeight; + } + } else { + if (!window.siyuan.mobile.size.portrait) { + window.siyuan.mobile.size.portrait = { + height1: window.innerHeight, + height2: window.innerHeight, + } + } + if (window.innerHeight < window.siyuan.mobile.size.portrait.height1) { + window.siyuan.mobile.size.portrait.height2 = window.innerHeight; + } + if (window.innerHeight > window.siyuan.mobile.size.portrait.height1) { + window.siyuan.mobile.size.portrait.height1 = window.innerHeight; + } + } }); fetchPost("/api/system/getConf", {}, async (confResponse) => { addScriptSync(`${Constants.PROTYLE_CDN}/js/lute/lute.min.js?v=${Constants.SIYUAN_VERSION}`, "protyleLuteScript"); @@ -160,19 +220,6 @@ class App { } }); }); - - window.siyuan.mobile.size.isLandscape = window.matchMedia && window.matchMedia("(orientation: landscape)").matches; - if (window.siyuan.mobile.size.isLandscape) { - window.siyuan.mobile.size.landscape = { - height1: window.innerHeight, - height2: window.innerHeight, - } - } else { - window.siyuan.mobile.size.portrait = { - height1: window.innerHeight, - height2: window.innerHeight, - } - } } } @@ -198,34 +245,3 @@ window.openFileByURL = (openURL) => { } return false; }; -window.addEventListener("resize", () => { - // 获取键盘高度 - window.siyuan.mobile.size.isLandscape = window.matchMedia && window.matchMedia("(orientation: landscape)").matches; - if (window.siyuan.mobile.size.isLandscape) { - if (!window.siyuan.mobile.size.landscape) { - window.siyuan.mobile.size.landscape = { - height1: window.innerHeight, - height2: window.innerHeight, - } - } - if (window.innerHeight < window.siyuan.mobile.size.landscape.height1) { - window.siyuan.mobile.size.landscape.height2 = window.innerHeight; - } - if (window.innerHeight > window.siyuan.mobile.size.landscape.height1) { - window.siyuan.mobile.size.landscape.height1 = window.innerHeight; - } - } else { - if (!window.siyuan.mobile.size.portrait) { - window.siyuan.mobile.size.portrait = { - height1: window.innerHeight, - height2: window.innerHeight, - } - } - if (window.innerHeight < window.siyuan.mobile.size.portrait.height1) { - window.siyuan.mobile.size.portrait.height2 = window.innerHeight; - } - if (window.innerHeight > window.siyuan.mobile.size.portrait.height1) { - window.siyuan.mobile.size.portrait.height1 = window.innerHeight; - } - } -}); diff --git a/app/src/mobile/util/touch.ts b/app/src/mobile/util/touch.ts index 9da64b383..3f77a9dc4 100644 --- a/app/src/mobile/util/touch.ts +++ b/app/src/mobile/util/touch.ts @@ -28,19 +28,6 @@ const popSide = (render = true) => { export const handleTouchEnd = (event: TouchEvent, app: App) => { const target = event.target as HTMLElement; - const wysisygElement = hasClosestByClassName(target, "protyle-wysiwyg", true); - if (!yDiff || Math.abs(yDiff) < 8) { - let editElement: HTMLElement; - if (["INPUT", "TEXTAREA"].includes(target.tagName) && target.getAttribute("readonly") !== "readonly") { - editElement = target; - } else if (wysisygElement && wysisygElement.getAttribute("data-readonly") === "false") { - editElement = hasClosestByAttribute(target, "contenteditable", "true") as HTMLElement; - } - if (editElement) { - window.JSAndroid?.showKeyboard(); - } - } - if (isIPhone() && globalTouchEnd(event, yDiff, time, app)) { event.stopImmediatePropagation(); event.preventDefault(); @@ -80,7 +67,7 @@ export const handleTouchEnd = (event: TouchEvent, app: App) => { const isXScroll = Math.abs(xDiff) > Math.abs(yDiff); const modelElement = hasClosestByAttribute(target, "id", "model", true); if (modelElement) { - if (isXScroll && firstDirection === "toRight" && !lastClientX && !wysisygElement) { + if (isXScroll && firstDirection === "toRight" && !lastClientX && !hasClosestByClassName(target, "protyle-wysiwyg", true)) { closeModel(); } return;