Browse Source

enhance: add recent search

Tienson Qin 4 years ago
parent
commit
279a6007fe

+ 3 - 3
cypress/integration/app/basic.cljs

@@ -15,7 +15,7 @@
 
   (it "Search" []
     (.. cy
-        (get "#search-field")
+        (get "#search-button")
         (click)
         (type "welcome to Logseq"))
     (.. cy (get "#ui__ac-inner")
@@ -25,14 +25,14 @@
 
     ;; create new page
     (.. cy
-        (get "#search-field")
+        (get "#search-button")
         (click)
         (type "new page"))
 
     (.wait cy 1000)
 
     (.. cy
-        (get "#search-field")
+        (get "#search-button")
         (type "{enter}"))
 
     ;; edit bullet

+ 1 - 1
cypress/integration/app/template.cljs

@@ -15,7 +15,7 @@
                   (.visit cy "http://localhost:3001"))
           (it "template-basic" []
               (.. cy
-                  (get "#search-field")
+                  (get "#search-button")
                   (click)
                   (type "template test page")
                   (wait 1000)

+ 0 - 1
src/main/frontend/components/command_palette.css

@@ -42,7 +42,6 @@
     padding: 16px;
     font-size: 20px;
     outline: none;
-    margin-bottom: 5px;
   }
 
   &-results {

+ 14 - 4
src/main/frontend/components/header.cljs

@@ -41,7 +41,8 @@
 
       (ui/dropdown-with-links
        (fn [{:keys [toggle-fn]}]
-         [:a.fade-link.block.p-2 {:on-click toggle-fn}
+         [:a.button.text-sm.font-medium.block {:on-click toggle-fn
+                                               :style {:margin-right 12}}
           [:span (t :login)]])
        (let [list [;; {:title (t :login-google)
                    ;;  :url (str config/website "/login/google")}
@@ -180,9 +181,18 @@
 
        (when electron-not-mac? (back-and-forward))
 
-       (if current-repo
-         (search/search)
-         [:div.flex-1])
+       [:div.flex-1.flex]
+
+       (when current-repo
+         (ui/tippy
+          {:html [:div.text-sm.font-medium
+                  "Shortcut: "
+                  [:code (util/->platform-shortcut "Ctrl + k")]]
+           :interactive     true
+           :arrow true}
+          [:a.button#search-button
+           {:on-click #(state/pub-event! [:go/search])}
+           svg/search]))
 
        (when plugin-handler/lsp-enabled?
          (plugins/hook-ui-items :toolbar))

+ 0 - 30
src/main/frontend/components/right_sidebar.cljs

@@ -39,27 +39,6 @@
               :sidebar?   true
               :repo       repo}))
 
-(defn recent-pages
-  []
-  (let [pages (->> (db/get-key-value :recent/pages)
-                   (remove nil?)
-                   (remove #(= (string/lower-case %) "contents")))]
-    [:div.recent-pages.text-sm.flex-col.flex.ml-3.mt-2
-     (when (seq pages)
-       (for [page pages]
-         [:a.page-ref.mb-1 {:key      (str "recent-page-" page)
-                   :href     (rfe/href :page {:name page})
-                   :on-click (fn [e]
-                               (when (gobj/get e "shiftKey")
-                                 (when-let [page (db/pull [:block/name (string/lower-case page)])]
-                                   (state/sidebar-add-block!
-                                    (state/get-current-repo)
-                                    (:db/id page)
-                                    :page
-                                    {:page page}))
-                                 (.preventDefault e)))}
-          page]))]))
-
 (rum/defc contents < rum/reactive db-mixins/query
   []
   [:div.contents.flex-col.flex.ml-3
@@ -74,9 +53,6 @@
          (t :right-side-bar/favorites))
      (contents)]
 
-    :recent
-    [(t :right-side-bar/recent) (recent-pages)]
-
     :help
     [(t :right-side-bar/help) (onboarding/help)]
 
@@ -250,12 +226,6 @@
               (or (state/get-favorites-name)
                   (t :right-side-bar/favorites))]]
 
-            [:div.ml-4.text-sm
-             [:a.cp__right-sidebar-settings-btn {:on-click (fn [_e]
-                                                             (state/sidebar-add-block! repo "recent" :recent nil))}
-
-              (t :right-side-bar/recent)]]
-
             [:div.ml-4.text-sm
              [:a.cp__right-sidebar-settings-btn {:on-click (fn []
                                                              (when-let [page (get-current-page)]

+ 105 - 57
src/main/frontend/components/search.cljs

@@ -131,11 +131,6 @@
      (when-not (string/blank? after)
        [:span after])]))
 
-(defn- leave-focus
-  []
-  (when-let [input (gdom/getElement "search-field")]
-    (.blur input)))
-
 (defonce search-timeout (atom nil))
 
 (rum/defc search-auto-complete
@@ -165,14 +160,15 @@
                    (concat new-page pages files blocks))
           result (if (= search-mode :graph)
                    [{:type :graph-add-filter}]
-                   result)]
+                   result)
+          repo (state/get-current-repo)]
       [:div
        (ui/auto-complete
         result
         {:class "search-results"
          :on-chosen (fn [{:keys [type data alias]}]
+                      (search-handler/add-search-to-recent! repo search-q)
                       (search-handler/clear-search!)
-                      (leave-focus)
                       (case type
                         :graph-add-filter
                         (state/add-graph-search-filter! search-q)
@@ -201,6 +197,7 @@
                                                 :query-params {:anchor (str "ls-block-" (:block/uuid data))}}))))
                         nil))
          :on-shift-chosen (fn [{:keys [type data alias]}]
+                            (search-handler/add-search-to-recent! repo search-q)
                             (case type
                               :page
                               (let [data (or alias data)
@@ -266,6 +263,71 @@
                                                  (search-handler/clear-search!)))}
            (t :more)]])])))
 
