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

This commit is contained in:
Andrey Antukh 2022-10-04 13:29:03 +02:00
commit c2158b0f3c
15 changed files with 377 additions and 271 deletions

View file

@ -6,6 +6,7 @@
### :sparkles: New features ### :sparkles: New features
### :bug: Bugs fixed ### :bug: Bugs fixed
- Add title to color bullets [Taiga #4218](https://tree.taiga.io/project/penpot/task/4218)
- Fix color bullets in library color modal [Taiga #4186](https://tree.taiga.io/project/penpot/issue/4186) - Fix color bullets in library color modal [Taiga #4186](https://tree.taiga.io/project/penpot/issue/4186)
- Fix shortcut texts alignment [Taiga #4275](https://tree.taiga.io/project/penpot/issue/4275) - Fix shortcut texts alignment [Taiga #4275](https://tree.taiga.io/project/penpot/issue/4275)
- Fix some texts and a typo [Taiga #4215](https://tree.taiga.io/project/penpot/issue/4215) - Fix some texts and a typo [Taiga #4215](https://tree.taiga.io/project/penpot/issue/4215)
@ -27,7 +28,7 @@
### :sparkles: New features ### :sparkles: New features
- Add title to color bullets [Taiga #4218](https://tree.taiga.io/project/penpot/task/4218) - Improve interactions with nested boards [Taiga #4054](https://tree.taiga.io/project/penpot/us/4054)
- Add team hero in projects dashboard [Taiga #3863](https://tree.taiga.io/project/penpot/us/3863) - Add team hero in projects dashboard [Taiga #3863](https://tree.taiga.io/project/penpot/us/3863)
- Add zoom style to shared link [Taiga #3874](https://tree.taiga.io/project/penpot/us/3874) - Add zoom style to shared link [Taiga #3874](https://tree.taiga.io/project/penpot/us/3874)
- Add dashboard creation button as placeholder [Taiga #3861](https://tree.taiga.io/project/penpot/us/3861) - Add dashboard creation button as placeholder [Taiga #3861](https://tree.taiga.io/project/penpot/us/3861)
@ -42,6 +43,7 @@
- Newsletter Opt-in options for subscription categories [Taiga #3242](https://tree.taiga.io/project/penpot/us/3242) - Newsletter Opt-in options for subscription categories [Taiga #3242](https://tree.taiga.io/project/penpot/us/3242)
- Print emails to console by default if smtp is disabled - Print emails to console by default if smtp is disabled
- Add `email-verification` flag for enable/disable email verification - Add `email-verification` flag for enable/disable email verification
- Make graphics thumbnails load lazy [Taiga #4252](https://tree.taiga.io/project/penpot/issue/4252)
### :bug: Bugs fixed ### :bug: Bugs fixed
@ -55,6 +57,7 @@
- Fix change multiple colors with SVG [Taiga #3889](https://tree.taiga.io/project/penpot/issue/3889) - Fix change multiple colors with SVG [Taiga #3889](https://tree.taiga.io/project/penpot/issue/3889)
- Fix ungroup does not work for typographies [Taiga #4195](https://tree.taiga.io/project/penpot/issue/4195) - Fix ungroup does not work for typographies [Taiga #4195](https://tree.taiga.io/project/penpot/issue/4195)
- Fix inviting to non existing users can fail [Taiga #4108](https://tree.taiga.io/project/penpot/issue/4108) - Fix inviting to non existing users can fail [Taiga #4108](https://tree.taiga.io/project/penpot/issue/4108)
- Fix components marked as touched when moved [Taiga #4061](https://tree.taiga.io/project/penpot/task/4061)
### :arrow_up: Deps updates ### :arrow_up: Deps updates
### :heart: Community contributions by (Thank you!) ### :heart: Community contributions by (Thank you!)

View file

@ -11,17 +11,22 @@
io.prometheus/simpleclient {:mvn/version "0.16.0"} io.prometheus/simpleclient {:mvn/version "0.16.0"}
io.prometheus/simpleclient_hotspot {:mvn/version "0.16.0"} io.prometheus/simpleclient_hotspot {:mvn/version "0.16.0"}
io.prometheus/simpleclient_jetty {:mvn/version "0.16.0" io.prometheus/simpleclient_jetty
:exclusions [org.eclipse.jetty/jetty-server {:mvn/version "0.16.0"
org.eclipse.jetty/jetty-servlet]} :exclusions [org.eclipse.jetty/jetty-server
org.eclipse.jetty/jetty-servlet]}
io.prometheus/simpleclient_httpserver {:mvn/version "0.16.0"} io.prometheus/simpleclient_httpserver {:mvn/version "0.16.0"}
io.lettuce/lettuce-core {:mvn/version "6.2.0.RELEASE"} io.lettuce/lettuce-core {:mvn/version "6.2.0.RELEASE"}
java-http-clj/java-http-clj {:mvn/version "0.4.3"} java-http-clj/java-http-clj {:mvn/version "0.4.3"}
funcool/yetti {:git/tag "v9.8" :git/sha "fbe1d7d" funcool/yetti
:git/url "https://github.com/funcool/yetti.git" {:git/tag "v9.9"
:exclusions [org.slf4j/slf4j-api]} :git/sha "f0a455d"
:git/url "https://github.com/funcool/yetti.git"
:exclusions [org.slf4j/slf4j-api]}
com.github.seancorfield/next.jdbc {:mvn/version "1.3.828"} com.github.seancorfield/next.jdbc {:mvn/version "1.3.828"}
metosin/reitit-core {:mvn/version "0.5.18"} metosin/reitit-core {:mvn/version "0.5.18"}
@ -34,8 +39,10 @@
buddy/buddy-sign {:mvn/version "3.4.333"} buddy/buddy-sign {:mvn/version "3.4.333"}
org.jsoup/jsoup {:mvn/version "1.15.1"} org.jsoup/jsoup {:mvn/version "1.15.1"}
org.im4java/im4java {:git/tag "1.4.0-penpot-2" :git/sha "e2b3e16" org.im4java/im4java
:git/url "https://github.com/penpot/im4java"} {:git/tag "1.4.0-penpot-2"
:git/sha "e2b3e16"
:git/url "https://github.com/penpot/im4java"}
org.lz4/lz4-java {:mvn/version "1.8.0"} org.lz4/lz4-java {:mvn/version "1.8.0"}

View file

@ -280,7 +280,7 @@
(assoc ::binf/file-ids file-ids) (assoc ::binf/file-ids file-ids)
(assoc ::binf/embed-assets? embed?) (assoc ::binf/embed-assets? embed?)
(assoc ::binf/include-libraries? libs?) (assoc ::binf/include-libraries? libs?)
(binf/export!))] (binf/export-to-tmpfile!))]
(if clone? (if clone?
(let [project-id (some-> (profile/retrieve-additional-data pool profile-id) :default-project-id)] (let [project-id (some-> (profile/retrieve-additional-data pool profile-id) :default-project-id)]
(binf/import! (binf/import!

View file

@ -89,7 +89,7 @@
[id] [id]
(when-let [wsp (get @state id)] (when-let [wsp (get @state id)]
{:id id {:id id
:created-at (dt/instant id) :created-at (::created-at @wsp)
:profile-id (::profile-id @wsp) :profile-id (::profile-id @wsp)
:session-id (::session-id @wsp) :session-id (::session-id @wsp)
:user-agent (::ws/user-agent @wsp) :user-agent (::ws/user-agent @wsp)

View file

@ -30,7 +30,8 @@
[clojure.walk :as walk] [clojure.walk :as walk]
[cuerdas.core :as str] [cuerdas.core :as str]
[datoteka.io :as io] [datoteka.io :as io]
[yetti.adapter :as yt]) [yetti.adapter :as yt]
[yetti.response :as yrs])
(:import (:import
com.github.luben.zstd.ZstdInputStream com.github.luben.zstd.ZstdInputStream
com.github.luben.zstd.ZstdOutputStream com.github.luben.zstd.ZstdOutputStream
@ -799,27 +800,40 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn export! (defn export!
[cfg] [cfg output]
(let [path (tmp/tempfile :prefix "penpot.export.") (let [id (uuid/next)
id (uuid/next) tp (dt/tpoint)
ts (dt/now) ab (volatile! false)
cs (volatile! nil)] cs (volatile! nil)]
(try (try
(l/info :hint "start exportation" :export-id id) (l/info :hint "start exportation" :export-id id)
(with-open [output (io/output-stream path)] (with-open [output (io/output-stream output)]
(binding [*position* (atom 0)] (binding [*position* (atom 0)]
(write-export! (assoc cfg ::output output)) (write-export! (assoc cfg ::output output))))
path))
(catch java.io.IOException _cause
;; Do nothing, EOF means client closes connection abruptly
(vreset! ab true)
nil)
(catch Throwable cause (catch Throwable cause
(vreset! cs cause) (vreset! cs cause)
(vreset! ab true)
(throw cause)) (throw cause))
(finally (finally
(l/info :hint "exportation finished" :export-id id (l/info :hint "exportation finished" :export-id id
:elapsed (str (inst-ms (dt/diff ts (dt/now))) "ms") :elapsed (str (inst-ms (tp)) "ms")
:aborted @ab
:cause @cs))))) :cause @cs)))))
(defn export-to-tmpfile!
[cfg]
(let [path (tmp/tempfile :prefix "penpot.export.")]
(with-open [output (io/output-stream path)]
(export! cfg output)
path)))
(defn import! (defn import!
[{:keys [::input] :as cfg}] [{:keys [::input] :as cfg}]
(let [id (uuid/next) (let [id (uuid/next)
@ -855,17 +869,20 @@
"Export a penpot file in a binary format." "Export a penpot file in a binary format."
{::doc/added "1.15"} {::doc/added "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id file-id include-libraries? embed-assets?] :as params}] [{:keys [pool] :as cfg} {:keys [profile-id file-id include-libraries? embed-assets?] :as params}]
(db/with-atomic [conn pool] (files/check-read-permissions! pool profile-id file-id)
(files/check-read-permissions! conn profile-id file-id) (let [resp (reify yrs/StreamableResponseBody
(let [path (export! (assoc cfg (-write-body-to-stream [_ _ output-stream]
::file-ids [file-id] (-> cfg
::embed-assets? embed-assets? (assoc ::file-ids [file-id])
::include-libraries? include-libraries?))] (assoc ::embed-assets? embed-assets?)
(with-meta {} (assoc ::include-libraries? include-libraries?)
{:transform-response (fn [_ response] (export! output-stream))))]
(assoc response
:body (io/input-stream path) (with-meta (sv/wrap nil)
:headers {"content-type" "application/octet-stream"}))})))) {:transform-response (fn [_ response]
(-> response
(assoc :body resp)
(assoc :headers {"content-type" "application/octet-stream"})))})))
(s/def ::file ::media/upload) (s/def ::file ::media/upload)
(s/def ::import-binfile (s/def ::import-binfile

View file

@ -10,6 +10,7 @@
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.logging :as l] [app.common.logging :as l]
[app.common.transit :as t] [app.common.transit :as t]
[app.common.uuid :as uuid]
[app.loggers.audit :refer [parse-client-ip]] [app.loggers.audit :refer [parse-client-ip]]
[app.util.time :as dt] [app.util.time :as dt]
[clojure.core.async :as a] [clojure.core.async :as a]
@ -21,9 +22,7 @@
(declare decode-beat) (declare decode-beat)
(declare encode-beat) (declare encode-beat)
(declare process-heartbeat) (declare start-io-loop)
(declare process-input)
(declare process-output)
(declare ws-ping!) (declare ws-ping!)
(declare ws-send!) (declare ws-send!)
(declare filter-options) (declare filter-options)
@ -51,7 +50,7 @@
::idle-timeout] ::idle-timeout]
:or {input-buff-size 64 :or {input-buff-size 64
output-buff-size 64 output-buff-size 64
idle-timeout 30000 idle-timeout 60000
on-connect noop on-connect noop
on-snd-message identity-3 on-snd-message identity-3
on-rcv-message identity-3} on-rcv-message identity-3}
@ -64,17 +63,19 @@
(fn [{:keys [::yws/channel session-id] :as request}] (fn [{:keys [::yws/channel session-id] :as request}]
(let [input-ch (a/chan input-buff-size) (let [input-ch (a/chan input-buff-size)
output-ch (a/chan output-buff-size) output-ch (a/chan output-buff-size)
pong-ch (a/chan (a/sliding-buffer 6)) hbeat-ch (a/chan (a/sliding-buffer 6))
close-ch (a/chan) close-ch (a/chan)
stop-ch (a/chan) stop-ch (a/chan)
ip-addr (parse-client-ip request) ip-addr (parse-client-ip request)
uagent (yr/get-header request "user-agent") uagent (yr/get-header request "user-agent")
id (inst-ms (dt/now)) id (uuid/next)
options (-> (filter-options options) options (-> (filter-options options)
(merge {::id id (merge {::id id
::created-at (dt/now)
::input-ch input-ch ::input-ch input-ch
::heartbeat-ch hbeat-ch
::output-ch output-ch ::output-ch output-ch
::close-ch close-ch ::close-ch close-ch
::stop-ch stop-ch ::stop-ch stop-ch
@ -99,11 +100,13 @@
on-ws-error on-ws-error
(fn [_ error] (fn [_ error]
(a/close! close-ch)
(when-not (or (instance? java.nio.channels.ClosedChannelException error) (when-not (or (instance? java.nio.channels.ClosedChannelException error)
(instance? java.net.SocketException error) (instance? java.net.SocketException error)
(instance? java.io.IOException error)) (instance? java.io.IOException error))
(l/error :hint (ex-message error) :cause error))) (l/error :fn "on-ws-error" :conn-id id
:hint (ex-message error)
:cause error))
(on-ws-terminate nil 8801 "close after error"))
on-ws-message on-ws-message
(fn [_ message] (fn [_ message]
@ -116,23 +119,18 @@
(l/warn :hint "error on decoding incoming message from websocket" (l/warn :hint "error on decoding incoming message from websocket"
:wsmsg (pr-str message) :wsmsg (pr-str message)
:cause e) :cause e)
(a/>! close-ch [8801 "decode error"]) (a/>! close-ch [8802 "decode error"])
(a/close! close-ch)))) (a/close! close-ch))))
on-ws-pong on-ws-pong
(fn [_ buffers] (fn [_ buffers]
(a/>!! pong-ch (yu/copy-many buffers)))] (a/>!! hbeat-ch (yu/copy-many buffers)))]
;; Launch heartbeat process
(-> @options
(assoc ::pong-ch pong-ch)
(process-heartbeat))
;; Wait a close signal ;; Wait a close signal
(a/go (a/go
(let [[code reason] (a/<! close-ch)] (let [[code reason] (a/<! close-ch)]
(a/close! stop-ch) (a/close! stop-ch)
(a/close! pong-ch) (a/close! hbeat-ch)
(a/close! output-ch) (a/close! output-ch)
(a/close! input-ch) (a/close! input-ch)
@ -141,19 +139,14 @@
(yws/close! channel code reason)) (yws/close! channel code reason))
(when (fn? on-terminate) (when (fn? on-terminate)
(on-terminate)))) (on-terminate))
;; Forward all messages from output-ch to the websocket (l/trace :hint "connection terminated")))
;; connection
(a/go-loop []
(when-let [val (a/<! output-ch)]
(let [val (on-snd-message options val)]
(a/<! (ws-send! channel (t/encode-str val)))
(recur))))
;; React on messages received from the client ;; React on messages received from the client
(a/go
(process-input options handler) (a/<! (start-io-loop options handler on-snd-message on-ws-terminate))
(l/trace :hint "io loop terminated"))
{:on-open on-ws-open {:on-open on-ws-open
:on-error on-ws-error :on-error on-ws-error
@ -168,7 +161,7 @@
(yws/send! channel s (fn [e] (yws/send! channel s (fn [e]
(when e (a/offer! ch e)) (when e (a/offer! ch e))
(a/close! ch))) (a/close! ch)))
(catch java.io.IOException cause (catch Throwable cause
(a/offer! ch cause) (a/offer! ch cause)
(a/close! ch))) (a/close! ch)))
ch)) ch))
@ -178,9 +171,9 @@
(let [ch (a/chan 1)] (let [ch (a/chan 1)]
(try (try
(yws/ping! channel s (fn [e] (yws/ping! channel s (fn [e]
(when e (a/offer! ch e)) (when e (a/offer! ch e))
(a/close! ch))) (a/close! ch)))
(catch java.io.IOException cause (catch Throwable cause
(a/offer! ch cause) (a/offer! ch cause)
(a/close! ch))) (a/close! ch)))
ch)) ch))
@ -203,51 +196,71 @@
(locking wsp (locking wsp
(handler wsp message)))) (handler wsp message))))
(defn- process-input (def max-missed-heartbeats 3)
[wsp handler] (def heartbeat-interval 5000)
(let [{:keys [::input-ch ::output-ch ::stop-ch]} @wsp
handler (wrap-handler handler)] (defn- start-io-loop
[wsp handler on-snd-message on-ws-terminate]
(let [input-ch (::input-ch @wsp)
output-ch (::output-ch @wsp)
stop-ch (::stop-ch @wsp)
hbeat-pong-ch (::heartbeat-ch @wsp)
channel (::channel @wsp)
conn-id (::id @wsp)
handler (wrap-handler handler)
beats (atom #{})
choices [stop-ch
input-ch
output-ch
hbeat-pong-ch]]
;; Start IO loop
(a/go (a/go
(a/<! (handler wsp {:type :connect})) (a/<! (handler wsp {:type :connect}))
(a/<! (a/go-loop [] (a/<! (a/go-loop [i 0]
(when-let [message (a/<! input-ch)] (let [hbeat-ping-ch (a/timeout heartbeat-interval)
(let [[val port] (a/alts! [stop-ch (handler wsp message)] :priority true)] [v p] (a/alts! (conj choices hbeat-ping-ch))]
(when-not (= port stop-ch) (cond
(not (yws/connected? channel))
(on-ws-terminate nil 8800 "channel disconnected")
(= p hbeat-ping-ch)
(do
(l/trace :hint "ping" :beat i :conn-id conn-id)
(a/<! (ws-ping! channel (encode-beat i)))
(let [issued (swap! beats conj (long i))]
(if (>= (count issued) max-missed-heartbeats)
(on-ws-terminate nil 8802 "heartbeat: timeout")
(recur (inc i)))))
(= p hbeat-pong-ch)
(let [beat (decode-beat v)]
(l/trace :hint "pong" :beat beat :conn-id conn-id)
(swap! beats disj beat)
(recur i))
(= p input-ch)
(let [result (a/<! (handler wsp v))]
;; (l/trace :hint "message received" :message v)
(cond (cond
(ex/ex-info? val) (ex/ex-info? result)
(a/>! output-ch {:type :error :error (ex-data val)}) (a/>! output-ch {:type :error :error (ex-data result)})
(ex/exception? val) (ex/exception? result)
(a/>! output-ch {:type :error :error {:message (ex-message val)}}) (a/>! output-ch {:type :error :error {:message (ex-message result)}})
(map? result)
(a/>! output-ch (cond-> result (:request-id v) (assoc :request-id (:request-id v)))))
(recur i))
(= p output-ch)
(let [v (on-snd-message wsp v)]
;; (l/trace :hint "writing message to output" :message v)
(a/<! (ws-send! channel (t/encode-str v)))
(recur i))))))
(map? val)
(a/>! output-ch (cond-> val (:request-id message) (assoc :request-id (:request-id message)))))
(recur))))))
(a/<! (handler wsp {:type :disconnect}))))) (a/<! (handler wsp {:type :disconnect})))))
(defn- process-heartbeat
[{:keys [::channel ::stop-ch ::close-ch ::pong-ch
::heartbeat-interval ::max-missed-heartbeats]
:or {heartbeat-interval 2000
max-missed-heartbeats 4}}]
(let [beats (atom #{})]
(a/go-loop [i 0]
(let [[_ port] (a/alts! [stop-ch (a/timeout heartbeat-interval)] :priority true)]
(when (and (yws/connected? channel)
(not= port stop-ch))
(a/<! (ws-ping! channel (encode-beat i)))
(let [issued (swap! beats conj (long i))]
(if (>= (count issued) max-missed-heartbeats)
(do
(a/>! close-ch [8802 "heart-beat timeout"])
(a/close! close-ch))
(recur (inc i)))))))
(a/go-loop []
(when-let [buffer (a/<! pong-ch)]
(swap! beats disj (decode-beat buffer))
(recur)))))
(defn- filter-options (defn- filter-options
"Remove from options all namespace qualified keys that matches the "Remove from options all namespace qualified keys that matches the
current namespace." current namespace."

View file

@ -512,6 +512,18 @@
(assert (has-offset-effect? interaction)) (assert (has-offset-effect? interaction))
(update interaction :animation assoc :offset-effect offset-effect)) (update interaction :animation assoc :offset-effect offset-effect))
(defn dest-to?
"Check if the interaction has the given frame as destination."
[interaction frame-id]
(and (has-destination interaction)
(= (:destination interaction) frame-id)))
(defn navs-to?
"Check if the interaction is a navigation to the given frame."
[interaction frame-id]
(and (= (:action-type interaction) :navigate)
(= (:destination interaction) frame-id)))
;; -- Helpers for interactions ;; -- Helpers for interactions
(defn add-interaction (defn add-interaction
@ -543,6 +555,12 @@
(d/update-when interaction :destination #(get ids-map % %)))))] (d/update-when interaction :destination #(get ids-map % %)))))]
(into [] xform interactions)))) (into [] xform interactions))))
(defn remove-interactions
"Remove all interactions that the fn returns true."
[f interactions]
(-> (d/removev f interactions)
not-empty))
(defn actionable? (defn actionable?
"Check if there is any interaction that is clickable by the user" "Check if there is any interaction that is clickable by the user"
[interactions] [interactions]

View file

@ -142,7 +142,6 @@ RUN set -ex; \
apt-get -qqy install postgresql-client-14; \ apt-get -qqy install postgresql-client-14; \
rm -rf /var/lib/apt/lists/*; rm -rf /var/lib/apt/lists/*;
RUN set -eux; \ RUN set -eux; \
ARCH="$(dpkg --print-architecture)"; \ ARCH="$(dpkg --print-architecture)"; \
case "${ARCH}" in \ case "${ARCH}" in \

View file

@ -17,6 +17,7 @@
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.data.workspace.changes :as dch] [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
[app.main.streams :as ms] [app.main.streams :as ms]
[beicon.core :as rx] [beicon.core :as rx]
[potok.core :as ptk])) [potok.core :as ptk]))
@ -149,6 +150,29 @@
(update shape :interactions (update shape :interactions
ctsi/update-interaction index update-fn))))))) ctsi/update-interaction index update-fn)))))))
(defn remove-all-interactions-nav-to
"Remove all interactions that navigate to the given frame."
[frame-id]
(ptk/reify ::remove-all-interactions-nav-to
ptk/WatchEvent
(watch [_ state _]
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id)
remove-interactions-shape
(fn [shape]
(let [interactions (:interactions shape)
new-interactions (ctsi/remove-interactions #(ctsi/navs-to? % frame-id)
interactions)]
(when (not= (count interactions) (count new-interactions))
(dch/update-shapes [(:id shape)]
(fn [shape]
(assoc shape :interactions new-interactions))))))]
(rx/from (->> (vals objects)
(map remove-interactions-shape)
(d/vec-without-nils)))))))
(declare move-edit-interaction) (declare move-edit-interaction)
(declare finish-edit-interaction) (declare finish-edit-interaction)
@ -171,8 +195,7 @@
(rx/map #(move-edit-interaction initial-pos %))) (rx/map #(move-edit-interaction initial-pos %)))
(rx/of (finish-edit-interaction index initial-pos)))))))) (rx/of (finish-edit-interaction index initial-pos))))))))
(defn- get-target-frame
(defn get-target-frame
[state position] [state position]
(let [objects (wsh/lookup-page-objects state) (let [objects (wsh/lookup-page-objects state)
@ -185,8 +208,7 @@
target-frame (ctst/frame-by-position objects position)] target-frame (ctst/frame-by-position objects position)]
(when (and (not= (:id target-frame) uuid/zero) (when (and (not= (:id target-frame) uuid/zero)
(not= (:id target-frame) from-frame-id) (not= (:id target-frame) from-frame-id))
(not (:hide-in-viewer target-frame)))
target-frame))) target-frame)))
(defn move-edit-interaction (defn move-edit-interaction
@ -225,25 +247,34 @@
:always :always
(ctsi/set-destination (:id target-frame))))] (ctsi/set-destination (:id target-frame))))]
(cond (rx/of
(or (nil? shape) (dwu/start-undo-transaction)
;; Didn't changed the position for the interaction (when (:hide-in-viewer target-frame)
(= position initial-pos) ; If the target frame is hidden, we need to unhide it so
; users can navigate to it.
(dch/update-shapes [(:id target-frame)]
#(dissoc % :hide-in-viewer)))
;; New interaction but invalid target (cond
(and (nil? index) (nil? target-frame))) (or (nil? shape)
nil ;; Didn't changed the position for the interaction
(= position initial-pos)
;; New interaction but invalid target
(and (nil? index) (nil? target-frame)))
nil
;; Dropped interaction in an invalid target. We remove it ;; Dropped interaction in an invalid target. We remove it
(and (some? index) (nil? target-frame)) (and (some? index) (nil? target-frame))
(rx/of (remove-interaction shape index)) (remove-interaction shape index)
(nil? index) (nil? index)
(rx/of (add-new-interaction shape (:id target-frame))) (add-new-interaction shape (:id target-frame))
:else :else
(rx/of (update-interaction shape index change-interaction))))))) (update-interaction shape index change-interaction))
(dwu/commit-undo-transaction))))))
;; --- Overlays ;; --- Overlays

View file

@ -17,7 +17,6 @@
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.types.shape-tree :as ctst] [app.common.types.shape-tree :as ctst]
[app.common.uuid :as uuid]
[app.main.data.workspace.changes :as dch] [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.collapse :as dwc] [app.main.data.workspace.collapse :as dwc]
[app.main.data.workspace.comments :as-alias dwcm] [app.main.data.workspace.comments :as-alias dwcm]
@ -243,7 +242,7 @@
(defn- check-delta (defn- check-delta
"If the shape is a component instance, check its relative position respect the "If the shape is a component instance, check its relative position respect the
root of the component, and see if it changes after applying a transformation." root of the component, and see if it changes after applying a transformation."
[shape root transformed-shape transformed-root objects] [shape root transformed-shape transformed-root objects modif-tree]
(let [root (let [root
(cond (cond
(:component-root? shape) (:component-root? shape)
@ -260,7 +259,8 @@
transformed-shape transformed-shape
(nil? transformed-root) (nil? transformed-root)
(cph/get-root-shape objects transformed-shape) (as-> (cph/get-root-shape objects transformed-shape) $
(gsh/transform-shape (merge $ (get modif-tree (:id $)))))
:else transformed-root) :else transformed-root)
@ -298,7 +298,7 @@
transformed-shape (gsh/transform-shape (merge shape (get modif-tree shape-id))) transformed-shape (gsh/transform-shape (merge shape (get modif-tree shape-id)))
[root transformed-root ignore-geometry?] [root transformed-root ignore-geometry?]
(check-delta shape root transformed-shape transformed-root objects) (check-delta shape root transformed-shape transformed-root objects modif-tree)
ignore-tree (assoc ignore-tree shape-id ignore-geometry?) ignore-tree (assoc ignore-tree shape-id ignore-geometry?)
@ -758,9 +758,6 @@
(keep lookup) (keep lookup)
(remove #(= (:frame-id %) frame-id))) (remove #(= (:frame-id %) frame-id)))
moving-frames
(filter #(cph/frame-shape? (lookup %)) ids)
changes changes
(-> (pcb/empty-changes it page-id) (-> (pcb/empty-changes it page-id)
(pcb/with-objects objects) (pcb/with-objects objects)

View file

@ -355,8 +355,7 @@
(dnd/has-type? e "application/x-moz-file")) (dnd/has-type? e "application/x-moz-file"))
(dom/prevent-default e) (dom/prevent-default e)
(reset! dragging? false) (reset! dragging? false)
(import-files (.-files (.-dataTransfer e)))))) (import-files (.-files (.-dataTransfer e))))))]
]
[:section.dashboard-grid [:section.dashboard-grid
{:on-drag-enter on-drag-enter {:on-drag-enter on-drag-enter

View file

@ -9,6 +9,7 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.math :as mth] [app.common.math :as mth]
[app.main.data.dashboard :as dd] [app.main.data.dashboard :as dd]
[app.main.features :as features]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.dashboard.grid :refer [grid]] [app.main.ui.dashboard.grid :refer [grid]]
@ -20,20 +21,25 @@
(mf/defc libraries-page (mf/defc libraries-page
[{:keys [team] :as props}] [{:keys [team] :as props}]
(let [files-map (mf/deref refs/dashboard-shared-files) (let [files-map (mf/deref refs/dashboard-shared-files)
projects (mf/deref refs/dashboard-projects) projects (mf/deref refs/dashboard-projects)
default-project (->> projects vals (d/seek :is-default)) default-project (->> projects vals (d/seek :is-default))
files (->> (vals files-map) files (->> (vals files-map)
(sort-by :modified-at) (sort-by :modified-at)
(reverse)) (reverse)
(not-empty))
width (mf/use-state nil) components-v2 (features/use-feature :components-v2)
rowref (mf/use-ref)
itemsize 330 width (mf/use-state nil)
ratio (if (some? @width) (/ @width itemsize) 0) rowref (mf/use-ref)
nitems (mth/floor ratio) itemsize (if (>= @width 1030)
limit (min 10 nitems) 280
limit (max 1 limit)] 230)
ratio (if (some? @width) (/ @width itemsize) 0)
nitems (mth/floor ratio)
limit (min 10 nitems)
limit (max 1 limit)]
(mf/use-effect (mf/use-effect
(mf/deps team) (mf/deps team)
(fn [] (fn []
@ -46,7 +52,7 @@
(mf/use-effect (mf/use-effect
#(st/emit! (dd/fetch-shared-files) #(st/emit! (dd/fetch-shared-files)
(dd/clear-selected-files))) (dd/clear-selected-files)))
(mf/with-effect (mf/with-effect
(let [node (mf/ref-val rowref) (let [node (mf/ref-val rowref)
mnt? (volatile! true) mnt? (volatile! true)
@ -71,5 +77,5 @@
:project default-project :project default-project
:origin :libraries :origin :libraries
:limit limit :limit limit
:library-view? true}]]])) :library-view? components-v2}]]]))

View file

@ -12,7 +12,7 @@
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.text :as txt] [app.common.text :as txt]
[app.config :as cfg] [app.config :as cf]
[app.main.data.events :as ev] [app.main.data.events :as ev]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
@ -31,6 +31,7 @@
[app.main.ui.components.file-uploader :refer [file-uploader]] [app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.components.forms :as fm] [app.main.ui.components.forms :as fm]
[app.main.ui.context :as ctx] [app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.options.menus.typography :refer [typography-entry]] [app.main.ui.workspace.sidebar.options.menus.typography :refer [typography-entry]]
[app.util.color :as uc] [app.util.color :as uc]
@ -135,7 +136,7 @@
on-close #(modal/hide!) on-close #(modal/hide!)
on-accept on-accept
(mf/use-callback (mf/use-fn
(mf/deps form) (mf/deps form)
(fn [_] (fn [_]
(let [asset-name (get-in @form [:clean-data :asset-name])] (let [asset-name (get-in @form [:clean-data :asset-name])]
@ -247,8 +248,6 @@
(when (> num-selected 1) (when (> num-selected 1)
(set-drag-image event item-ref num-selected)))) (set-drag-image event item-ref num-selected))))
(defn- on-drag-enter-asset-group (defn- on-drag-enter-asset-group
[event dragging? prefix selected-assets-paths] [event dragging? prefix selected-assets-paths]
(dom/stop-propagation event) (dom/stop-propagation event)
@ -270,9 +269,10 @@
;; ---- Common blocks ---- ;; ---- Common blocks ----
(def auto-pos-menu-state {:open? false (def auto-pos-menu-state
:top nil {:open? false
:left nil}) :top nil
:left nil})
(defn- open-auto-pos-menu (defn- open-auto-pos-menu
[state event] [state event]
@ -326,7 +326,7 @@
menu-state (mf/use-state auto-pos-menu-state) menu-state (mf/use-state auto-pos-menu-state)
on-fold-group on-fold-group
(mf/use-callback (mf/use-fn
(mf/deps file-id box path group-open?) (mf/deps file-id box path group-open?)
(fn [event] (fn [event]
(dom/stop-propagation event) (dom/stop-propagation event)
@ -335,12 +335,12 @@
path path
(not group-open?))))) (not group-open?)))))
on-context-menu on-context-menu
(mf/use-callback (mf/use-fn
(fn [event] (fn [event]
(swap! menu-state #(open-auto-pos-menu % event)))) (swap! menu-state #(open-auto-pos-menu % event))))
on-close-menu on-close-menu
(mf/use-callback (mf/use-fn
(fn [] (fn []
(swap! menu-state close-auto-pos-menu)))] (swap! menu-state close-auto-pos-menu)))]
@ -371,12 +371,12 @@
dragging? (mf/use-state false) dragging? (mf/use-state false)
unselect-all unselect-all
(mf/use-callback (mf/use-fn
(fn [] (fn []
(st/emit! (dw/unselect-all-assets)))) (st/emit! (dw/unselect-all-assets))))
on-component-click on-component-click
(mf/use-callback (mf/use-fn
(mf/deps component selected-components) (mf/deps component selected-components)
(fn [event] (fn [event]
(dom/stop-propagation event) (dom/stop-propagation event)
@ -389,29 +389,29 @@
(on-asset-click event (:id component) unselect-all))))) (on-asset-click event (:id component) unselect-all)))))
on-drop on-drop
(mf/use-callback (mf/use-fn
(mf/deps component dragging? selected-components selected-components-full selected-components-paths) (mf/deps component dragging? selected-components selected-components-full selected-components-paths)
(fn [event] (fn [event]
(on-drop-asset event component dragging? selected-components selected-components-full (on-drop-asset event component dragging? selected-components selected-components-full
selected-components-paths dwl/rename-component))) selected-components-paths dwl/rename-component)))
on-drag-over on-drag-over
(mf/use-callback #(dom/prevent-default %)) (mf/use-fn #(dom/prevent-default %))
on-drag-enter on-drag-enter
(mf/use-callback (mf/use-fn
(mf/deps component dragging? selected-components selected-components-paths) (mf/deps component dragging? selected-components selected-components-paths)
(fn [event] (fn [event]
(on-drag-enter-asset event component dragging? selected-components selected-components-paths))) (on-drag-enter-asset event component dragging? selected-components selected-components-paths)))
on-drag-leave on-drag-leave
(mf/use-callback (mf/use-fn
(mf/deps dragging?) (mf/deps dragging?)
(fn [event] (fn [event]
(on-drag-leave-asset event dragging?))) (on-drag-leave-asset event dragging?)))
on-component-drag-start on-component-drag-start
(mf/use-callback (mf/use-fn
(mf/deps component selected-components item-ref on-drag-start) (mf/deps component selected-components item-ref on-drag-start)
(fn [event] (fn [event]
(on-asset-drag-start event component selected-components item-ref :components on-drag-start)))] (on-asset-drag-start event component selected-components item-ref :components on-drag-start)))]
@ -466,21 +466,21 @@
(map #(if (nil? %) "" %))) (map #(if (nil? %) "" %)))
on-drag-enter on-drag-enter
(mf/use-callback (mf/use-fn
(mf/deps dragging? prefix selected-components-paths) (mf/deps dragging? prefix selected-components-paths)
(fn [event] (fn [event]
(on-drag-enter-asset-group event dragging? prefix selected-components-paths))) (on-drag-enter-asset-group event dragging? prefix selected-components-paths)))
on-drag-leave on-drag-leave
(mf/use-callback (mf/use-fn
(mf/deps dragging?) (mf/deps dragging?)
(fn [event] (fn [event]
(on-drag-leave-asset event dragging?))) (on-drag-leave-asset event dragging?)))
on-drag-over (mf/use-callback #(dom/prevent-default %)) on-drag-over (mf/use-fn #(dom/prevent-default %))
on-drop on-drop
(mf/use-callback (mf/use-fn
(mf/deps dragging? prefix selected-components-paths selected-components-full) (mf/deps dragging? prefix selected-components-paths selected-components-full)
(fn [event] (fn [event]
(on-drop-asset-group event dragging? prefix selected-components-paths selected-components-full dwl/rename-component)))] (on-drop-asset-group event dragging? prefix selected-components-paths selected-components-full dwl/rename-component)))]
@ -567,7 +567,7 @@
groups (group-assets components reverse-sort?) groups (group-assets components reverse-sort?)
on-duplicate on-duplicate
(mf/use-callback (mf/use-fn
(mf/deps @state) (mf/deps @state)
(fn [] (fn []
(if (empty? selected-components) (if (empty? selected-components)
@ -578,7 +578,7 @@
(st/emit! (dwu/commit-undo-transaction)))))) (st/emit! (dwu/commit-undo-transaction))))))
on-delete on-delete
(mf/use-callback (mf/use-fn
(mf/deps @state file-id multi-components? multi-assets?) (mf/deps @state file-id multi-components? multi-assets?)
(fn [] (fn []
(if (or multi-components? multi-assets?) (if (or multi-components? multi-assets?)
@ -589,25 +589,25 @@
(dwu/commit-undo-transaction))))) (dwu/commit-undo-transaction)))))
on-rename on-rename
(mf/use-callback (mf/use-fn
(mf/deps @state) (mf/deps @state)
(fn [] (fn []
(swap! state assoc :renaming (:component-id @state)))) (swap! state assoc :renaming (:component-id @state))))
do-rename do-rename
(mf/use-callback (mf/use-fn
(mf/deps @state) (mf/deps @state)
(fn [new-name] (fn [new-name]
(st/emit! (dwl/rename-component (:renaming @state) new-name)) (st/emit! (dwl/rename-component (:renaming @state) new-name))
(swap! state assoc :renaming nil))) (swap! state assoc :renaming nil)))
cancel-rename cancel-rename
(mf/use-callback (mf/use-fn
(fn [] (fn []
(swap! state assoc :renaming nil))) (swap! state assoc :renaming nil)))
on-context-menu on-context-menu
(mf/use-callback (mf/use-fn
(mf/deps selected-components on-clear-selection) (mf/deps selected-components on-clear-selection)
(fn [component-id] (fn [component-id]
(fn [event] (fn [event]
@ -618,12 +618,12 @@
(swap! menu-state #(open-auto-pos-menu % event)))))) (swap! menu-state #(open-auto-pos-menu % event))))))
on-close-menu on-close-menu
(mf/use-callback (mf/use-fn
(fn [] (fn []
(swap! menu-state close-auto-pos-menu))) (swap! menu-state close-auto-pos-menu)))
create-group create-group
(mf/use-callback (mf/use-fn
(mf/deps components selected-components on-clear-selection) (mf/deps components selected-components on-clear-selection)
(fn [group-name] (fn [group-name]
(on-clear-selection) (on-clear-selection)
@ -639,7 +639,7 @@
(st/emit! (dwu/commit-undo-transaction)))) (st/emit! (dwu/commit-undo-transaction))))
rename-group rename-group
(mf/use-callback (mf/use-fn
(mf/deps components) (mf/deps components)
(fn [path last-path] (fn [path last-path]
(on-clear-selection) (on-clear-selection)
@ -653,14 +653,14 @@
(st/emit! (dwu/commit-undo-transaction)))) (st/emit! (dwu/commit-undo-transaction))))
on-group on-group
(mf/use-callback (mf/use-fn
(mf/deps components selected-components) (mf/deps components selected-components)
(fn [event] (fn [event]
(dom/stop-propagation event) (dom/stop-propagation event)
(modal/show! :name-group-dialog {:accept create-group}))) (modal/show! :name-group-dialog {:accept create-group})))
on-rename-group on-rename-group
(mf/use-callback (mf/use-fn
(mf/deps components) (mf/deps components)
(fn [event path last-path] (fn [event path last-path]
(dom/stop-propagation event) (dom/stop-propagation event)
@ -669,7 +669,7 @@
:accept rename-group}))) :accept rename-group})))
on-ungroup on-ungroup
(mf/use-callback (mf/use-fn
(mf/deps components) (mf/deps components)
(fn [path] (fn [path]
(on-clear-selection) (on-clear-selection)
@ -683,7 +683,7 @@
(st/emit! (dwu/commit-undo-transaction)))) (st/emit! (dwu/commit-undo-transaction))))
on-drag-start on-drag-start
(mf/use-callback (mf/use-fn
(fn [component event] (fn [component event]
(dnd/set-data! event "penpot/component" {:file-id file-id (dnd/set-data! event "penpot/component" {:file-id file-id
:component component}) :component component})
@ -730,36 +730,38 @@
[{:keys [object renaming listing-thumbs? selected-objects [{:keys [object renaming listing-thumbs? selected-objects
on-asset-click on-context-menu on-drag-start do-rename cancel-rename on-asset-click on-context-menu on-drag-start do-rename cancel-rename
selected-graphics-full selected-graphics-paths]}] selected-graphics-full selected-graphics-paths]}]
(let [item-ref (mf/use-ref) (let [item-ref (mf/use-ref)
visible? (h/use-visible item-ref :once? true)
dragging? (mf/use-state false) dragging? (mf/use-state false)
on-drop on-drop
(mf/use-callback (mf/use-fn
(mf/deps object dragging? selected-objects selected-graphics-full selected-graphics-paths) (mf/deps object dragging? selected-objects selected-graphics-full selected-graphics-paths)
(fn [event] (fn [event]
(on-drop-asset event object dragging? selected-objects selected-graphics-full (on-drop-asset event object dragging? selected-objects selected-graphics-full
selected-graphics-paths dwl/rename-media))) selected-graphics-paths dwl/rename-media)))
on-drag-over (mf/use-callback #(dom/prevent-default %)) on-drag-over (mf/use-fn #(dom/prevent-default %))
on-drag-enter on-drag-enter
(mf/use-callback (mf/use-fn
(mf/deps object dragging? selected-objects selected-graphics-paths) (mf/deps object dragging? selected-objects selected-graphics-paths)
(fn [event] (fn [event]
(on-drag-enter-asset event object dragging? selected-objects selected-graphics-paths))) (on-drag-enter-asset event object dragging? selected-objects selected-graphics-paths)))
on-drag-leave on-drag-leave
(mf/use-callback (mf/use-fn
(mf/deps dragging?) (mf/deps dragging?)
(fn [event] (fn [event]
(on-drag-leave-asset event dragging?))) (on-drag-leave-asset event dragging?)))
on-grahic-drag-start on-grahic-drag-start
(mf/use-callback (mf/use-fn
(mf/deps object selected-objects item-ref on-drag-start) (mf/deps object selected-objects item-ref on-drag-start)
(fn [event] (fn [event]
(on-asset-drag-start event object selected-objects item-ref :graphics on-drag-start)))] (on-asset-drag-start event object selected-objects item-ref :graphics on-drag-start)))
]
[:div {:ref item-ref [:div {:ref item-ref
:class-name (dom/classnames :class-name (dom/classnames
@ -774,28 +776,31 @@
:on-drag-leave on-drag-leave :on-drag-leave on-drag-leave
:on-drag-over on-drag-over :on-drag-over on-drag-over
:on-drop on-drop} :on-drop on-drop}
[:img {:src (cfg/resolve-file-media object true)
:draggable false}] ;; Also need to add css pointer-events: none
(let [renaming? (= renaming (:id object))] (when visible?
[:* [:*
[:& editable-label [:img {:src (when visible? (cf/resolve-file-media object true))
{:class-name (dom/classnames :draggable false}] ;; Also need to add css pointer-events: none
:cell-name @listing-thumbs?
:item-name (not @listing-thumbs?) (let [renaming? (= renaming (:id object))]
:editing renaming?) [:*
:value (cph/merge-path-item (:path object) (:name object)) [:& editable-label
:tooltip (cph/merge-path-item (:path object) (:name object)) {:class-name (dom/classnames
:display-value (if @listing-thumbs? :cell-name @listing-thumbs?
(:name object) :item-name (not @listing-thumbs?)
(cph/compact-name (:path object) :editing renaming?)
(:name object))) :value (cph/merge-path-item (:path object) (:name object))
:editing? renaming? :tooltip (cph/merge-path-item (:path object) (:name object))
:disable-dbl-click? true :display-value (if @listing-thumbs?
:on-change do-rename (:name object)
:on-cancel cancel-rename}] (cph/compact-name (:path object)
(when @dragging? (:name object)))
[:div.dragging])])])) :editing? renaming?
:disable-dbl-click? true
:on-change do-rename
:on-cancel cancel-rename}]
(when @dragging?
[:div.dragging])])])]))
(mf/defc graphics-group (mf/defc graphics-group
[{:keys [file-id prefix groups open-groups renaming listing-thumbs? selected-objects on-asset-click [{:keys [file-id prefix groups open-groups renaming listing-thumbs? selected-objects on-asset-click
@ -811,21 +816,21 @@
on-drag-enter on-drag-enter
(mf/use-callback (mf/use-fn
(mf/deps dragging? prefix selected-graphics-paths) (mf/deps dragging? prefix selected-graphics-paths)
(fn [event] (fn [event]
(on-drag-enter-asset-group event dragging? prefix selected-graphics-paths))) (on-drag-enter-asset-group event dragging? prefix selected-graphics-paths)))
on-drag-leave on-drag-leave
(mf/use-callback (mf/use-fn
(mf/deps dragging?) (mf/deps dragging?)
(fn [event] (fn [event]
(on-drag-leave-asset event dragging?))) (on-drag-leave-asset event dragging?)))
on-drag-over (mf/use-callback #(dom/prevent-default %)) on-drag-over (mf/use-fn #(dom/prevent-default %))
on-drop on-drop
(mf/use-callback (mf/use-fn
(mf/deps dragging? prefix selected-graphics-paths selected-graphics-full) (mf/deps dragging? prefix selected-graphics-paths selected-graphics-full)
(fn [event] (fn [event]
(on-drop-asset-group event dragging? prefix selected-graphics-paths selected-graphics-full dwl/rename-media)))] (on-drop-asset-group event dragging? prefix selected-graphics-paths selected-graphics-full dwl/rename-media)))]
@ -915,13 +920,13 @@
groups (group-assets objects reverse-sort?) groups (group-assets objects reverse-sort?)
add-graphic add-graphic
(mf/use-callback (mf/use-fn
(fn [] (fn []
#(st/emit! (dwl/set-assets-box-open file-id :graphics true)) #(st/emit! (dwl/set-assets-box-open file-id :graphics true))
(dom/click (mf/ref-val input-ref)))) (dom/click (mf/ref-val input-ref))))
on-file-selected on-file-selected
(mf/use-callback (mf/use-fn
(mf/deps file-id) (mf/deps file-id)
(fn [blobs] (fn [blobs]
(let [params {:file-id file-id (let [params {:file-id file-id
@ -931,7 +936,7 @@
:asset-type "graphics"}))))) :asset-type "graphics"})))))
on-delete on-delete
(mf/use-callback (mf/use-fn
(mf/deps @state multi-objects? multi-assets?) (mf/deps @state multi-objects? multi-assets?)
(fn [] (fn []
(if (or multi-objects? multi-assets?) (if (or multi-objects? multi-assets?)
@ -939,25 +944,25 @@
(st/emit! (dwl/delete-media {:id (:object-id @state)}))))) (st/emit! (dwl/delete-media {:id (:object-id @state)})))))
on-rename on-rename
(mf/use-callback (mf/use-fn
(mf/deps @state) (mf/deps @state)
(fn [] (fn []
(swap! state assoc :renaming (:object-id @state)))) (swap! state assoc :renaming (:object-id @state))))
cancel-rename cancel-rename
(mf/use-callback (mf/use-fn
(fn [] (fn []
(swap! state assoc :renaming nil))) (swap! state assoc :renaming nil)))
do-rename do-rename
(mf/use-callback (mf/use-fn
(mf/deps @state) (mf/deps @state)
(fn [new-name] (fn [new-name]
(st/emit! (dwl/rename-media (:renaming @state) new-name)) (st/emit! (dwl/rename-media (:renaming @state) new-name))
(swap! state assoc :renaming nil))) (swap! state assoc :renaming nil)))
on-context-menu on-context-menu
(mf/use-callback (mf/use-fn
(mf/deps selected-objects on-clear-selection) (mf/deps selected-objects on-clear-selection)
(fn [object-id] (fn [object-id]
(fn [event] (fn [event]
@ -968,12 +973,12 @@
(swap! menu-state #(open-auto-pos-menu % event)))))) (swap! menu-state #(open-auto-pos-menu % event))))))
on-close-menu on-close-menu
(mf/use-callback (mf/use-fn
(fn [] (fn []
(swap! menu-state close-auto-pos-menu))) (swap! menu-state close-auto-pos-menu)))
create-group create-group
(mf/use-callback (mf/use-fn
(mf/deps objects selected-objects on-clear-selection) (mf/deps objects selected-objects on-clear-selection)
(fn [group-name] (fn [group-name]
(on-clear-selection) (on-clear-selection)
@ -989,7 +994,7 @@
(st/emit! (dwu/commit-undo-transaction)))) (st/emit! (dwu/commit-undo-transaction))))
rename-group rename-group
(mf/use-callback (mf/use-fn
(mf/deps objects) (mf/deps objects)
(fn [path last-path] (fn [path last-path]
(on-clear-selection) (on-clear-selection)
@ -1003,14 +1008,14 @@
(st/emit! (dwu/commit-undo-transaction)))) (st/emit! (dwu/commit-undo-transaction))))
on-group on-group
(mf/use-callback (mf/use-fn
(mf/deps objects selected-objects) (mf/deps objects selected-objects)
(fn [event] (fn [event]
(dom/stop-propagation event) (dom/stop-propagation event)
(modal/show! :name-group-dialog {:accept create-group}))) (modal/show! :name-group-dialog {:accept create-group})))
on-rename-group on-rename-group
(mf/use-callback (mf/use-fn
(mf/deps objects) (mf/deps objects)
(fn [event path last-path] (fn [event path last-path]
(dom/stop-propagation event) (dom/stop-propagation event)
@ -1018,7 +1023,7 @@
:last-path last-path :last-path last-path
:accept rename-group}))) :accept rename-group})))
on-ungroup on-ungroup
(mf/use-callback (mf/use-fn
(mf/deps objects) (mf/deps objects)
(fn [path] (fn [path]
(on-clear-selection) (on-clear-selection)
@ -1032,7 +1037,7 @@
(st/emit! (dwu/commit-undo-transaction)))) (st/emit! (dwu/commit-undo-transaction))))
on-drag-start on-drag-start
(mf/use-callback (mf/use-fn
(fn [{:keys [name id mtype]} event] (fn [{:keys [name id mtype]} event]
(dnd/set-data! event "text/asset-id" (str id)) (dnd/set-data! event "text/asset-id" (str id))
(dnd/set-data! event "text/asset-name" name) (dnd/set-data! event "text/asset-name" name)
@ -1131,7 +1136,7 @@
(st/emit! (dwl/update-color updated-color file-id)))) (st/emit! (dwl/update-color updated-color file-id))))
delete-color delete-color
(mf/use-callback (mf/use-fn
(mf/deps @state multi-colors? multi-assets? file-id) (mf/deps @state multi-colors? multi-assets? file-id)
(fn [] (fn []
(if (or multi-colors? multi-assets?) (if (or multi-colors? multi-assets?)
@ -1173,7 +1178,7 @@
:position :right})) :position :right}))
on-context-menu on-context-menu
(mf/use-callback (mf/use-fn
(mf/deps color selected-colors on-clear-selection) (mf/deps color selected-colors on-clear-selection)
(fn [event] (fn [event]
(when local? (when local?
@ -1182,32 +1187,32 @@
(swap! menu-state #(open-auto-pos-menu % event))))) (swap! menu-state #(open-auto-pos-menu % event)))))
on-close-menu on-close-menu
(mf/use-callback (mf/use-fn
(fn [] (fn []
(swap! menu-state close-auto-pos-menu))) (swap! menu-state close-auto-pos-menu)))
on-drop on-drop
(mf/use-callback (mf/use-fn
(mf/deps color dragging? selected-colors selected-colors-full selected-colors-paths move-color) (mf/deps color dragging? selected-colors selected-colors-full selected-colors-paths move-color)
(fn [event] (fn [event]
(on-drop-asset event color dragging? selected-colors selected-colors-full (on-drop-asset event color dragging? selected-colors selected-colors-full
selected-colors-paths move-color))) selected-colors-paths move-color)))
on-drag-over (mf/use-callback #(dom/prevent-default %)) on-drag-over (mf/use-fn #(dom/prevent-default %))
on-drag-enter on-drag-enter
(mf/use-callback (mf/use-fn
(mf/deps color dragging? selected-colors selected-colors-paths) (mf/deps color dragging? selected-colors selected-colors-paths)
(fn [event] (fn [event]
(on-drag-enter-asset event color dragging? selected-colors selected-colors-paths))) (on-drag-enter-asset event color dragging? selected-colors selected-colors-paths)))
on-drag-leave on-drag-leave
(mf/use-callback (mf/use-fn
(mf/deps dragging?) (mf/deps dragging?)
(fn [event] (fn [event]
(on-drag-leave-asset event dragging?))) (on-drag-leave-asset event dragging?)))
on-color-drag-start on-color-drag-start
(mf/use-callback (mf/use-fn
(mf/deps color selected-colors item-ref) (mf/deps color selected-colors item-ref)
(fn [event] (fn [event]
(on-asset-drag-start event color selected-colors item-ref :colors identity)))] (on-asset-drag-start event color selected-colors item-ref :colors identity)))]
@ -1277,20 +1282,20 @@
move-color (partial dwl/rename-color file-id) move-color (partial dwl/rename-color file-id)
on-drag-enter on-drag-enter
(mf/use-callback (mf/use-fn
(mf/deps dragging? prefix selected-colors-paths) (mf/deps dragging? prefix selected-colors-paths)
(fn [event] (fn [event]
(on-drag-enter-asset-group event dragging? prefix selected-colors-paths))) (on-drag-enter-asset-group event dragging? prefix selected-colors-paths)))
on-drag-leave (mf/use-callback on-drag-leave (mf/use-fn
(mf/deps dragging?) (mf/deps dragging?)
(fn [event] (fn [event]
(on-drag-leave-asset event dragging?))) (on-drag-leave-asset event dragging?)))
on-drag-over (mf/use-callback #(dom/prevent-default %)) on-drag-over (mf/use-fn #(dom/prevent-default %))
on-drop on-drop
(mf/use-callback (mf/use-fn
(mf/deps dragging? prefix selected-colors-paths selected-colors-full move-color) (mf/deps dragging? prefix selected-colors-paths selected-colors-full move-color)
(fn [event] (fn [event]
(on-drop-asset-group event dragging? prefix selected-colors-paths selected-colors-full move-color)))] (on-drop-asset-group event dragging? prefix selected-colors-paths selected-colors-full move-color)))]
@ -1371,13 +1376,13 @@
groups (group-assets colors reverse-sort?) groups (group-assets colors reverse-sort?)
add-color add-color
(mf/use-callback (mf/use-fn
(mf/deps file-id) (mf/deps file-id)
(fn [value _opacity] (fn [value _opacity]
(st/emit! (dwl/add-color value)))) (st/emit! (dwl/add-color value))))
add-color-clicked add-color-clicked
(mf/use-callback (mf/use-fn
(mf/deps file-id) (mf/deps file-id)
(fn [event] (fn [event]
(st/emit! (dwl/set-assets-box-open file-id :colors true) (st/emit! (dwl/set-assets-box-open file-id :colors true)
@ -1392,7 +1397,7 @@
:position :right}))) :position :right})))
create-group create-group
(mf/use-callback (mf/use-fn
(mf/deps colors selected-colors on-clear-selection file-id) (mf/deps colors selected-colors on-clear-selection file-id)
(fn [color-id] (fn [color-id]
(fn [group-name] (fn [group-name]
@ -1410,7 +1415,7 @@
(st/emit! (dwu/commit-undo-transaction))))) (st/emit! (dwu/commit-undo-transaction)))))
rename-group rename-group
(mf/use-callback (mf/use-fn
(mf/deps colors) (mf/deps colors)
(fn [path last-path] (fn [path last-path]
(on-clear-selection) (on-clear-selection)
@ -1425,7 +1430,7 @@
(st/emit! (dwu/commit-undo-transaction)))) (st/emit! (dwu/commit-undo-transaction))))
on-group on-group
(mf/use-callback (mf/use-fn
(mf/deps colors selected-colors) (mf/deps colors selected-colors)
(fn [color-id] (fn [color-id]
(fn [event] (fn [event]
@ -1433,7 +1438,7 @@
(modal/show! :name-group-dialog {:accept (create-group color-id)})))) (modal/show! :name-group-dialog {:accept (create-group color-id)}))))
on-rename-group on-rename-group
(mf/use-callback (mf/use-fn
(mf/deps colors) (mf/deps colors)
(fn [event path last-path] (fn [event path last-path]
(dom/stop-propagation event) (dom/stop-propagation event)
@ -1441,7 +1446,7 @@
:last-path last-path :last-path last-path
:accept rename-group}))) :accept rename-group})))
on-ungroup on-ungroup
(mf/use-callback (mf/use-fn
(mf/deps colors) (mf/deps colors)
(fn [path] (fn [path]
(on-clear-selection) (on-clear-selection)
@ -1492,28 +1497,28 @@
(let [item-ref (mf/use-ref) (let [item-ref (mf/use-ref)
dragging? (mf/use-state false) dragging? (mf/use-state false)
on-drop on-drop
(mf/use-callback (mf/use-fn
(mf/deps typography dragging? selected-typographies selected-typographies-full selected-typographies-paths move-typography) (mf/deps typography dragging? selected-typographies selected-typographies-full selected-typographies-paths move-typography)
(fn [event] (fn [event]
(on-drop-asset event typography dragging? selected-typographies selected-typographies-full (on-drop-asset event typography dragging? selected-typographies selected-typographies-full
selected-typographies-paths move-typography))) selected-typographies-paths move-typography)))
on-drag-over (mf/use-callback #(dom/prevent-default %)) on-drag-over (mf/use-fn #(dom/prevent-default %))
on-drag-enter on-drag-enter
(mf/use-callback (mf/use-fn
(mf/deps typography dragging? selected-typographies selected-typographies-paths) (mf/deps typography dragging? selected-typographies selected-typographies-paths)
(fn [event] (fn [event]
(on-drag-enter-asset event typography dragging? selected-typographies selected-typographies-paths))) (on-drag-enter-asset event typography dragging? selected-typographies selected-typographies-paths)))
on-drag-leave on-drag-leave
(mf/use-callback (mf/use-fn
(mf/deps dragging?) (mf/deps dragging?)
(fn [event] (fn [event]
(on-drag-leave-asset event dragging?))) (on-drag-leave-asset event dragging?)))
on-typography-drag-start on-typography-drag-start
(mf/use-callback (mf/use-fn
(mf/deps typography selected-typographies item-ref) (mf/deps typography selected-typographies item-ref)
(fn [event] (fn [event]
(on-asset-drag-start event typography selected-typographies item-ref :typographies identity)))] (on-asset-drag-start event typography selected-typographies item-ref :typographies identity)))]
@ -1554,21 +1559,21 @@
move-typography (partial dwl/rename-typography file-id) move-typography (partial dwl/rename-typography file-id)
on-drag-enter on-drag-enter
(mf/use-callback (mf/use-fn
(mf/deps dragging? prefix selected-typographies-paths) (mf/deps dragging? prefix selected-typographies-paths)
(fn [event] (fn [event]
(on-drag-enter-asset-group event dragging? prefix selected-typographies-paths))) (on-drag-enter-asset-group event dragging? prefix selected-typographies-paths)))
on-drag-leave on-drag-leave
(mf/use-callback (mf/use-fn
(mf/deps dragging?) (mf/deps dragging?)
(fn [event] (fn [event]
(on-drag-leave-asset event dragging?))) (on-drag-leave-asset event dragging?)))
on-drag-over (mf/use-callback #(dom/prevent-default %)) on-drag-over (mf/use-fn #(dom/prevent-default %))
on-drop on-drop
(mf/use-callback (mf/use-fn
(mf/deps dragging? prefix selected-typographies-paths selected-typographies-full move-typography) (mf/deps dragging? prefix selected-typographies-paths selected-typographies-full move-typography)
(fn [event] (fn [event]
(on-drop-asset-group event dragging? prefix selected-typographies-paths selected-typographies-full move-typography)))] (on-drop-asset-group event dragging? prefix selected-typographies-paths selected-typographies-full move-typography)))]
@ -1653,7 +1658,7 @@
(seq (:colors selected-assets))) (seq (:colors selected-assets)))
add-typography add-typography
(mf/use-callback (mf/use-fn
(mf/deps file-id) (mf/deps file-id)
(fn [_] (fn [_]
(st/emit! (dwl/add-typography txt/default-typography) (st/emit! (dwl/add-typography txt/default-typography)
@ -1661,7 +1666,7 @@
:asset-type "typography"})))) :asset-type "typography"}))))
handle-change handle-change
(mf/use-callback (mf/use-fn
(mf/deps file-id) (mf/deps file-id)
(fn [typography changes] (fn [typography changes]
(st/emit! (dwl/update-typography (merge typography changes) file-id)))) (st/emit! (dwl/update-typography (merge typography changes) file-id))))
@ -1681,7 +1686,7 @@
ids))) ids)))
create-group create-group
(mf/use-callback (mf/use-fn
(mf/deps typographies selected-typographies on-clear-selection file-id) (mf/deps typographies selected-typographies on-clear-selection file-id)
(fn [group-name] (fn [group-name]
(on-clear-selection) (on-clear-selection)
@ -1698,7 +1703,7 @@
(st/emit! (dwu/commit-undo-transaction)))) (st/emit! (dwu/commit-undo-transaction))))
rename-group rename-group
(mf/use-callback (mf/use-fn
(mf/deps typographies) (mf/deps typographies)
(fn [path last-path] (fn [path last-path]
(on-clear-selection) (on-clear-selection)
@ -1713,14 +1718,14 @@
(st/emit! (dwu/commit-undo-transaction)))) (st/emit! (dwu/commit-undo-transaction))))
on-group on-group
(mf/use-callback (mf/use-fn
(mf/deps typographies selected-typographies) (mf/deps typographies selected-typographies)
(fn [event] (fn [event]
(dom/stop-propagation event) (dom/stop-propagation event)
(modal/show! :name-group-dialog {:accept create-group}))) (modal/show! :name-group-dialog {:accept create-group})))
on-rename-group on-rename-group
(mf/use-callback (mf/use-fn
(mf/deps typographies) (mf/deps typographies)
(fn [event path last-path] (fn [event path last-path]
(dom/stop-propagation event) (dom/stop-propagation event)
@ -1728,7 +1733,7 @@
:last-path last-path :last-path last-path
:accept rename-group}))) :accept rename-group})))
on-ungroup on-ungroup
(mf/use-callback (mf/use-fn
(mf/deps typographies) (mf/deps typographies)
(fn [path] (fn [path]
(on-clear-selection) (on-clear-selection)
@ -1743,7 +1748,7 @@
(st/emit! (dwu/commit-undo-transaction)))) (st/emit! (dwu/commit-undo-transaction))))
on-context-menu on-context-menu
(mf/use-callback (mf/use-fn
(mf/deps selected-typographies on-clear-selection) (mf/deps selected-typographies on-clear-selection)
(fn [id event] (fn [id event]
(when local? (when local?
@ -1753,7 +1758,7 @@
(swap! menu-state #(open-auto-pos-menu % event))))) (swap! menu-state #(open-auto-pos-menu % event)))))
on-close-menu on-close-menu
(mf/use-callback (mf/use-fn
(fn [] (fn []
(swap! menu-state close-auto-pos-menu))) (swap! menu-state close-auto-pos-menu)))
@ -1766,7 +1771,7 @@
(st/emit! #(assoc-in % [:workspace-global :edit-typography] (:id @state)))) (st/emit! #(assoc-in % [:workspace-global :edit-typography] (:id @state))))
handle-delete-typography handle-delete-typography
(mf/use-callback (mf/use-fn
(mf/deps @state multi-typographies? multi-assets?) (mf/deps @state multi-typographies? multi-assets?)
(fn [] (fn []
(if (or multi-typographies? multi-assets?) (if (or multi-typographies? multi-assets?)
@ -1936,17 +1941,17 @@
components (apply-filters (mf/deref components-ref) filters @reverse-sort?) components (apply-filters (mf/deref components-ref) filters @reverse-sort?)
toggle-sort toggle-sort
(mf/use-callback (mf/use-fn
(fn [_] (fn [_]
(swap! reverse-sort? not))) (swap! reverse-sort? not)))
toggle-listing toggle-listing
(mf/use-callback (mf/use-fn
(fn [_] (fn [_]
(swap! listing-thumbs? not))) (swap! listing-thumbs? not)))
extend-selected-assets extend-selected-assets
(mf/use-callback (mf/use-fn
(mf/deps selected-assets) (mf/deps selected-assets)
(fn [asset-type asset-groups asset-id] (fn [asset-type asset-groups asset-id]
(letfn [(flatten-groups (letfn [(flatten-groups
@ -1977,12 +1982,12 @@
(st/emit! (dw/select-assets values asset-type)))))))) (st/emit! (dw/select-assets values asset-type))))))))
unselect-all unselect-all
(mf/use-callback (mf/use-fn
(fn [] (fn []
(st/emit! (dw/unselect-all-assets)))) (st/emit! (dw/unselect-all-assets))))
on-asset-click on-asset-click
(mf/use-callback (mf/use-fn
(mf/deps selected-assets) (mf/deps selected-assets)
(fn [asset-type asset-groups event asset-id default-click] (fn [asset-type asset-groups event asset-id default-click]
(cond (cond
@ -2001,7 +2006,7 @@
(default-click event))))) (default-click event)))))
on-assets-delete on-assets-delete
(mf/use-callback (mf/use-fn
(mf/deps selected-assets) (mf/deps selected-assets)
(fn [] (fn []
(st/emit! (dwu/start-undo-transaction)) (st/emit! (dwu/start-undo-transaction))
@ -2136,20 +2141,20 @@
filters (mf/use-state {:term "" :box :all}) filters (mf/use-state {:term "" :box :all})
on-search-term-change on-search-term-change
(mf/use-callback (mf/use-fn
(mf/deps team-id) (mf/deps team-id)
(fn [event] (fn [event]
(let [value (dom/get-target-val event)] (let [value (dom/get-target-val event)]
(swap! filters assoc :term value)))) (swap! filters assoc :term value))))
on-search-clear-click on-search-clear-click
(mf/use-callback (mf/use-fn
(mf/deps team-id) (mf/deps team-id)
(fn [_] (fn [_]
(swap! filters assoc :term ""))) (swap! filters assoc :term "")))
on-box-filter-change on-box-filter-change
(mf/use-callback (mf/use-fn
(mf/deps team-id) (mf/deps team-id)
(fn [event] (fn [event]
(let [value (-> (dom/get-target event) (let [value (-> (dom/get-target event)

View file

@ -183,7 +183,7 @@
(let [objects (deref refs/workspace-page-objects) (let [objects (deref refs/workspace-page-objects)
destination (get objects (:destination interaction)) destination (get objects (:destination interaction))
frames (mf/with-memo [objects] (ctt/get-viewer-frames objects {:all-frames? (not= :navigate (:action-type interaction))})) frames (mf/with-memo [objects] (ctt/get-viewer-frames objects {:all-frames? true}))
overlay-pos-type (:overlay-pos-type interaction) overlay-pos-type (:overlay-pos-type interaction)
close-click-outside? (:close-click-outside interaction false) close-click-outside? (:close-click-outside interaction false)

View file

@ -12,6 +12,8 @@
[app.main.constants :refer [size-presets]] [app.main.constants :refer [size-presets]]
[app.main.data.workspace :as udw] [app.main.data.workspace :as udw]
[app.main.data.workspace.changes :as dch] [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.interactions :as dwi]
[app.main.data.workspace.undo :as dwu]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]] [app.main.ui.components.dropdown :refer [dropdown]]
@ -236,7 +238,16 @@
(mf/deps ids) (mf/deps ids)
(fn [event] (fn [event]
(let [value (-> event dom/get-target dom/checked?)] (let [value (-> event dom/get-target dom/checked?)]
(st/emit! (dch/update-shapes ids (fn [shape] (assoc shape :hide-in-viewer (not value)))))))) (do
(st/emit! (dwu/start-undo-transaction)
(dch/update-shapes ids (fn [shape] (assoc shape :hide-in-viewer (not value)))))
(when-not value
;; when a frame is no longer shown in view mode, cannot have
;; interactions that navigate to it.
(apply st/emit! (map #(dwi/remove-all-interactions-nav-to %) ids)))
(st/emit! (dwu/commit-undo-transaction))))))
select-all #(-> % (dom/get-target) (.select))] select-all #(-> % (dom/get-target) (.select))]