mirror of
https://github.com/logseq/logseq.git
synced 2026-04-24 14:14:55 +00:00
enhance(ux): search support both recent search and updates
This commit is contained in:
17
deps/db/src/logseq/db/common/initial_data.cljs
vendored
17
deps/db/src/logseq/db/common/initial_data.cljs
vendored
@@ -302,14 +302,15 @@
|
||||
|
||||
(defn get-recent-updated-pages
|
||||
[db]
|
||||
(some->>
|
||||
(d/datoms db :avet :block/updated-at)
|
||||
rseq
|
||||
(keep (fn [datom]
|
||||
(let [e (d/entity db (:e datom))]
|
||||
(when (and (common-entity-util/page? e) (not (entity-util/hidden? e)))
|
||||
e))))
|
||||
(take 30)))
|
||||
(when db
|
||||
(some->>
|
||||
(d/datoms db :avet :block/updated-at)
|
||||
rseq
|
||||
(keep (fn [datom]
|
||||
(let [e (d/entity db (:e datom))]
|
||||
(when (and (common-entity-util/page? e) (not (entity-util/hidden? e)))
|
||||
e))))
|
||||
(take 30))))
|
||||
|
||||
(defn get-initial-data
|
||||
"Returns current database schema and initial data.
|
||||
|
||||
@@ -5,9 +5,14 @@
|
||||
[clojure.string :as string]
|
||||
[dommy.core :as dom]
|
||||
[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 fstate]
|
||||
[frontend.ui :as ui]
|
||||
[frontend.util :as util]
|
||||
[logseq.db :as ldb]
|
||||
[logseq.shui.hooks :as hooks]
|
||||
[promesa.core :as p]
|
||||
[rum.core :as rum]))
|
||||
@@ -26,10 +31,47 @@
|
||||
(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)
|
||||
[search-result set-search-result!] (hooks/use-state nil)]
|
||||
[input set-input!] (hooks/use-state "")
|
||||
[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)]
|
||||
(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)])
|
||||
(ion/page
|
||||
{:id "search-tab"}
|
||||
(ion/header
|
||||
@@ -38,14 +80,40 @@
|
||||
{:ref *ref
|
||||
:slot "start"
|
||||
:placeholder "Search"
|
||||
:value input
|
||||
:on-ion-input (fn [^js e]
|
||||
(let [input (.-value (.-detail e))]
|
||||
(when-not (string/blank? input)
|
||||
(p/let [result (search-blocks input)]
|
||||
(set-search-result! result)))))})))
|
||||
(set-input! input)
|
||||
(set-last-input-at! (util/time-ms))))})))
|
||||
(ion/content
|
||||
(when (string/blank? input)
|
||||
[:<>
|
||||
[:div.mb-4
|
||||
[:div.px-4.text-sm.text-muted-foreground.border-b
|
||||
[:div.flex.flex-item.items-center.justify-between
|
||||
[:div "Recent search"]
|
||||
(ion/button
|
||||
{:fill "clear"
|
||||
:size "small"
|
||||
:mode "ios"
|
||||
:class "text-muted-foreground"
|
||||
:on-click (fn []
|
||||
(search-handler/clear-recents!)
|
||||
(set-recents! nil))}
|
||||
"Clear all")]]
|
||||
(ion/list
|
||||
(for [item recents]
|
||||
(ion/item
|
||||
{:on-click #(set-input! item)}
|
||||
[:div.flex.flex-row.items-center.gap-1
|
||||
(ui/icon "search" {:size 14
|
||||
:class "text-muted-foreground"})
|
||||
item])))]
|
||||
|
||||
[:div.px-4.py-2.text-sm.text-muted-foreground.border-b
|
||||
"Recent updates"]])
|
||||
(ion/list
|
||||
(for [{:keys [icon text header source-page source-block]} search-result]
|
||||
(for [{:keys [icon text header source-page source-block]} result]
|
||||
(let [block (or source-page source-block)]
|
||||
(ion/item
|
||||
{:on-click (fn []
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
;; Each result group has it's own load-results function
|
||||
(defmulti load-results (fn [group _state] group))
|
||||
|
||||
(defn- get-page-icon
|
||||
(defn get-page-icon
|
||||
[entity]
|
||||
(cond
|
||||
(ldb/class? entity)
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
(ns frontend.handler.search
|
||||
"Provides util handler fns for search"
|
||||
(:require [clojure.string :as string]
|
||||
[frontend.config :as config]
|
||||
[dommy.core :as dom]
|
||||
[electron.ipc :as ipc]
|
||||
[frontend.common.search-fuzzy :as fuzzy]
|
||||
[frontend.config :as config]
|
||||
[frontend.db :as db]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.search :as search]
|
||||
[frontend.state :as state]
|
||||
[frontend.storage :as storage]
|
||||
[frontend.util :as util]
|
||||
[promesa.core :as p]
|
||||
[logseq.graph-parser.text :as text]
|
||||
[electron.ipc :as ipc]
|
||||
[dommy.core :as dom]))
|
||||
[promesa.core :as p]))
|
||||
|
||||
(defn sanity-search-content
|
||||
"Convert a block to the display contents for searching"
|
||||
@@ -84,9 +85,9 @@
|
||||
(defn loop-find-in-page!
|
||||
[backward?]
|
||||
(if (and (get-in @state/state [:ui/find-in-page :active?])
|
||||
(not (state/editing?)))
|
||||
(not (state/editing?)))
|
||||
(do (state/set-state! [:ui/find-in-page :backward?] backward?)
|
||||
(debounced-search))
|
||||
(debounced-search))
|
||||
;; return false to skip prevent default event behavior (Enter key)
|
||||
false))
|
||||
|
||||
@@ -157,3 +158,18 @@
|
||||
result)))
|
||||
(conj result [:span content])))]
|
||||
[:p {:class "m-0"} elements]))))))
|
||||
|
||||
(defn get-recents
|
||||
[]
|
||||
(storage/get :recent-search-items))
|
||||
|
||||
(defn add-recent!
|
||||
[item]
|
||||
(when-not (string/blank? item)
|
||||
(let [recents (get-recents)]
|
||||
(storage/set :recent-search-items
|
||||
(distinct (take 20 (cons item recents)))))))
|
||||
|
||||
(defn clear-recents!
|
||||
[]
|
||||
(storage/remove :recent-search-items))
|
||||
|
||||
Reference in New Issue
Block a user