Procházet zdrojové kódy

feat: property icon emoji picker

Tienson Qin před 2 roky
rodič
revize
6ec79d48cb

+ 1 - 1
deps/graph-parser/src/logseq/graph_parser/property.cljs

@@ -190,7 +190,7 @@
    :logseq.order-list-type {:schema {:type :checkbox}}
    :logseq.tldraw.page {:schema {:type :map}}
    :logseq.tldraw.shape {:schema {:type :map}}
-   :icon {:schema {:type :default}}
+   :icon {:schema {:type :map}}
    :public {:schema {:type :checkbox}}
    :filters {:schema {:type :map}}
    :exclude-from-graph-view {:schema {:type :checkbox}}})

+ 3 - 0
package.json

@@ -88,6 +88,8 @@
         "@capacitor/splash-screen": "^4.0.0",
         "@capacitor/status-bar": "^4.0.0",
         "@capawesome/capacitor-background-task": "^2.0.0",
+        "@emoji-mart/data": "^1.1.2",
+        "@emoji-mart/react": "^1.1.1",
         "@excalidraw/excalidraw": "0.12.0",
         "@hugotomazi/capacitor-navigation-bar": "^2.0.0",
         "@logseq/capacitor-file-sync": "0.0.32",
@@ -109,6 +111,7 @@
         "dompurify": "2.4.0",
         "electron": "24.6.3",
         "electron-dl": "3.3.0",
+        "emoji-mart": "^5.5.2",
         "fs": "0.0.1-security",
         "fs-extra": "9.1.0",
         "fuse.js": "6.4.6",

+ 52 - 13
src/main/frontend/components/property.cljs

@@ -23,10 +23,35 @@
             [medley.core :as medley]
             [cljs-time.coerce :as tc]
             [clojure.set :as set]
-            [frontend.db-mixins :as db-mixins]))
+            [frontend.db-mixins :as db-mixins]
+            [frontend.handler.property.util :as pu]))
+
+(rum/defc icon
+  [block {:keys [_type id]}]            ; only :emoji supported yet
+  (let [value (or id "Pick an Icon")
+        repo (state/get-current-repo)
+        icon-property-id (:block/uuid (db/entity [:block/name "icon"]))]
+    (ui/dropdown
+     (fn [{:keys [toggle-fn]}]
+       (if id
+         [:a {:on-click toggle-fn}
+          [:em-emoji {:id id}]]
+         (ui/button value
+                    :small? true
+                    :intent "border-link"
+                    :on-click toggle-fn)))
+     (fn [{:keys [toggle-fn]}]
+       (ui/emoji-picker
+        {:auto-focus true
+         :on-emoji-select (fn [icon]
+                            (when-let [id (.-id icon)]
+                              (property-handler/update-property! repo (:block/uuid block) {:properties {icon-property-id {:type :emoji
+                                                                                                                          :id id}}}))
+                            (toggle-fn))})))))
+
 
 (rum/defcs property-config <
-  rum/static
+  rum/reactive
   (rum/local nil ::property-name)
   (rum/local nil ::property-schema)
   {:will-mount (fn [state]
@@ -34,10 +59,11 @@
                    (reset! (::property-name state) (:block/original-name property))
                    (reset! (::property-schema state) (:block/schema property))
                    state))}
-  [state repo property ]
+  [state repo property]
   (let [*property-name (::property-name state)
         *property-schema (::property-schema state)
-        built-in-property? (contains? gp-property/db-built-in-properties-keys-str (:block/original-name property))]
+        built-in-property? (contains? gp-property/db-built-in-properties-keys-str (:block/original-name property))
+        property (db/sub-block (:db/id property))]
     [:div.property-configure
      [:h1.title
       (if built-in-property?
@@ -52,6 +78,11 @@
          :disabled built-in-property?
          :value @*property-name}]]
 
