Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2025-04-23 08:59:33 +02:00
commit 40fe6369cb
15 changed files with 174 additions and 77 deletions

View file

@ -40,6 +40,8 @@
- Fix several issues with internal srepl helpers
- Fix unexpected exception on template import from libraries
- Fix incorrect uuid parsing from different parts of code
- Fix update layout on component restore [Taiga #10637](https://tree.taiga.io/project/penpot/issue/10637)
- Fix horizontal scroll in viewer [Github #6290](https://github.com/penpot/penpot/issues/6290)
## 2.6.1

View file

@ -0,0 +1,63 @@
;; 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.binfile.cleaner
"A collection of helpers for perform cleaning of artifacts; mainly
for recently imported shapes."
(:require
[app.common.data :as d]
[app.common.uuid :as uuid]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; PRE DECODE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn clean-shape-pre-decode
"Applies a pre-decode phase migration to the shape"
[shape]
(if (= "bool" (:type shape))
(if-let [content (get shape :bool-content)]
(-> shape
(assoc :content content)
(dissoc :bool-content))
shape)
shape))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; POST DECODE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- fix-shape-shadow-color
"Some shapes can come with invalid `id` property on shadow colors
caused by incorrect uuid parsing bug that should be already fixed;
this function removes the invalid id from the data structure."
[shape]
(let [fix-color
(fn [{:keys [id] :as color}]
(if (uuid? id)
color
(if (and (string? id)
(re-matches uuid/regex id))
(assoc color :id (uuid/uuid id))
(dissoc color :id))))
fix-shadow
(fn [shadow]
(d/update-when shadow :color fix-color))
xform
(map fix-shadow)]
(d/update-when shape :shadow
(fn [shadows]
(into [] xform shadows)))))
(defn clean-shape-post-decode
"A shape procesor that expected to be executed after schema decoding
process but before validation."
[shape]
(-> shape
(fix-shape-shadow-color)))

View file

@ -8,6 +8,7 @@
"A ZIP based binary file exportation"
(:refer-clojure :exclude [read])
(:require
[app.binfile.cleaner :as bfl]
[app.binfile.common :as bfc]
[app.binfile.migrations :as bfm]
[app.common.data :as d]
@ -592,6 +593,38 @@
{})
(not-empty)))
(defn- read-file-components
[{:keys [::bfc/input ::file-id ::entries]}]
(let [clean-component-post-decode
(fn [component]
(d/update-when component :objects
(fn [objects]
(reduce-kv (fn [objects id shape]
(assoc objects id (bfl/clean-shape-post-decode shape)))
objects
objects))))
clean-component-pre-decode
(fn [component]
(d/update-when component :objects
(fn [objects]
(reduce-kv (fn [objects id shape]
(assoc objects id (bfl/clean-shape-pre-decode shape)))
objects
objects))))]
(->> (keep (match-component-entry-fn file-id) entries)
(reduce (fn [result {:keys [id entry]}]
(let [object (->> (read-entry input entry)
(clean-component-pre-decode)
(decode-component)
(clean-component-post-decode)
(validate-component))]
(if (= id (:id object))
(assoc result id object)
result)))
{})
(not-empty))))
(defn- read-file-typographies
[{:keys [::bfc/input ::file-id ::entries]}]
(->> (keep (match-typography-entry-fn file-id) entries)
@ -612,48 +645,14 @@
(decode-tokens-lib)
(validate-tokens-lib))))
(defn- pre-decode-migrate-shape
"Applies a pre-decode phase migration to the shape"
[shape]
(if (= "bool" (:type shape))
(if-let [content (get shape :bool-content)]
(-> shape
(assoc :content content)
(dissoc :bool-content))
shape)
shape))
(defn- pre-decode-migrate-component
"Applies a pre-decode phase migration to component"
[component]
(d/update-when component :objects
(fn [objects]
(reduce-kv (fn [objects id shape]
(assoc objects id (pre-decode-migrate-shape shape)))
objects
objects))))
(defn- read-file-components
[{:keys [::bfc/input ::file-id ::entries]}]
(->> (keep (match-component-entry-fn file-id) entries)
(reduce (fn [result {:keys [id entry]}]
(let [object (->> (read-entry input entry)
(pre-decode-migrate-component)
(decode-component)
(validate-component))]
(if (= id (:id object))
(assoc result id object)
result)))
{})
(not-empty)))
(defn- read-file-shapes
[{:keys [::bfc/input ::file-id ::page-id ::entries] :as cfg}]
(->> (keep (match-shape-entry-fn file-id page-id) entries)
(reduce (fn [result {:keys [id entry]}]
(let [object (-> (read-entry input entry)
(pre-decode-migrate-shape)
(let [object (->> (read-entry input entry)
(bfl/clean-shape-pre-decode)
(decode-shape)
(bfl/clean-shape-post-decode)
(validate-shape))]
(if (= id (:id object))
(assoc result id object)

View file

@ -238,6 +238,7 @@
(db/update! conn :file
{:data (blob/encode (:data file))
:version (:version file)
:modified-at (dt/now)
:features (db/create-array conn "text" (:features file))}
{:id id})

View file

@ -180,8 +180,7 @@
(def ^:private
schema:get-file-data-for-thumbnail
[:map {:title "get-file-data-for-thumbnail"}
[:file-id ::sm/uuid]
[:features {:optional true} ::cfeat/features]])
[:file-id ::sm/uuid]])
(def ^:private
schema:partial-file
@ -211,7 +210,6 @@
(fmg/migrate-file)))]
(-> (cfeat/get-team-enabled-features cf/flags team)
(cfeat/check-client-features! (:features params))
(cfeat/check-file-features! (:features file)))
{:file-id file-id

View file

@ -28,6 +28,7 @@
[app.common.types.container :as ctn]
[app.common.types.file :as ctf]
[app.common.types.shape :as cts]
[app.common.types.shape.interactions :as ctsi]
[app.common.types.shape.shadow :as ctss]
[app.common.uuid :as uuid]
[clojure.set :as set]
@ -847,9 +848,6 @@
(update :pages-index update-vals update-container)
(update :components update-vals update-container))))
(def ^:private valid-shadow?
(sm/lazy-validator ::ctss/shadow))
(defmethod migrate-data "legacy-44"
[data _]
(letfn [(fix-shadow [shadow]
@ -861,7 +859,7 @@
(update-object [object]
(let [xform (comp (map fix-shadow)
(filter valid-shadow?))]
(filter ctss/valid-shadow?))]
(d/update-when object :shadow #(into [] xform %))))
(update-container [container]
@ -1036,7 +1034,7 @@
(update-shape [shape]
(let [xform (comp (map fix-shadow)
(filter valid-shadow?))]
(filter ctss/valid-shadow?))]
(d/update-when shape :shadow #(into [] xform %))))
(update-container [container]
@ -1207,11 +1205,11 @@
object))
(update-container [container]
(d/update-when container :objects update-vals update-object))]
(d/update-when container :objects d/update-vals update-object))]
(-> data
(update :pages-index update-vals update-container)
(update :components update-vals update-container))))
(update :pages-index d/update-vals update-container)
(update :components d/update-vals update-container))))
(defmethod migrate-data "legacy-67"
[data _]
@ -1222,8 +1220,8 @@
(d/update-when container :objects update-vals update-object))]
(-> data
(update :pages-index update-vals update-container)
(update :components update-vals update-container))))
(update :pages-index d/update-vals update-container)
(update :components d/update-vals update-container))))
(defmethod migrate-data "0001-remove-tokens-from-groups"
[data _]
@ -1237,8 +1235,33 @@
(dissoc :applied-tokens)))
(update-page [page]
(d/update-when page :objects update-vals update-object))]
(update data :pages-index update-vals update-page)))
(d/update-when page :objects d/update-vals update-object))]
(update data :pages-index d/update-vals update-page)))
(defmethod migrate-data "0002-clean-shape-interactions"
[data _]
(let [decode-fn (sm/decoder ctsi/schema:interaction sm/json-transformer)
validate-fn (sm/validator ctsi/schema:interaction)
xform
(comp
(map decode-fn)
(filter validate-fn))
update-object
(fn [object]
(d/update-when object :interactions
(fn [interactions]
(into [] xform interactions))))
update-container
(fn [container]
(d/update-when container :objects d/update-vals update-object))]
(-> data
(update :pages-index d/update-vals update-container)
(update :components d/update-vals update-container))))
(defmethod migrate-data "0002-normalize-bool-content"
[data _]
@ -1315,4 +1338,5 @@
"legacy-66"
"legacy-67"
"0001-remove-tokens-from-groups"
"0002-normalize-bool-content"]))
"0002-normalize-bool-content"
"0002-clean-shape-interactions"]))

