mirror of
https://github.com/penpot/penpot.git
synced 2025-05-28 03:26:12 +02:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
d48616d510
45 changed files with 1348 additions and 352 deletions
|
@ -69,7 +69,8 @@
|
|||
:enable-onboarding-questions
|
||||
:enable-onboarding-newsletter
|
||||
:enable-dashboard-templates-section
|
||||
:enable-google-fonts-provider])
|
||||
:enable-google-fonts-provider
|
||||
:enable-component-thumbnails])
|
||||
|
||||
(defn- parse-flags
|
||||
[global]
|
||||
|
|
|
@ -29,18 +29,24 @@
|
|||
(def commit?
|
||||
(ptk/type? ::commit))
|
||||
|
||||
(defn update-indexes
|
||||
(defn- fix-page-id
|
||||
"For events that modifies the page, page-id does not comes
|
||||
as a property so we assign it from the `id` property."
|
||||
[{:keys [id type page] :as change}]
|
||||
(cond-> change
|
||||
(and (page-change? type)
|
||||
(nil? (:page-id change)))
|
||||
(assoc :page-id (or id (:id page)))))
|
||||
|
||||
(defn- update-indexes
|
||||
"Given a commit, send the changes to the worker for updating the
|
||||
indexes."
|
||||
[{:keys [changes] :as commit}]
|
||||
[commit attr]
|
||||
(ptk/reify ::update-indexes
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [changes (->> changes
|
||||
(map (fn [{:keys [id type page] :as change}]
|
||||
(cond-> change
|
||||
(and (page-change? type) (nil? (:page-id change)))
|
||||
(assoc :page-id (or id (:id page))))))
|
||||
(let [changes (->> (get commit attr)
|
||||
(map fix-page-id)
|
||||
(filter :page-id)
|
||||
(group-by :page-id))]
|
||||
|
||||
|
@ -58,6 +64,41 @@
|
|||
(map (d/getf (:index persistence)))
|
||||
(not-empty)))
|
||||
|
||||
(def ^:private xf:map-page-id
|
||||
(map :page-id))
|
||||
|
||||
(defn- apply-changes-localy
|
||||
[{:keys [file-id redo-changes] :as commit} pending]
|
||||
(ptk/reify ::apply-changes-localy
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [current-file-id (get state :current-file-id)
|
||||
path (if (= file-id current-file-id)
|
||||
[:workspace-data]
|
||||
[:workspace-libraries file-id :data])
|
||||
|
||||
undo-changes (if pending
|
||||
(->> pending
|
||||
(map :undo-changes)
|
||||
(reverse)
|
||||
(mapcat identity)
|
||||
(vec))
|
||||
nil)
|
||||
|
||||
redo-changes (if pending
|
||||
(into redo-changes
|
||||
(mapcat :redo-changes)
|
||||
pending)
|
||||
redo-changes)]
|
||||
|
||||
(d/update-in-when state path
|
||||
(fn [file]
|
||||
(let [file (cpc/process-changes file undo-changes false)
|
||||
file (cpc/process-changes file redo-changes false)
|
||||
pids (into #{} xf:map-page-id redo-changes)]
|
||||
(reduce #(ctst/update-object-indices %1 %2) file pids))))))))
|
||||
|
||||
|
||||
(defn commit
|
||||
"Create a commit event instance"
|
||||
[{:keys [commit-id redo-changes undo-changes origin save-undo? features
|
||||
|
@ -70,6 +111,7 @@
|
|||
|
||||
(let [commit-id (or commit-id (uuid/next))
|
||||
source (d/nilv source :local)
|
||||
local? (= source :local)
|
||||
commit {:id commit-id
|
||||
:created-at (dt/now)
|
||||
:source source
|
||||
|
@ -89,38 +131,20 @@
|
|||
cljs.core/IDeref
|
||||
(-deref [_] commit)
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [current-file-id (get state :current-file-id)
|
||||
path (if (= file-id current-file-id)
|
||||
[:workspace-data]
|
||||
[:workspace-libraries file-id :data])
|
||||
|
||||
not-local? (not= source :local)
|
||||
pending (if not-local?
|
||||
(get-pending-commits state)
|
||||
nil)
|
||||
|
||||
undo-changes (if pending
|
||||
(->> pending
|
||||
(map :undo-changes)
|
||||
(reverse)
|
||||
(mapcat identity)
|
||||
(vec))
|
||||
nil)
|
||||
|
||||
redo-changes (if pending
|
||||
(into redo-changes
|
||||
(mapcat :redo-changes)
|
||||
pending)
|
||||
redo-changes)]
|
||||
|
||||
(d/update-in-when state path
|
||||
(fn [file]
|
||||
(let [file (cpc/process-changes file undo-changes false)
|
||||
file (cpc/process-changes file redo-changes false)
|
||||
pids (into #{} (map :page-id) redo-changes)]
|
||||
(reduce #(ctst/update-object-indices %1 %2) file pids)))))))))
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [pending (when-not local?
|
||||
(get-pending-commits state))]
|
||||
(rx/concat
|
||||
(rx/of (apply-changes-localy commit pending))
|
||||
(if pending
|
||||
(rx/concat
|
||||
(->> (rx/from (reverse pending))
|
||||
(rx/map (fn [commit] (update-indexes commit :undo-changes))))
|
||||
(rx/of (update-indexes commit :redo-changes))
|
||||
(->> (rx/from pending)
|
||||
(rx/map (fn [commit] (update-indexes commit :redo-changes)))))
|
||||
(rx/of (update-indexes commit :redo-changes)))))))))
|
||||
|
||||
(defn- resolve-file-revn
|
||||
[state file-id]
|
||||
|
|
|
@ -211,14 +211,6 @@
|
|||
(update-status :pending)))
|
||||
(rx/take-until stoper-s))
|
||||
|
||||
(->> local-commits-s
|
||||
(rx/buffer-time 200)
|
||||
(rx/mapcat merge-commit)
|
||||
(rx/map dch/update-indexes)
|
||||
(rx/take-until stoper-s)
|
||||
(rx/finalize (fn []
|
||||
(log/debug :hint "finalize persistence: changes watcher [index]"))))
|
||||
|
||||
;; Here we watch for local commits, buffer them in a small
|
||||
;; chunks (very near in time commits) and append them to the
|
||||
;; persistence queue
|
||||
|
@ -237,6 +229,5 @@
|
|||
(rx/map deref)
|
||||
(rx/filter #(= :remote (:source %)))
|
||||
(rx/mapcat (fn [{:keys [file-id file-revn] :as commit}]
|
||||
(rx/of (update-file-revn file-id file-revn)
|
||||
(dch/update-indexes commit))))
|
||||
(rx/of (update-file-revn file-id file-revn))))
|
||||
(rx/take-until stoper-s)))))))
|
||||
|
|
|
@ -590,7 +590,7 @@
|
|||
(update [_ state]
|
||||
(update state :colorpicker
|
||||
(fn [state]
|
||||
(let [type (:type state)
|
||||
(let [type (:type state)
|
||||
state (-> state
|
||||
(update :current-color merge changes)
|
||||
(update :current-color materialize-color-components)
|
||||
|
@ -605,11 +605,12 @@
|
|||
|
||||
(-> state
|
||||
(dissoc :gradient :stops :editing-stop)
|
||||
(cond-> (not= :image (:type state))
|
||||
(cond-> (not= :image type)
|
||||
(assoc :type :color))))))))
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when add-recent?
|
||||
;; Type can be null, because the colorpicker can be closed while a color image finish its upload
|
||||
(when (and add-recent? (some? (:type state)))
|
||||
(let [formated-color (get-color-from-colorpicker-state (:colorpicker state))]
|
||||
(rx/of (dwl/add-recent-color formated-color)))))))
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.types.typography :as ctt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.comments :as dc]
|
||||
[app.main.data.events :as ev]
|
||||
|
@ -1203,7 +1204,7 @@
|
|||
(rx/debounce 5000)
|
||||
(rx/tap #(log/trc :hint "buffer initialized")))]
|
||||
|
||||
(when components-v2?
|
||||
(when (and components-v2? (contains? cf/flags :component-thumbnails))
|
||||
(->> (rx/merge
|
||||
changes-s
|
||||
|
||||
|
|
|
@ -217,40 +217,16 @@
|
|||
(-deref [_] {:changes changes})
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
|
||||
position-data-operation?
|
||||
(fn [{:keys [type attr]}]
|
||||
(and (= :set type)
|
||||
(= attr :position-data)))
|
||||
|
||||
update-position-data
|
||||
(fn [change]
|
||||
;; Remove the position data from remote operations. Will be changed localy, otherwise
|
||||
;; creates a strange "out-of-sync" behaviour.
|
||||
(cond-> change
|
||||
(and (= page-id (:page-id change))
|
||||
(= :mod-obj (:type change)))
|
||||
(update :operations #(d/removev position-data-operation? %))))
|
||||
|
||||
;; We update `position-data` from the incoming message
|
||||
changes (->> changes
|
||||
(map update-position-data)
|
||||
(remove (fn [change]
|
||||
(and (= page-id (:page-id change))
|
||||
(:ignore-remote? change))))
|
||||
(vec))]
|
||||
|
||||
;; The commit event is responsible to apply the data localy
|
||||
;; and update the persistence internal state with the updated
|
||||
;; file-revn
|
||||
(rx/of (dch/commit {:file-id file-id
|
||||
:file-revn revn
|
||||
:save-undo? false
|
||||
:source :remote
|
||||
:redo-changes changes
|
||||
:undo-changes []}))))))
|
||||
(watch [_ _ _]
|
||||
;; The commit event is responsible to apply the data localy
|
||||
;; and update the persistence internal state with the updated
|
||||
;; file-revn
|
||||
(rx/of (dch/commit {:file-id file-id
|
||||
:file-revn revn
|
||||
:save-undo? false
|
||||
:source :remote
|
||||
:redo-changes (vec changes)
|
||||
:undo-changes []})))))
|
||||
|
||||
(def ^:private
|
||||
schema:handle-library-change
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
|
||||
(defn update-shapes
|
||||
([ids update-fn] (update-shapes ids update-fn nil))
|
||||
([ids update-fn {:keys [reg-objects? save-undo? stack-undo? attrs ignore-tree page-id ignore-remote? ignore-touched undo-group with-objects?]
|
||||
:or {reg-objects? false save-undo? true stack-undo? false ignore-remote? false ignore-touched false with-objects? false}}]
|
||||
([ids update-fn {:keys [reg-objects? save-undo? stack-undo? attrs ignore-tree page-id ignore-touched undo-group with-objects?]
|
||||
:or {reg-objects? false save-undo? true stack-undo? false ignore-touched false with-objects? false}}]
|
||||
|
||||
(dm/assert!
|
||||
"expected a valid coll of uuid's"
|
||||
|
@ -84,8 +84,7 @@
|
|||
changes (add-undo-group changes state)]
|
||||
(rx/concat
|
||||
(if (seq (:redo-changes changes))
|
||||
(let [changes (cond-> changes reg-objects? (pcb/resize-parents ids))
|
||||
changes (cond-> changes ignore-remote? (pcb/ignore-remote))]
|
||||
(let [changes (cond-> changes reg-objects? (pcb/resize-parents ids))]
|
||||
(rx/of (dch/commit-changes changes)))
|
||||
(rx/empty))
|
||||
|
||||
|
|
|
@ -486,7 +486,6 @@
|
|||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dwsh/update-shapes ids update-fn {:reg-objects? true
|
||||
:stack-undo? true
|
||||
:ignore-remote? true
|
||||
:ignore-touched true})
|
||||
(ptk/data-event :layout/update {:ids ids})
|
||||
(dwu/commit-undo-transaction undo-id))))))))
|
||||
|
@ -631,7 +630,7 @@
|
|||
(fn [shape]
|
||||
(-> shape
|
||||
(assoc :position-data (get position-data (:id shape)))))
|
||||
{:stack-undo? true :reg-objects? false :ignore-remote? true}))
|
||||
{:stack-undo? true :reg-objects? false}))
|
||||
(rx/of (fn [state]
|
||||
(dissoc state ::update-position-data-debounce ::update-position-data))))))))
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[app.common.files.helpers :as cfh]
|
||||
[app.common.logging :as l]
|
||||
[app.common.thumbnails :as thc]
|
||||
[app.config :as cf]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.persistence :as-alias dps]
|
||||
[app.main.data.workspace.notifications :as-alias wnt]
|
||||
|
@ -19,7 +19,6 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.render :as render]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.http :as http]
|
||||
[app.util.queue :as q]
|
||||
[app.util.time :as tp]
|
||||
[app.util.timers :as tm]
|
||||
|
@ -149,34 +148,34 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(l/dbg :hint "update thumbnail" :requester requester :object-id object-id :tag tag)
|
||||
;; Send the update to the back-end
|
||||
(->> (request-thumbnail state file-id page-id frame-id tag)
|
||||
(rx/mapcat (fn [blob]
|
||||
;; Send the data to backend
|
||||
(let [params {:file-id file-id
|
||||
:object-id object-id
|
||||
:media blob
|
||||
:tag (or tag "frame")}]
|
||||
(rp/cmd! :create-file-object-thumbnail params))))
|
||||
(let [tp (tp/tpoint-ms)]
|
||||
;; Send the update to the back-end
|
||||
(->> (request-thumbnail state file-id page-id frame-id tag)
|
||||
(rx/mapcat (fn [blob]
|
||||
(let [uri (wapi/create-uri blob)
|
||||
params {:file-id file-id
|
||||
:object-id object-id
|
||||
:media blob
|
||||
:tag (or tag "frame")}]
|
||||
|
||||
(rx/mapcat (fn [{:keys [object-id media-id]}]
|
||||
(let [uri (cf/resolve-media media-id)]
|
||||
;; We perform this request just for
|
||||
;; populate the browser CACHE and avoid
|
||||
;; unnecesary image flickering
|
||||
(->> (http/send! {:uri uri :method :get})
|
||||
(rx/map #(assoc-thumbnail object-id uri))))))
|
||||
(rx/merge
|
||||
(rx/of (assoc-thumbnail object-id uri))
|
||||
(->> (rp/cmd! :create-file-object-thumbnail params)
|
||||
(rx/catch rx/empty)
|
||||
(rx/ignore))))))
|
||||
|
||||
(rx/catch (fn [cause]
|
||||
(.error js/console cause)
|
||||
(rx/empty)))
|
||||
(rx/catch (fn [cause]
|
||||
(.error js/console cause)
|
||||
(rx/empty)))
|
||||
|
||||
;; We cancel all the stream if user starts editing while
|
||||
;; thumbnail is generating
|
||||
(rx/take-until
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::clear-thumbnail))
|
||||
(rx/filter #(= (deref %) object-id)))))))))
|
||||
(rx/tap #(l/trc :hint "thumbnail updated" :elapsed (dm/str (tp) "ms")))
|
||||
|
||||
;; We cancel all the stream if user starts editing while
|
||||
;; thumbnail is generating
|
||||
(rx/take-until
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::clear-thumbnail))
|
||||
(rx/filter #(= (deref %) object-id))))))))))
|
||||
|
||||
(defn- extract-root-frame-changes
|
||||
"Process a changes set in a commit to extract the frames that are changing"
|
||||
|
@ -192,8 +191,8 @@
|
|||
:mov-objects (->> (:shapes change) (map #(vector page-id %)))
|
||||
[]))
|
||||
|
||||
get-frame-id
|
||||
(fn [[_ id]]
|
||||
get-frame-ids
|
||||
(fn get-frame-ids [id]
|
||||
(let [old-objects (wsh/lookup-data-objects old-data page-id)
|
||||
new-objects (wsh/lookup-data-objects new-data page-id)
|
||||
|
||||
|
@ -208,12 +207,21 @@
|
|||
(conj old-frame-id)
|
||||
|
||||
(cfh/root-frame? new-objects new-frame-id)
|
||||
(conj new-frame-id))))]
|
||||
(conj new-frame-id)
|
||||
|
||||
(and (uuid? (:frame-id old-shape))
|
||||
(not= uuid/zero (:frame-id old-shape)))
|
||||
(into (get-frame-ids (:frame-id old-shape)))
|
||||
|
||||
(and (uuid? (:frame-id new-shape))
|
||||
(not= uuid/zero (:frame-id new-shape)))
|
||||
(into (get-frame-ids (:frame-id new-shape))))))]
|
||||
|
||||
(into #{}
|
||||
(comp (mapcat extract-ids)
|
||||
(filter (fn [[page-id']] (= page-id page-id')))
|
||||
(mapcat get-frame-id))
|
||||
(map (fn [[_ id]] id))
|
||||
(mapcat get-frame-ids))
|
||||
changes)))
|
||||
|
||||
(defn watch-state-changes
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
(->> (http/send! {:method :post
|
||||
:uri uri
|
||||
:credentials "include"
|
||||
:headers {"x-external-session-id" (cf/external-session-id)}
|
||||
:query params})
|
||||
(rx/map http/conditional-decode-transit)
|
||||
(rx/mapcat handle-response))))
|
||||
|
@ -146,6 +147,7 @@
|
|||
(->> (http/send! {:method :post
|
||||
:uri (u/join cf/public-uri "api/export")
|
||||
:body (http/transit-data (dissoc params :blob?))
|
||||
:headers {"x-external-session-id" (cf/external-session-id)}
|
||||
:credentials "include"
|
||||
:response-type (if blob? :blob :text)})
|
||||
(rx/map http/conditional-decode-transit)
|
||||
|
@ -165,6 +167,7 @@
|
|||
(->> (http/send! {:method :post
|
||||
:uri (u/join cf/public-uri "api/rpc/command/" (name id))
|
||||
:credentials "include"
|
||||
:headers {"x-external-session-id" (cf/external-session-id)}
|
||||
:body (http/form-data params)})
|
||||
(rx/map http/conditional-decode-transit)
|
||||
(rx/mapcat handle-response)))
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
{::ev/name "onboarding-step"
|
||||
:label "team:create-team-and-invite-later"
|
||||
:team-name name
|
||||
:step 7})
|
||||
:step 8})
|
||||
(ptk/data-event ::ev/event
|
||||
{::ev/name "onboarding-finish"})))))
|
||||
|
||||
|
@ -122,7 +122,7 @@
|
|||
:invites (count emails)
|
||||
:team-name name
|
||||
:role (:role params)
|
||||
:step 7})
|
||||
:step 8})
|
||||
(ptk/data-event ::ev/event
|
||||
{::ev/name "onboarding-finish"})))))
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
(st/emit! (dcm/update-options {:show-sidebar? (not mode)})))))]
|
||||
|
||||
[:div {:class (stl/css :view-options)
|
||||
:data-testid "viewer-comments-dropdown"
|
||||
:on-click toggle-dropdown}
|
||||
[:span {:class (stl/css :dropdown-title)} (tr "labels.comments")]
|
||||
[:span {:class (stl/css :icon-dropdown)} i/arrow]
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
[promesa.core :as p]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn fix-position [shape]
|
||||
(defn fix-position
|
||||
[shape]
|
||||
(if-let [modifiers (:modifiers shape)]
|
||||
(let [shape' (gsh/transform-shape shape modifiers)
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@
|
|||
:expanded (> size 276))
|
||||
|
||||
:id "right-sidebar-aside"
|
||||
:data-testid "right-sidebar"
|
||||
:data-size (str size)
|
||||
:style #js {"--width" (if can-be-expanded? (dm/str size "px") 276)}}
|
||||
(when can-be-expanded?
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
[app.common.types.component :as ctk]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.config :as cf]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
|
@ -287,7 +288,7 @@
|
|||
(when (< @retry 3)
|
||||
(inc retry))))]
|
||||
|
||||
(if (some? thumbnail-uri)
|
||||
(if (and (some? thumbnail-uri) (contains? cf/flags :component-thumbnails))
|
||||
[:& component-svg-thumbnail
|
||||
{:thumbnail-uri thumbnail-uri
|
||||
:class class
|
||||
|
|
|
@ -520,9 +520,11 @@
|
|||
:name "listing-style"}
|
||||
[:& radio-button {:icon i/view-as-list
|
||||
:value "list"
|
||||
:title (tr "workspace.assets.list-view")
|
||||
:id "opt-list"}]
|
||||
[:& radio-button {:icon i/flex-grid
|
||||
:value "grid"
|
||||
:title (tr "workspace.assets.grid-view")
|
||||
:id "opt-grid"}]]])
|
||||
|
||||
(when (and components-v2 (not read-only?) local?)
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
(let [{:keys [text-align]} values
|
||||
handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps on-blur)
|
||||
(mf/deps on-change on-blur)
|
||||
(fn [value]
|
||||
(on-change {:text-align value})
|
||||
(when (some? on-blur) (on-blur))))]
|
||||
|
@ -64,7 +64,7 @@
|
|||
(let [direction (:text-direction values)
|
||||
handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps direction)
|
||||
(mf/deps on-change on-blur direction)
|
||||
(fn [value]
|
||||
(let [dir (if (= value direction)
|
||||
"none"
|
||||
|
@ -93,7 +93,7 @@
|
|||
vertical-align (or vertical-align "top")
|
||||
handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps on-blur)
|
||||
(mf/deps on-change on-blur)
|
||||
(fn [value]
|
||||
(on-change {:vertical-align value})
|
||||
(when (some? on-blur) (on-blur))))]
|
||||
|
@ -154,7 +154,7 @@
|
|||
(let [text-decoration (or (:text-decoration values) "none")
|
||||
handle-change
|
||||
(mf/use-fn
|
||||
(mf/deps text-decoration)
|
||||
(mf/deps on-change on-blur text-decoration)
|
||||
(fn [value]
|
||||
(let [decoration (if (= value text-decoration)
|
||||
"none"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue