Procházet zdrojové kódy

enhance(mobile): no need to swipe from edge to navigate back

Tienson Qin před 4 měsíci
rodič
revize
6d4bc92cad

+ 21 - 20
src/main/mobile/components/app.cljs

@@ -52,30 +52,32 @@
         max-vertical-drift 50
 
         on-touch-start (fn [^js e]
-                         (let [t (aget e "touches" 0)]
-                           (reset! touch-start-x (.-pageX t))
-                           (reset! touch-start-y (.-pageY t))
-                           (reset! has-triggered? false)
-                           (reset! blocking-scroll? false)))
+                         (when (empty? @mobile-state/*modal-blocks)
+                           (let [t (aget e "touches" 0)]
+                             (reset! touch-start-x (.-pageX t))
+                             (reset! touch-start-y (.-pageY t))
+                             (reset! has-triggered? false)
+                             (reset! blocking-scroll? false))))
 
         on-touch-move (fn [^js e]
-                        (let [t (aget e "touches" 0)
-                              dx (- (.-pageX t) @touch-start-x)
-                              dy (js/Math.abs (- (.-pageY t) @touch-start-y))
-                              horizontal-intent (and (> dx horiz-intent-threshold)
-                                                     (> dx dy))
-                              is-horizontal-swipe (and (> dx swipe-trigger-distance)
-                                                       (< dy max-vertical-drift))]
+                        (when (empty? @mobile-state/*modal-blocks)
+                          (let [t (aget e "touches" 0)
+                                dx (- (.-pageX t) @touch-start-x)
+                                dy (js/Math.abs (- (.-pageY t) @touch-start-y))
+                                horizontal-intent (and (> dx horiz-intent-threshold)
+                                                       (> dx dy))
+                                is-horizontal-swipe (and (> dx swipe-trigger-distance)
+                                                         (< dy max-vertical-drift))]
 
                           ;; as soon as we detect horizontal intent, block vertical scrolling
-                          (when (or @blocking-scroll? horizontal-intent)
-                            (reset! blocking-scroll? true)
-                            (.preventDefault e))       ;; <-- stops page from scrolling
+                            (when (or @blocking-scroll? horizontal-intent)
+                              (reset! blocking-scroll? true)
+                              (.preventDefault e))       ;; <-- stops page from scrolling
 
-                          (when (and (not @has-triggered?)
-                                     is-horizontal-swipe)
-                            (reset! has-triggered? true)
-                            (mobile-state/open-left-sidebar!))))
+                            (when (and (not @has-triggered?)
+                                       is-horizontal-swipe)
+                              (reset! has-triggered? true)
+                              (mobile-state/open-left-sidebar!)))))
 
         on-touch-end (fn [_]
                        (reset! blocking-scroll? false))]
@@ -163,7 +165,6 @@
     (use-theme-effects! current-repo)
     (hooks/use-effect!
      (fn []
-       (setup-sidebar-touch-swipe!)
        (when-let [element (util/mobile-page-scroll)]
          (common-handler/listen-to-scroll! element))) [])
     (silkhq/depth-sheet-stack

+ 98 - 79
src/main/mobile/components/modal.cljs

@@ -41,41 +41,60 @@
    ;; block page content
    [:div.block-modal-page-content
     (mobile-ui/classic-app-container-wrap
-      (page/page-cp (db/entity [:block/uuid (:block/uuid block)])))]])
+     (page/page-cp (db/entity [:block/uuid (:block/uuid block)])))]])
 
-(defn setup-sidebar-touch-swipe! []
+(defn- setup-sidebar-touch-swipe!
+  []
   (let [touch-start-x (atom 0)
         touch-start-y (atom 0)
         has-triggered? (atom false)
-        edge-threshold 30
-        swipe-trigger-distance 50
+        blocking-scroll? (atom false)
+
+        swipe-trigger-distance 50         ;; when to actually open sidebar
+        horiz-intent-threshold 10         ;; when to start blocking scroll
         max-vertical-drift 50
 
         on-touch-start (fn [^js e]
-                         (let [touch (aget e "touches" 0)]
-                           (reset! touch-start-x (.-pageX touch))
-                           (reset! touch-start-y (.-pageY touch))
-                           (reset! has-triggered? false)))
+                         (let [t (aget e "touches" 0)]
+                           (reset! touch-start-x (.-pageX t))
+                           (reset! touch-start-y (.-pageY t))
+                           (reset! has-triggered? false)
+                           (reset! blocking-scroll? false)))
 
         on-touch-move (fn [^js e]
-                        (when-not @has-triggered?
-                          (let [touch (aget e "touches" 0)
-                                delta-x (- (.-pageX touch) @touch-start-x)
-                                delta-y (js/Math.abs (- (.-pageY touch) @touch-start-y))
-                                started-from-edge (<= @touch-start-x edge-threshold)
-                                is-horizontal-swipe (and (> delta-x swipe-trigger-distance)
-                                                         (< delta-y max-vertical-drift))]
-                            (when (and started-from-edge is-horizontal-swipe)
-                              (reset! has-triggered? true)
-                              (mobile-state/pop-navigation-history!)))))]
-
-    (.addEventListener js/document "touchstart" on-touch-start #js {:passive true})
-    (.addEventListener js/document "touchmove" on-touch-move #js {:passive true})
-
-    ;; Return cleanup function
+                        (let [t (aget e "touches" 0)
+                              dx (- (.-pageX t) @touch-start-x)
+                              dy (js/Math.abs (- (.-pageY t) @touch-start-y))
+                              horizontal-intent (and (> dx horiz-intent-threshold)
+                                                     (> dx dy))
+                              is-horizontal-swipe (and (> dx swipe-trigger-distance)
+                                                       (< dy max-vertical-drift))]
+
+                          ;; as soon as we detect horizontal intent, block vertical scrolling
+                          (when (or @blocking-scroll? horizontal-intent)
+                            (reset! blocking-scroll? true)
+                            (.preventDefault e))       ;; <-- stops page from scrolling
+
+                          (when (and (not @has-triggered?)
+                                     is-horizontal-swipe)
+                            (reset! has-triggered? true)
+                            (mobile-state/pop-navigation-history!))))
+
+        on-touch-end (fn [_]
+                       (reset! blocking-scroll? false))]
+
+    ;; IMPORTANT: passive:false so preventDefault actually works
+    (.addEventListener js/document "touchstart" on-touch-start #js {:passive false})
+    (.addEventListener js/document "touchmove"  on-touch-move  #js {:passive false})
+    (.addEventListener js/document "touchend"   on-touch-end   #js {:passive false})
+    (.addEventListener js/document "touchcancel" on-touch-end  #js {:passive false})
+
+    ;; cleanup
     #(do
        (.removeEventListener js/document "touchstart" on-touch-start)
-       (.removeEventListener js/document "touchmove" on-touch-move))))
+       (.removeEventListener js/document "touchmove"  on-touch-move)
+       (.removeEventListener js/document "touchend"   on-touch-end)
+       (.removeEventListener js/document "touchcancel" on-touch-end))))
 
 (rum/defc block-sheet-topbar
   [block {:keys [favorited? set-favorited!]}]
@@ -87,49 +106,49 @@
      [:span.flex.items-center.-mr-2
       (when-let [block-id-str (str (:block/uuid block))]
         (shui/button
-          {:variant :text
-           :size :sm
-           :class (when favorited? "!text-yellow-800")
-           :on-click #(-> (if favorited?
-                            (page-handler/<unfavorite-page! block-id-str)
-                            (page-handler/<favorite-page! block-id-str))
-                        (p/then (fn [] (set-favorited! (not favorited?)))))}
-          (shui/tabler-icon (if favorited? "star-filled" "star") {:size 20})))
+         {:variant :text
+          :size :sm
+          :class (when favorited? "!text-yellow-800")
+          :on-click #(-> (if favorited?
+                           (page-handler/<unfavorite-page! block-id-str)
+                           (page-handler/<favorite-page! block-id-str))
+                         (p/then (fn [] (set-favorited! (not favorited?)))))}
+         (shui/tabler-icon (if favorited? "star-filled" "star") {:size 20})))
       (shui/button
-        {:variant :text
-         :size :sm
-         :on-click (fn []
-                     (mobile-ui/open-popup!
-                       (fn []
-                         [:div.-mx-2
-                          (ui/menu-link
-                            {:on-click #(mobile-ui/close-popup!)}
-                            [:span.text-lg.flex.gap-2.items-center
-                             (shui/tabler-icon "copy" {:class "opacity-80" :size 22})
-                             "Copy"])
-
-                          (ui/menu-link
-                            {:on-click #(-> (shui/dialog-confirm!
-                                              (str "⚠️ Are you sure you want to delete this "
-                                                (if (entity-util/page? block) "page" "block")
-                                                "?"))
-                                          (p/then
-                                            (fn []
-                                              (mobile-ui/close-popup!)
-                                              (some->
-                                                (:block/uuid block)
-                                                (page-handler/<delete!
-                                                  (fn [] (close!))
-                                                  {:error-handler
-                                                   (fn [{:keys [msg]}]
-                                                     (notification/show! msg :warning))})))))}
-                            [:span.text-lg.flex.gap-2.items-center.text-red-700
-                             (shui/tabler-icon "trash" {:class "opacity-80" :size 22})
-                             "Delete"])])
-                       {:title "Actions"
-                        :default-height false
-                        :type :action-sheet}))}
-        (shui/tabler-icon "dots-vertical" {:size 20}))]]))
+       {:variant :text
+        :size :sm
+        :on-click (fn []
+                    (mobile-ui/open-popup!
+                     (fn []
+                       [:div.-mx-2
+                        (ui/menu-link
+                         {:on-click #(mobile-ui/close-popup!)}
+                         [:span.text-lg.flex.gap-2.items-center
+                          (shui/tabler-icon "copy" {:class "opacity-80" :size 22})
+                          "Copy"])
+
+                        (ui/menu-link
+                         {:on-click #(-> (shui/dialog-confirm!
+                                          (str "⚠️ Are you sure you want to delete this "
+                                               (if (entity-util/page? block) "page" "block")
+                                               "?"))
+                                         (p/then
+                                          (fn []
+                                            (mobile-ui/close-popup!)
+                                            (some->
+                                             (:block/uuid block)
+                                             (page-handler/<delete!
+                                              (fn [] (close!))
+                                              {:error-handler
+                                               (fn [{:keys [msg]}]
+                                                 (notification/show! msg :warning))})))))}
+                         [:span.text-lg.flex.gap-2.items-center.text-red-700
+                          (shui/tabler-icon "trash" {:class "opacity-80" :size 22})
+                          "Delete"])])
+                     {:title "Actions"
+                      :default-height false
+                      :type :action-sheet}))}
+       (shui/tabler-icon "dots-vertical" {:size 20}))]]))
 
 (rum/defc block-sheet
   [block]
@@ -169,19 +188,19 @@
         :onClickOutside (bean/->js {:dismiss false
                                     :stopOverlayPropagation false})}
        (silkhq/depth-sheet-backdrop)
-        (silkhq/depth-sheet-content
-          {:class "app-silk-depth-sheet-content"}
-          (block-sheet-topbar block {:favorited? favorited?
-                                     :set-favorited! set-favorited!})
-          (silkhq/scroll
-            {:as-child true}
-            (silkhq/scroll-view
-              {:class "app-silk-scroll-view"
-               :scrollGestureTrap {:yEnd true}}
-              (silkhq/scroll-content
-                {:class "app-silk-scroll-content"}
-
-                (block-cp block))))))))))
+       (silkhq/depth-sheet-content
+        {:class "app-silk-depth-sheet-content"}
+        (block-sheet-topbar block {:favorited? favorited?
+                                   :set-favorited! set-favorited!})
+        (silkhq/scroll
+         {:as-child true}
+         (silkhq/scroll-view
+          {:class "app-silk-scroll-view"
+           :scrollGestureTrap {:yEnd true}}
+          (silkhq/scroll-content
+           {:class "app-silk-scroll-content"}
+
+           (block-cp block))))))))))
 
 (rum/defc blocks-modal < rum/reactive
   []