View file

@ -864,7 +864,7 @@
choices))]
{:pred pred
:type-properties
{:title "contains"
{:title "contains any"
:description "contains predicate"}}))})
(register!

View file

@ -212,7 +212,7 @@
[:interactions {:optional true}
[:vector {:gen/max 2} ::ctsi/interaction]]
[:shadow {:optional true}
[:vector {:gen/max 1} ::ctss/shadow]]
[:vector {:gen/max 1} ctss/schema:shadow]]
[:blur {:optional true} ::ctsb/blur]
[:grow-type {:optional true}
[::sm/one-of grow-types]]

View file

@ -26,7 +26,9 @@
[:hidden :boolean]
[:color ::ctc/color]])
(sm/register! ::shadow schema:shadow)
(def check-shadow
(sm/check-fn schema:shadow))
(def valid-shadow?
(sm/validator schema:shadow))

View file

@ -579,8 +579,13 @@
ldata (dsh/lookup-file-data state library-id)
changes (-> (pcb/empty-changes it)
(cll/generate-restore-component ldata component-id library-id page objects))]
(rx/of (dch/commit-changes changes))))))
(cll/generate-restore-component ldata component-id library-id page objects))
frames
(->> changes :redo-changes (keep :frame-id))]
(rx/of (dch/commit-changes changes)
(ptk/data-event :layout/update {:ids frames}))))))
(defn restore-components

View file

@ -89,6 +89,7 @@
(mf/with-effect [file-id revn visible? thumbnail-id]
(when (and visible? (not thumbnail-id))
(let [subscription
(->> (ask-for-thumbnail file-id revn)
(rx/subs! (fn [thumbnail-id]
(st/emit! (dd/set-file-thumbnail file-id thumbnail-id)))
@ -96,7 +97,8 @@
(log/error :hint "unable to render thumbnail"
:file-if file-id
:revn revn
:message (ex-message cause)))))))
:message (ex-message cause)))))]
(partial rx/dispose! subscription))))
[:div {:class (stl/css :grid-item-th)
:style {:background-color bg-color}

View file

@ -117,6 +117,7 @@
padding-right: 0 $s-8 $s-40 $s-8;
transition: transform 400ms ease 300ms;
z-index: $z-index-2;
pointer-events: none;
}
.reset-button {

View file

@ -432,7 +432,7 @@
(let [id (obj/get self "$id")
value (mapv #(shadow-defaults (parser/parse-shadow %)) value)]
(cond
(not (sm/validate [:vector ::ctss/shadow] value))
(not (sm/validate [:vector ctss/schema:shadow] value))
(u/display-not-valid :shadows value)
(not (r/check-permission plugin-id "content:write"))

View file

@ -50,7 +50,8 @@
[headers]
(into {} (map vec) (seq (.entries ^js headers))))
(def default-headers
(defn default-headers
[]
{"x-frontend-version" (:full cfg/version)})
(defn fetch
@ -74,7 +75,7 @@
headers (cond-> headers
(not omit-default-headers)
(d/merge default-headers))
(merge (default-headers)))
headers (-update-headers body headers)

View file

@ -42,12 +42,11 @@
:http-body body})))
(defn- request-data-for-thumbnail
[file-id revn features]
[file-id revn]
(let [path "api/rpc/command/get-file-data-for-thumbnail"
params {:file-id file-id
:revn revn
:strip-frames-with-thumbnails true
:features features}
:strip-frames-with-thumbnails true}
request {:method :get
:uri (u/join cf/public-uri path)
:credentials "include"
@ -86,6 +85,6 @@
nil)))
(defmethod impl/handler :thumbnails/generate-for-file
[{:keys [file-id revn features] :as message} _]
(->> (request-data-for-thumbnail file-id revn features)
[{:keys [file-id revn] :as message} _]
(->> (request-data-for-thumbnail file-id revn)
(rx/map render-thumbnail)))