diff --git a/CHANGES.md b/CHANGES.md index cd3c68c3a..14ffe6921 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -50,6 +50,7 @@ ### :bug: Bugs fixed +- Remove gitter information from feedback page [Taiga #4157](https://tree.taiga.io/project/penpot/issue/4157) - Fix overlay remains open on frame change [Taiga #4066](https://tree.taiga.io/project/penpot/issue/4066) - Fix toggle overlay position [Taiga #4091](https://tree.taiga.io/project/penpot/issue/4091) - Fix overlay closed on clicked outside [Taiga #4027](https://tree.taiga.io/project/penpot/issue/4027) @@ -57,6 +58,16 @@ - Fix problem with snap to grids [#2221](https://github.com/penpot/penpot/issues/2221) - Fix issue when scaling to value 0 [#2252](https://github.com/penpot/penpot/issues/2252) - Fix problem when moving shapes inside nested frames [Taiga #4113](https://tree.taiga.io/project/penpot/issue/4113) +- Fix color type icon does not change [Taiga #4133](https://tree.taiga.io/project/penpot/issue/4133) +- Fix recent colors are not working [Taiga #4153](https://tree.taiga.io/project/penpot/issue/4153) +- Fix change opacity in colorpicker cause bugged color [Taiga #4154](https://tree.taiga.io/project/penpot/issue/4154) +- Fix gradient colors don't arrive in recent colors palette (https://tree.taiga.io/project/penpot/issue/4155) +- Fix selected colors allow gradients in shadows [Taiga #4156](https://tree.taiga.io/project/penpot/issue/4156) +- Fix import files with unexpected format or invalid content [Taiga #4136](https://tree.taiga.io/project/penpot/issue/4136) +- Fix wrong shortcut button tip of "Delete" function [Taiga #4162](https://tree.taiga.io/project/penpot/issue/4162) +- Fix error after user drags any layer in search functionality [Taiga #4161](https://tree.taiga.io/project/penpot/issue/4161) +- Fix font search works only with lowercase letters [Taiga #4140](https://tree.taiga.io/project/penpot/issue/4140) +- Fix Terms and Privacy links overlapping [Taiga #4137](https://tree.taiga.io/project/penpot/issue/4137) ## 1.15.3-beta diff --git a/backend/deps.edn b/backend/deps.edn index b69343ea5..fa1287599 100644 --- a/backend/deps.edn +++ b/backend/deps.edn @@ -28,6 +28,8 @@ org.postgresql/postgresql {:mvn/version "42.4.0"} com.zaxxer/HikariCP {:mvn/version "5.0.1"} + io.whitfin/siphash {:mvn/version "2.0.0"} + buddy/buddy-hashers {:mvn/version "1.8.158"} buddy/buddy-sign {:mvn/version "3.4.333"} diff --git a/backend/src/app/db.clj b/backend/src/app/db.clj index d97cd21a2..f547cfa9a 100644 --- a/backend/src/app/db.clj +++ b/backend/src/app/db.clj @@ -27,6 +27,8 @@ com.zaxxer.hikari.HikariConfig com.zaxxer.hikari.HikariDataSource com.zaxxer.hikari.metrics.prometheus.PrometheusMetricsTrackerFactory + io.whitfin.siphash.SipHasher + io.whitfin.siphash.SipHasherContainer java.io.InputStream java.io.OutputStream java.lang.AutoCloseable @@ -431,10 +433,19 @@ ;; --- Locks +(def ^:private siphash-state + (SipHasher/container + (uuid/get-bytes uuid/zero))) + +(defn uuid->hash-code + [o] + (.hash ^SipHasherContainer siphash-state + ^bytes (uuid/get-bytes o))) + (defn- xact-check-param [n] (cond - (uuid? n) (uuid/get-word-high n) + (uuid? n) (uuid->hash-code n) (int? n) n :else (throw (IllegalArgumentException. "uuid or number allowed")))) diff --git a/backend/src/app/media.clj b/backend/src/app/media.clj index 98b25b2f3..4cf1d8437 100644 --- a/backend/src/app/media.clj +++ b/backend/src/app/media.clj @@ -229,17 +229,6 @@ (when (zero? (:exit res)) foutput))) - (ttf-or-otf->woff2 [data] - ;; NOTE: foutput is not used directly, it represents the - ;; default output of the exection of the underlying - ;; command. - (let [finput (tmp/tempfile :prefix "penpot.font." :suffix ".tmp") - foutput (fs/path (str (fs/base finput) ".woff2")) - _ (io/write-to-file! data finput) - res (sh/sh "woff2_compress" (str finput))] - (when (zero? (:exit res)) - foutput))) - (woff->sfnt [data] (let [finput (tmp/tempfile :prefix "penpot" :suffix "") _ (io/write-to-file! data finput) @@ -271,15 +260,13 @@ (let [data (get input "font/ttf")] (-> input (update "font/otf" gen-if-nil #(ttf->otf data)) - (update "font/woff" gen-if-nil #(ttf-or-otf->woff data)) - (assoc "font/woff2" (ttf-or-otf->woff2 data)))) + (update "font/woff" gen-if-nil #(ttf-or-otf->woff data)))) (contains? current "font/otf") (let [data (get input "font/otf")] (-> input (update "font/woff" gen-if-nil #(ttf-or-otf->woff data)) - (assoc "font/ttf" (otf->ttf data)) - (assoc "font/woff2" (ttf-or-otf->woff2 data)))) + (assoc "font/ttf" (otf->ttf data)))) (contains? current "font/woff") (let [data (get input "font/woff") @@ -291,8 +278,7 @@ (let [stype (get-sfnt-type sfnt)] (cond-> input true - (-> (assoc "font/woff" data) - (assoc "font/woff2" (ttf-or-otf->woff2 sfnt))) + (-> (assoc "font/woff" data)) (= stype :otf) (-> (assoc "font/otf" sfnt) diff --git a/backend/test/app/services_fonts_test.clj b/backend/test/app/services_fonts_test.clj index 96ecb58aa..36c6112cf 100644 --- a/backend/test/app/services_fonts_test.clj +++ b/backend/test/app/services_fonts_test.clj @@ -45,7 +45,6 @@ (t/is (uuid? (:ttf-file-id result))) (t/is (uuid? (:otf-file-id result))) (t/is (uuid? (:woff1-file-id result))) - (t/is (uuid? (:woff2-file-id result))) (t/are [k] (= (get params k) (get result k)) :team-id @@ -81,7 +80,6 @@ (t/is (uuid? (:ttf-file-id result))) (t/is (uuid? (:otf-file-id result))) (t/is (uuid? (:woff1-file-id result))) - (t/is (uuid? (:woff2-file-id result))) (t/are [k] (= (get params k) (get result k)) :team-id diff --git a/backend/test/app/storage_test.clj b/backend/test/app/storage_test.clj index 03d5092f2..b619cbda3 100644 --- a/backend/test/app/storage_test.clj +++ b/backend/test/app/storage_test.clj @@ -232,7 +232,7 @@ ;; run the touched gc task (let [task (:app.storage/gc-touched-task th/*system*) res (task {})] - (t/is (= 6 (:freeze res))) + (t/is (= 5 (:freeze res))) (t/is (= 0 (:delete res))) (let [result-1 (:result out1) @@ -247,7 +247,7 @@ ;; Run the task again (let [res (task {})] (t/is (= 2 (:freeze res))) - (t/is (= 4 (:delete res)))) + (t/is (= 3 (:delete res)))) ;; now check that there are no touched objects (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object where touched_at is not null"])] @@ -255,7 +255,7 @@ ;; now check that all objects are marked to be deleted (let [res (db/exec-one! th/*pool* ["select count(*) from storage_object where deleted_at is not null"])] - (t/is (= 4 (:count res)))))))) + (t/is (= 3 (:count res)))))))) (t/deftest test-touched-gc-task-3 (let [storage (-> (:app.storage/storage th/*system*) diff --git a/common/src/app/common/geom/matrix.cljc b/common/src/app/common/geom/matrix.cljc index f83f5cca7..b9d8eca19 100644 --- a/common/src/app/common/geom/matrix.cljc +++ b/common/src/app/common/geom/matrix.cljc @@ -14,7 +14,7 @@ [app.common.spec :as us] [clojure.spec.alpha :as s])) -(def precision 3) +(def precision 6) ;; --- Matrix Impl diff --git a/common/src/app/common/uuid.cljc b/common/src/app/common/uuid.cljc index 966ee0cc9..85d3086a7 100644 --- a/common/src/app/common/uuid.cljc +++ b/common/src/app/common/uuid.cljc @@ -11,8 +11,9 @@ #?(:cljs [app.common.uuid-impl :as impl]) #?(:cljs [cljs.core :as c])) #?(:clj (:import + app.common.UUIDv8 java.util.UUID - app.common.UUIDv8))) + java.nio.ByteBuffer))) (def zero #uuid "00000000-0000-0000-0000-000000000000") @@ -50,3 +51,11 @@ (defn get-word-low [id] (.getLeastSignificantBits ^UUID id))) + +#?(:clj + (defn get-bytes + [^UUID o] + (let [buf (ByteBuffer/allocate 16)] + (.putLong buf (.getMostSignificantBits o)) + (.putLong buf (.getLeastSignificantBits o)) + (.array buf)))) diff --git a/frontend/resources/styles/main/layouts/login.scss b/frontend/resources/styles/main/layouts/login.scss index 574343485..b092b7e23 100644 --- a/frontend/resources/styles/main/layouts/login.scss +++ b/frontend/resources/styles/main/layouts/login.scss @@ -11,6 +11,8 @@ display: grid; grid-template-rows: auto; grid-template-columns: 33% auto; + height: 100vh; + overflow-y: scroll; } .auth-sidebar { @@ -53,6 +55,7 @@ height: 100vh; justify-content: center; position: relative; + min-height: 48rem; input { margin-bottom: 0px; diff --git a/frontend/src/app/main/data/shortcuts.cljs b/frontend/src/app/main/data/shortcuts.cljs index f326b8816..ec17b59ae 100644 --- a/frontend/src/app/main/data/shortcuts.cljs +++ b/frontend/src/app/main/data/shortcuts.cljs @@ -93,7 +93,7 @@ [] (if (cf/check-platform? :macos) mac-delete - "Supr")) + "Del")) (defn esc [] diff --git a/frontend/src/app/main/data/workspace/colors.cljs b/frontend/src/app/main/data/workspace/colors.cljs index 9d89abaeb..abe3bd8ac 100644 --- a/frontend/src/app/main/data/workspace/colors.cljs +++ b/frontend/src/app/main/data/workspace/colors.cljs @@ -13,6 +13,7 @@ [app.main.data.modal :as md] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.layout :as layout] + [app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.texts :as dwt] [app.util.color :as uc] @@ -242,7 +243,10 @@ ptk/WatchEvent (watch [_ _ _] (rx/of (dch/update-shapes ids (fn [shape] - (let [new-attrs (merge (get-in shape [:shadow index :color]) attrs)] + (let [;; If we try to set a gradient to a shadow (for example using the color selection from multiple shapes) let's use the first stop color + attrs (cond-> attrs + (:gradient attrs) (get-in [:gradient :stops 0])) + new-attrs (merge (get-in shape [:shadow index :color]) attrs)] (assoc-in shape [:shadow index :color] new-attrs)))))))) (defn add-stroke @@ -487,7 +491,7 @@ (dissoc :stops))))))))) (defn update-colorpicker-color - [changes] + [changes add-recent?] (ptk/reify ::update-colorpicker-color ptk/UpdateEvent (update [_ state] @@ -495,14 +499,22 @@ (fn [state] (let [state (-> state (update :current-color merge changes) - (update :current-color materialize-color-components))] + (update :current-color materialize-color-components) + ;; current color can be a library one I'm changing via colorpicker + (d/dissoc-in [:current-color :id]) + (d/dissoc-in [:current-color :file-id]))] (if-let [stop (:editing-stop state)] (update-in state [:stops stop] (fn [data] (->> changes (merge data) (materialize-color-components)))) (-> state (assoc :type :color) - (dissoc :gradient :stops :editing-stop))))))))) + (dissoc :gradient :stops :editing-stop))))))) + ptk/WatchEvent + (watch [_ state _] + (when add-recent? + (let [formated-color (get-color-from-colorpicker-state (:colorpicker state))] + (rx/of (dwl/add-recent-color formated-color))))))) (defn update-colorpicker-gradient [changes] diff --git a/frontend/src/app/main/ui/dashboard/fonts.cljs b/frontend/src/app/main/ui/dashboard/fonts.cljs index 4b02ac4e1..987c5f190 100644 --- a/frontend/src/app/main/ui/dashboard/fonts.cljs +++ b/frontend/src/app/main/ui/dashboard/fonts.cljs @@ -292,7 +292,7 @@ (mf/use-callback (fn [event] (let [val (dom/get-target-val event)] - (reset! sterm val))))] + (reset! sterm (str/lower val)))))] [:div.dashboard-installed-fonts [:h3 (tr "labels.installed-fonts")] diff --git a/frontend/src/app/main/ui/dashboard/import.cljs b/frontend/src/app/main/ui/dashboard/import.cljs index 4c0fff130..7aed54536 100644 --- a/frontend/src/app/main/ui/dashboard/import.cljs +++ b/frontend/src/app/main/ui/dashboard/import.cljs @@ -347,7 +347,11 @@ success-files (->> @state :files (filter #(and (= (:status %) :import-finish) (empty? (:errors %)))) count) pending-analysis? (> (->> @state :files (filter #(= (:status %) :analyzing)) count) 0) pending-import? (> num-importing 0) - files (->> (:files @state) (filterv (comp not :deleted?)))] + files (->> (:files @state) (filterv (comp not :deleted?))) + ;; pending-import? (> (->> @state :files (filter #(= (:status %) :importing)) count) 0) + ;; files (->> (:files @state) (filterv (comp not :deleted?))) + valid-files? (or (some? template) + (> (+ (->> files (filterv (fn [x] (not= (:status x) :analyze-error))) count)) 0))] (mf/use-effect (fn [] @@ -408,7 +412,7 @@ {:class "primary" :type "button" :value (tr "labels.continue") - :disabled pending-analysis? + :disabled (or pending-analysis? (not valid-files?)) :on-click handle-continue}]) (when (= :importing (:status @state)) @@ -416,5 +420,5 @@ {:class "primary" :type "button" :value (tr "labels.accept") - :disabled pending-import? + :disabled (or pending-import? (not valid-files?)) :on-click handle-accept}])]]]])) diff --git a/frontend/src/app/main/ui/hooks.cljs b/frontend/src/app/main/ui/hooks.cljs index 6fc2c6850..1b9c06105 100644 --- a/frontend/src/app/main/ui/hooks.cljs +++ b/frontend/src/app/main/ui/hooks.cljs @@ -300,13 +300,13 @@ [key default] (let [id (use-id) state (mf/use-state (get @storage key default)) - stream (mf/with-memo [] + stream (mf/with-memo [id] (->> mbc/stream - (rx/filter #(= (:type %) key)) (rx/filter #(not= (:id %) id)) + (rx/filter #(= (:type %) key)) (rx/map deref)))] - (mf/with-effect [@state key] + (mf/with-effect [@state key id] (mbc/emit! id key @state) (swap! storage assoc key @state)) diff --git a/frontend/src/app/main/ui/hooks/mutable_observer.cljs b/frontend/src/app/main/ui/hooks/mutable_observer.cljs index 608894bbe..329efd24c 100644 --- a/frontend/src/app/main/ui/hooks/mutable_observer.cljs +++ b/frontend/src/app/main/ui/hooks/mutable_observer.cljs @@ -27,7 +27,7 @@ (remove #(= "transform" (.-attributeName ^js %))))] (when (d/not-empty? mutations) (on-change (mf/ref-val node-ref)))))) - + set-node (mf/use-callback (mf/deps on-mutation) diff --git a/frontend/src/app/main/ui/onboarding/questions.cljs b/frontend/src/app/main/ui/onboarding/questions.cljs index f08935f07..0ffa76599 100644 --- a/frontend/src/app/main/ui/onboarding/questions.cljs +++ b/frontend/src/app/main/ui/onboarding/questions.cljs @@ -26,7 +26,6 @@ (st/emit! (ptk/event ::ev/event {::ev/name "arengu-form-load-success" ::ev/origin "onboarding-questions" ::ev/type "fact"})) - (resolve))) (p/catch reject)))) @@ -54,9 +53,7 @@ (st/emit! (ptk/event ::ev/event {::ev/name "arengu-form-load-error" ::ev/origin "onboarding-questions" ::ev/type "fact"})) - (mark-as-answered)) - - ] + (mark-as-answered))] (let [cleaners (atom #{})] (-> (p/create (partial initialize cleaners)) diff --git a/frontend/src/app/main/ui/settings/feedback.cljs b/frontend/src/app/main/ui/settings/feedback.cljs index 1550f6d80..8fb14f560 100644 --- a/frontend/src/app/main/ui/settings/feedback.cljs +++ b/frontend/src/app/main/ui/settings/feedback.cljs @@ -96,14 +96,6 @@ {:href "https://twitter.com/PenpotSupport" :target "_blank"} (tr "feedback.twitter-go-to")] - [:hr] - - [:h2 "Gitter"] - [:p (tr "feedback.chat-subtitle")] - [:a.btn-secondary.btn-large - {:href "https://gitter.im/penpot/community" :target "_blank"} - (tr "feedback.chat-start")] - ])) (mf/defc feedback-page diff --git a/frontend/src/app/main/ui/workspace/colorpalette.cljs b/frontend/src/app/main/ui/workspace/colorpalette.cljs index 832ae8239..1a8b194dc 100644 --- a/frontend/src/app/main/ui/workspace/colorpalette.cljs +++ b/frontend/src/app/main/ui/workspace/colorpalette.cljs @@ -36,16 +36,18 @@ (mf/defc palette [{:keys [current-colors recent-colors file-colors shared-libs selected on-select]}] - (let [state (mf/use-state {:show-menu false}) + (let [;; We had to do this due to a bug that leave some bugged colors + current-colors (h/use-equal-memo (filter #(or (:gradient %) (:color %)) current-colors)) + state (mf/use-state {:show-menu false}) - width (:width @state 0) - visible (/ width 66) + width (:width @state 0) + visible (/ width 66) - offset (:offset @state 0) - max-offset (- (count current-colors) - visible) + offset (:offset @state 0) + max-offset (- (count current-colors) + visible) - container (mf/use-ref nil) + container (mf/use-ref nil) {:keys [on-pointer-down on-lost-pointer-capture on-mouse-move parent-ref size]} (use-resize-hook :palette 72 54 80 :y true :bottom) @@ -137,7 +139,7 @@ (tr "workspace.libraries.colors.file-library") (str/ffmt " (%)" (count file-colors)))] [:div.color-sample - (for [[i color] (map-indexed vector (take 7 (vals file-colors))) ] + (for [[i color] (map-indexed vector (take 7 (vals file-colors)))] [:& cb/color-bullet {:key (dm/str "color-" i) :color color}])]] @@ -148,7 +150,7 @@ [:div.library-name (str (tr "workspace.libraries.colors.recent-colors") (str/format " (%s)" (count recent-colors)))] [:div.color-sample - (for [[idx color] (map-indexed vector (take 7 (reverse recent-colors))) ] + (for [[idx color] (map-indexed vector (take 7 (reverse recent-colors)))] [:& cb/color-bullet {:key (str "color-" idx) :color color}])]]]] @@ -183,13 +185,11 @@ on-select (mf/use-fn #(reset! selected %))] (mf/with-effect [@selected] - (fn [] - (reset! colors - (into [] - (cond - (= @selected :recent) (reverse recent-colors) - (= @selected :file) (->> (vals file-colors) (sort-by :name)) - :else (->> (library->colors shared-libs @selected) (sort-by :name))))))) + (let [colors' (cond + (= @selected :recent) (reverse recent-colors) + (= @selected :file) (->> (vals file-colors) (sort-by :name)) + :else (->> (library->colors shared-libs @selected) (sort-by :name)))] + (reset! colors (into [] colors')))) (mf/with-effect [recent-colors @selected] (when (= @selected :recent) diff --git a/frontend/src/app/main/ui/workspace/colorpicker.cljs b/frontend/src/app/main/ui/workspace/colorpicker.cljs index 73634f2d6..2573b464d 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker.cljs @@ -67,11 +67,9 @@ (mf/use-fn (mf/deps @drag?) (fn [color] - (let [recent-color (merge color) + (let [recent-color (merge current-color color) recent-color (dc/materialize-color-components recent-color)] - (when (not @drag?) - (st/emit! (dwl/add-recent-color recent-color))) - (st/emit! (dc/update-colorpicker-color color))))) + (st/emit! (dc/update-colorpicker-color recent-color (not @drag?)))))) handle-click-picker (mf/use-fn diff --git a/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs b/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs index 925f0e455..b9e68a851 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/harmony.cljs @@ -131,6 +131,7 @@ :width canvas-side :height canvas-side :on-pointer-down handle-start-drag + :on-pointer-up handle-stop-drag :on-lost-pointer-capture handle-stop-drag :on-click calculate-pos :on-mouse-move #(when @dragging? (calculate-pos %))}] diff --git a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs index 5c2b5de3b..fa7455792 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/libraries.cljs @@ -7,7 +7,7 @@ (ns app.main.ui.workspace.colorpicker.libraries (:require [app.common.data.macros :as dm] - [app.main.data.workspace.colors :as dc] + [app.main.data.workspace.colors :as mdc] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.color-bullet :refer [color-bullet]] @@ -19,12 +19,13 @@ (mf/defc libraries [{:keys [on-select-color on-add-library-color disable-gradient disable-opacity]}] - (let [selected (h/use-shared-state dc/colorpicker-selected-broadcast-key :recent) + (let [selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent) current-colors (mf/use-state []) shared-libs (mf/deref refs/workspace-libraries) file-colors (mf/deref refs/workspace-file-colors) recent-colors (mf/deref refs/workspace-recent-colors) + recent-colors (h/use-equal-memo (filter #(or (:gradient %) (:color %)) recent-colors)) on-library-change (mf/use-fn @@ -80,7 +81,7 @@ i/plus]) [:div.color-bullet.button {:style {:background-color "var(--color-white)"} - :on-click #(st/emit! (dc/show-palette @selected))} + :on-click #(st/emit! (mdc/show-palette @selected))} i/palette] (for [[idx color] (map-indexed vector @current-colors)] diff --git a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs index 575aafe9f..19ea5e510 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/ramp.cljs @@ -41,6 +41,7 @@ ] [:div.value-saturation-selector {:on-pointer-down handle-start-drag + :on-pointer-up handle-stop-drag :on-lost-pointer-capture handle-stop-drag :on-click calculate-pos :on-mouse-move #(when @dragging? (calculate-pos %))} diff --git a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs index 4454679d0..80739060c 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/slider_selector.cljs @@ -52,6 +52,7 @@ [:div.slider-selector {:class (str (if vertical? "vertical " "") class) :on-pointer-down handle-start-drag + :on-pointer-up handle-stop-drag :on-lost-pointer-capture handle-stop-drag :on-click calculate-pos :on-mouse-move #(when @dragging? (calculate-pos %))} diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index e838e3c9d..c6248642b 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -86,7 +86,7 @@ (when (seq (:touched shape)) " *")]))) (mf/defc layer-item - [{:keys [index item selected objects] :as props}] + [{:keys [index item selected objects sortable?] :as props}] (let [id (:id item) blocked? (:blocked item) hidden? (:hidden item) @@ -199,16 +199,17 @@ (when-not expanded? (st/emit! (dwc/toggle-collapse id))))) - [dprops dref] (hooks/use-sortable - :data-type "penpot/layer" - :on-drop on-drop - :on-drag on-drag - :on-hold on-hold - :disabled @disable-drag - :detect-center? container? - :data {:id (:id item) - :index index - :name (:name item)}) + [dprops dref] (when sortable? + (hooks/use-sortable + :data-type "penpot/layer" + :on-drop on-drop + :on-drag on-drag + :on-hold on-hold + :disabled @disable-drag + :detect-center? container? + :data {:id (:id item) + :index index + :name (:name item)})) ref (mf/use-ref)] @@ -309,13 +310,15 @@ :selected selected :index index :objects objects - :key id}] + :key id + :sortable? true}] [:& layer-item {:item obj :selected selected :index index :objects objects - :key id}])))]])) + :key id + :sortable? true}])))]])) (mf/defc filters-tree {::mf/wrap [#(mf/memo % =) @@ -332,7 +335,8 @@ :selected selected :index index :objects objects - :key id}]))])) + :key id + :sortable? false}]))])) (defn calc-reparented-objects diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs index 1cb8cc283..c7d008629 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs @@ -10,7 +10,9 @@ [app.common.data.macros :as dm] [app.common.pages :as cp] [app.main.data.modal :as modal] + [app.main.data.workspace.libraries :as dwl] [app.main.refs :as refs] + [app.main.store :as st] [app.main.ui.components.color-bullet :as cb] [app.main.ui.components.color-input :refer [color-input]] [app.main.ui.components.numeric-input :refer [numeric-input]] @@ -73,18 +75,22 @@ (mf/use-fn (mf/deps color on-change) (fn [new-value] - (on-change (-> color - (assoc :color new-value) - (dissoc :gradient))))) + (let [color (-> color + (assoc :color new-value) + (dissoc :gradient))] + (st/emit! (dwl/add-recent-color color) + (on-change color))))) handle-opacity-change (mf/use-fn (mf/deps color on-change) (fn [value] - (on-change (assoc color - :opacity (/ value 100) - :id nil - :file-id nil)))) + (let [color (assoc color + :opacity (/ value 100) + :id nil + :file-id nil)] + (st/emit! (dwl/add-recent-color color) + (on-change color))))) handle-click-color (mf/use-fn diff --git a/frontend/src/app/worker/import.cljs b/frontend/src/app/worker/import.cljs index 073cf81a0..f7610e0cd 100644 --- a/frontend/src/app/worker/import.cljs +++ b/frontend/src/app/worker/import.cljs @@ -19,6 +19,7 @@ [app.common.uuid :as uuid] [app.main.repo :as rp] [app.util.http :as http] + [app.util.i18n :as i18n :refer [tr]] [app.util.import.parser :as cip] [app.util.json :as json] [app.util.webapi :as wapi] @@ -584,7 +585,8 @@ sg (areduce u8 i ret "" (str ret (if (zero? i) "" " ") (.toString (aget u8 i) 8)))] (case sg "120 113 3 4" "application/zip" - "application/octet-stream"))) + "1 13 32 206" "application/octet-stream" + "other"))) (defmethod impl/handler :analyze-import [{:keys [files]}] @@ -618,8 +620,15 @@ :file-id file-id :files {file-id {:name (:name file)}} :status :ready} - :type "application/octet-stream"}))))) - (rx/catch #(rx/of {:uri (:uri file) :error (.-message %)})))))))) + :type "application/octet-stream"})))) + (->> st + (rx/filter (fn [data] (= "other" (:type data)))) + (rx/map (fn [_] + {:uri (:uri file) + :error (tr "dashboard.import.analyze-error")})))) + (rx/catch (fn [data] + (let [error (or (.-message data) (tr "dashboard.import.analyze-error"))] + (rx/of {:uri (:uri file) :error error})))))))))) (defmethod impl/handler :import-files [{:keys [project-id files components-v2]}]