瀏覽代碼

:art: https://github.com/siyuan-note/siyuan/issues/9111

Vanessa 1 年之前
父節點
當前提交
c33fef2f72

+ 11 - 0
app/src/assets/scss/mobile.scss

@@ -31,6 +31,16 @@
   width: 80vw;
 }
 
+.fn__flex-column[data-type="sidebar-file"] {
+  .b3-list-item {
+    -webkit-user-select: none;
+
+    &:hover {
+      background-color: transparent;
+    }
+  }
+}
+
 .b3-list--mobile {
 
   & > .fn__flex-column {
@@ -38,6 +48,7 @@
   }
 
   .b3-list-item {
+
     font-size: 16px;
     line-height: 40px;
 

+ 1 - 1
app/src/mobile/index.ts

@@ -106,7 +106,7 @@ class App {
             document.addEventListener("touchstart", handleTouchStart, false);
             document.addEventListener("touchmove", handleTouchMove, false);
             document.addEventListener("touchend", (event) => {
-                handleTouchEnd(event);
+                handleTouchEnd(event, siyuanApp);
             }, false);
         });
     }

+ 2 - 2
app/src/mobile/util/initFramework.ts

@@ -2,7 +2,7 @@ import {Constants} from "../../constants";
 import {closeModel, closePanel} from "./closePanel";
 import {openMobileFileById} from "../editor";
 import {validateName} from "../../editor/rename";
-import {getEventName} from "../../protyle/util/compatibility";
+import {getEventName, isIPhone} from "../../protyle/util/compatibility";
 import {fetchPost} from "../../util/fetch";
 import {setInlineStyle} from "../../util/assets";
 import {renderSnippet} from "../../config/util/snippets";