+      [:div.grid.grid-cols-4.gap-1.items-center.leading-8
+       [:label "Icon:"]
+       (let [icon-value (pu/get-property property :icon)]
+         (icon property icon-value))]
+
       [:div.grid.grid-cols-4.gap-1.leading-8
        [:label "Schema type:"]
        (let [schema-types (->> (keys property-handler/builtin-schema-types)
@@ -89,13 +120,13 @@
       [:div
        (when-not built-in-property?
          (ui/button
-         "Save"
-         :on-click (fn []
-                     (property-handler/update-property!
-                      repo (:block/uuid property)
-                      {:property-name @*property-name
-                       :property-schema @*property-schema})
-                     (state/close-modal!))))]
+          "Save"
+          :on-click (fn []
+                      (property-handler/update-property!
+                       repo (:block/uuid property)
+                       {:property-name @*property-name
+                        :property-schema @*property-schema})
+                      (state/close-modal!))))]
 
       (when config/dev?
         [:div {:style {:max-width 900}}
@@ -442,7 +473,8 @@
 
 (rum/defcs property-key
   [state block property {:keys [class-schema?]}]
-  (let [repo (state/get-current-repo)]
+  (let [repo (state/get-current-repo)
+        icon (pu/get-property property :icon)]
     [:a
      {:data-propertyid (:block/uuid property)
       :data-blockid (:block/uuid block)
@@ -450,7 +482,14 @@
       :title (str "Configure property: " (:block/original-name property))
       :on-click (fn []
                   (state/set-sub-modal! #(property-config repo property)))}
-     (:block/original-name property)]))
+     [:div.flex.flex-row.items-center
+      (or
+       (when-let [id (:id icon)]
+         (when (= :emoji (:type icon))
+           [:em-emoji {:id id}]))
+       ;; default property icon
+       (ui/icon "circle-dotted" {:size 16}))
+      [:div.ml-1 (:block/original-name property)]]]))
 
 (rum/defcs multiple-value-item < (rum/local false ::show-close?)
   [state entity property item {:keys [editor-id row?]

+ 6 - 2
src/main/frontend/handler/db_based/property.cljs

@@ -217,7 +217,8 @@
         {:outliner-op :save-block}))))
 
 (defn update-property!
-  [repo property-uuid {:keys [property-name property-schema]}]
+  [repo property-uuid {:keys [property-name property-schema
+                              properties]}]
   {:pre [(uuid? property-uuid)]}
   (when-let [property (db/entity [:block/uuid property-uuid])]
     (when (and (= :many (:cardinality property-schema))
@@ -229,9 +230,12 @@
                                    {:block/original-name property-name
                                     :block/name (gp-util/page-name-sanity-lc property-name)})
                     property-schema (assoc :block/schema property-schema)
+                    properties (assoc :block/properties
+                                      (merge (:block/properties property)
+                                             properties))
                     true outliner-core/block-with-updated-at)]
       (db/transact! repo [tx-data]
-        {:outliner-op :save-block}))))
+                    {:outliner-op :save-block}))))
 
 (defn delete-property-value!
   "Delete value if a property has multiple values"

+ 6 - 5
src/main/frontend/handler/editor.cljs

@@ -3335,11 +3335,12 @@
   [block]
   (let [entity (db/entity (:db/id block))
         content (:block/content entity)]
-    (when (and (string/includes? content "#+BEGIN_QUERY")
-               (string/includes? content "#+END_QUERY"))
-      (let [ast (mldoc/->edn (string/trim content) (gp-mldoc/default-config (or (:block/format entity) :markdown)))
-            q (mldoc/extract-first-query-from-ast ast)]
-        (some? (:query (gp-util/safe-read-string q)))))))
+    (when content
+      (when (and (string/includes? content "#+BEGIN_QUERY")
+                 (string/includes? content "#+END_QUERY"))
+        (let [ast (mldoc/->edn (string/trim content) (gp-mldoc/default-config (or (:block/format entity) :markdown)))
+              q (mldoc/extract-first-query-from-ast ast)]
+          (some? (:query (gp-util/safe-read-string q))))))))
 
 (defn collapsable?
   ([block-id]

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

@@ -27,7 +27,7 @@
   [repo property-uuid opts]
   {:pre [(uuid? property-uuid)]}
   #_:clj-kondo/ignore
-  (if (config/db-based-graph? repo)
+  (when (config/db-based-graph? repo)
     (db-property/update-property! repo property-uuid opts)))
 
 (defn delete-property-value!

+ 15 - 6
src/main/frontend/ui.cljs

@@ -6,6 +6,9 @@
             ["react-textarea-autosize" :as TextareaAutosize]
             ["react-tippy" :as react-tippy]
             ["react-transition-group" :refer [CSSTransition TransitionGroup]]
+            ["@emoji-mart/data" :as emoji-data]
+            ["@emoji-mart/react" :as Picker]
+            ["emoji-mart" :as emoji-mart]
             [camel-snake-kebab.core :as csk]
             [cljs-bean.core :as bean]
             [clojure.string :as string]
@@ -46,6 +49,8 @@
 (def Tippy (r/adapt-class (gobj/get react-tippy "Tooltip")))
 (def ReactTweetEmbed (r/adapt-class react-tweet-embed))
 (def useInView (gobj/get react-intersection-observer "useInView"))
+(defonce _emoji-init-data ((gobj/get emoji-mart "init") #js {:data emoji-data}))
+(def EmojiPicker (r/adapt-class (gobj/get Picker "default")))
 
 (defn reset-ios-whole-page-offset!
   []
@@ -1013,16 +1018,16 @@
 
 (rum/defc icon
   ([name] (icon name nil))
-  ([name {:keys [extension? font? class] :as opts}]
+  ([name {:keys [extension? font? class size] :as opts}]
    (when-not (string/blank? name)
      (let [^js jsTablerIcons (gobj/get js/window "tablerIcons")]
        (if (or extension? font? (not jsTablerIcons))
          [:span.ui__icon (merge {:class
                                  (util/format
-                                   (str "%s-" name
-                                        (when (:class opts)
-                                          (str " " (string/trim (:class opts)))))
-                                   (if extension? "tie tie" "ti ti"))}
+                                  (str "%s-" name
+                                       (when (:class opts)
+                                         (str " " (string/trim (:class opts)))))
+                                  (if extension? "tie tie" "ti ti"))}
                                 (dissoc opts :class :extension? :font?))]
 
          ;; tabler svg react
@@ -1030,7 +1035,7 @@
            (let [f (get-adapt-icon-class klass)]
              [:span.ui__icon.ti
               {:class (str "ls-icon-" name " " class)}
-              (f (merge {:size 18} (r/map-keys->camel-case (dissoc opts :class))))])))))))
+              (f (merge {:size (or size 18)} (r/map-keys->camel-case (dissoc opts :class))))])))))))
 
 (rum/defc button
   [text & {:keys [background href class intent on-click small? large? title icon icon-props disabled?]
@@ -1210,3 +1215,7 @@
       :on-click rm-heading-fn
       :intent "link"
       :small? true)]]))
