0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-08 08:09:14 -05:00

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
### :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 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)
@ -27,7 +28,7 @@
### :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 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)
@ -42,6 +43,7 @@
- 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
- 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
@ -55,6 +57,7 @@
- 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 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
### :heart: Community contributions by (Thank you!)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -512,6 +512,18 @@
(assert (has-offset-effect? interaction))
(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
(defn add-interaction
@ -543,6 +555,12 @@
(d/update-when interaction :destination #(get ids-map % %)))))]
(into [] xform interactions))))
(defn remove-interactions
"Remove all interactions that the fn returns true."
[f interactions]
(-> (d/removev f interactions)
not-empty))
(defn actionable?
"Check if there is any interaction that is clickable by the user"
[interactions]

View file

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

View file

@ -17,6 +17,7 @@
[app.common.uuid :as uuid]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.undo :as dwu]
[app.main.streams :as ms]
[beicon.core :as rx]
[potok.core :as ptk]))
@ -149,6 +150,29 @@
(update shape :interactions
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 finish-edit-interaction)
@ -171,8 +195,7 @@
(rx/map #(move-edit-interaction initial-pos %)))
(rx/of (finish-edit-interaction index initial-pos))))))))
(defn get-target-frame
(defn- get-target-frame
[state position]
(let [objects (wsh/lookup-page-objects state)
@ -185,8 +208,7 @@
target-frame (ctst/frame-by-position objects position)]
(when (and (not= (:id target-frame) uuid/zero)
(not= (:id target-frame) from-frame-id)
(not (:hide-in-viewer target-frame)))
(not= (:id target-frame) from-frame-id))
target-frame)))
(defn move-edit-interaction
@ -225,25 +247,34 @@
:always
(ctsi/set-destination (:id target-frame))))]
(cond
(or (nil? shape)
(rx/of
(dwu/start-undo-transaction)
;; Didn't changed the position for the interaction
(= position initial-pos)
(when (:hide-in-viewer target-frame)
; 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
(and (nil? index) (nil? target-frame)))
nil
(cond
(or (nil? shape)
;; 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
(and (some? index) (nil? target-frame))
(rx/of (remove-interaction shape index))
;; Dropped interaction in an invalid target. We remove it
(and (some? index) (nil? target-frame))
(remove-interaction shape index)
(nil? index)
(rx/of (add-new-interaction shape (:id target-frame)))
(nil? index)
(add-new-interaction shape (:id target-frame))
:else
(rx/of (update-interaction shape index change-interaction)))))))
:else
(update-interaction shape index change-interaction))
(dwu/commit-undo-transaction))))))
;; --- Overlays

View file

@ -17,7 +17,6 @@
[app.common.pages.helpers :as cph]
[app.common.spec :as us]
[app.common.types.shape-tree :as ctst]
[app.common.uuid :as uuid]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.collapse :as dwc]
[app.main.data.workspace.comments :as-alias dwcm]
@ -243,7 +242,7 @@
(defn- check-delta
"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."
[shape root transformed-shape transformed-root objects]
[shape root transformed-shape transformed-root objects modif-tree]
(let [root
(cond
(:component-root? shape)
@ -260,7 +259,8 @@
transformed-shape
(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)
@ -298,7 +298,7 @@
transformed-shape (gsh/transform-shape (merge shape (get modif-tree shape-id)))
[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?)
@ -758,9 +758,6 @@
(keep lookup)
(remove #(= (:frame-id %) frame-id)))
moving-frames
(filter #(cph/frame-shape? (lookup %)) ids)
changes
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects)

View file

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

View file

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

View file

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

View file

@ -183,7 +183,7 @@
(let [objects (deref refs/workspace-page-objects)
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)
close-click-outside? (:close-click-outside interaction false)

View file

@ -12,6 +12,8 @@
[app.main.constants :refer [size-presets]]
[app.main.data.workspace :as udw]
[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.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
@ -236,7 +238,16 @@
(mf/deps ids)
(fn [event]
(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))]