From 060a0dd86b7466b278972f6ad531cc5728cccba8 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 14 Aug 2025 13:50:34 +0800 Subject: [PATCH 1/2] fix(mobile): don't switch to editing mode when scrolling --- src/main/frontend/components/block.cljs | 159 ++++++++++++------------ src/main/frontend/handler/common.cljs | 2 +- src/main/mobile/components/app.cljs | 8 +- yarn.lock | 15 +-- 4 files changed, 92 insertions(+), 92 deletions(-) diff --git a/src/main/frontend/components/block.cljs b/src/main/frontend/components/block.cljs index d9c1d54947..622ae3d9db 100644 --- a/src/main/frontend/components/block.cljs +++ b/src/main/frontend/components/block.cljs @@ -2629,93 +2629,94 @@ (defn- block-content-on-pointer-down [e block block-id edit-input-id content config] - (let [target (.-target e) - selection-blocks (state/get-selection-blocks) - starting-block (state/get-selection-start-block-or-first) - mobile? (util/mobile?) - mobile-selection? (and mobile? (seq selection-blocks)) - block-dom-element (util/rec-get-node target "ls-block")] - (if mobile-selection? - (let [ids (set (state/get-selection-block-ids))] - (if (contains? ids (:block/uuid block)) - (do - (state/drop-selection-block! block-dom-element) - (when (= 1 (count ids)) - (state/set-state! :mobile/show-action-bar? false))) - (state/conj-selection-block! block-dom-element))) - (when-not (or - (:closed-values? config) - (> (count content) (state/block-content-max-length (state/get-current-repo)))) - (let [target (gobj/get e "target") - button (gobj/get e "buttons") - shift? (gobj/get e "shiftKey") - meta? (util/meta-key? e) - forbidden-edit? (target-forbidden-edit? target) - get-cursor-range #(some-> block-dom-element - (dom/by-class "block-content-inner") - first - util/caret-range) - mobile-range (when mobile? (get-cursor-range))] - (when-not forbidden-edit? - (util/mobile-keep-keyboard-open false)) - (when (and (not forbidden-edit?) (contains? #{1 0} button)) - (cond - (and meta? shift?) - (when-not (empty? selection-blocks) - (util/stop e) - (editor-handler/highlight-selection-area! block-id block-dom-element {:append? true})) + (when-not @(:ui/scrolling? @state/state) + (let [target (.-target e) + selection-blocks (state/get-selection-blocks) + starting-block (state/get-selection-start-block-or-first) + mobile? (util/mobile?) + mobile-selection? (and mobile? (seq selection-blocks)) + block-dom-element (util/rec-get-node target "ls-block")] + (if mobile-selection? + (let [ids (set (state/get-selection-block-ids))] + (if (contains? ids (:block/uuid block)) + (do + (state/drop-selection-block! block-dom-element) + (when (= 1 (count ids)) + (state/set-state! :mobile/show-action-bar? false))) + (state/conj-selection-block! block-dom-element))) + (when-not (or + (:closed-values? config) + (> (count content) (state/block-content-max-length (state/get-current-repo)))) + (let [target (gobj/get e "target") + button (gobj/get e "buttons") + shift? (gobj/get e "shiftKey") + meta? (util/meta-key? e) + forbidden-edit? (target-forbidden-edit? target) + get-cursor-range #(some-> block-dom-element + (dom/by-class "block-content-inner") + first + util/caret-range) + mobile-range (when mobile? (get-cursor-range))] + (when-not forbidden-edit? + (util/mobile-keep-keyboard-open false)) + (when (and (not forbidden-edit?) (contains? #{1 0} button)) + (cond + (and meta? shift?) + (when-not (empty? selection-blocks) + (util/stop e) + (editor-handler/highlight-selection-area! block-id block-dom-element {:append? true})) - meta? - (do - (util/stop e) - (if (some #(= block-dom-element %) selection-blocks) - (state/drop-selection-block! block-dom-element) - (state/conj-selection-block! block-dom-element :down)) - (if (empty? (state/get-selection-blocks)) - (state/clear-selection!) - (state/set-selection-start-block! block-dom-element))) + meta? + (do + (util/stop e) + (if (some #(= block-dom-element %) selection-blocks) + (state/drop-selection-block! block-dom-element) + (state/conj-selection-block! block-dom-element :down)) + (if (empty? (state/get-selection-blocks)) + (state/clear-selection!) + (state/set-selection-start-block! block-dom-element))) - (and shift? starting-block) - (do - (util/stop e) - (util/clear-selection!) - (editor-handler/highlight-selection-area! block-id block-dom-element)) + (and shift? starting-block) + (do + (util/stop e) + (util/clear-selection!) + (editor-handler/highlight-selection-area! block-id block-dom-element)) - shift? - (do - (util/clear-selection!) - (state/set-selection-start-block! block-dom-element)) + shift? + (do + (util/clear-selection!) + (state/set-selection-start-block! block-dom-element)) - :else - (let [block (or (db/entity [:block/uuid (:block/uuid block)]) block)] - (editor-handler/clear-selection!) - (editor-handler/unhighlight-blocks!) - (p/do! - (state/pub-event! [:editor/save-code-editor]) + :else + (let [block (or (db/entity [:block/uuid (:block/uuid block)]) block)] + (editor-handler/clear-selection!) + (editor-handler/unhighlight-blocks!) + (p/do! + (state/pub-event! [:editor/save-code-editor]) - (when-not (:block.temp/load-status (db/entity (:db/id block))) - (db-async/> title - (property-file/remove-built-in-properties-when-file-based - (state/get-current-repo) format) - (drawer/remove-logbook)))] + (let [cursor-range (if mobile? mobile-range (get-cursor-range)) + block (db/entity (:db/id block)) + {:block/keys [title format]} block + content (if (config/db-based-graph? (state/get-current-repo)) + (:block/title block) + (->> title + (property-file/remove-built-in-properties-when-file-based + (state/get-current-repo) format) + (drawer/remove-logbook)))] - (state/set-editing! - edit-input-id - content - block - cursor-range - {:db (db/get-db) - :move-cursor? false - :container-id (:container-id config)})) + (state/set-editing! + edit-input-id + content + block + cursor-range + {:db (db/get-db) + :move-cursor? false + :container-id (:container-id config)})) - (state/set-selection-start-block! block-dom-element)))))))))) + (state/set-selection-start-block! block-dom-element))))))))))) (rum/defc dnd-separator-wrapper < rum/reactive [block block-id top?] diff --git a/src/main/frontend/handler/common.cljs b/src/main/frontend/handler/common.cljs index a923c2da5e..fdad50ed62 100644 --- a/src/main/frontend/handler/common.cljs +++ b/src/main/frontend/handler/common.cljs @@ -53,6 +53,6 @@ (-> (util/app-scroll-container-node) (gobj/get "scrollTop"))) (reset! *scroll-timer (js/setTimeout - (fn [] (state/set-state! :ui/scrolling? false)) 500))) + (fn [] (state/set-state! :ui/scrolling? false)) 150))) debounced-on-scroll (debounce on-scroll 100)] (.addEventListener element "scroll" debounced-on-scroll false))) diff --git a/src/main/mobile/components/app.cljs b/src/main/mobile/components/app.cljs index 89c0054489..bdc804ccc8 100644 --- a/src/main/mobile/components/app.cljs +++ b/src/main/mobile/components/app.cljs @@ -2,10 +2,12 @@ "App root" (:require ["../externals.js"] [frontend.components.journal :as journal] + [frontend.handler.common :as common-handler] [frontend.handler.user :as user-handler] [frontend.rum :as frum] [frontend.state :as state] [frontend.ui :as ui] + [frontend.util :as util] [logseq.shui.dialog.core :as shui-dialog] [logseq.shui.hooks :as hooks] [logseq.shui.popup.core :as shui-popup] @@ -137,7 +139,11 @@ *home (rum/use-ref nil)] (use-screen-size-effects!) (use-theme-effects! current-repo) - (hooks/use-effect! (fn [] (setup-sidebar-touch-swipe!)) []) + (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 {:as-child true} (silkhq/depth-sheet-scenery-outlets diff --git a/yarn.lock b/yarn.lock index b84227f60a..6dfde52410 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1442,13 +1442,6 @@ dependencies: undici-types "~7.10.0" -"@types/node@^20.9.0": - version "20.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.9.tgz#ca9a58193fec361cc6e859d88b52261853f1f0d3" - integrity sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw== - dependencies: - undici-types "~6.21.0" - "@types/normalize-package-data@^2.4.0": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" @@ -10477,10 +10470,10 @@ undertaker@^1.2.1: object.reduce "^1.0.0" undertaker-registry "^1.0.0" -undici-types@~7.8.0: - version "7.8.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.8.0.tgz#de00b85b710c54122e44fbfd911f8d70174cd294" - integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw== +undici-types@~7.10.0: + version "7.10.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.10.0.tgz#4ac2e058ce56b462b056e629cc6a02393d3ff350" + integrity sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag== unified@^9.1.0: version "9.2.2" From af99188c1e1fa0162d6bf35f50d159f3ddbc0a95 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Thu, 14 Aug 2025 14:00:52 +0800 Subject: [PATCH 2/2] remove recent pages from search since they're listed on sidebar --- src/main/mobile/components/app.css | 6 +- src/main/mobile/components/search.cljs | 134 ++++++++++--------------- 2 files changed, 58 insertions(+), 82 deletions(-) diff --git a/src/main/mobile/components/app.css b/src/main/mobile/components/app.css index 21a7faffa4..25047b7801 100644 --- a/src/main/mobile/components/app.css +++ b/src/main/mobile/components/app.css @@ -425,7 +425,7 @@ html[data-silk-native-page-scroll-replaced=false] .app-silk-index-scroll-view { transition: padding 0.1s ease-in-out; .ls-icon-search { - @apply absolute left-2.5 top-[9px] opacity-60; + @apply absolute left-2.5 top-[8px] opacity-60; } .cancel { @@ -468,7 +468,7 @@ html[data-silk-native-page-scroll-replaced=false] .app-silk-index-scroll-view { } > .bd { - @apply -mx-4 pt-8; + @apply -mx-4 pt-5; ul { &.as-results > li { @@ -508,4 +508,4 @@ html[data-silk-native-page-scroll-replaced=false] .app-silk-index-scroll-view { display: flex !important; } } -} \ No newline at end of file +} diff --git a/src/main/mobile/components/search.cljs b/src/main/mobile/components/search.cljs index b6c378aaeb..af4ea5ec5a 100644 --- a/src/main/mobile/components/search.cljs +++ b/src/main/mobile/components/search.cljs @@ -2,14 +2,11 @@ "Mobile search" (:require [clojure.string :as string] [frontend.components.cmdk.core :as cmdk] - [frontend.db :as db] - [frontend.handler.block :as block-handler] [frontend.handler.search :as search-handler] [frontend.search :as search] [frontend.state :as state] [frontend.ui :as ui] [frontend.util :as util] - [logseq.db :as ldb] [logseq.shui.hooks :as hooks] [logseq.shui.ui :as shui] [mobile.state :as mobile-state] @@ -20,7 +17,7 @@ [input] (p/let [repo (state/get-current-repo) blocks (search/block-search repo input - {:limit 100 :built-in? true}) + {:limit 100 :built-in? true}) blocks (remove nil? blocks) blocks (search/fuzzy-search blocks input {:limit 100 :extract-fn :block/title}) @@ -30,19 +27,6 @@ (cmdk/block-item repo block nil input))) blocks)] items)) -(defn- get-recent-pages - [] - (let [recent-pages (->> (ldb/get-recent-updated-pages (db/get-db)) - (remove ldb/built-in?))] - (map (fn [block] - (let [text (block-handler/block-unique-title block) - icon (cmdk/get-page-icon block)] - {:icon icon - :icon-theme :gray - :text text - :source-block block})) - recent-pages))) - (rum/defc search [] (let [*ref (hooks/use-ref nil) @@ -51,58 +35,56 @@ [search-result set-search-result!] (hooks/use-state nil) [last-input-at set-last-input-at!] (hooks/use-state nil) [recents set-recents!] (hooks/use-state (search-handler/get-recents)) - result (if (string/blank? input) - (get-recent-pages) - search-result) + result search-result clear! (fn [] (set-input! "") (set-search-result! nil))] (hooks/use-effect! - (fn [] - (let [*timeout (atom nil)] - (when-not (string/blank? input) - (p/let [result (search-blocks input)] - (set-search-result! result) - (when (seq result) - (reset! *timeout - (js/setTimeout - (fn [] - (let [now (util/time-ms)] - (when (and last-input-at (>= (- now last-input-at) 2000)) - (search-handler/add-recent! input) - (set-recents! (search-handler/get-recents))))) - 2000))))) - #(when-let [timeout @*timeout] - (js/clearTimeout timeout)))) - [(hooks/use-debounced-value input 150)]) + (fn [] + (let [*timeout (atom nil)] + (when-not (string/blank? input) + (p/let [result (search-blocks input)] + (set-search-result! result) + (when (seq result) + (reset! *timeout + (js/setTimeout + (fn [] + (let [now (util/time-ms)] + (when (and last-input-at (>= (- now last-input-at) 2000)) + (search-handler/add-recent! input) + (set-recents! (search-handler/get-recents))))) + 2000))))) + #(when-let [timeout @*timeout] + (js/clearTimeout timeout)))) + [(hooks/use-debounced-value input 150)]) [:div.app-silk-search-page [:div.hd {:class (when (or focused? - (not (string/blank? input))) + (not (string/blank? input))) "input-focused")} [:div.relative (shui/tabler-icon "search") (shui/input - {:ref *ref - :placeholder "Search" - :value input - :on-focus #(set-focused? true) - :on-blur #(set-focused? false) - :on-change (fn [^js e] - (let [input (.-value (.-target e))] - (set-input! input) - (set-last-input-at! (util/time-ms))))})] + {:ref *ref + :placeholder "Search" + :value input + :on-focus #(set-focused? true) + :on-blur #(set-focused? false) + :on-change (fn [^js e] + (let [input (.-value (.-target e))] + (set-input! input) + (set-last-input-at! (util/time-ms))))})] (shui/button - {:class "cancel" - :variant :text - :on-pointer-down - (fn [e] - (util/stop e) - (some-> (rum/deref *ref) (.blur)) - (util/schedule #(clear!)))} - "cancel") + {:class "cancel" + :variant :text + :on-pointer-down + (fn [e] + (util/stop e) + (some-> (rum/deref *ref) (.blur)) + (util/schedule #(clear!)))} + "Cancel") (when-not (string/blank? input) [:a.x {:on-click (fn [] (clear!) @@ -112,35 +94,29 @@ [:div.bd (when (string/blank? input) [:<> - (when (seq recents) - [:div.mb-4 - [:div.px-4.text-sm.text-muted-foreground.border-b - [:div.flex.flex-item.items-center.justify-between.py-1 - "Recent search" + [:div.mb-4 + [:div.px-4.text-sm.text-muted-foreground.border-b + [:div.flex.flex-item.items-center.justify-between.py-1 + "Recent search" + (when (seq recents) (shui/button - {:variant :text - :size :sm - :class "text-muted-foreground flex justify-end pr-1" - :on-click (fn [] - (search-handler/clear-recents!) - (set-recents! nil))} - "Clear all")]] + {:variant :text + :size :sm + :class "text-muted-foreground flex justify-end pr-1" + :on-click (fn [] + (search-handler/clear-recents!) + (set-recents! nil))} + "Clear all"))]] - [:ul.px-3 - (for [item recents] - [:li.flex.gap-1 - {:on-click #(set-input! item)} - [:div.flex.flex-row.items-center.gap-1 - (ui/icon "search" {:size 15 - :class "text-muted-foreground"}) - item]])]]) - - [:div.px-4.py-2.text-sm.text-muted-foreground.border-b - "Recent updates"]]) + [:ul.px-3 + (for [item recents] + [:li.flex.gap-1 + {:on-click #(set-input! item)} + item])]]]) [:ul.px-3 {:class (when (and (not (string/blank? input)) - (seq search-result)) + (seq search-result)) "as-results")} (for [{:keys [icon text header source-page source-block]} result] (let [block (or source-page source-block)]