diff --git a/common/src/app/common/types/color.cljc b/common/src/app/common/types/color.cljc index c8a1ef67b..dea0ee6fc 100644 --- a/common/src/app/common/types/color.cljc +++ b/common/src/app/common/types/color.cljc @@ -7,6 +7,7 @@ (ns app.common.types.color (:require [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.schema :as sm] [app.common.schema.openapi :as-alias oapi] [app.common.text :as txt] @@ -14,7 +15,8 @@ [app.common.types.color.gradient :as-alias color-gradient] [app.common.types.color.gradient.stop :as-alias color-gradient-stop] [app.common.uuid :as uuid] - [clojure.test.check.generators :as tgen])) + [clojure.test.check.generators :as tgen] + [cuerdas.core :as str])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; SCHEMAS @@ -383,3 +385,121 @@ (and (some? (:color c1)) (some? (:color c2)) (= (:color c1) (:color c2))))) + + +(defn stroke->color-att + [stroke file-id shared-libs] + (let [color-file-id (:stroke-color-ref-file stroke) + color-id (:stroke-color-ref-id stroke) + shared-libs-colors (dm/get-in shared-libs [color-file-id :data :colors]) + is-shared? (contains? shared-libs-colors color-id) + has-color? (or (not (nil? (:stroke-color stroke))) (not (nil? (:stroke-color-gradient stroke)))) + attrs (if (or is-shared? (= color-file-id file-id)) + (d/without-nils {:color (str/lower (:stroke-color stroke)) + :opacity (:stroke-opacity stroke) + :id color-id + :file-id color-file-id + :gradient (:stroke-color-gradient stroke)}) + (d/without-nils {:color (str/lower (:stroke-color stroke)) + :opacity (:stroke-opacity stroke) + :gradient (:stroke-color-gradient stroke)}))] + (when has-color? + {:attrs attrs + :prop :stroke + :shape-id (:shape-id stroke) + :index (:index stroke)}))) + +(defn shadow->color-att + [shadow file-id shared-libs] + (let [color-file-id (dm/get-in shadow [:color :file-id]) + color-id (dm/get-in shadow [:color :id]) + shared-libs-colors (dm/get-in shared-libs [color-file-id :data :colors]) + is-shared? (contains? shared-libs-colors color-id) + attrs (if (or is-shared? (= color-file-id file-id)) + (d/without-nils {:color (str/lower (dm/get-in shadow [:color :color])) + :opacity (dm/get-in shadow [:color :opacity]) + :id color-id + :file-id (dm/get-in shadow [:color :file-id]) + :gradient (dm/get-in shadow [:color :gradient])}) + (d/without-nils {:color (str/lower (dm/get-in shadow [:color :color])) + :opacity (dm/get-in shadow [:color :opacity]) + :gradient (dm/get-in shadow [:color :gradient])}))] + + + {:attrs attrs + :prop :shadow + :shape-id (:shape-id shadow) + :index (:index shadow)})) + +(defn text->color-att + [fill file-id shared-libs] + (let [color-file-id (:fill-color-ref-file fill) + color-id (:fill-color-ref-id fill) + shared-libs-colors (dm/get-in shared-libs [color-file-id :data :colors]) + is-shared? (contains? shared-libs-colors color-id) + attrs (if (or is-shared? (= color-file-id file-id)) + (d/without-nils {:color (str/lower (:fill-color fill)) + :opacity (:fill-opacity fill) + :id color-id + :file-id color-file-id + :gradient (:fill-color-gradient fill)}) + (d/without-nils {:color (str/lower (:fill-color fill)) + :opacity (:fill-opacity fill) + :gradient (:fill-color-gradient fill)}))] + {:attrs attrs + :prop :content + :shape-id (:shape-id fill) + :index (:index fill)})) + +(defn treat-node + [node shape-id] + (map-indexed #(assoc %2 :shape-id shape-id :index %1) node)) + +(defn extract-text-colors + [text file-id shared-libs] + (let [content (txt/node-seq txt/is-text-node? (:content text)) + content-filtered (map :fills content) + indexed (mapcat #(treat-node % (:id text)) content-filtered)] + (map #(text->color-att % file-id shared-libs) indexed))) + +(defn fill->color-att + [fill file-id shared-libs] + (let [color-file-id (:fill-color-ref-file fill) + color-id (:fill-color-ref-id fill) + shared-libs-colors (dm/get-in shared-libs [color-file-id :data :colors]) + is-shared? (contains? shared-libs-colors color-id) + has-color? (or (not (nil? (:fill-color fill))) (not (nil? (:fill-color-gradient fill)))) + attrs (if (or is-shared? (= color-file-id file-id)) + (d/without-nils {:color (str/lower (:fill-color fill)) + :opacity (:fill-opacity fill) + :id color-id + :file-id color-file-id + :gradient (:fill-color-gradient fill)}) + (d/without-nils {:color (str/lower (:fill-color fill)) + :opacity (:fill-opacity fill) + :gradient (:fill-color-gradient fill)}))] + (when has-color? + {:attrs attrs + :prop :fill + :shape-id (:shape-id fill) + :index (:index fill)}))) + +(defn extract-all-colors + [shapes file-id shared-libs] + (reduce + (fn [list shape] + (let [fill-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:fills shape)) + stroke-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:strokes shape)) + shadow-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:shadow shape))] + (if (= :text (:type shape)) + (-> list + (into (map #(stroke->color-att % file-id shared-libs)) stroke-obj) + (into (map #(shadow->color-att % file-id shared-libs)) shadow-obj) + (into (extract-text-colors shape file-id shared-libs))) + + (-> list + (into (map #(fill->color-att % file-id shared-libs)) fill-obj) + (into (map #(stroke->color-att % file-id shared-libs)) stroke-obj) + (into (map #(shadow->color-att % file-id shared-libs)) shadow-obj))))) + [] + shapes)) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs index 88f0ef0b4..b0c5b0cdc 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs @@ -9,143 +9,24 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] - [app.common.text :as txt] + [app.common.types.color :as ctc] [app.main.data.workspace.colors :as dc] [app.main.data.workspace.selection :as dws] [app.main.store :as st] [app.main.ui.components.title-bar :refer [title-bar]] [app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]] [app.util.i18n :as i18n :refer [tr]] - [cuerdas.core :as str] [rumext.v2 :as mf])) -(defn fill->color-att - [fill file-id shared-libs] - (let [color-file-id (:fill-color-ref-file fill) - color-id (:fill-color-ref-id fill) - shared-libs-colors (dm/get-in shared-libs [color-file-id :data :colors]) - is-shared? (contains? shared-libs-colors color-id) - has-color? (or (not (nil? (:fill-color fill))) (not (nil? (:fill-color-gradient fill)))) - attrs (if (or is-shared? (= color-file-id file-id)) - (d/without-nils {:color (str/lower (:fill-color fill)) - :opacity (:fill-opacity fill) - :id color-id - :file-id color-file-id - :gradient (:fill-color-gradient fill)}) - (d/without-nils {:color (str/lower (:fill-color fill)) - :opacity (:fill-opacity fill) - :gradient (:fill-color-gradient fill)}))] - (when has-color? - {:attrs attrs - :prop :fill - :shape-id (:shape-id fill) - :index (:index fill)}))) - -(defn stroke->color-att - [stroke file-id shared-libs] - (let [color-file-id (:stroke-color-ref-file stroke) - color-id (:stroke-color-ref-id stroke) - shared-libs-colors (dm/get-in shared-libs [color-file-id :data :colors]) - is-shared? (contains? shared-libs-colors color-id) - has-color? (or (not (nil? (:stroke-color stroke))) (not (nil? (:stroke-color-gradient stroke)))) - attrs (if (or is-shared? (= color-file-id file-id)) - (d/without-nils {:color (str/lower (:stroke-color stroke)) - :opacity (:stroke-opacity stroke) - :id color-id - :file-id color-file-id - :gradient (:stroke-color-gradient stroke)}) - (d/without-nils {:color (str/lower (:stroke-color stroke)) - :opacity (:stroke-opacity stroke) - :gradient (:stroke-color-gradient stroke)}))] - (when has-color? - {:attrs attrs - :prop :stroke - :shape-id (:shape-id stroke) - :index (:index stroke)}))) - -(defn shadow->color-att - [shadow file-id shared-libs] - (let [color-file-id (dm/get-in shadow [:color :file-id]) - color-id (dm/get-in shadow [:color :id]) - shared-libs-colors (dm/get-in shared-libs [color-file-id :data :colors]) - is-shared? (contains? shared-libs-colors color-id) - attrs (if (or is-shared? (= color-file-id file-id)) - (d/without-nils {:color (str/lower (dm/get-in shadow [:color :color])) - :opacity (dm/get-in shadow [:color :opacity]) - :id color-id - :file-id (dm/get-in shadow [:color :file-id]) - :gradient (dm/get-in shadow [:color :gradient])}) - (d/without-nils {:color (str/lower (dm/get-in shadow [:color :color])) - :opacity (dm/get-in shadow [:color :opacity]) - :gradient (dm/get-in shadow [:color :gradient])}))] - - - {:attrs attrs - :prop :shadow - :shape-id (:shape-id shadow) - :index (:index shadow)})) - -(defn text->color-att - [fill file-id shared-libs] - (let [color-file-id (:fill-color-ref-file fill) - color-id (:fill-color-ref-id fill) - shared-libs-colors (dm/get-in shared-libs [color-file-id :data :colors]) - is-shared? (contains? shared-libs-colors color-id) - attrs (if (or is-shared? (= color-file-id file-id)) - (d/without-nils {:color (str/lower (:fill-color fill)) - :opacity (:fill-opacity fill) - :id color-id - :file-id color-file-id - :gradient (:fill-color-gradient fill)}) - (d/without-nils {:color (str/lower (:fill-color fill)) - :opacity (:fill-opacity fill) - :gradient (:fill-color-gradient fill)}))] - {:attrs attrs - :prop :content - :shape-id (:shape-id fill) - :index (:index fill)})) - -(defn treat-node - [node shape-id] - (map-indexed #(assoc %2 :shape-id shape-id :index %1) node)) - -(defn extract-text-colors - [text file-id shared-libs] - (let [content (txt/node-seq txt/is-text-node? (:content text)) - content-filtered (map :fills content) - indexed (mapcat #(treat-node % (:id text)) content-filtered)] - (map #(text->color-att % file-id shared-libs) indexed))) - -(defn- extract-all-colors - [shapes file-id shared-libs] - (reduce - (fn [list shape] - (let [fill-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:fills shape)) - stroke-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:strokes shape)) - shadow-obj (map-indexed #(assoc %2 :shape-id (:id shape) :index %1) (:shadow shape))] - (if (= :text (:type shape)) - (-> list - (into (map #(stroke->color-att % file-id shared-libs)) stroke-obj) - (into (map #(shadow->color-att % file-id shared-libs)) shadow-obj) - (into (extract-text-colors shape file-id shared-libs))) - - (-> list - (into (map #(fill->color-att % file-id shared-libs)) fill-obj) - (into (map #(stroke->color-att % file-id shared-libs)) stroke-obj) - (into (map #(shadow->color-att % file-id shared-libs)) shadow-obj))))) - [] - shapes)) - (defn- prepare-colors [shapes file-id shared-libs] - (let [data (into [] (remove nil? (extract-all-colors shapes file-id shared-libs))) + (let [data (into [] (remove nil? (ctc/extract-all-colors shapes file-id shared-libs))) grouped-colors (group-by :attrs data) all-colors (distinct (mapv :attrs data)) tmp (group-by #(some? (:id %)) all-colors) library-colors (get tmp true) colors (get tmp false)] - {:grouped-colors grouped-colors :all-colors all-colors :colors colors diff --git a/frontend/src/app/plugins/api.cljs b/frontend/src/app/plugins/api.cljs index 6ebdfa441..f6157303e 100644 --- a/frontend/src/app/plugins/api.cljs +++ b/frontend/src/app/plugins/api.cljs @@ -7,11 +7,14 @@ (ns app.plugins.api "RPC for plugins runtime." (:require + [app.common.data :as d] [app.common.data.macros :as dm] [app.common.files.changes-builder :as cb] + [app.common.files.helpers :as cfh] [app.common.geom.point :as gpt] [app.common.record :as cr] [app.common.text :as txt] + [app.common.types.color :as ctc] [app.common.types.shape :as cts] [app.common.uuid :as uuid] [app.main.data.changes :as ch] @@ -28,6 +31,7 @@ [app.plugins.user :as user] [app.plugins.utils :as u] [app.plugins.viewport :as viewport] + [app.util.code-gen :as cg] [app.util.object :as obj] [beicon.v2.core :as rx] [promesa.core :as p])) @@ -83,6 +87,36 @@ (let [selection (get-in @st/state [:workspace-local :selected])] (apply array (sequence (map (partial shape/shape-proxy $plugin)) selection)))) + (getColors + [_ shapes] + (let [objects (u/locate-objects) + shapes (->> shapes + (map #(obj/get % "$id")) + (mapcat #(cfh/get-children-with-self objects %))) + + file-id (:current-file-id @st/state) + shared-libs (:workspace-libraries @st/state) + + colors + (apply + array + (->> (ctc/extract-all-colors shapes file-id shared-libs) + (group-by :attrs) + (map (fn [[color attrs]] + (let [shapes-info (apply array (map (fn [{:keys [prop shape-id index]}] + #js {:property (d/name prop) + :index index + :shapeId (str shape-id)}) attrs)) + color (u/to-js color)] + (obj/set! color "shapeInfo" shapes-info) + color)))))] + colors)) + + (changeColor + [_ _shapes _old-color _new-color] + ;; TODO + ) + (getRoot [_] (shape/shape-proxy $plugin uuid/zero))