From 4690f740b9352e7d8f87498477de3247ac941ac8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 1 Dec 2025 13:18:56 +0100 Subject: [PATCH 01/23] :sparkles: Add minor improvements to the audit module --- backend/src/app/loggers/audit.clj | 70 +++++++++++++++++---------- frontend/src/app/main/data/event.cljs | 2 +- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/backend/src/app/loggers/audit.clj b/backend/src/app/loggers/audit.clj index 9471f5dad4..7d64b768b0 100644 --- a/backend/src/app/loggers/audit.clj +++ b/backend/src/app/loggers/audit.clj @@ -79,18 +79,6 @@ (remove #(contains? reserved-props (key %)))) props)) -(defn event-from-rpc-params - "Create a base event skeleton with pre-filled some important - data that can be extracted from RPC params object" - [params] - (let [context {:external-session-id (::rpc/external-session-id params) - :external-event-origin (::rpc/external-event-origin params) - :triggered-by (::rpc/handler-name params)}] - {::type "action" - ::profile-id (::rpc/profile-id params) - ::ip-addr (::rpc/ip-addr params) - ::context (d/without-nils context)})) - (defn get-external-session-id [request] (when-let [session-id (yreq/get-header request "x-external-session-id")] @@ -99,13 +87,24 @@ (str/blank? session-id)) session-id))) -(defn- get-external-event-origin +(defn- get-client-event-origin [request] (when-let [origin (yreq/get-header request "x-event-origin")] - (when-not (or (> (count origin) 256) - (= origin "null") + (when-not (or (= origin "null") (str/blank? origin)) - origin))) + (str/prune origin 200)))) + +(defn get-client-user-agent + [request] + (when-let [user-agent (yreq/get-header request "user-agent")] + (str/prune user-agent 500))) + +(defn- get-client-version + [request] + (when-let [origin (yreq/get-header request "x-frontend-version")] + (when-not (or (= origin "null") + (str/blank? origin)) + (str/prune origin 100)))) ;; --- SPECS @@ -134,6 +133,33 @@ (def ^:private check-event (sm/check-fn schema:event)) +(defn- prepare-context-from-request + [request] + (let [client-event-origin (get-client-event-origin request) + client-version (get-client-version request) + client-user-agent (get-client-user-agent request) + session-id (get-external-session-id request) + token-id (::actoken/id request)] + (d/without-nils + {:external-session-id session-id + :access-token-id (some-> token-id str) + :client-event-origin client-event-origin + :client-user-agent client-user-agent + :client-version client-version + :version (:full cf/version)}))) + +(defn event-from-rpc-params + "Create a base event skeleton with pre-filled some important + data that can be extracted from RPC params object" + [params] + (let [context (some-> params meta ::http/request prepare-context-from-request) + event {::type "action" + ::profile-id (or (::rpc/profile-id params) uuid/zero) + ::ip-addr (::rpc/ip-addr params)}] + (cond-> event + (some? context) + (assoc ::context context)))) + (defn prepare-event [cfg mdata params result] (let [resultm (meta result) @@ -148,18 +174,10 @@ (merge (::props resultm)) (dissoc :profile-id) (dissoc :type))) - (clean-props)) - token-id (::actoken/id request) - context (-> (::context resultm) - (assoc :external-session-id - (get-external-session-id request)) - (assoc :external-event-origin - (get-external-event-origin request)) - (assoc :access-token-id (some-> token-id str)) - (d/without-nils)) - + context (merge (::context resultm) + (prepare-context-from-request request)) ip-addr (inet/parse-request request)] {::type (or (::type resultm) diff --git a/frontend/src/app/main/data/event.cljs b/frontend/src/app/main/data/event.cljs index dfba7479ef..4e2fc316e3 100644 --- a/frontend/src/app/main/data/event.cljs +++ b/frontend/src/app/main/data/event.cljs @@ -67,7 +67,7 @@ [] (let [uagent (new ua/UAParser)] (merge - {:app-version (:full cf/version) + {:version (:full cf/version) :locale @i18n/locale} (let [browser (.getBrowser uagent)] {:browser (obj/get browser "name") From 95b7784a422624ac2bcb665c178cabd725991449 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 1 Dec 2025 14:19:02 +0100 Subject: [PATCH 02/23] :bug: Change internal ordering on how email parts are assembled This fixes the html email rendering on gmail. Other clients (like proton, emailcatcher) properly renders html independently of the order of parts on the multipart email structure but gmail requires that html should be the last one. --- backend/src/app/email.clj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/app/email.clj b/backend/src/app/email.clj index 91563b4d95..43361039d9 100644 --- a/backend/src/app/email.clj +++ b/backend/src/app/email.clj @@ -106,17 +106,17 @@ (let [content-part (MimeBodyPart.) alternative-mpart (MimeMultipart. "alternative")] + (when-let [content (get body "text/plain")] + (let [text-part (MimeBodyPart.)] + (.setText text-part ^String content ^String charset) + (.addBodyPart alternative-mpart text-part))) + (when-let [content (get body "text/html")] (let [html-part (MimeBodyPart.)] (.setContent html-part ^String content (str "text/html; charset=" charset)) (.addBodyPart alternative-mpart html-part))) - (when-let [content (get body "text/plain")] - (let [text-part (MimeBodyPart.)] - (.setText text-part ^String content ^String charset) - (.addBodyPart alternative-mpart text-part))) - (.setContent content-part alternative-mpart) (.addBodyPart mixed-mpart content-part)) From a28c5b61ca7f8e1d0c9697bd907bc10df71a96a2 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 3 Dec 2025 08:09:13 +0100 Subject: [PATCH 03/23] :lipstick: Adapt viewport paste code codestyle And remove some not necessary constructions --- .../src/app/main/ui/workspace/viewport.cljs | 14 +++---- .../main/ui/workspace/viewport/actions.cljs | 31 ++++++++------- .../app/main/ui/workspace/viewport/hooks.cljs | 39 ++++++++----------- .../app/main/ui/workspace/viewport_wasm.cljs | 14 +++---- 4 files changed, 47 insertions(+), 51 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index f27ca272e5..7d08054fb4 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -149,9 +149,9 @@ canvas-ref (mf/use-ref nil) - ;; VARS - disable-paste (mf/use-var false) - in-viewport? (mf/use-var false) + ;; STATE REFS + disable-paste-ref (mf/use-ref false) + in-viewport-ref (mf/use-ref false) ;; STREAMS move-stream (mf/use-memo #(rx/subject)) @@ -210,10 +210,10 @@ on-pointer-down (actions/on-pointer-down @hover selected edition drawing-tool text-editing? path-editing? grid-editing? path-drawing? create-comment? space? panning z? read-only?) - on-pointer-up (actions/on-pointer-up disable-paste) + on-pointer-up (actions/on-pointer-up disable-paste-ref) - on-pointer-enter (actions/on-pointer-enter in-viewport?) - on-pointer-leave (actions/on-pointer-leave in-viewport?) + on-pointer-enter (actions/on-pointer-enter in-viewport-ref) + on-pointer-leave (actions/on-pointer-leave in-viewport-ref) on-pointer-move (actions/on-pointer-move move-stream) on-move-selected (actions/on-move-selected hover hover-ids selected space? z? read-only?) on-menu-selected (actions/on-menu-selected hover hover-ids selected read-only?) @@ -304,7 +304,7 @@ #(st/emit! (dwv/add-new-variant (:id first-shape))))] - (hooks/setup-dom-events zoom disable-paste in-viewport? read-only? drawing-tool path-drawing?) + (hooks/setup-dom-events zoom disable-paste-ref in-viewport-ref read-only? drawing-tool path-drawing?) (hooks/setup-viewport-size vport viewport-ref) (hooks/setup-cursor cursor alt? mod? space? panning drawing-tool path-drawing? path-editing? z? read-only?) (hooks/setup-keyboard alt? mod? space? z? shift?) diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs index 56c70d1748..4d3c6123e2 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -266,7 +266,7 @@ (st/emit! (dw/show-shape-context-menu {:position position :hover-ids @hover-ids}))))))) (defn on-pointer-up - [disable-paste] + [disable-paste-ref] (mf/use-callback (fn [event] (dom/stop-propagation event) @@ -291,21 +291,19 @@ (dom/prevent-default event) ;; We store this so in Firefox the middle button won't do a paste of the content - (reset! disable-paste true) - (ts/schedule #(reset! disable-paste false))) + (mf/set-ref-val! disable-paste-ref true) + (ts/schedule #(mf/set-ref-val! disable-paste-ref false))) (st/emit! (dw/finish-panning) (dw/finish-zooming)))))) -(defn on-pointer-enter [in-viewport?] - (mf/use-callback - (fn [] - (reset! in-viewport? true)))) +(defn on-pointer-enter + [in-viewport-ref] + (mf/use-fn #(mf/set-ref-val! in-viewport-ref true))) -(defn on-pointer-leave [in-viewport?] - (mf/use-callback - (fn [] - (reset! in-viewport? false)))) +(defn on-pointer-leave + [in-viewport-ref] + (mf/use-fn #(mf/set-ref-val! in-viewport-ref false))) (defn on-key-down [] (mf/use-callback @@ -525,14 +523,17 @@ (st/emit! (dwm/upload-media-workspace params)))))))) (defn on-paste - [disable-paste in-viewport? read-only?] + [disable-paste-ref in-viewport-ref read-only?] (mf/use-fn (mf/deps read-only?) (fn [event] ;; We disable the paste just after mouse-up of a middle button so ;; when panning won't paste the content into the workspace - (let [tag-name (-> event dom/get-target dom/get-tag-name)] + (let [tag-name (-> event dom/get-target dom/get-tag-name) + disable-paste? (mf/ref-val disable-paste-ref) + in-viewport? (mf/ref-val in-viewport-ref)] + (when (and (not (#{"INPUT" "TEXTAREA"} tag-name)) - (not @disable-paste) + (not disable-paste?) (not read-only?)) - (st/emit! (dw/paste-from-event event @in-viewport?))))))) + (st/emit! (dw/paste-from-event event in-viewport?))))))) diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index 230abf8a28..8f00ca0031 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -42,11 +42,12 @@ [rumext.v2 :as mf]) (:import goog.events.EventType)) -(defn setup-dom-events [zoom disable-paste in-viewport? workspace-read-only? drawing-tool drawing-path?] +(defn setup-dom-events + [zoom disable-paste-ref in-viewport-ref workspace-read-only? drawing-tool drawing-path?] (let [on-key-down (actions/on-key-down) on-key-up (actions/on-key-up) on-mouse-wheel (actions/on-mouse-wheel zoom) - on-paste (actions/on-paste disable-paste in-viewport? workspace-read-only?) + on-paste (actions/on-paste disable-paste-ref in-viewport-ref workspace-read-only?) on-pointer-down (mf/use-fn (mf/deps drawing-tool drawing-path?) (fn [e] @@ -56,27 +57,21 @@ (st/emit! (dwe/clear-edition-mode)))))) on-blur (mf/use-fn #(st/emit! (mse/->BlurEvent)))] - (mf/use-effect - (mf/deps drawing-tool drawing-path?) - (fn [] - (let [keys [(events/listen js/window EventType.POINTERDOWN on-pointer-down)]] - (fn [] - (doseq [key keys] - (events/unlistenByKey key)))))) + (mf/with-effect [drawing-tool drawing-path?] + (let [key (events/listen js/window EventType.POINTERDOWN on-pointer-down)] + #(events/unlistenByKey key))) - (mf/use-layout-effect - (mf/deps on-key-down on-key-up on-mouse-wheel on-paste workspace-read-only?) - (fn [] - (let [keys [(events/listen js/document EventType.KEYDOWN on-key-down) - (events/listen js/document EventType.KEYUP on-key-up) - ;; bind with passive=false to allow the event to be cancelled - ;; https://stackoverflow.com/a/57582286/3219895 - (events/listen js/window EventType.WHEEL on-mouse-wheel #js {:passive false}) - (events/listen js/window EventType.PASTE on-paste) - (events/listen js/window EventType.BLUR on-blur)]] - (fn [] - (doseq [key keys] - (events/unlistenByKey key)))))))) + (mf/with-layout-effect [on-key-down on-key-up on-mouse-wheel on-paste workspace-read-only?] + (let [keys [(events/listen js/document EventType.KEYDOWN on-key-down) + (events/listen js/document EventType.KEYUP on-key-up) + ;; bind with passive=false to allow the event to be cancelled + ;; https://stackoverflow.com/a/57582286/3219895 + (events/listen js/window EventType.WHEEL on-mouse-wheel #js {:passive false}) + (events/listen js/window EventType.PASTE on-paste) + (events/listen js/window EventType.BLUR on-blur)]] + (fn [] + (doseq [key keys] + (events/unlistenByKey key))))))) (defn setup-viewport-size [vport viewport-ref] (mf/with-effect [vport] diff --git a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs index 54dde7688d..acb1f51de0 100644 --- a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs +++ b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs @@ -142,9 +142,9 @@ canvas-ref (mf/use-ref nil) text-editor-ref (mf/use-ref nil) - ;; VARS - disable-paste (mf/use-var false) - in-viewport? (mf/use-var false) + ;; STATE REFS + disable-paste-ref (mf/use-ref false) + in-viewport-ref (mf/use-ref false) ;; STREAMS move-stream (mf/use-memo #(rx/subject)) @@ -204,10 +204,10 @@ on-pointer-down (actions/on-pointer-down @hover selected edition drawing-tool text-editing? path-editing? grid-editing? path-drawing? create-comment? space? panning z? read-only?) - on-pointer-up (actions/on-pointer-up disable-paste) + on-pointer-up (actions/on-pointer-up disable-paste-ref) - on-pointer-enter (actions/on-pointer-enter in-viewport?) - on-pointer-leave (actions/on-pointer-leave in-viewport?) + on-pointer-enter (actions/on-pointer-enter in-viewport-ref) + on-pointer-leave (actions/on-pointer-leave in-viewport-ref) on-pointer-move (actions/on-pointer-move move-stream) on-move-selected (actions/on-move-selected hover hover-ids selected space? z? read-only?) on-menu-selected (actions/on-menu-selected hover hover-ids selected read-only?) @@ -349,7 +349,7 @@ (wasm.api/show-grid @hover-top-frame-id) (wasm.api/clear-grid)))) - (hooks/setup-dom-events zoom disable-paste in-viewport? read-only? drawing-tool path-drawing?) + (hooks/setup-dom-events zoom disable-paste-ref in-viewport-ref read-only? drawing-tool path-drawing?) (hooks/setup-viewport-size vport viewport-ref) (hooks/setup-cursor cursor alt? mod? space? panning drawing-tool path-drawing? path-editing? z? read-only?) (hooks/setup-keyboard alt? mod? space? z? shift?) From 58f82da61eb3fc7314b786b399340b7f8202bf1b Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 3 Dec 2025 08:20:58 +0100 Subject: [PATCH 04/23] :bug: Fix exception on paste text on comments input --- .../src/app/main/ui/workspace/viewport/actions.cljs | 12 ++++++++---- .../src/app/main/ui/workspace/viewport/hooks.cljs | 6 ++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs index 4d3c6123e2..902c8f860b 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -522,18 +522,22 @@ :blobs (seq files)}] (st/emit! (dwm/upload-media-workspace params)))))))) +(def ^:private invalid-paste-targets + #{"INPUT" "TEXTAREA"}) + (defn on-paste [disable-paste-ref in-viewport-ref read-only?] (mf/use-fn (mf/deps read-only?) (fn [event] - ;; We disable the paste just after mouse-up of a middle button so - ;; when panning won't paste the content into the workspace + ;; We disable the paste when: 1. just after mouse-up of a middle + ;; button (so when panning won't paste the content into the + ;; workspace); 2. when we paste content in an input on the + ;; sidebar (let [tag-name (-> event dom/get-target dom/get-tag-name) disable-paste? (mf/ref-val disable-paste-ref) in-viewport? (mf/ref-val in-viewport-ref)] - - (when (and (not (#{"INPUT" "TEXTAREA"} tag-name)) + (when (and (not (contains? invalid-paste-targets tag-name)) (not disable-paste?) (not read-only?)) (st/emit! (dw/paste-from-event event in-viewport?))))))) diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index 8f00ca0031..922e18057d 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -59,6 +59,12 @@ (mf/with-effect [drawing-tool drawing-path?] (let [key (events/listen js/window EventType.POINTERDOWN on-pointer-down)] + + ;; We need to disable workspace paste when we on comments + (if (= drawing-tool :comments) + (mf/set-ref-val! disable-paste-ref true) + (mf/set-ref-val! disable-paste-ref false)) + #(events/unlistenByKey key))) (mf/with-layout-effect [on-key-down on-key-up on-mouse-wheel on-paste workspace-read-only?] From 57fcec5afcb2297b649825890e7ec82f2092a1c1 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 3 Dec 2025 08:32:38 +0100 Subject: [PATCH 05/23] :bug: Make from-synthetic-clipboard-event function return always a stream Causes an execption on steam processing when it returns nil --- frontend/src/app/util/clipboard.cljs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/util/clipboard.cljs b/frontend/src/app/util/clipboard.cljs index e70c567881..92729e5ec4 100644 --- a/frontend/src/app/util/clipboard.cljs +++ b/frontend/src/app/util/clipboard.cljs @@ -57,10 +57,11 @@ (= (dom/get-tag-name target) "INPUT")] ;; ignore when pasting into an editable control - (when-not (or content-editable? is-input?) + (if-not (or content-editable? is-input?) (-> event (dom/event->browser-event) - (from-clipboard-event options)))))) + (from-clipboard-event options)) + (rx/empty))))) (defn from-drop-event "Get clipboard stream from drop event" From 5ef06685fc5a4ab86953fe6900ea9390f2e05ae4 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 3 Dec 2025 09:38:23 +0100 Subject: [PATCH 06/23] :lipstick: Add cosmetic improvements to workspace palette component --- frontend/src/app/main/ui/workspace.cljs | 6 +- .../src/app/main/ui/workspace/palette.cljs | 71 +++++++++++-------- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index 4125e47b99..cec1ca975f 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -27,7 +27,7 @@ [app.main.ui.workspace.coordinates :as coordinates] [app.main.ui.workspace.libraries] [app.main.ui.workspace.nudge] - [app.main.ui.workspace.palette :refer [palette]] + [app.main.ui.workspace.palette :refer [palette*]] [app.main.ui.workspace.plugins] [app.main.ui.workspace.sidebar :refer [sidebar*]] [app.main.ui.workspace.sidebar.history :refer [history-toolbox*]] @@ -84,8 +84,8 @@ node-ref (use-resize-observer on-resize)] [:* (when (not ^boolean hide-ui?) - [:& palette {:layout layout - :on-change-palette-size on-resize-palette}]) + [:> palette* {:layout layout + :on-change-size on-resize-palette}]) [:section {:key (dm/str "workspace-" page-id) diff --git a/frontend/src/app/main/ui/workspace/palette.cljs b/frontend/src/app/main/ui/workspace/palette.cljs index 43f7b5e4e4..da670897d4 100644 --- a/frontend/src/app/main/ui/workspace/palette.cljs +++ b/frontend/src/app/main/ui/workspace/palette.cljs @@ -33,10 +33,11 @@ [okulary.core :as l] [rumext.v2 :as mf])) -(def viewport +(def ^:private ref:viewport (l/derived :vport refs/workspace-local)) -(defn calculate-palette-padding [rulers?] +(defn- calculate-palette-style + [rulers?] (let [left-sidebar (dom/get-element "left-sidebar-aside") left-sidebar-size (-> (dom/get-data left-sidebar "left-sidebar-width") (d/parse-integer)) @@ -48,36 +49,46 @@ #js {"paddingLeft" (dm/str calculate-padding-left "px") "paddingRight" "322px"})) -(mf/defc palette - [{:keys [layout on-change-palette-size]}] - (let [color-palette? (:colorpalette layout) - text-palette? (:textpalette layout) - hide-palettes? (:hide-palettes layout) - workspace-read-only? (mf/use-ctx ctx/workspace-read-only?) - container (mf/use-ref nil) - state* (mf/use-state {:show-menu false}) - state (deref state*) - show-menu? (:show-menu state) - selected (h/use-shared-state mdc/colorpalette-selected-broadcast-key :recent) - selected-text* (mf/use-state :file) - selected-text (deref selected-text*) - on-select (mf/use-fn #(reset! selected %)) - rulers? (mf/deref refs/rulers?) - {:keys [on-pointer-down on-lost-pointer-capture on-pointer-move parent-ref size]} - (r/use-resize-hook :palette 72 54 80 :y true :bottom on-change-palette-size) +(mf/defc palette* + [{:keys [layout on-change-size]}] + (let [color-palette? (:colorpalette layout) + text-palette? (:textpalette layout) + hide-palettes? (:hide-palettes layout) - vport (mf/deref viewport) - vport-width (:width vport) + read-only? (mf/use-ctx ctx/workspace-read-only?) + container (mf/use-ref nil) + + state* (mf/use-state #(-> {:show-menu false})) + state (deref state*) + show-menu? (:show-menu state) + + selected (h/use-shared-state mdc/colorpalette-selected-broadcast-key :recent) + + selected-text* (mf/use-state :file) + selected-text (deref selected-text*) + + on-select (mf/use-fn #(reset! selected %)) + + rulers? (mf/deref refs/rulers?) + vport (mf/deref ref:viewport) + vport-width (get vport :width) + + {:keys [on-pointer-down + on-lost-pointer-capture + on-pointer-move + parent-ref + size]} + (r/use-resize-hook :palette 72 54 80 :y true :bottom on-change-size) on-resize - (mf/use-callback + (mf/use-fn (fn [_] (let [dom (mf/ref-val container) width (obj/get dom "clientWidth")] (swap! state* assoc :width width)))) on-close-menu - (mf/use-callback + (mf/use-fn (fn [_] (swap! state* assoc :show-menu false))) @@ -100,7 +111,7 @@ (reset! selected-text* (:id lib))))) toggle-palettes - (mf/use-callback + (mf/use-fn (fn [_] (r/set-resize-type! :top) (dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down") @@ -131,7 +142,9 @@ (vary-meta assoc ::ev/origin "workspace-left-toolbar")))) (dom/blur! node)))) - any-palette? (or color-palette? text-palette?) + any-palette? + (or color-palette? text-palette?) + size-classname (cond (<= size 64) (stl/css :small-palette) @@ -142,16 +155,16 @@ (let [key1 (events/listen js/window "resize" on-resize)] #(events/unlistenByKey key1))) - (mf/use-layout-effect - #(let [dom (mf/ref-val parent-ref) + (mf/with-layout-effect [] + (let [dom (mf/ref-val parent-ref) width (obj/get dom "clientWidth")] (swap! state* assoc :width width))) [:div {:class (stl/css :palette-wrapper) :id "palette-wrapper" - :style (calculate-palette-padding rulers?) + :style (calculate-palette-style rulers?) :data-testid "palette"} - (when-not workspace-read-only? + (when-not ^boolean read-only? [:div {:ref parent-ref :class (dm/str size-classname " " (stl/css-case :palettes true :wide any-palette? From feababe2a859c848c35654d6b4818b3226f32855 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 3 Dec 2025 09:56:14 +0100 Subject: [PATCH 07/23] :bug: Make workspace palette reposition on left sidebar collapse --- .../workspace/colorpicker/color_tokens.cljs | 2 +- .../src/app/main/ui/workspace/palette.cljs | 2 +- .../src/app/main/ui/workspace/sidebar.cljs | 27 ++++++++--- .../src/app/main/ui/workspace/sidebar.scss | 38 ++++++++++++++++ .../workspace/sidebar/collapsable_button.cljs | 29 ------------ .../workspace/sidebar/collapsable_button.scss | 45 ------------------- 6 files changed, 61 insertions(+), 82 deletions(-) delete mode 100644 frontend/src/app/main/ui/workspace/sidebar/collapsable_button.cljs delete mode 100644 frontend/src/app/main/ui/workspace/sidebar/collapsable_button.scss diff --git a/frontend/src/app/main/ui/workspace/colorpicker/color_tokens.cljs b/frontend/src/app/main/ui/workspace/colorpicker/color_tokens.cljs index 78c9d7d884..61871dfcdd 100644 --- a/frontend/src/app/main/ui/workspace/colorpicker/color_tokens.cljs +++ b/frontend/src/app/main/ui/workspace/colorpicker/color_tokens.cljs @@ -156,7 +156,7 @@ (let [{:keys [modal title]} (get dwta/token-properties :color) window-size (dom/get-window-size) left-sidebar (dom/get-element "left-sidebar-aside") - x-size (dom/get-data left-sidebar "left-sidebar-width") + x-size (dom/get-data left-sidebar "width") modal-height 392 x (- (int x-size) 30) y (- (/ (:height window-size) 2) (/ modal-height 2))] diff --git a/frontend/src/app/main/ui/workspace/palette.cljs b/frontend/src/app/main/ui/workspace/palette.cljs index da670897d4..80c396989e 100644 --- a/frontend/src/app/main/ui/workspace/palette.cljs +++ b/frontend/src/app/main/ui/workspace/palette.cljs @@ -39,7 +39,7 @@ (defn- calculate-palette-style [rulers?] (let [left-sidebar (dom/get-element "left-sidebar-aside") - left-sidebar-size (-> (dom/get-data left-sidebar "left-sidebar-width") + left-sidebar-size (-> (dom/get-data left-sidebar "width") (d/parse-integer)) rulers-width (if rulers? 22 0) min-left-sidebar-width left-sidebar-default-width diff --git a/frontend/src/app/main/ui/workspace/sidebar.cljs b/frontend/src/app/main/ui/workspace/sidebar.cljs index a9733567d7..58f299f666 100644 --- a/frontend/src/app/main/ui/workspace/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar.cljs @@ -27,7 +27,6 @@ [app.main.ui.workspace.left-header :refer [left-header*]] [app.main.ui.workspace.right-header :refer [right-header*]] [app.main.ui.workspace.sidebar.assets :refer [assets-toolbox*]] - [app.main.ui.workspace.sidebar.collapsable-button :refer [collapsed-button*]] [app.main.ui.workspace.sidebar.debug :refer [debug-panel*]] [app.main.ui.workspace.sidebar.debug-shape-info :refer [debug-shape-info*]] [app.main.ui.workspace.sidebar.history :refer [history-toolbox*]] @@ -44,19 +43,34 @@ ;; --- Left Sidebar (Component) -(defn- on-collapse-left-sidebar - [] - (st/emit! (dw/toggle-layout-flag :collapse-left-sidebar))) +(def ^:private toggle-collapse-left-sidebar + (partial st/emit! (dw/toggle-layout-flag :collapse-left-sidebar))) (mf/defc collapse-button* + {::mf/private true} [] ;; NOTE: This custom button may be replace by an action button when this variant is designed [:button {:class (stl/css :collapse-sidebar-button) - :on-click on-collapse-left-sidebar} + :on-click toggle-collapse-left-sidebar} [:> icon* {:icon-id i/arrow :size "s" :aria-label (tr "workspace.sidebar.collapse")}]]) +(mf/defc collapsed-button* + {::mf/memo true + ::mf/private true} + [] + [:div {:id "left-sidebar-aside" + :data-width "0" + :class (stl/css :collapsed-sidebar)} + [:div {:class (stl/css :collapsed-title)} + [:button {:class (stl/css :collapsed-button) + :title (tr "workspace.sidebar.expand") + :on-click toggle-collapse-left-sidebar} + [:> icon* {:icon-id i/arrow + :size "s" + :aria-label (tr "workspace.sidebar.expand")}]]]]) + (mf/defc layers-content* {::mf/private true ::mf/memo true} @@ -97,6 +111,7 @@ [:> layers-toolbox* {:size-parent width}]])) + (mf/defc left-sidebar* {::mf/memo true} [{:keys [layout file page-id tokens-lib active-tokens resolved-active-tokens]}] @@ -161,7 +176,7 @@ [:aside {:ref parent-ref :id "left-sidebar-aside" :data-testid "left-sidebar" - :data-left-sidebar-width (str width) + :data-width (str width) :class aside-class :style {:--left-sidebar-width (dm/str width "px")}} diff --git a/frontend/src/app/main/ui/workspace/sidebar.scss b/frontend/src/app/main/ui/workspace/sidebar.scss index 3c6871e784..acceaf4f7d 100644 --- a/frontend/src/app/main/ui/workspace/sidebar.scss +++ b/frontend/src/app/main/ui/workspace/sidebar.scss @@ -116,6 +116,44 @@ } } +.collapsed-sidebar { + @include deprecated.flexCenter; + position: absolute; + top: deprecated.$s-48; + left: 0; + padding: deprecated.$s-4; + border-radius: deprecated.$br-8; + background: var(--color-background-primary); + margin-inline-start: var(--sp-m); +} +.collapsed-title { + @include deprecated.flexCenter; + height: deprecated.$s-36; + width: deprecated.$s-24; + border-radius: deprecated.$br-8; + background: var(--color-background-secondary); +} +.collapsed-button { + @include deprecated.buttonStyle; + height: deprecated.$s-24; + width: deprecated.$s-16; + padding: 0; + border-radius: deprecated.$br-5; + svg { + @include deprecated.flexCenter; + height: deprecated.$s-16; + width: deprecated.$s-16; + color: transparent; + fill: none; + stroke: var(--icon-foreground); + } + &:hover { + svg { + stroke: var(--icon-foreground-hover); + } + } +} + .versions-tab { width: 100%; overflow: hidden; diff --git a/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.cljs b/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.cljs deleted file mode 100644 index 8d6160c147..0000000000 --- a/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.cljs +++ /dev/null @@ -1,29 +0,0 @@ -;; 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.main.ui.workspace.sidebar.collapsable-button - (:require-macros [app.main.style :as stl]) - (:require - [app.main.data.workspace :as dw] - [app.main.store :as st] - [app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i] - [app.util.i18n :refer [tr]] - [rumext.v2 :as mf])) - -(mf/defc collapsed-button* - {::mf/memo true} - [] - (let [on-click (mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))] - [:div {:id "left-sidebar-aside" - :data-size "0" - :class (stl/css :collapsed-sidebar)} - [:div {:class (stl/css :collapsed-title)} - [:button {:class (stl/css :collapsed-button) - :title (tr "workspace.sidebar.expand") - :on-click on-click} - [:> icon* {:icon-id i/arrow - :size "s" - :aria-label (tr "workspace.sidebar.expand")}]]]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.scss b/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.scss deleted file mode 100644 index 9d2f6156f5..0000000000 --- a/frontend/src/app/main/ui/workspace/sidebar/collapsable_button.scss +++ /dev/null @@ -1,45 +0,0 @@ -// 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 - -@use "refactor/common-refactor.scss" as deprecated; - -.collapsed-sidebar { - @include deprecated.flexCenter; - position: absolute; - top: deprecated.$s-48; - left: 0; - padding: deprecated.$s-4; - border-radius: deprecated.$br-8; - background: var(--color-background-primary); - margin-inline-start: var(--sp-m); -} -.collapsed-title { - @include deprecated.flexCenter; - height: deprecated.$s-36; - width: deprecated.$s-24; - border-radius: deprecated.$br-8; - background: var(--color-background-secondary); -} -.collapsed-button { - @include deprecated.buttonStyle; - height: deprecated.$s-24; - width: deprecated.$s-16; - padding: 0; - border-radius: deprecated.$br-5; - svg { - @include deprecated.flexCenter; - height: deprecated.$s-16; - width: deprecated.$s-16; - color: transparent; - fill: none; - stroke: var(--icon-foreground); - } - &:hover { - svg { - stroke: var(--icon-foreground-hover); - } - } -} From 94af978be8401965ef1393359d07312c38d37bde Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 3 Dec 2025 10:22:45 +0100 Subject: [PATCH 08/23] :bug: Fix casing on a translation of export files modal option --- frontend/translations/ca.po | 2 +- frontend/translations/cs.po | 2 +- frontend/translations/en.po | 2 +- frontend/translations/es.po | 2 +- frontend/translations/eu.po | 2 +- frontend/translations/gl.po | 2 +- frontend/translations/ha.po | 2 +- frontend/translations/hr.po | 2 +- frontend/translations/id.po | 2 +- frontend/translations/lt.po | 2 +- frontend/translations/lv.po | 2 +- frontend/translations/ms.po | 2 +- frontend/translations/pl.po | 2 +- frontend/translations/pt_BR.po | 2 +- frontend/translations/pt_PT.po | 2 +- frontend/translations/ro.po | 2 +- frontend/translations/sr.po | 2 +- frontend/translations/sv.po | 2 +- frontend/translations/tr.po | 2 +- frontend/translations/ukr_UA.po | 2 +- 20 files changed, 20 insertions(+), 20 deletions(-) diff --git a/frontend/translations/ca.po b/frontend/translations/ca.po index a1b1add7bb..986f9364d5 100644 --- a/frontend/translations/ca.po +++ b/frontend/translations/ca.po @@ -392,7 +392,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"els fitxers amb biblioteques compartides s’inclouran a l’exportació, " +"Els fitxers amb biblioteques compartides s’inclouran a l’exportació, " "mantenint la vinculació." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/cs.po b/frontend/translations/cs.po index a6385aa048..7ba4527bd7 100644 --- a/frontend/translations/cs.po +++ b/frontend/translations/cs.po @@ -542,7 +542,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"soubory se sdílenými knihovnami budou zahrnuty do exportu, čímž se zachová " +"Soubory se sdílenými knihovnami budou zahrnuty do exportu, čímž se zachová " "jejich propojení." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 0a5c4a727f..f560cba50d 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -576,7 +576,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"files with shared libraries will be included in the export, maintaining " +"Files with shared libraries will be included in the export, maintaining " "their linkage." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/es.po b/frontend/translations/es.po index e58facf94b..84d3160301 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -585,7 +585,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"ficheros con librerias compartidas se inclurán en el paquete de exportación " +"Ficheros con librerias compartidas se inclurán en el paquete de exportación " "y mantendrán los enlaces." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/eu.po b/frontend/translations/eu.po index fc8c7c1d7b..2287cf419d 100644 --- a/frontend/translations/eu.po +++ b/frontend/translations/eu.po @@ -370,7 +370,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"partekatutako liburutegiak dituzten fitxategiak esportazio paketean sartuko " +"Partekatutako liburutegiak dituzten fitxategiak esportazio paketean sartuko " "dira eta loturak mantenduko dituzte." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/gl.po b/frontend/translations/gl.po index c80223a5fa..6aa59619a0 100644 --- a/frontend/translations/gl.po +++ b/frontend/translations/gl.po @@ -368,7 +368,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"os ficheiros con bibliotecas compartidas incluiranse na exportación " +"Os ficheiros con bibliotecas compartidas incluiranse na exportación " "mantendo os vínculos." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/ha.po b/frontend/translations/ha.po index 32066e0f0d..64c8ff41d6 100644 --- a/frontend/translations/ha.po +++ b/frontend/translations/ha.po @@ -430,7 +430,7 @@ msgstr "za ka iya fitar da kundi daya ko fiye ta hanyar tura taska. \"me \"*?" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" -msgstr "manhajar tura kundi ta kunshi fitarwa, tattali mahaxarsu." +msgstr "Manhajar tura kundi ta kunshi fitarwa, tattali mahaxarsu." #: src/app/main/ui/exports/files.cljs:165 msgid "dashboard.export.options.all.title" diff --git a/frontend/translations/hr.po b/frontend/translations/hr.po index 9480cca8c3..7da4caaa2f 100644 --- a/frontend/translations/hr.po +++ b/frontend/translations/hr.po @@ -541,7 +541,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"datoteke sa zajedničkim bibliotekama bit će uključene u izvoz, održavajući " +"Datoteke sa zajedničkim bibliotekama bit će uključene u izvoz, održavajući " "njihovu poveznicu." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/id.po b/frontend/translations/id.po index 8a4035cae7..fd479185d1 100644 --- a/frontend/translations/id.po +++ b/frontend/translations/id.po @@ -573,7 +573,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" -msgstr "berkas dengan pustaka bersama akan dimasukkan dalam hasil ekspor." +msgstr "Berkas dengan pustaka bersama akan dimasukkan dalam hasil ekspor." #: src/app/main/ui/exports/files.cljs:165 msgid "dashboard.export.options.all.title" diff --git a/frontend/translations/lt.po b/frontend/translations/lt.po index e6aeaf46e6..133777fb19 100644 --- a/frontend/translations/lt.po +++ b/frontend/translations/lt.po @@ -346,7 +346,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"failai su bendromis bibliotekomis bus įtraukti į eksportą, išlaikant jų " +"Failai su bendromis bibliotekomis bus įtraukti į eksportą, išlaikant jų " "susiejimą." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/lv.po b/frontend/translations/lv.po index ebe6191634..8cb32beadc 100644 --- a/frontend/translations/lv.po +++ b/frontend/translations/lv.po @@ -584,7 +584,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"izguvē tiks iekļautas datnes ar koplietojamām bibliotēkām, saglabājot to " +"Izguvē tiks iekļautas datnes ar koplietojamām bibliotēkām, saglabājot to " "sasaisti." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/ms.po b/frontend/translations/ms.po index 1ffbaae2ae..6f4170622e 100644 --- a/frontend/translations/ms.po +++ b/frontend/translations/ms.po @@ -438,7 +438,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"fail dengan perpustakaan kongsi akan disertakan dalam eksport, mengekalkan " +"Fail dengan perpustakaan kongsi akan disertakan dalam eksport, mengekalkan " "hubungannya." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/pl.po b/frontend/translations/pl.po index ffb9ae9a3d..99f73dea19 100644 --- a/frontend/translations/pl.po +++ b/frontend/translations/pl.po @@ -372,7 +372,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"pliki z bibliotekami współdzielonymi zostaną uwzględnione w eksporcie, z " +"Pliki z bibliotekami współdzielonymi zostaną uwzględnione w eksporcie, z " "zachowaniem ich powiązania." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/pt_BR.po b/frontend/translations/pt_BR.po index 2e3fbe5e08..71ca2086c4 100644 --- a/frontend/translations/pt_BR.po +++ b/frontend/translations/pt_BR.po @@ -581,7 +581,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"arquivos com bibliotecas compartilhadas serão incluídos na exportação, " +"Arquivos com bibliotecas compartilhadas serão incluídos na exportação, " "mantendo seu vínculo." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/pt_PT.po b/frontend/translations/pt_PT.po index 29bd74b418..403f522460 100644 --- a/frontend/translations/pt_PT.po +++ b/frontend/translations/pt_PT.po @@ -555,7 +555,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"ficheiros com bibliotecas partilhadas serão incluídos na exportação, " +"Ficheiros com bibliotecas partilhadas serão incluídos na exportação, " "mantendo as ligações." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/ro.po b/frontend/translations/ro.po index b46d16e098..2f91d64376 100644 --- a/frontend/translations/ro.po +++ b/frontend/translations/ro.po @@ -590,7 +590,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"fișierele cu biblioteci partajate vor fi incluse în export, menținându-le " +"Fișierele cu biblioteci partajate vor fi incluse în export, menținându-le " "legătura." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/sr.po b/frontend/translations/sr.po index 816e57dcfe..7c306486c2 100644 --- a/frontend/translations/sr.po +++ b/frontend/translations/sr.po @@ -491,7 +491,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"датотеке са дељеним библиотекама ће бити укључене у извоз, одржавајући " +"Датотеке са дељеним библиотекама ће бити укључене у извоз, одржавајући " "њихову повезаност." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/sv.po b/frontend/translations/sv.po index e5a55008c1..1c5fb8ddef 100644 --- a/frontend/translations/sv.po +++ b/frontend/translations/sv.po @@ -582,7 +582,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"filer med delade bibliotek kommer att ingå i exporten, bibehåller deras " +"Filer med delade bibliotek kommer att ingå i exporten, bibehåller deras " "koppling." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/tr.po b/frontend/translations/tr.po index 9292c86732..3299351b93 100644 --- a/frontend/translations/tr.po +++ b/frontend/translations/tr.po @@ -583,7 +583,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"paylaşılan kütüphanelere sahip dosyalar, bağlantılarını koruyarak dışarı " +"Paylaşılan kütüphanelere sahip dosyalar, bağlantılarını koruyarak dışarı " "aktarmaya dahil edilecek." #: src/app/main/ui/exports/files.cljs:165 diff --git a/frontend/translations/ukr_UA.po b/frontend/translations/ukr_UA.po index 87e685a6d8..502f8f0b4b 100644 --- a/frontend/translations/ukr_UA.po +++ b/frontend/translations/ukr_UA.po @@ -577,7 +577,7 @@ msgstr "" #: src/app/main/ui/exports/files.cljs:164 msgid "dashboard.export.options.all.message" msgstr "" -"файли з спільними бібліотеками буде додано до експорту зі збереженням " +"Файли з спільними бібліотеками буде додано до експорту зі збереженням " "зв'язків між ними." #: src/app/main/ui/exports/files.cljs:165 From 6e254c2cf4ed7d7a4b033fd646fb1a5c134e4d10 Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Wed, 3 Dec 2025 22:40:23 +0100 Subject: [PATCH 09/23] :bug: Fix change of library on swap (#7898) --- .../app/main/ui/workspace/sidebar/options/menus/component.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs index 42f7456ba0..85545f00b1 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.cljs @@ -687,7 +687,7 @@ (str/upper (tr "workspace.assets.local-library")) (dm/get-in libraries [current-library-id :name])) - current-lib-data (mf/with-memo [libraries] + current-lib-data (mf/with-memo [libraries current-library-id] (get-in libraries [current-library-id :data])) current-lib-counts (mf/with-memo [current-lib-data] From 38efa88460b30ee9efcf573a5979d876aa9678eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bel=C3=A9n=20Albeza?= Date: Wed, 3 Dec 2025 22:41:20 +0100 Subject: [PATCH 10/23] :bug: Fix unpublish library modal not scrolling file list (#7892) * :bug: Fix unpublish library modal not scrolling when the linked files list is too long * :lipstick: Remove deprecated tokens in unpublish library modal * :wrench: Update CHANGELOG --- CHANGES.md | 1 + frontend/src/app/main/ui/delete_shared.cljs | 16 ++++++------ frontend/src/app/main/ui/delete_shared.scss | 29 +++++++++++++++------ 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f1e153712d..1f541a0a9e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -90,6 +90,7 @@ example. It's still usable as before, we just removed the example. - Fix copy/pasting application/transit+json [Taiga #12721](https://tree.taiga.io/project/penpot/issue/12721) - Fix problem with plugins content attribute [Plugins #209](https://github.com/penpot/penpot-plugins/issues/209) - Fix U and E icon displayed in project list [Taiga #12806](https://tree.taiga.io/project/penpot/issue/12806) +- Fix unpublish library modal not scrolling a long file list [Taiga #12285](https://tree.taiga.io/project/penpot/issue/12285) ## 2.11.1 diff --git a/frontend/src/app/main/ui/delete_shared.cljs b/frontend/src/app/main/ui/delete_shared.cljs index 43a2a2425b..51fcb8225e 100644 --- a/frontend/src/app/main/ui/delete_shared.cljs +++ b/frontend/src/app/main/ui/delete_shared.cljs @@ -106,14 +106,14 @@ (when (not= 0 count-libraries) (if (pos? (count references)) [:* - [:div - (when (and (string? scd-msg) (not= scd-msg "")) - [:h3 {:class (stl/css :modal-scd-msg)} scd-msg]) - [:ul {:class (stl/css :element-list)} - (for [[file-id file-name] references] - [:li {:class (stl/css :list-item) - :key (dm/str file-id)} - [:span "- " file-name]])]] + (when (and (string? scd-msg) (not= scd-msg "")) + [:p {:class (stl/css :modal-scd-msg)} scd-msg]) + + [:ul {:class (stl/css :element-list)} + (for [[file-id file-name] references] + [:li {:class (stl/css :list-item) + :key (dm/str file-id)} + [:span "- " file-name]])] (when (and (string? hint) (not= hint "")) [:> context-notification* {:level :info :appearance :ghost} diff --git a/frontend/src/app/main/ui/delete_shared.scss b/frontend/src/app/main/ui/delete_shared.scss index ff842933da..8e06bb4720 100644 --- a/frontend/src/app/main/ui/delete_shared.scss +++ b/frontend/src/app/main/ui/delete_shared.scss @@ -4,7 +4,8 @@ // // Copyright (c) KALEIDOS INC -@use "refactor/common-refactor.scss" as deprecated; +@use "refactor/basic-rules.scss" as *; +@use "ds/typography.scss" as t; .modal-overlay { @extend .modal-overlay-base; @@ -15,14 +16,19 @@ .modal-container { @extend .modal-container-base; + display: grid; + gap: var(--sp-xxl); + grid-template-rows: auto minmax(0, 1fr) auto; } -.modal-header { - margin-bottom: deprecated.$s-24; +.list-wrapper { + display: grid; + grid-template-rows: auto 1fr auto; + max-height: 100%; } .modal-title { - @include deprecated.headlineMediumTypography; + @include t.use-typography("headline-medium"); color: var(--modal-title-foreground-color); } @@ -31,13 +37,16 @@ } .modal-content { - @include deprecated.bodySmallTypography; - margin-bottom: deprecated.$s-24; + @include t.use-typography("body-small"); + display: grid; + gap: var(--sp-s); } .element-list { - @include deprecated.bodyLargeTypography; + @include t.use-typography("body-large"); color: var(--modal-text-foreground-color); + overflow-y: scroll; + margin-block: 0; } .action-buttons { @@ -55,10 +64,14 @@ } } +.modal-scd-msg { + margin-block: 0; +} + .modal-scd-msg, .modal-subtitle, .modal-msg { - @include deprecated.bodyLargeTypography; + @include t.use-typography("body-large"); color: var(--modal-text-foreground-color); line-height: 1.5; } From 4be046406d6b570fb4f4010124cc441ca87d0ca9 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 3 Dec 2025 11:15:57 +0100 Subject: [PATCH 11/23] :zap: Pass direct args instead of a vector to toggle-values on sidebar assets --- frontend/src/app/main/ui/workspace/sidebar/assets.cljs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index 2227de25b9..a908cbc46d 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -68,7 +68,7 @@ :filters filters}])) (defn- toggle-values - [v [a b]] + [v a b] (if (= v a) b a)) (mf/defc assets-toolbox* @@ -97,7 +97,7 @@ (mf/use-fn (mf/deps ordering) (fn [] - (let [new-value (toggle-values ordering [:asc :desc])] + (let [new-value (toggle-values ordering :asc :desc)] (swap! filters* assoc :ordering new-value) (dwa/set-current-assets-ordering! new-value)))) @@ -105,7 +105,7 @@ (mf/use-fn (mf/deps list-style) (fn [] - (let [new-value (toggle-values list-style [:thumbs :list])] + (let [new-value (toggle-values list-style :thumbs :list)] (swap! filters* assoc :list-style new-value) (dwa/set-current-assets-list-style! new-value)))) From 9245ba6bc2b444bf798c6d4221128a39b64590e8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 3 Dec 2025 11:17:32 +0100 Subject: [PATCH 12/23] :lipstick: Adapt component style for assets-local-library on sidebar assets --- frontend/src/app/main/ui/workspace/sidebar/assets.cljs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index a908cbc46d..d899f20d67 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -56,9 +56,8 @@ (update file :data dissoc :pages-index)) refs/file)) -(mf/defc assets-local-library - {::mf/wrap [mf/memo] - ::mf/wrap-props false} +(mf/defc assets-local-library* + {::mf/private true} [{:keys [filters]}] (let [file (mf/deref ref:local-library)] [:> file-library* @@ -209,5 +208,5 @@ [:& (mf/provider cmm/assets-toggle-ordering) {:value toggle-ordering} [:& (mf/provider cmm/assets-toggle-list-style) {:value toggle-list-style} [:* - [:& assets-local-library {:filters filters}] + [:> assets-local-library* {:filters filters}] [:> assets-libraries* {:filters filters}]]]]]])) From 84273508adf5ad72427ca371ec277a67fd17d74c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 3 Dec 2025 15:59:17 +0100 Subject: [PATCH 13/23] :bug: Fix incorrect interaction betwen hower and scroll on assets sidebar --- CHANGES.md | 1 + frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1f541a0a9e..78b4f28a3e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -91,6 +91,7 @@ example. It's still usable as before, we just removed the example. - Fix problem with plugins content attribute [Plugins #209](https://github.com/penpot/penpot-plugins/issues/209) - Fix U and E icon displayed in project list [Taiga #12806](https://tree.taiga.io/project/penpot/issue/12806) - Fix unpublish library modal not scrolling a long file list [Taiga #12285](https://tree.taiga.io/project/penpot/issue/12285) +- Fix incorrect interaction betwen hower and scroll on assets sidebar [Taiga #12389](https://tree.taiga.io/project/penpot/issue/12389) ## 2.11.1 diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss b/frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss index 223a6d920e..1237c53323 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/groups.scss @@ -15,7 +15,7 @@ cursor: pointer; .title-menu { - display: block; + visibility: visible; } } } @@ -25,7 +25,7 @@ } .title-menu { - display: none; + visibility: hidden; } .group-title { From 75a2331edf4f625df8eb81ff12bd159017c14a96 Mon Sep 17 00:00:00 2001 From: Xaviju Date: Thu, 4 Dec 2025 11:04:07 +0100 Subject: [PATCH 14/23] :lipstick: Set low-emphasis color for both light/dark modes (#7884) --- .../src/app/main/ui/inspect/styles/style_box.scss | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/main/ui/inspect/styles/style_box.scss b/frontend/src/app/main/ui/inspect/styles/style_box.scss index 846d3ca5ad..fcb9ac73b7 100644 --- a/frontend/src/app/main/ui/inspect/styles/style_box.scss +++ b/frontend/src/app/main/ui/inspect/styles/style_box.scss @@ -6,6 +6,15 @@ @use "ds/typography.scss" as *; +// TODO: this must be a custom property in the design system +:global(.light) { + --low-emphasis-background: #fafafa; +} + +:global(.default) { + --low-emphasis-background: #121214; +} + .style-box { --title-gap: var(--sp-xs); --title-padding: var(--sp-s); @@ -13,12 +22,9 @@ --arrow-color: var(--color-foreground-secondary); --box-border-color: var(--color-background-primary); - // TODO: this must be a custom property in the design system - --lowEmphasis-background: #121214; - padding-block: var(--sp-s); padding-inline: var(--sp-m); - background-color: var(--lowEmphasis-background); + background-color: var(--low-emphasis-background); border-block-end: 2px solid var(--box-border-color); } From 19bb69cc60b12a036f63ae2a6003ee6e69eb0a8e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 4 Dec 2025 11:38:16 +0100 Subject: [PATCH 15/23] :sparkles: Improve invalid schema error report --- common/src/app/common/schema.cljc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/common/src/app/common/schema.cljc b/common/src/app/common/schema.cljc index f452c7b66e..1794aa7a59 100644 --- a/common/src/app/common/schema.cljc +++ b/common/src/app/common/schema.cljc @@ -281,7 +281,20 @@ (defn check-fn "Create a predefined check function" [s & {:keys [hint type code]}] - (let [s (schema s) + (let [s #?(:clj + (schema s) + :cljs + (try + (schema s) + (catch :default cause + (let [data (ex-data cause)] + (if (= :malli.core/invalid-schema (:type data)) + (throw (ex-info + (str "Invalid schema\n" + (pp/pprint-str (:data data))) + {})) + (throw cause)))))) + validator* (delay (m/validator s)) explainer* (delay (m/explainer s)) hint (or ^boolean hint "check error") From 0e0106f69a4edb61438050e93878d6c4232fb8df Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 4 Dec 2025 11:38:32 +0100 Subject: [PATCH 16/23] :bug: Add correct assertion on create-invitation fn --- frontend/src/app/main/data/team.cljs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/frontend/src/app/main/data/team.cljs b/frontend/src/app/main/data/team.cljs index e05cf81748..82faaf6685 100644 --- a/frontend/src/app/main/data/team.cljs +++ b/frontend/src/app/main/data/team.cljs @@ -351,19 +351,31 @@ (on-success)))) (rx/catch on-error)))))) + +(def ^:private schema:create-invitation + [:and + [:map + [:emails {:optional true} [::sm/set ::sm/email]] + [:invitations {:optional true} + [:vector + [:map + [:email ::sm/email] + [:role [::sm/one-of ctt/valid-roles]]]]] + [:team-id ::sm/uuid] + [:resend? ::sm/boolean]] + [:fn (fn [attrs] + (or (contains? attrs :emails) + (contains? attrs :invitations)))]]) + +(def ^:private check-create-invitations-params + (sm/check-fn schema:create-invitation)) + (defn create-invitations "Unified function to create invitations. Supports two parameter formats: 1. {:emails #{...} :role :admin :team-id uuid} - single role for all emails 2. {:invitations [{:email ... :role ...}] :team-id uuid} - individual roles per email" [{:keys [emails role team-id invitations resend?] :as params}] - - (assert (uuid? team-id)) - ;; Validate input format - must have either emails+role OR invitations - (assert (or (and emails role (sm/check-set-of-emails emails) (keyword? role)) - (and invitations - (sm/check-set-of-emails (map :email invitations)) - (every? #(contains? ctt/valid-roles (:role %)) invitations))) - "Must provide either emails+role or invitations with individual roles") + (check-create-invitations-params params) (ptk/reify ::create-invitations ev/Event From bf1dc21c7502e2cff63c634677351233c02d8e58 Mon Sep 17 00:00:00 2001 From: Xaviju Date: Thu, 4 Dec 2025 14:11:57 +0100 Subject: [PATCH 17/23] :lipstick: Hide themes & sets panels when none active (#7902) --- frontend/src/app/main/ui/inspect/styles.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/inspect/styles.cljs b/frontend/src/app/main/ui/inspect/styles.cljs index fc9b9fa17d..4c46bf393a 100644 --- a/frontend/src/app/main/ui/inspect/styles.cljs +++ b/frontend/src/app/main/ui/inspect/styles.cljs @@ -133,7 +133,7 @@ (swap! shorthands* assoc (:panel shorthand) (:property shorthand))))] [:ol {:class (stl/css :styles-tab) :aria-label (tr "labels.styles")} ;; TOKENS PANEL - (when (or active-themes active-sets) + (when (or (seq active-themes) (seq active-sets)) [:li [:> style-box* {:panel :token} [:> tokens-panel* {:theme-paths active-themes :set-names active-sets}]]]) From b6598d1f0714de5d16422cb435e9dae35a6eee5d Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Fri, 5 Dec 2025 09:55:41 +0100 Subject: [PATCH 18/23] :bug: Fix scrollbar on color modal (#7906) --- .../tokens/management/create/modals.cljs | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/tokens/management/create/modals.cljs b/frontend/src/app/main/ui/workspace/tokens/management/create/modals.cljs index 7a706976ed..861bbafcc9 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/create/modals.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/create/modals.cljs @@ -20,15 +20,21 @@ ;; Component ------------------------------------------------------------------- -(defn calculate-position +(defn- calculate-position "Calculates the style properties for the given coordinates and position" - [{vh :height} position x y color?] - (let [;; picker height in pixels - ;; TODO: Revisit these harcoded values - h (if color? 610 510) + [{vh :height} position x y token-type] + (let [; TODO: Revisit these harcoded values + modal-height (case token-type + :color + 500 + :typography + 660 + :shadow + 660 + 400) ;; Checks for overflow outside the viewport height - max-y (- vh h) - overflow-fix (max 0 (+ y (- 50) h (- vh))) + max-y (- vh modal-height) + overflow-fix (max 0 (+ y (- 50) modal-height (- vh))) bottom-offset "1rem" top-offset (dm/str (- y 70) "px") max-height-top (str "calc(100vh - " top-offset) @@ -61,17 +67,19 @@ :top (dm/str (- y 70 overflow-fix) "px") :maxHeight max-height-top})))) -(defn use-viewport-position-style [x y position color?] +(defn use-viewport-position-style [x y position token-type] (let [vport (-> (l/derived :vport refs/workspace-local) (mf/deref))] - (-> (calculate-position vport position x y color?) + (-> (calculate-position vport position x y token-type) (clj->js)))) (mf/defc token-update-create-modal {::mf/wrap-props false} [{:keys [x y position token token-type action selected-token-set-id] :as _args}] - (let [wrapper-style (use-viewport-position-style x y position (= token-type :color)) - modal-size-large* (mf/use-state (= token-type :typography)) + (let [wrapper-style (use-viewport-position-style x y position token-type) + modal-size-large* (mf/use-state (or (= token-type :typography) + (= token-type :color) + (= token-type :shadow))) modal-size-large? (deref modal-size-large*) close-modal (mf/use-fn (fn [] From 77dba477caff002b6a791f6e870452f445571003 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 5 Dec 2025 10:25:03 +0100 Subject: [PATCH 19/23] :wrench: Backport build-tag github workflow from develop --- .github/workflows/build-tag.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/build-tag.yml b/.github/workflows/build-tag.yml index 9f5bc8a512..ca51181cbd 100644 --- a/.github/workflows/build-tag.yml +++ b/.github/workflows/build-tag.yml @@ -21,6 +21,22 @@ jobs: with: gh_ref: ${{ github.ref_name }} + notify: + name: Notifications + runs-on: ubuntu-24.04 + needs: build-docker + + steps: + - name: Notify Mattermost + uses: mattermost/action-mattermost-notify@master + with: + MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }} + MATTERMOST_CHANNEL: bot-alerts-cicd + TEXT: | + 🐳 *[PENPOT] Docker image available.* + 🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + @infra + publish-final-tag: if: ${{ !contains(github.ref_name, '-RC') && !contains(github.ref_name, '-alpha') && !contains(github.ref_name, '-beta') && contains(github.ref_name, '.') }} needs: build-docker From b8392b3731f4e975196fe756b9a693328df1948e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 5 Dec 2025 12:36:06 +0100 Subject: [PATCH 20/23] :bug: Fix regression on sending team invitations (#7912) --- frontend/src/app/main/data/team.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/team.cljs b/frontend/src/app/main/data/team.cljs index 82faaf6685..8c0a35b8e0 100644 --- a/frontend/src/app/main/data/team.cljs +++ b/frontend/src/app/main/data/team.cljs @@ -362,7 +362,7 @@ [:email ::sm/email] [:role [::sm/one-of ctt/valid-roles]]]]] [:team-id ::sm/uuid] - [:resend? ::sm/boolean]] + [:resend? {:optional true} ::sm/boolean]] [:fn (fn [attrs] (or (contains? attrs :emails) (contains? attrs :invitations)))]]) From b0351be724374fa0d365c263b52be2cb2bfdbc7a Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Fri, 5 Dec 2025 12:48:37 +0100 Subject: [PATCH 21/23] :bug: Fix switch variants with paths --- CHANGES.md | 1 + common/src/app/common/logic/libraries.cljc | 52 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 78b4f28a3e..54df8056ee 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -92,6 +92,7 @@ example. It's still usable as before, we just removed the example. - Fix U and E icon displayed in project list [Taiga #12806](https://tree.taiga.io/project/penpot/issue/12806) - Fix unpublish library modal not scrolling a long file list [Taiga #12285](https://tree.taiga.io/project/penpot/issue/12285) - Fix incorrect interaction betwen hower and scroll on assets sidebar [Taiga #12389](https://tree.taiga.io/project/penpot/issue/12389) +- Fix switch variants with paths [Taiga #12841](https://tree.taiga.io/project/penpot/issue/12841) ## 2.11.1 diff --git a/common/src/app/common/logic/libraries.cljc b/common/src/app/common/logic/libraries.cljc index 3734774932..4d7b0a59aa 100644 --- a/common/src/app/common/logic/libraries.cljc +++ b/common/src/app/common/logic/libraries.cljc @@ -12,8 +12,11 @@ [app.common.files.changes-builder :as pcb] [app.common.files.helpers :as cfh] [app.common.files.variant :as cfv] + [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] + [app.common.geom.rect :as grc] [app.common.geom.shapes :as gsh] + [app.common.geom.shapes.common :as gco] [app.common.logging :as log] [app.common.logic.shapes :as cls] [app.common.logic.variant-properties :as clvp] @@ -26,6 +29,7 @@ [app.common.types.library :as ctl] [app.common.types.page :as ctp] [app.common.types.pages-list :as ctpl] + [app.common.types.path.segment :as segment] [app.common.types.shape :as cts] [app.common.types.shape-tree :as ctst] [app.common.types.shape.interactions :as ctsi] @@ -1876,6 +1880,44 @@ roperations' uoperations'))))))) +(defn- set-path-new-values + [current-shape prev-shape transform] + (let [new-content (segment/transform-content + (:content current-shape) + (gmt/transform-in (gpt/point 0 0) transform)) + new-points (-> (segment/content->selrect new-content) + (grc/rect->points)) + points-center (gco/points->center new-points) + new-selrect (gsh/calculate-selrect new-points points-center) + shape (assoc current-shape + :content new-content + :points new-points + :selrect new-selrect) + + prev-center (segment/content-center (:content prev-shape)) + delta (gpt/subtract points-center (first new-points)) + new-pos (gpt/subtract prev-center delta)] + (gsh/absolute-move shape new-pos))) + +(defn- switch-path-change-value + [prev-shape ;; The shape before the switch + current-shape ;; The shape after the switch (a clean copy) + ref-shape ;; The referenced shape on the main component + ;; before the switch + attr] + (let [old-width (-> ref-shape :selrect :width) + new-width (-> prev-shape :selrect :width) + + old-height (-> ref-shape :selrect :height) + new-height (-> prev-shape :selrect :height) + + transform (-> (gpt/point (/ new-width old-width) + (/ new-height old-height)) + (gmt/scale-matrix)) + + shape (set-path-new-values current-shape prev-shape transform)] + (get shape attr))) + (defn- switch-text-change-value [prev-content ;; The :content of the text before the switch @@ -2027,6 +2069,10 @@ (= :content attr) (touched attr-group)) + path-change? + (and (= :path (:type current-shape)) + (contains? #{:points :selrect :content} attr)) + ;; position-data is a special case because can be affected by :geometry-group and :content-group ;; so, if the position-data changes but the geometry is touched we need to reset the position-data ;; so it's calculated again @@ -2055,6 +2101,12 @@ (:content origin-ref-shape) touched) + path-change? + (switch-path-change-value previous-shape + current-shape + origin-ref-shape + attr) + :else (get previous-shape attr))) From 6ce3249c6d89b10d2a8c4576e83afbf50226168b Mon Sep 17 00:00:00 2001 From: Luis de Dios Date: Tue, 9 Dec 2025 14:38:15 +0100 Subject: [PATCH 22/23] :bug: Fix color format does not switch in the view mode (#7923) * :bug: Fix color format does not switch in the inspect mode of the view mode * :recycle: Update components --- .../src/app/main/ui/inspect/attributes.cljs | 2 +- frontend/src/app/main/ui/inspect/code.cljs | 2 +- .../app/main/ui/inspect/right_sidebar.cljs | 57 +++++++++---------- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/frontend/src/app/main/ui/inspect/attributes.cljs b/frontend/src/app/main/ui/inspect/attributes.cljs index 2eb274d4d5..8255782af5 100644 --- a/frontend/src/app/main/ui/inspect/attributes.cljs +++ b/frontend/src/app/main/ui/inspect/attributes.cljs @@ -36,7 +36,7 @@ :text [:visibility :geometry :text :shadow :blur :stroke :layout-element] :variant [:variant :geometry :fill :stroke :shadow :blur :layout :layout-element]}) -(mf/defc attributes +(mf/defc attributes* [{:keys [page-id file-id shapes frame from libraries share-id objects color-space]}] (let [shapes (hooks/use-equal-memo shapes) first-shape (first shapes) diff --git a/frontend/src/app/main/ui/inspect/code.cljs b/frontend/src/app/main/ui/inspect/code.cljs index 3e93b2898a..661bee9075 100644 --- a/frontend/src/app/main/ui/inspect/code.cljs +++ b/frontend/src/app/main/ui/inspect/code.cljs @@ -96,7 +96,7 @@ embed-images? (replace-map images-data))] (str/format page-template style-code markup-code))) -(mf/defc code +(mf/defc code* [{:keys [shapes frame on-expand from]}] (let [style-type* (mf/use-state "css") markup-type* (mf/use-state "html") diff --git a/frontend/src/app/main/ui/inspect/right_sidebar.cljs b/frontend/src/app/main/ui/inspect/right_sidebar.cljs index a91e4f2664..fb8a607aaf 100644 --- a/frontend/src/app/main/ui/inspect/right_sidebar.cljs +++ b/frontend/src/app/main/ui/inspect/right_sidebar.cljs @@ -16,8 +16,8 @@ [app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i] [app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]] [app.main.ui.icons :as deprecated-icon] - [app.main.ui.inspect.attributes :refer [attributes]] - [app.main.ui.inspect.code :refer [code]] + [app.main.ui.inspect.attributes :refer [attributes*]] + [app.main.ui.inspect.code :refer [code*]] [app.main.ui.inspect.selection-feedback :refer [resolve-shapes]] [app.main.ui.inspect.styles :refer [styles-tab*]] [app.util.dom :as dom] @@ -122,8 +122,7 @@ (fn [] (if (seq shapes) (st/emit! (ptk/event ::ev/event {::ev/name "inspect-mode-click-element"})) - (handle-change-tab (if (contains? cf/flags :inspect-styles) :styles :info))) - (reset! color-space* "hex"))) + (handle-change-tab (if (contains? cf/flags :inspect-styles) :styles :info))))) [:aside {:class (stl/css-case :settings-bar-right true :viewer-code (= from :viewer))} @@ -189,41 +188,41 @@ :libraries libraries :file-id file-id}] :computed - [:& attributes {:color-space color-space - :page-id page-id - :objects objects - :file-id file-id - :frame frame - :shapes shapes - :from from - :libraries libraries - :share-id share-id}] + [:> attributes* {:color-space color-space + :page-id page-id + :objects objects + :file-id file-id + :frame frame + :shapes shapes + :from from + :libraries libraries + :share-id share-id}] :code - [:& code {:frame frame - :shapes shapes - :on-expand handle-expand - :from from}])] + [:> code* {:frame frame + :shapes shapes + :on-expand handle-expand + :from from}])] [:> tab-switcher* {:tabs tabs :selected (name @section) :on-change handle-change-tab :class (stl/css :viewer-tab-switcher)} (case @section :info - [:& attributes {:page-id page-id - :objects objects - :file-id file-id - :frame frame - :shapes shapes - :from from - :libraries libraries - :share-id share-id}] + [:> attributes* {:page-id page-id + :objects objects + :file-id file-id + :frame frame + :shapes shapes + :from from + :libraries libraries + :share-id share-id}] :code - [:& code {:frame frame - :shapes shapes - :on-expand handle-expand - :from from}])])]] + [:> code* {:frame frame + :shapes shapes + :on-expand handle-expand + :from from}])])]] [:div {:class (stl/css :empty)} [:div {:class (stl/css :code-info)} [:span {:class (stl/css :placeholder-icon)} From a614207f7e8febb0a6ddcabf8900172a833f0416 Mon Sep 17 00:00:00 2001 From: Aitor Moreno Date: Tue, 9 Dec 2025 12:26:05 +0100 Subject: [PATCH 23/23] :bug: Fix exporter failing with HTTPS --- exporter/scripts/wait-and-start.sh | 1 + exporter/src/app/browser.cljs | 2 +- exporter/src/app/handlers/export_shapes.cljs | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/exporter/scripts/wait-and-start.sh b/exporter/scripts/wait-and-start.sh index f9638eb06d..c3848228dc 100755 --- a/exporter/scripts/wait-and-start.sh +++ b/exporter/scripts/wait-and-start.sh @@ -7,4 +7,5 @@ bb -i '(babashka.wait/wait-for-port "localhost" 9630)'; bb -i '(babashka.wait/wait-for-path "target/app.js")'; sleep 2; +export NODE_TLS_REJECT_UNAUTHORIZED=0 exec node target/app.js diff --git a/exporter/src/app/browser.cljs b/exporter/src/app/browser.cljs index 816fb1c954..526ae77380 100644 --- a/exporter/src/app/browser.cljs +++ b/exporter/src/app/browser.cljs @@ -100,7 +100,7 @@ (def browser-pool-factory (letfn [(create [] - (p/let [opts #js {:args #js ["--font-render-hinting=none"]} + (p/let [opts #js {:args #js ["--allow-insecure-localhost" "--font-render-hinting=none"]} browser (.launch pw/chromium opts) id (swap! pool-browser-id inc)] (l/info :origin "factory" :action "create" :browser-id id) diff --git a/exporter/src/app/handlers/export_shapes.cljs b/exporter/src/app/handlers/export_shapes.cljs index c254aba5b5..82f1d78855 100644 --- a/exporter/src/app/handlers/export_shapes.cljs +++ b/exporter/src/app/handlers/export_shapes.cljs @@ -74,7 +74,7 @@ (p/fmap (fn [resource] (assoc exchange :response/body resource))) (p/merr (fn [cause] - (l/error :hint "unexpected error on export multiple" + (l/error :hint "unexpected error on single export" :cause cause) (p/rejected cause)))))) @@ -94,7 +94,7 @@ (redis/pub! topic data)))) on-error (fn [cause] - (l/error :hint "unexpected error on multiple exportation" :cause cause) + (l/error :hint "unexpected error on multiple export" :cause cause) (if wait (p/rejected cause) (redis/pub! topic {:type :export-update