@@ -125,7 +125,7 @@ export const initFramework = (app: App) => {
     document.getElementById("toolbarSync").addEventListener(getEventName(), () => {
         syncGuide(app);
     });
-    if (navigator.userAgent.indexOf("iPhone") > -1 && !window.siyuan.config.readonly && !window.siyuan.config.editor.readOnly) {
+    if (isIPhone() && !window.siyuan.config.readonly && !window.siyuan.config.editor.readOnly) {
         // 不知道为什么 iPhone 中如果是编辑状态,点击文档后无法点击标题
         setTimeout(() => {
             editElement.dispatchEvent(new CustomEvent(getEventName()));

+ 48 - 22
app/src/mobile/util/touch.ts

@@ -1,10 +1,17 @@
-import {hasClosestByAttribute, hasClosestByClassName, hasTopClosestByClassName} from "../../protyle/util/hasClosest";
+import {
+    hasClosestByAttribute,
+    hasClosestByClassName,
+    hasTopClosestByClassName,
+    hasTopClosestByTag
+} from "../../protyle/util/hasClosest";
 import {closePanel} from "./closePanel";
 import {popMenu} from "../menu";
 import {activeBlur, hideKeyboardToolbar} from "./keyboardToolbar";
 import {getCurrentEditor} from "../editor";
 import {fileAnnotationRefMenu, linkMenu, refMenu, tagMenu} from "../../menus/protyle";
-import {isInIOS} from "../../protyle/util/compatibility";
+import {isIPhone} from "../../protyle/util/compatibility";
+import {initFileMenu, initNavigationMenu} from "../../menus/navigation";
+import {App} from "../../index";
 
 let clientX: number;
 let clientY: number;
@@ -24,30 +31,49 @@ const popSide = (render = true) => {
     }
 };
 
-export const handleTouchEnd = (event: TouchEvent) => {
+export const handleTouchEnd = (event: TouchEvent, app: App) => {
     const editor = getCurrentEditor();
     const target = event.target as HTMLElement;
-    if (editor && typeof yDiff === "undefined" && new Date().getTime() - time > 900 &&
-        target.tagName === "SPAN" && isInIOS() &&
-        !hasClosestByAttribute(target, "data-type", "NodeBlockQueryEmbed")) {
-        // ios 长按行内元素弹出菜单
-        const types = (target.getAttribute("data-type") || "").split(" ");
-        if (types.includes("inline-memo")) {
-            editor.protyle.toolbar.showRender(editor.protyle, target);
-        }
-        if (editor.protyle.disabled) {
+    if (typeof yDiff === "undefined" && new Date().getTime() - time > 900 && isIPhone()) {
+        // ios 长按行
+        // 文档树
+        const fileItemElement = hasClosestByAttribute(target, "data-type", "navigation-root") || hasClosestByAttribute(target, "data-type", "navigation-file")
+        if (fileItemElement) {
+            if (!window.siyuan.config.readonly && fileItemElement.dataset.type === "navigation-root") {
+                initNavigationMenu(app, fileItemElement);
+                window.siyuan.menus.menu.fullscreen("bottom");
+            } else if (fileItemElement.dataset.type === "navigation-file") {
+                const rootElement = hasTopClosestByTag(fileItemElement, "UL");
+                if (rootElement) {
+                    initFileMenu(app, rootElement.dataset.url, fileItemElement.dataset.path, fileItemElement);
+                    window.siyuan.menus.menu.fullscreen("bottom");
+                }
+            }
+            event.stopImmediatePropagation();
+            event.preventDefault();
             return;
         }
-        if (types.includes("block-ref")) {
-            refMenu(editor.protyle, target);
-        } else if (types.includes("file-annotation-ref")) {
-            fileAnnotationRefMenu(editor.protyle, target);
-        } else if (types.includes("tag")) {
-            tagMenu(editor.protyle, target);
-        } else if (types.includes("a")) {
-            linkMenu(editor.protyle, target);
+        // 内元素弹出菜单
+        if (editor && hasClosestByClassName(target, "protyle-wysiwyg") &&
+            target.tagName === "SPAN" && !hasClosestByAttribute(target, "data-type", "NodeBlockQueryEmbed")) {
+            const types = (target.getAttribute("data-type") || "").split(" ");
+            if (types.includes("inline-memo")) {
+                editor.protyle.toolbar.showRender(editor.protyle, target);
+            }
+            if (editor.protyle.disabled) {
+                return;
+            }
+            if (types.includes("block-ref")) {
+                refMenu(editor.protyle, target);
+            } else if (types.includes("file-annotation-ref")) {
+                fileAnnotationRefMenu(editor.protyle, target);
+            } else if (types.includes("tag")) {
+                tagMenu(editor.protyle, target);
+            } else if (types.includes("a")) {
+                linkMenu(editor.protyle, target);
+            }
+            return;
         }
-        return;
     }
     if (!clientX || !clientY || typeof yDiff === "undefined" ||
         target.tagName === "AUDIO" ||
@@ -163,7 +189,7 @@ export const handleTouchStart = (event: TouchEvent) => {
     xDiff = undefined;
     yDiff = undefined;
     lastClientX = undefined;
-    if (navigator.userAgent.indexOf("iPhone") > -1 ||
+    if (isIPhone() ||
         (event.touches[0].clientX > 8 && event.touches[0].clientX < window.innerWidth - 8)) {
         clientX = event.touches[0].clientX;
         clientY = event.touches[0].clientY;

+ 2 - 2
app/src/protyle/hint/index.ts

@@ -30,7 +30,7 @@ import {openMobileFileById} from "../../mobile/editor";
 import {processRender} from "../util/processCode";
 import {AIChat} from "../../ai/chat";
 import {isMobile} from "../../util/functions";
-import {isCtrl} from "../util/compatibility";
+import {isCtrl, isIPhone} from "../util/compatibility";
 import {avRender} from "../render/av/render";
 import {genIconHTML} from "../render/util";
 
@@ -494,7 +494,7 @@ ${genHintItemHTML(item)}
 
         if (this.lastIndex > -1) {
             range.setStart(range.startContainer, this.lastIndex);
-            if (navigator.userAgent.indexOf("iPhone") > -1) {
+            if (isIPhone()) {
                 focusByRange(range);
             }
         }

+ 5 - 1
app/src/protyle/util/compatibility.ts

@@ -66,7 +66,7 @@ export const copyPlainText = async (text: string) => {
 
 // 用户 iPhone 点击延迟/需要双击的处理
 export const getEventName = () => {
-    if (navigator.userAgent.indexOf("iPhone") > -1) {
+    if (isIPhone()) {
         return "touchstart";
     } else {
         return "click";
@@ -93,6 +93,10 @@ export const isHuawei = () => {
     return window.siyuan.config.system.osPlatform.toLowerCase().indexOf("huawei") > -1;
 };
 
+export const isIPhone = () => {
+    return navigator.userAgent.indexOf("iPhone") > -1
+}
+
 export const isMac = () => {
     return navigator.platform.toUpperCase().indexOf("MAC") > -1;
 };