From 42230f263015538e847260ac833c10c8b602aafd Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 25 Jun 2024 14:59:13 +0200 Subject: [PATCH] :sparkles: Change shapes color --- .../src/app/main/data/workspace/colors.cljs | 3 +- frontend/src/app/plugins/api.cljs | 84 +++++++++++----- frontend/src/app/plugins/format.cljs | 8 ++ frontend/src/app/plugins/parser.cljs | 98 +++++++++++++++++++ 4 files changed, 167 insertions(+), 26 deletions(-) create mode 100644 frontend/src/app/plugins/format.cljs create mode 100644 frontend/src/app/plugins/parser.cljs diff --git a/frontend/src/app/main/data/workspace/colors.cljs b/frontend/src/app/main/data/workspace/colors.cljs index af771bd4a..dc0a44d4a 100644 --- a/frontend/src/app/main/data/workspace/colors.cljs +++ b/frontend/src/app/main/data/workspace/colors.cljs @@ -24,6 +24,7 @@ [app.util.color :as uc] [app.util.storage :refer [storage]] [beicon.v2.core :as rx] + [cuerdas.core :as str] [potok.v2.core :as ptk])) ;; A set of keys that are used for shared state identifiers @@ -377,7 +378,7 @@ (defn color-att->text [color] - {:fill-color (:color color) + {:fill-color (when (:color color) (str/lower (:color color))) :fill-opacity (:opacity color) :fill-color-ref-id (:id color) :fill-color-ref-file (:file-id color) diff --git a/frontend/src/app/plugins/api.cljs b/frontend/src/app/plugins/api.cljs index f6157303e..a645bb791 100644 --- a/frontend/src/app/plugins/api.cljs +++ b/frontend/src/app/plugins/api.cljs @@ -13,12 +13,14 @@ [app.common.files.helpers :as cfh] [app.common.geom.point :as gpt] [app.common.record :as cr] + [app.common.schema :as sm] [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] [app.main.data.workspace.bool :as dwb] + [app.main.data.workspace.colors :as dwc] [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.media :as dwm] [app.main.store :as st] @@ -27,6 +29,7 @@ [app.plugins.fonts :as fonts] [app.plugins.library :as library] [app.plugins.page :as page] + [app.plugins.parser :as parser] [app.plugins.shape :as shape] [app.plugins.user :as user] [app.plugins.utils :as u] @@ -87,35 +90,66 @@ (let [selection (get-in @st/state [:workspace-local :selected])] (apply array (sequence (map (partial shape/shape-proxy $plugin)) selection)))) - (getColors + (shapesColors [_ shapes] - (let [objects (u/locate-objects) - shapes (->> shapes - (map #(obj/get % "$id")) - (mapcat #(cfh/get-children-with-self objects %))) + (cond + (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes))) + (u/display-not-valid :shapesColors-shapes shapes) - file-id (:current-file-id @st/state) - shared-libs (:workspace-libraries @st/state) + :else + (let [objects (u/locate-objects) + shapes (->> shapes + (map #(obj/get % "$id")) + (mapcat #(cfh/get-children-with-self objects %))) - 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)) + file-id (:current-file-id @st/state) + shared-libs (:workspace-libraries @st/state) - (changeColor - [_ _shapes _old-color _new-color] - ;; TODO - ) + format-entry + (fn [{:keys [prop shape-id index]}] + #js {:property (d/name prop) + :index index + :shapeId (str shape-id)}) + format-result + (fn [[color attrs]] + (let [shapes-info (apply array (map format-entry attrs)) + color (u/to-js color)] + (obj/set! color "shapeInfo" shapes-info) + color))] + (apply + array + (->> (ctc/extract-all-colors shapes file-id shared-libs) + (group-by :attrs) + (map format-result)))))) + + (replaceColor + [_ shapes old-color new-color] + + (let [old-color (parser/parse-color old-color) + new-color (parser/parse-color new-color)] + (cond + (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes))) + (u/display-not-valid :replaceColor-shapes shapes) + + (not (sm/validate ::ctc/color old-color)) + (u/display-not-valid :replaceColor-oldColor old-color) + + (not (sm/validate ::ctc/color new-color)) + (u/display-not-valid :replaceColor-newColor new-color) + + :else + (let [file-id (:current-file-id @st/state) + shared-libs (:workspace-libraries @st/state) + objects (u/locate-objects) + shapes + (->> shapes + (map #(obj/get % "$id")) + (mapcat #(cfh/get-children-with-self objects %))) + + shapes-by-color + (->> (ctc/extract-all-colors shapes file-id shared-libs) + (group-by :attrs))] + (st/emit! (dwc/change-color-in-selected new-color (get shapes-by-color old-color) old-color)))))) (getRoot [_] diff --git a/frontend/src/app/plugins/format.cljs b/frontend/src/app/plugins/format.cljs new file mode 100644 index 000000000..4b2a44c09 --- /dev/null +++ b/frontend/src/app/plugins/format.cljs @@ -0,0 +1,8 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns app.plugins.format) + diff --git a/frontend/src/app/plugins/parser.cljs b/frontend/src/app/plugins/parser.cljs new file mode 100644 index 000000000..0b12c9643 --- /dev/null +++ b/frontend/src/app/plugins/parser.cljs @@ -0,0 +1,98 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns app.plugins.parser + (:require + [app.common.data :as d] + [app.common.uuid :as uuid] + [app.util.object :as obj] + [cuerdas.core :as str])) + +(defn parse-id + [id] + (when id (uuid/uuid id))) + +(defn parse-keyword + [kw] + (when kw (keyword kw))) + +(defn parse-hex + [color] + (when color (-> color str/lower))) + +;;export type PenpotImageData = { +;; name?: string; +;; width: number; +;; height: number; +;; mtype?: string; +;; id: string; +;; keepApectRatio?: boolean; +;;} +(defn parse-image-data + [^js image-data] + (when image-data + (d/without-nils + {:id (-> (obj/get image-data "id") parse-id) + :name (obj/get image-data "name") + :width (obj/get image-data "width") + :height (obj/get image-data "height") + :mtype (obj/get image-data "mtype") + :keep-aspect-ratio (obj/get image-data "keepApectRatio")}))) + +;; export type PenpotGradient = { +;; type: 'linear' | 'radial'; +;; startX: number; +;; startY: number; +;; endX: number; +;; endY: number; +;; width: number; +;; stops: Array<{ color: string; opacity?: number; offset: number }>; +;; } +(defn parse-gradient-stop + [^js stop] + (when stop + (d/without-nils + {:color (-> (obj/get stop "color") parse-hex) + :opacity (obj/get stop "opacity") + :offset (obj/get stop "offset")}))) + +(defn parse-gradient + [^js gradient] + (when gradient + (d/without-nils + {:type (-> (obj/get gradient "type") parse-keyword) + :start-x (obj/get gradient "startX") + :start-y (obj/get gradient "startY") + :end-x (obj/get gradient "endX") + :end-y (obj/get gradient "endY") + :width (obj/get gradient "width") + :stops (->> (obj/get gradient "stops") + (mapv parse-gradient-stop))}))) + +;; export interface PenpotColor { +;; id?: string; +;; name?: string; +;; path?: string; +;; color?: string; +;; opacity?: number; +;; refId?: string; +;; refFile?: string; +;; gradient?: PenpotGradient; +;; image?: PenpotImageData; +;; } +(defn parse-color + [^js color] + (when color + (d/without-nils + {:id (-> (obj/get color "id") parse-id) + :name (obj/get color "name") + :path (obj/get color "path") + :color (-> (obj/get color "color") parse-hex) + :opacity (obj/get color "opacity") + :ref-id (-> (obj/get color "refId") parse-id) + :ref-file (-> (obj/get color "refFile") parse-id) + :gradient (-> (obj/get color "gradient") parse-gradient) + :image (-> (obj/get color "image") parse-image-data)})))