소스 검색

feat: search inside the current page

Tienson Qin 4 년 전
부모
커밋
6e62f90a09

+ 6 - 0
resources/css/common.css

@@ -810,3 +810,9 @@ a.tooltip-priority {
 .katex * {
   border-color: var(--ls-primary-text-color);
 }
+
+a.page-op {
+    svg {
+        transform: scale(0.9);
+    }
+}

+ 1 - 0
src/main/frontend/components/onboarding.cljs

@@ -259,6 +259,7 @@
          [:tr [:td (t :help/toggle)] [:td "?"]]
          [:tr [:td (t :help/git-commit-message)] [:td "c"]]
          [:tr [:td (t :help/full-text-search)] [:td (util/->platform-shortcut "Ctrl-u")]]
+         [:tr [:td (t :help/full-text-search)] [:td (util/->platform-shortcut "Ctrl-Shift-u")]]
          [:tr [:td (t :help/open-link-in-sidebar)] [:td "Shift-Click"]]
          [:tr [:td (t :help/context-menu)] [:td "Right Click"]]
          [:tr [:td (t :help/fold-unfold)] [:td "Tab"]]

+ 22 - 18
src/main/frontend/components/page.cljs

@@ -108,8 +108,9 @@
 
 (defn presentation
   [repo page]
-  [:a.opacity-50.hover:opacity-100
+  [:a.opacity-30.hover:opacity-100.page-op
    {:title "Presentation mode (Powered by Reveal.js)"
+    :style {:margin-top -2}
     :on-click (fn []
                 (state/sidebar-add-block!
                  repo
@@ -347,20 +348,26 @@
                                                         false)))}})]
                            (flatten)
                            (remove nil?))]