+(rum/defc recent-search-and-pages
+  [in-page-search?]
+  [:div.recent-search
+   [:div.px-4.py-2.text-sm.opacity-70.flex.flex-row.justify-between.align-items
+    [:div "Recent search:"]
+    (ui/tippy {:html [:div.text-sm.font-medium
+                      "Shortcut: "
+                      [:code (util/->platform-shortcut "Ctrl + Shift + k")]]
+               :interactive     true
+               :arrow true}
+              [:div.flex-row.flex.align-items
+               [:div.mr-2 "Search in page:"]
+               [:div {:style {:margin-top 3}}
+                (ui/toggle in-page-search?
+                           (fn [_value]
+                             (state/set-search-mode! (if in-page-search? :global :page)))
+                           true)]])]
+   (let [recent-search (mapv (fn [q] {:type :search :data q}) (db/get-key-value :recent/search))
+         pages (->> (db/get-key-value :recent/pages)
+                    (remove nil?)
+                    (remove #(= (string/lower-case %) "contents"))
+                    (mapv (fn [page] {:type :page :data page})))
+         result (concat (take 5 recent-search) pages)]
+     (ui/auto-complete
+      result
+      {:on-chosen (fn [{:keys [type data]}]
+                    (case type
+                      :page
+                      (route/redirect! {:to :page
+                                        :path-params {:name data}})
+                      :search
+                      (let [q data]
+                        (fn []
+                          (state/set-q! q)
+                          (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 [:block/name (string/lower-case current-page)]))})
+                                       {})]
+                            (if (= :page search-mode)
+                              (search-handler/search (state/get-current-repo) q opts)
+                              (search-handler/search (state/get-current-repo) q)))))
+
+                      nil))
+       :on-shift-chosen (fn [{:keys [type data]}]
+                          (case type
+                            :page
+                            (let [page data]
+                              (when-let [page (db/pull [:block/name (string/lower-case page)])]
+                               (state/sidebar-add-block!
+                                (state/get-current-repo)
+                                (:db/id page)
+                                :page
+                                {:page page})))
+
+                            nil))
+       :item-render (fn [{:keys [type data]}]
+                      (case type
+                        :search [:div.flex-row.flex.search-item.font-medium
+                                 svg/search
+                                 [:span.ml-2 data]]
+                        :page (search-result-item "Page" data)
+                        nil))}))])
+
 (rum/defcs search-modal < rum/reactive
   (shortcut/disable-all-shortcuts)
   (mixins/event-mixin
@@ -273,8 +335,7 @@
      (mixins/hide-when-esc-or-outside
       state
       :on-hide (fn []
-                 (search-handler/clear-search!)
-                 (leave-focus)))))
+                 (search-handler/clear-search!)))))
   [state]
   (let [search-result (state/sub :search/result)
         search-q (state/sub :search/q)
@@ -288,61 +349,48 @@
                   500
 
                   :else
-                  300)]
+                  300)
+        in-page-search? (= search-mode :page)]
     (rum/with-context [[t] i18n/*tongue-context*]
-     (let [input (::input state)]
-       [:div.cp__palette.cp__palette-main
+      (let [input (::input state)]
+        [:div.cp__palette.cp__palette-main
 
-        [:div.input-wrap
-         [:input.cp__palette-input.w-full
-          {:type          "text"
-           :auto-focus    true
-           :placeholder   (case search-mode
-                            :graph
-                            (t :graph-search)
-                            :page
-                            (t :page-search)
-                            (t :search))
-           :auto-complete (if (util/chrome?) "chrome-off" "off") ; off not working here
-           :default-value ""
-           :on-change     (fn [e]
-                            (when @search-timeout
-                              (js/clearTimeout @search-timeout))
-                            (let [value (util/evalue e)]
-                              (if (string/blank? value)
-                                (search-handler/clear-search! false)
-                                (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 [:block/name (string/lower-case current-page)]))})
-                                             {})]
-                                  (state/set-q! value)
-                                  (reset! search-timeout
-                                          (js/setTimeout
+         [:div.input-wrap
+          [:input.cp__palette-input.w-full
+           {:type          "text"
+            :auto-focus    true
+            :placeholder   (case search-mode
+                             :graph
+                             (t :graph-search)
+                             :page
+                             (t :page-search)
+                             (t :search))
+            :auto-complete (if (util/chrome?) "chrome-off" "off") ; off not working here
+            :default-value ""
+            :on-change     (fn [e]
+                             (when @search-timeout
+                               (js/clearTimeout @search-timeout))
+                             (let [value (util/evalue e)]
+                               (if (string/blank? value)
+                                 (search-handler/clear-search! false)
+                                 (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 [:block/name (string/lower-case current-page)]))})
+                                              {})]
+                                   (state/set-q! value)
+                                   (reset! search-timeout
+                                           (js/setTimeout
                                             (fn []
                                               (if (= :page search-mode)
                                                 (search-handler/search (state/get-current-repo) value opts)
                                                 (search-handler/search (state/get-current-repo) value)))
                                             timeout))))))}]]
-
-        [:div.search-results-wrap
-         (search-auto-complete search-result search-q false)]]))))
-
-(rum/defcs search < rum/reactive
-  {:will-unmount (fn [state]
-                   (search-handler/clear-search!)
-                   state)}
-  [state]
-  (rum/with-context [[t] i18n/*tongue-context*]
-    [:div#search.flex-1.flex.p-2
-     [:div.inner
-      [:label.sr-only {:for "search-field"} (t :search)]
-      [:div#search-wrapper.relative.w-full.text-gray-400.focus-within:text-gray-600
-       [:a.block.cursor
-        {:style {:left 6}
-         :on-click #(state/pub-event! [:go/search])}
-        svg/search]]]]))
+         [:div.search-results-wrap
+          (if (seq search-result)
+            (search-auto-complete search-result search-q false)
+            (recent-search-and-pages in-page-search?))]]))))
 
 (rum/defc more < rum/reactive
   [route]

+ 4 - 0
src/main/frontend/components/search.css

@@ -49,3 +49,7 @@
 .dark-theme #search-field:focus {
     box-shadow: 0px 0px 20px 0px rgba(18, 18, 18, .3);
 }
+
+.search-item svg {
+    transform: scale(0.8);
+}

+ 2 - 0
src/main/frontend/components/svg.cljs

@@ -224,9 +224,11 @@
 (defn vertical-dots
   [options]
   (hero-icon "M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" options))
+
 (defn horizontal-dots
   [options]
   (hero-icon "M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z" options))
+
 (def external-link
   [:svg {:fill   "none", :view-box "0 0 24 24", :height "21", :width "21"
          :stroke "currentColor"}

+ 0 - 2
src/main/frontend/handler/editor.cljs

@@ -1712,8 +1712,6 @@
   (or @*show-commands
       @*show-block-commands
       @*asset-uploading?
-      (= (gdom/getElement "search-field")
-         (.-activeElement js/document))
       (state/get-editor-show-input)
       (state/get-editor-show-page-search?)
       (state/get-editor-show-block-search?)

+ 1 - 1
src/main/frontend/handler/page.cljs

@@ -493,7 +493,7 @@
   [repo page]
   (let [pages (or (db/get-key-value repo :recent/pages)
                   '())
-        new-pages (take 12 (distinct (cons page pages)))]
+        new-pages (take 10 (distinct (cons page pages)))]
     (db/set-key-value repo :recent/pages new-pages)))
 
 (defn template-exists?

+ 2 - 0
src/main/frontend/handler/route.cljs

@@ -4,6 +4,7 @@
             [frontend.db :as db]
             [frontend.handler.plugin :as plugin-handler]
             [frontend.handler.ui :as ui-handler]
+            [frontend.handler.search :as search-handler]
             [frontend.state :as state]
             [frontend.text :as text]
             [frontend.util :as util]
@@ -102,6 +103,7 @@
 
 (defn go-to-search!
   [search-mode]
+  (search-handler/clear-search! false)
   (when search-mode
     (state/set-search-mode! search-mode))
   (state/pub-event! [:go/search]))

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

@@ -8,6 +8,14 @@
             [goog.object :as gobj]
             [promesa.core :as p]))
 
+(defn add-search-to-recent!
+  [repo q]
+  (when-not (string/blank? q)
+    (let [items (or (db/get-key-value repo :recent/search)
+                    '())
+          new-items (take 10 (distinct (cons q items)))]
+      (db/set-key-value repo :recent/search new-items))))
+
 (defn search
   ([repo q]
    (search repo q {:limit 20}))
@@ -15,19 +23,20 @@
             :or {page-db-id nil
                  limit 20}
             :as opts}]
-   (let [page-db-id (if (string? page-db-id)
-                      (:db/id (db/entity repo [:block/name (string/lower-case page-db-id)]))
-                      page-db-id)
-         opts (if page-db-id (assoc opts :page (str page-db-id)) opts)]
-     (p/let [blocks (search/block-search repo q opts)]
-      (let [result (merge
-                    {:blocks blocks
-                     :has-more? (= limit (count blocks))}
-                    (when-not page-db-id
-                      {:pages (search/page-search q)
-                       :files (search/file-search q)}))
-            search-key (if more? :search/more-result :search/result)]
-        (swap! state/state assoc search-key result))))))
+   (when-not (string/blank? q)
+     (let [page-db-id (if (string? page-db-id)
+                        (:db/id (db/entity repo [:block/name (string/lower-case page-db-id)]))
+                        page-db-id)
+           opts (if page-db-id (assoc opts :page (str page-db-id)) opts)]
+       (p/let [blocks (search/block-search repo q opts)]
+         (let [result (merge
+                       {:blocks blocks
+                        :has-more? (= limit (count blocks))}
+                       (when-not page-db-id
+                         {:pages (search/page-search q)
+                          :files (search/file-search q)}))
+               search-key (if more? :search/more-result :search/result)]
+           (swap! state/state assoc search-key result)))))))
 
 (defn clear-search!
   ([]
@@ -37,9 +46,7 @@
             :search/q ""}]
      (swap! state/state merge m))
    (when (and clear-search-mode? (not= (state/get-search-mode) :graph))
-     (state/set-search-mode! :global))
-   (when-let [input (gdom/getElement "search-field")]
-     (gobj/set input "value" ""))))
+     (state/set-search-mode! :global))))
 
 (defn rebuild-indices!
   []