+
+(rum/defc emoji-picker
+  [opts]
+  (EmojiPicker. (assoc opts :data emoji-data)))

+ 15 - 0
yarn.lock

@@ -350,6 +350,16 @@
   optionalDependencies:
     global-agent "^3.0.0"
 
+"@emoji-mart/data@^1.1.2":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@emoji-mart/data/-/data-1.1.2.tgz#777c976f8f143df47cbb23a7077c9ca9fe5fc513"
+  integrity sha512-1HP8BxD2azjqWJvxIaWAMyTySeZY0Osr83ukYjltPVkNXeJvTz7yDrPLBtnrD5uqJ3tg4CcLuuBW09wahqL/fg==
+
+"@emoji-mart/react@^1.1.1":
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/@emoji-mart/react/-/react-1.1.1.tgz#ddad52f93a25baf31c5383c3e7e4c6e05554312a"
+  integrity sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==
+
 "@excalidraw/[email protected]":
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.12.0.tgz#0c281624f29aa7834a015035b21dfd928be861d4"
@@ -2611,6 +2621,11 @@ elliptic@^6.5.3:
     minimalistic-assert "^1.0.1"
     minimalistic-crypto-utils "^1.0.1"
 
+emoji-mart@^5.5.2:
+  version "5.5.2"
+  resolved "https://registry.yarnpkg.com/emoji-mart/-/emoji-mart-5.5.2.tgz#3ddbaf053139cf4aa217650078bc1c50ca8381af"
+  integrity sha512-Sqc/nso4cjxhOwWJsp9xkVm8OF5c+mJLZJFoFfzRuKO+yWiN7K8c96xmtughYb0d/fZ8UC6cLIQ/p4BR6Pv3/A==
+
 emoji-regex@^8.0.0:
   version "8.0.0"
   resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"