-                (when (seq links)
-                  (ui/dropdown-with-links
-                   (fn [{:keys [toggle-fn]}]
-                     [:a.opacity-70.hover:opacity-100
-                      {:style {:position "absolute"
+                [:div {:style {:position "absolute"
                                :right 0
-                               :top 20}
-                       :title "More options"
-                       :on-click toggle-fn}
-                      (svg/vertical-dots {:class (util/hiccup->class "opacity-50.hover:opacity-100.h-5.w-5")})])
-                   links
-                   {:modal-class (util/hiccup->class
-                                  "origin-top-right.absolute.right-0.top-10.mt-2.rounded-md.shadow-lg.whitespace-no-wrap.dropdown-overflow-auto.page-drop-options")
-                    :z-index 1}))))
+                               :top 20}}
+                 [:div.flex.flex-row
+                  [:a.opacity-30.hover:opacity-100.page-op.mr-2
+                   {:on-click #(route-handler/go-to-search! :page)}
+                   svg/search]
+                  (when (not config/mobile?)
+                    (presentation repo page))
+                  (when (seq links)
+                    (ui/dropdown-with-links
+                     (fn [{:keys [toggle-fn]}]
+                       [:a.opacity-30.hover:opacity-100
+                        {:title "More options"
+                         :on-click toggle-fn}
+                        (svg/vertical-dots {:class (util/hiccup->class "opacity-30.hover:opacity-100.h-5.w-5")})])
+                     links
+                     {:modal-class (util/hiccup->class
+                                    "origin-top-right.absolute.right-0.top-10.mt-2.rounded-md.shadow-lg.whitespace-no-wrap.dropdown-overflow-auto.page-drop-options")
+                      :z-index 1}))]]))
             (when (and (not sidebar?)
                        (not block?))
               [:a {:on-click (fn [e]
@@ -395,10 +402,7 @@
                  [:a.bg-base-2.px-1.ml-1.mr-3 {:style {:border-radius 4
                                                        :word-break    "break-word"}
                                                :href  (rfe/href :file {:path file-path})}
-                  file-path]
-
-                 (when (not config/mobile?)
-                   (presentation repo page))])]
+                  file-path]])]
 
              (when (and repo (not block?))
                (let [alias (db/get-page-alias-names repo page-name)]

+ 42 - 34
src/main/frontend/components/search.cljs

@@ -2,6 +2,7 @@
   (:require [rum.core :as rum]
             [frontend.util :as util]
             [frontend.components.block :as block]
+            [frontend.components.svg :as svg]
             [frontend.handler.route :as route]
             [frontend.handler.page :as page-handler]
             [frontend.handler.file :as file-handler]
@@ -15,7 +16,8 @@
             [clojure.string :as string]
             [goog.dom :as gdom]
             [medley.core :as medley]
-            [frontend.context.i18n :as i18n]))
+            [frontend.context.i18n :as i18n]
+            [frontend.date :as date]))
 
 (defn- partition-between
   "Split `coll` at positions where `pred?` is true."
@@ -69,8 +71,10 @@
    content])
 
 (rum/defc block-search-result-item
-  [repo uuid format content q]
-  [:div [[:div {:class "mb-1"} (block/block-parents {:id "block-search-block-parent" :block? true} repo (clojure.core/uuid uuid) format)]
+  [repo uuid format content q search-mode]
+  [:div [
+         (when (not= search-mode :page)
+           [:div {:class "mb-1"} (block/block-parents {:id "block-search-block-parent" :block? true} repo (clojure.core/uuid uuid) format)])
          [:div {:class "font-medium"} (highlight-exact-query content q)]]])
 
 (rum/defc highlight-fuzzy
@@ -142,11 +146,13 @@
           pages (map (fn [page] {:type :page :data page}) pages)
           files (map (fn [file] {:type :file :data file}) files)
           blocks (map (fn [block] {:type :block :data block}) blocks)
+          search-mode (state/get-search-mode)
           new-page (if (or
                         (and (seq pages)
                              (= (string/lower-case search-q)
                                 (string/lower-case (:data (first pages)))))
-                        (nil? result))
+                        (nil? result)
+                        (not= :global search-mode))
                      []
                      [{:type :new-page}])
           result (if config/publishing?
@@ -206,31 +212,31 @@
 
                               nil))
          :item-render (fn [{:keys [type data]}]
+                        (let [search-mode (state/get-search-mode)]
+                          [:div {:class "py-2"} (case type
+                                                 :new-page
+                                                 [:div.text.font-bold (str (t :new-page) ": ")
+                                                  [:span.ml-1 (str "\"" search-q "\"")]]
 
-                        [:div {:class "py-2"} (case type
-                                                :new-page
-                                                [:div.text.font-bold (str (t :new-page) ": ")
-                                                 [:span.ml-1 (str "\"" search-q "\"")]]
+                                                 :new-file
+                                                 [:div.text.font-bold (str (t :new-file) ": ")
+                                                  [:span.ml-1 (str "\"" search-q "\"")]]
 
-                                                :new-file
-                                                [:div.text.font-bold (str (t :new-file) ": ")
-                                                 [:span.ml-1 (str "\"" search-q "\"")]]
+                                                 :page
+                                                 (search-result-item "Page" (highlight-exact-query data search-q))
 
-                                                :page
-                                                (search-result-item "Page" (highlight-exact-query data search-q))
+                                                 :file
+                                                 (search-result-item "File" (highlight-exact-query data search-q))
 
-                                                :file
-                                                (search-result-item "File" (highlight-exact-query data search-q))
+                                                 :block
+                                                 (let [{:block/keys [page content uuid]} data
+                                                       page (or (:page/original-name page)
+                                                                (:page/name page))
+                                                       repo (state/sub :git/current-repo)
+                                                       format (db/get-page-format page)]
+                                                   (search-result-item "Block" (block-search-result-item repo uuid format content search-q search-mode)))
 
-                                                :block
-                                                (let [{:block/keys [page content uuid]} data
-                                                      page (or (:page/original-name page)
-                                                               (:page/name page))
-                                                      repo (state/sub :git/current-repo)
-                                                      format (db/get-page-format page)]
-                                                  (search-result-item "Block" (block-search-result-item repo uuid format content search-q)))
-
-                                                nil)])})])))
+                                                 nil)]))})])))
 
 (rum/defcs search < rum/reactive
   (rum/local false ::inside-box?)
@@ -246,6 +252,7 @@
         search-q (state/sub :search/q)
         show-result? (boolean (seq search-result))
         blocks-count (or (db/blocks-count) 0)
+        search-mode (state/sub :search/mode)
         timeout (cond
                   (util/electron?)
                   180
@@ -261,16 +268,12 @@
         [:label.sr-only {:for "search-field"} (t :search)]
         [:div#search-wrapper.relative.w-full.text-gray-400.focus-within:text-gray-600
          [:div.absolute.inset-y-0.flex.items-center.pointer-events-none {:style {:left 6}}
-          [:svg.h-5.w-5
-           {:view-box "0 0 20 20", :fill "currentColor"}
-           [:path
-            {:d
-             "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
-             :clip-rule "evenodd"
-             :fill-rule "evenodd"}]]]
+          svg/search]
          [:input#search-field.block.w-full.h-full.pr-3.py-2.rounded-md.focus:outline-none.placeholder-gray-500.focus:placeholder-gray-400.sm:text-sm.sm:bg-transparent
           {:style {:padding-left "2rem"}
-           :placeholder (t :search)
+           :placeholder (if (= search-mode :page)
+                          (t :page-search)
+                          (t :search))
            :auto-complete (if (util/chrome?) "chrome-off" "off") ; off not working here
            :default-value ""
            :on-change (fn [e]
@@ -279,11 +282,16 @@
                         (let [value (util/evalue e)]
                           (if (string/blank? value)
                             (search-handler/clear-search!)
-                            (do
+                            (let [search-mode (state/get-search-mode)
+                                  opts (if (= :page search-mode)
+                                         (let [current-page (or (state/get-current-page)
+                                                                (date/today))]
+                                           {:page-db-id (:db/id (db/entity [:page/name (string/lower-case current-page)]))})
+                                         {})]
                               (state/set-q! value)
                               (reset! search-timeout
                                       (js/setTimeout
-                                       #(search-handler/search (state/get-current-repo) value)
+                                       #(search-handler/search (state/get-current-repo) value opts)
                                        timeout))))))}]
          (when-not (string/blank? search-q)
            (ui/css-transition

+ 12 - 3
src/main/frontend/components/svg.cljs

@@ -300,9 +300,9 @@
    [:path
     {:d
      "M322.397,252.352l75.068-75.067c19.346,5.06,40.078,3.441,58.536-4.873L339.589,56c-8.313,18.458-9.933,39.189-4.873,58.536
-	l-75.066,75.067c-35.168-16.745-76.173-17.14-111.618-1.176l65.009,65.01L55.999,456l202.563-157.041l65.01,65.01
-	C339.535,328.526,339.142,287.519,322.397,252.352z M201.513,216.553c0,0-16.568-16.568-21.323-21.035
-	c37.027-10.806,61.375,4.323,61.375,4.323C218.946,192.781,201.513,216.553,201.513,216.553z"}]])
+        l-75.066,75.067c-35.168-16.745-76.173-17.14-111.618-1.176l65.009,65.01L55.999,456l202.563-157.041l65.01,65.01
+        C339.535,328.526,339.142,287.519,322.397,252.352z M201.513,216.553c0,0-16.568-16.568-21.323-21.035
+        c37.027-10.806,61.375,4.323,61.375,4.323C218.946,192.781,201.513,216.553,201.513,216.553z"}]])
 
 
 (rum/defc caret-down
@@ -520,3 +520,12 @@
 
 (def collapse-right
   (hero-icon "M4 6h16M4 12h16m-7 6h7"))
+
+(def search
+  [:svg.h-5.w-5
+   {:view-box "0 0 20 20", :fill "currentColor"}
+   [:path
+    {:d
+     "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
+     :clip-rule "evenodd"
+     :fill-rule "evenodd"}]])

+ 4 - 0
src/main/frontend/dicts.cljs

@@ -156,6 +156,7 @@ title: How to take dummy notes?
         :help/toggle "Toggle help"
         :help/git-commit-message "Git commit message"
         :help/full-text-search "Full Text Search"
+        :help/page-search "Search in the current page"
         :help/context-menu "Context Menu"
         :help/fold-unfold "Fold/Unfold blocks (when not in edit mode)"
         :help/toggle-doc-mode "Toggle document mode"
@@ -316,6 +317,7 @@ title: How to take dummy notes?
         :search (if config/publishing?
                   "Search"
                   "Search or Create Page")
+        :page-search "Search in the current page"
         :new-page "New page"
         :new-file "New file"
         :graph "Graph"
@@ -884,6 +886,7 @@ title: How to take dummy notes?
            :help/toggle "显示/关闭帮助"
            :help/git-commit-message "提交消息"
            :help/full-text-search "全文搜索"
+           :help/page-search "在当前页面搜索"
            :help/context-menu "右键菜单"
            :help/fold-unfold "折叠/展开方块(不在编辑模式中)"
            :help/toggle-doc-mode "切换文档模式"
@@ -1041,6 +1044,7 @@ title: How to take dummy notes?
            :search (if config/publishing?
                      "搜索"
                      "搜索或者创建新页面")
+           :page-search "在当前页面搜索"
            :new-page "新页面"
            :new-file "新文件"
            :graph "图谱"

+ 3 - 1
src/main/frontend/handler/route.cljs

@@ -92,7 +92,9 @@
       (util/scroll-to-top))))
 
 (defn go-to-search!
-  []
+  [search-mode]
+  (when search-mode
+    (state/set-search-mode! search-mode))
   (when-let [element (gdom/getElement "search-field")]
     (.focus element)))
 

+ 23 - 8
src/main/frontend/handler/search.cljs

@@ -1,25 +1,40 @@
 (ns frontend.handler.search
   (:require [goog.object :as gobj]
             [frontend.state :as state]
+            [frontend.db :as db]
             [goog.dom :as gdom]
             [frontend.search :as search]
             [frontend.search.db :as search-db]
             [frontend.handler.notification :as notification-handler]
-            [promesa.core :as p]))
+            [promesa.core :as p]
+            [clojure.string :as string]))
 
 (defn search
-  [repo q]
-  (p/let [blocks (search/block-search repo q nil)]
-    (swap! state/state assoc :search/result
-          {:pages (search/page-search q)
-           :files (search/file-search q)
-           :blocks blocks})))
+  ([repo q]
+   (search repo q nil))
+  ([repo q {:keys [page-db-id]
+            :or {page-db-id nil}
+            :as opts}]
+   (let [page-db-id (if (string? page-db-id)
+                      (:db/id (db/entity repo [:page/name (string/lower-case page-db-id)]))
+                      page-db-id)]
+     (p/let [blocks (search/block-search repo q opts)]
+      (let [blocks (if page-db-id
+                     (filter (fn [block] (= (get-in block [:block/page :db/id]) page-db-id)) blocks)
+                     blocks)
+            result (merge
+                    {:blocks blocks}
+                    (when-not page-db-id
+                      {:pages (search/page-search q)
+                       :files (search/file-search q)}))]
+        (swap! state/state assoc :search/result result))))))
 
 (defn clear-search!
   []
   (swap! state/state assoc
          :search/result nil
-         :search/q "")
+         :search/q ""
+         :search/mode :global)
   (when-let [input (gdom/getElement "search-field")]
     (gobj/set input "value" "")))
 

+ 2 - 1
src/main/frontend/keyboards.cljs

@@ -74,7 +74,8 @@
        (or (shortcut :editor/undo) "mod+z") [history-handler/undo! true]
        (or (shortcut :editor/redo) "mod+y") [history-handler/redo! true]
        (or (shortcut :editor/redo) "mod+shift+z") [history-handler/redo! true]
-       (or (shortcut :go/search) "mod+u") [route-handler/go-to-search! true]
+       (or (shortcut :go/search) "mod+u") [#(route-handler/go-to-search! :global) true]
+       (or (shortcut :go/page-search) "mod+shift+u") [#(route-handler/go-to-search! :page) true]
        (or (shortcut :go/journals) (if util/mac? "mod+j" "alt+j")) [route-handler/go-to-journals! true]
        (or (shortcut :editor/zoom-in) (if util/mac? "mod+." "alt+right")) [editor-handler/zoom-in! true]
        (or (shortcut :editor/zoom-out) (if util/mac? "mod+," "alt+left")) [editor-handler/zoom-out! true]

+ 9 - 0
src/main/frontend/state.cljs

@@ -41,6 +41,7 @@
     :journals-length 2
 
     :search/q ""
+    :search/mode :global
     :search/result nil
 
     ;; custom shortcuts
@@ -444,6 +445,10 @@
   [value]
   (set-state! :search/q value))
 
+(defn set-search-mode!
+  [value]
+  (set-state! :search/mode value))
+
 (defn set-editor-show-page-search!
   [value]
   (set-state! :editor/show-page-search? value)
@@ -1116,6 +1121,10 @@
   []
   (set-search-result! nil))
 
+(defn get-search-mode
+  []
+  (:search/mode @state))
+
 (defn toggle!
   [path]
   (update-state! path not))