diff --git a/resources/css/common.css b/resources/css/common.css index 6e5ea983891..383a99787ab 100644 --- a/resources/css/common.css +++ b/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); + } +} diff --git a/src/main/frontend/components/onboarding.cljs b/src/main/frontend/components/onboarding.cljs index c6f03b3d1c1..11146a9b675 100644 --- a/src/main/frontend/components/onboarding.cljs +++ b/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"]] diff --git a/src/main/frontend/components/page.cljs b/src/main/frontend/components/page.cljs index 4405445493d..05ee3b2b310 100644 --- a/src/main/frontend/components/page.cljs +++ b/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)] diff --git a/src/main/frontend/components/search.cljs b/src/main/frontend/components/search.cljs index fab3c786424..6593a0b5326 100644 --- a/src/main/frontend/components/search.cljs +++ b/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 diff --git a/src/main/frontend/components/svg.cljs b/src/main/frontend/components/svg.cljs index 78219cd2069..12a7c259c75 100644 --- a/src/main/frontend/components/svg.cljs +++ b/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"}]]) diff --git a/src/main/frontend/dicts.cljs b/src/main/frontend/dicts.cljs index 2c853ba2a62..9ce43c5f0c0 100644 --- a/src/main/frontend/dicts.cljs +++ b/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 "图谱" diff --git a/src/main/frontend/handler/route.cljs b/src/main/frontend/handler/route.cljs index 61311861b0c..11db3be1b2a 100644 --- a/src/main/frontend/handler/route.cljs +++ b/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))) diff --git a/src/main/frontend/handler/search.cljs b/src/main/frontend/handler/search.cljs index 18a580fd92a..48579295367 100644 --- a/src/main/frontend/handler/search.cljs +++ b/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" ""))) diff --git a/src/main/frontend/keyboards.cljs b/src/main/frontend/keyboards.cljs index 368789ef0f3..e36f2dac026 100644 --- a/src/main/frontend/keyboards.cljs +++ b/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] diff --git a/src/main/frontend/state.cljs b/src/main/frontend/state.cljs index d983d9de8d8..18f9dfd11ca 100644 --- a/src/main/frontend/state.cljs +++ b/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))