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

This commit is contained in:
Alejandro Alonso 2024-06-13 11:04:58 +02:00
commit 7e87362a39
48 changed files with 995 additions and 145 deletions

View file

@ -328,11 +328,15 @@
(-data [_] {})
ptk/WatchEvent
(watch [_ _ _]
(->> (rp/cmd! :logout)
(rx/delay-at-least 300)
(rx/catch (constantly (rx/of 1)))
(rx/map #(logged-out params)))))))
(watch [_ state _]
(let [profile-id (:profile-id state)]
(->> (rx/interval 500)
(rx/take 1)
(rx/mapcat (fn [_]
(->> (rp/cmd! :logout {:profile-id profile-id})
(rx/delay-at-least 300)
(rx/catch (constantly (rx/of 1))))))
(rx/map #(logged-out params))))))))
;; --- Update Profile

View file

@ -248,7 +248,7 @@
(assoc :stroke-style :solid)
(not (contains? new-attrs :stroke-alignment))
(assoc :stroke-alignment :inner)
(assoc :stroke-alignment :center)
:always
(d/without-nils))]

View file

@ -198,7 +198,8 @@
(dws/select-shapes (d/ordered-set (:id group))))
(ptk/data-event :layout/update {:ids parents}))))))))
(def group-selected
(defn group-selected
[]
(ptk/reify ::group-selected
ptk/WatchEvent
(watch [_ state _]
@ -258,7 +259,8 @@
(when change-selection?
(dws/select-shapes child-ids))))))))
(def ungroup-selected
(defn ungroup-selected
[]
(ptk/reify ::ungroup-selected
ptk/WatchEvent
(watch [_ state _]

View file

@ -79,20 +79,21 @@
(rx/from (->> guides (mapv #(remove-guide %))))))))
(defmethod ptk/resolve ::move-frame-guides
[_ ids]
[_ args]
(dm/assert!
"expected a coll of uuids"
(every? uuid? ids))
(every? uuid? (:ids args)))
(ptk/reify ::move-frame-guides
ptk/WatchEvent
(watch [_ state _]
(let [objects (wsh/lookup-page-objects state)
(let [ids (:ids args)
object-modifiers (:modifiers args)
objects (wsh/lookup-page-objects state)
is-frame? (fn [id] (= :frame (get-in objects [id :type])))
frame-ids? (into #{} (filter is-frame?) ids)
object-modifiers (get state :workspace-modifiers)
build-move-event
(fn [guide]
(let [frame (get objects (:frame-id guide))

View file

@ -497,7 +497,7 @@
(if undo-transation?
(rx/of (dwu/start-undo-transaction undo-id))
(rx/empty))
(rx/of (ptk/event ::dwg/move-frame-guides ids-with-children)
(rx/of (ptk/event ::dwg/move-frame-guides {:ids ids-with-children :modifiers object-modifiers})
(ptk/event ::dwcm/move-frame-comment-threads ids-with-children)
(dwsh/update-shapes
ids

View file

@ -22,6 +22,7 @@
(or (= type ::common/finish-path)
(= type :app.main.data.workspace.path.shortcuts/esc-pressed)
(= type :app.main.data.workspace.common/clear-edition-mode)
(= type :app.main.data.workspace.edition/clear-edition-mode)
(= type :app.main.data.workspace/finalize-page)
(= event :interrupt) ;; ESC
(and ^boolean (mse/mouse-event? event)

View file

@ -119,12 +119,12 @@
:group {:tooltip (ds/meta "G")
:command (ds/c-mod "g")
:subsections [:modify-layers]
:fn #(emit-when-no-readonly dw/group-selected)}
:fn #(emit-when-no-readonly (dw/group-selected))}
:ungroup {:tooltip (ds/shift "G")
:command "shift+g"
:subsections [:modify-layers]
:fn #(emit-when-no-readonly dw/ungroup-selected)}
:fn #(emit-when-no-readonly (dw/ungroup-selected))}
:mask {:tooltip (ds/meta "M")
:command (ds/c-mod "m")

View file

@ -20,6 +20,7 @@
[app.main.ui.icons :as i]
[app.util.i18n :refer [tr tr-html]]
[app.util.router :as rt]
[app.util.storage :as sto]
[beicon.v2.core :as rx]
[cljs.spec.alpha :as s]
[rumext.v2 :as mf]))
@ -163,11 +164,7 @@
;; --- PAGE: register validation
(defn- handle-register-error
[_form _data]
(st/emit! (msg/error (tr "errors.generic"))))
(defn- handle-register-success
(defn- on-register-success
[data]
(cond
(some? (:invitation-token data))
@ -178,7 +175,9 @@
(st/emit! (du/login-from-register))
:else
(st/emit! (rt/nav :auth-register-success {} {:email (:email data)}))))
(do
(swap! sto/storage assoc ::email (:email data))
(st/emit! (rt/nav :auth-register-success)))))
(s/def ::accept-terms-and-privacy (s/and ::us/boolean true?))
(s/def ::accept-newsletter-subscription ::us/boolean)
@ -192,31 +191,63 @@
:opt-un [::accept-terms-and-privacy
::accept-newsletter-subscription])))
(mf/defc terms-and-privacy
{::mf/props :obj
::mf/private true}
[]
(let [terms-label
(mf/html
[:& tr-html
{:tag-name "div"
:label "auth.terms-and-privacy-agreement"
:params [cf/terms-of-service-uri cf/privacy-policy-uri]}])]
[:div {:class (stl/css :fields-row :input-visible :accept-terms-and-privacy-wrapper)}
[:& fm/input {:name :accept-terms-and-privacy
:class (stl/css :checkbox-terms-and-privacy)
:type "checkbox"
:default-checked false
:label terms-label}]]))
(mf/defc register-validate-form
{::mf/props :obj}
[{:keys [params on-success-callback]}]
(let [form (fm/use-form :spec ::register-validate-form
:validators [(fm/validate-not-empty :fullname (tr "auth.name.not-all-space"))
(fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long"))]
(let [validators (mf/with-memo []
[(fm/validate-not-empty :fullname (tr "auth.name.not-all-space"))
(fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long"))])
form (fm/use-form :spec ::register-validate-form
:validators validators
:initial params)
submitted? (mf/use-state false)
on-success (fn [p]
(if (nil? on-success-callback)
(handle-register-success p)
(on-success-callback (:email p))))
on-success
(mf/use-fn
(mf/deps on-success-callback)
(fn [params]
(if (nil? on-success-callback)
(on-register-success params)
(on-success-callback (:email params)))))
on-error
(mf/use-fn
(fn [_cause]
(st/emit! (msg/error (tr "errors.generic")))))
on-submit
(mf/use-fn
(fn [form _event]
(fn [form _]
(reset! submitted? true)
(let [params (:clean-data @form)]
(->> (rp/cmd! :register-profile params)
(rx/finalize #(reset! submitted? false))
(rx/subs! on-success
(partial handle-register-error form))))))]
(rx/subs! on-success on-error)))))]
[:& fm/form {:on-submit on-submit :form form
[:& fm/form {:on-submit on-submit
:form form
:class (stl/css :register-validate-form)}
[:div {:class (stl/css :fields-row)}
[:& fm/input {:name :fullname
:label (tr "auth.fullname")
@ -225,18 +256,7 @@
:class (stl/css :form-field)}]]
(when (contains? cf/flags :terms-and-privacy-checkbox)
(let [terms-label
(mf/html
[:& tr-html
{:tag-name "div"
:label "auth.terms-and-privacy-agreement"
:params [cf/terms-of-service-uri cf/privacy-policy-uri]}])]
[:div {:class (stl/css :fields-row :input-visible :accept-terms-and-privacy-wrapper)}
[:& fm/input {:name :accept-terms-and-privacy
:class (stl/css :checkbox-terms-and-privacy)
:type "checkbox"
:default-checked false
:label terms-label}]]))
[:& terms-and-privacy])
[:> fm/submit-button*
{:label (tr "auth.register-submit")
@ -245,6 +265,7 @@
(mf/defc register-validate-page
{::mf/props :obj}
[{:keys [params]}]
[:div {:class (stl/css :auth-form-wrapper)}
[:h1 {:class (stl/css :logo-container)}
@ -263,13 +284,15 @@
(tr "labels.go-back")]]]])
(mf/defc register-success-page
[{:keys [params]}]
[:div {:class (stl/css :auth-form-wrapper :register-success)}
[:h1 {:class (stl/css :logo-container)}
[:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]]
[:div {:class (stl/css :auth-title-wrapper)}
[:h2 {:class (stl/css :auth-title)}
(tr "auth.check-mail")]
[:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]]
[:div {:class (stl/css :notification-text-email)} (:email params "")]
[:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]])
{::mf/props :obj}
[]
(let [email (::email @sto/storage)]
[:div {:class (stl/css :auth-form-wrapper :register-success)}
[:h1 {:class (stl/css :logo-container)}
[:a {:href "#/" :title "Penpot" :class (stl/css :logo-btn)} i/logo]]
[:div {:class (stl/css :auth-title-wrapper)}
[:h2 {:class (stl/css :auth-title)}
(tr "auth.check-mail")]
[:div {:class (stl/css :notification-text)} (tr "auth.verification-email-sent")]]
[:div {:class (stl/css :notification-text-email)} email]
[:div {:class (stl/css :notification-text)} (tr "auth.check-your-email")]]))

View file

@ -142,11 +142,10 @@
// thread-content
.thread-content {
position: absolute;
overflow-y: scroll;
scrollbar-gutter: stable;
overflow-y: auto;
width: $s-284;
padding: $s-12;
padding-inline-end: 0;
padding-inline-end: $s-8;
pointer-events: auto;
user-select: text;

View file

@ -44,9 +44,17 @@
(or (empty? overlays-ids) (nil? shape) (cfh/root? shape)) base-frame
:else (find-relative-to-base-frame (cfh/get-parent objects (:id shape)) objects overlays-ids base-frame)))
(defn- ignore-frame-shape
[shape objects manual?]
(let [shape (cond-> shape ;; When the the interaction is not manual and its origin is a frame,
;; we need to ignore it on all the find-frame calculations
(and (:frame-id shape) (not manual?))
(assoc :type :rect))
objects (assoc objects (:id shape) shape)]
[shape objects]))
(defn- activate-interaction
[interaction shape base-frame frame-offset objects overlays]
(case (:action-type interaction)
:navigate
(when-let [frame-id (:destination interaction)]
@ -58,9 +66,11 @@
(dv/go-to-frame frame-id (:animation interaction)))))
:open-overlay
(let [dest-frame-id (:destination interaction)
(let [manual? (= :manual (:overlay-pos-type interaction))
[shape objects] (ignore-frame-shape shape objects manual?)
dest-frame-id (:destination interaction)
dest-frame (get objects dest-frame-id)
relative-to-id (if (= :manual (:overlay-pos-type interaction))
relative-to-id (if manual?
(if (= (:type shape) :frame) ;; manual interactions are always from "self"
(:frame-id shape)
(:id shape))
@ -88,7 +98,9 @@
fixed-base?))))
:toggle-overlay
(let [dest-frame-id (:destination interaction)
(let [manual? (= :manual (:overlay-pos-type interaction))
[shape objects] (ignore-frame-shape shape objects manual?)
dest-frame-id (:destination interaction)
dest-frame (get objects dest-frame-id)
relative-to-id (if (= :manual (:overlay-pos-type interaction))
(if (= (:type shape) :frame) ;; manual interactions are always from "self"
@ -146,7 +158,9 @@
(st/emit! (dv/close-overlay frame-id)))
:toggle-overlay
(let [dest-frame-id (:destination interaction)
(let [manual? (= :manual (:overlay-pos-type interaction))
[shape objects] (ignore-frame-shape shape objects manual?)
dest-frame-id (:destination interaction)
dest-frame (get objects dest-frame-id)
relative-to-id (if (= :manual (:overlay-pos-type interaction))
(if (= (:type shape) :frame) ;; manual interactions are always from "self"
@ -178,7 +192,9 @@
:close-overlay
(let [dest-frame-id (:destination interaction)
(let [manual? (= :manual (:overlay-pos-type interaction))
[shape objects] (ignore-frame-shape shape objects manual?)
dest-frame-id (:destination interaction)
dest-frame (get objects dest-frame-id)
relative-to-id (if (= :manual (:overlay-pos-type interaction))
(if (= (:type shape) :frame) ;; manual interactions are always from "self"

View file

@ -243,8 +243,8 @@
is-group? (and single? has-group?)
is-bool? (and single? has-bool?)
do-create-group #(st/emit! dw/group-selected)
do-remove-group #(st/emit! dw/ungroup-selected)
do-create-group #(st/emit! (dw/group-selected))
do-remove-group #(st/emit! (dw/ungroup-selected))
do-mask-group #(st/emit! (dw/mask-group))
do-unmask-group #(st/emit! (dw/unmask-group))
do-create-artboard-from-selection

View file

@ -519,6 +519,7 @@
[:div {:class (stl/css :modal-dialog)}
[:button {:class (stl/css :close-btn)
:on-click close-dialog
:aria-label (tr "labels.close")
:data-testid "close-libraries"}
close-icon]
[:div {:class (stl/css :modal-title)}

View file

@ -38,8 +38,7 @@
(let [options-mode (mf/deref refs/options-mode-global)
mode-inspect? (= options-mode :inspect)
project (mf/deref refs/workspace-project)
show-pages? (mf/use-state true)
toggle-pages (mf/use-callback #(reset! show-pages? not))
section (cond (or mode-inspect? (contains? layout :layers)) :layers
(contains? layout :assets) :assets)
@ -50,9 +49,12 @@
{on-pointer-down :on-pointer-down on-lost-pointer-capture :on-lost-pointer-capture on-pointer-move :on-pointer-move parent-ref :parent-ref size :size}
(use-resize-hook :left-sidebar 275 275 500 :x false :left)
{on-pointer-down-pages :on-pointer-down on-lost-pointer-capture-pages :on-lost-pointer-capture on-pointer-move-pages :on-pointer-move size-pages :size}
{on-pointer-down-pages :on-pointer-down on-lost-pointer-capture-pages :on-lost-pointer-capture on-pointer-move-pages :on-pointer-move size-pages-opened :size}
(use-resize-hook :sitemap 200 38 400 :y false nil)
show-pages? (mf/use-state true)
toggle-pages (mf/use-callback #(reset! show-pages? not))
size-pages (mf/use-memo (mf/deps show-pages? size-pages-opened) (fn [] (if @show-pages? size-pages-opened 32)))
handle-collapse
(mf/use-fn #(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
@ -63,6 +65,7 @@
[:& (mf/provider muc/sidebar) {:value :left}
[:aside {:ref parent-ref
:id "left-sidebar-aside"
:data-testid "left-sidebar"
:data-size (str size)
:class (stl/css-case :left-settings-bar true
:global/two-row (<= size 300)

View file

@ -84,10 +84,8 @@ $width-settings-bar-max: $s-500;
.resize-area-horiz {
position: absolute;
// top: calc($s-88 + var(--height, 200px));
left: 0;
width: 100%;
// height: $s-8;
border-bottom: $s-2 solid var(--resize-area-border-color);
cursor: ns-resize;
}

View file

@ -510,7 +510,7 @@
(mf/use-fn
#(st/emit! (dw/toggle-focus-mode)))]
[:div#layers {:class (stl/css :layers) :data-testid "layers"}
[:div#layers {:class (stl/css :layers) :data-testid "layer-tree"}
(if (d/not-empty? focus)
[:div {:class (stl/css :tool-window-bar)}
[:button {:class (stl/css :focus-title)

View file

@ -87,6 +87,7 @@
:class (stl/css-case :title-spacing-blur (not has-value?))}
(when-not has-value?
[:button {:class (stl/css :add-blur)
:data-testid "add-blur"
:on-click handle-add} i/add])]]
(when (and open? has-value?)
[:div {:class (stl/css :element-set-content)}

View file

@ -86,6 +86,7 @@
(mf/deps adjust-textarea-size creating?)
(fn [event]
(dom/stop-propagation event)
(rerender-fn)
(when-let [textarea (mf/ref-val textarea-ref)]
(dom/set-value! textarea annotation)
(reset! editing* false)
@ -98,6 +99,7 @@
(mf/use-fn
(fn [event]
(dom/stop-propagation event)
(rerender-fn)
(when ^boolean main-instance?
(when-let [textarea (mf/ref-val textarea-ref)]
(reset! editing* true)
@ -109,6 +111,7 @@
(mf/deps creating?)
(fn [event]
(dom/stop-propagation event)
(rerender-fn)
(when-let [textarea (mf/ref-val textarea-ref)]
(let [text (dom/get-value textarea)]
(when-not (str/blank? text)
@ -124,6 +127,7 @@
(fn [event]
(dom/stop-propagation event)
(let [on-accept (fn []
(rerender-fn)
(st/emit!
;; (ptk/data-event {::ev/name "delete-component-annotation"})
(when creating?

View file

@ -146,6 +146,7 @@
(when (and (not disable-remove?) (not (= :multiple fills)))
[:button {:class (stl/css :add-fill)
:data-testid "add-fill"
:on-click on-add} i/add])]]
(when open?

View file

@ -298,6 +298,7 @@
(when-not (= :multiple shadows)
[:button {:class (stl/css :add-shadow)
:data-testid "add-shadow"
:on-click on-add-shadow} i/add])]]
(when open?

View file

@ -169,9 +169,10 @@
:on-collapsed toggle-content
:title label
:class (stl/css-case :title-spacing-stroke (not has-strokes?))}
[:button {:class (stl/css :add-stroke)
:on-click on-add-stroke} i/add]]]
(when (not (= :multiple strokes))
[:button {:class (stl/css :add-stroke)
:data-testid "add-stroke"
:on-click on-add-stroke} i/add])]]
(when open?
[:div {:class (stl/css-case :element-content true
:empty-content (not has-strokes?))}

View file

@ -205,7 +205,6 @@
(fn [event]
(st/emit! (dw/create-page {:file-id file-id :project-id project-id}))
(-> event dom/get-current-target dom/blur!)))
size (if show-pages? size 32)
read-only? (mf/use-ctx ctx/workspace-read-only?)]
[:div {:class (stl/css :sitemap)

View file

@ -115,13 +115,16 @@
toggle-toolbar
(mf/use-fn
#(st/emit! (dwc/toggle-toolbar-visibility)))]
(fn [event]
(dom/blur! (dom/get-target event))
(st/emit! (dwc/toggle-toolbar-visibility))))]
(when-not ^boolean read-only?
[:aside {:class (stl/css-case :main-toolbar true
:main-toolbar-no-rulers (not rulers?)
:main-toolbar-hidden hide-toolbar?)}
[:ul {:class (stl/css :main-toolbar-options)}
[:ul {:class (stl/css :main-toolbar-options)
:data-testid "toolbar-options"}
[:li
[:button
{:title (tr "workspace.toolbar.move" (sc/get-tooltip :move))
@ -197,7 +200,9 @@
:on-click toggle-debug-panel}
i/bug]])]]
[:button {:class (stl/css :toolbar-handler)
[:button {:title (tr "workspace.toolbar.toggle-toolbar")
:aria-label (tr "workspace.toolbar.toggle-toolbar")
:class (stl/css :toolbar-handler)
:on-click toggle-toolbar}
[:div {:class (stl/css :toolbar-handler-btn)}]]])))

View file

@ -636,8 +636,8 @@
:objects base-objects
:modifiers modifiers
:shape frame
:view-only true}]))
:view-only true}]))]
[:g.scrollbar-wrapper {:clipPath "url(#clip-handlers)"}
[:& scroll-bars/viewport-scrollbars
{:objects base-objects
:zoom zoom

View file

@ -196,7 +196,8 @@
[:*
(when show-v-scroll?
[:g.v-scroll {:fill clr/black}
[:g.v-scroll {:fill clr/black
:data-testid "vertical-scrollbar"}
[:rect {:on-pointer-move #(on-pointer-move % :y)
:on-pointer-down #(on-pointer-down % :y)
:on-pointer-up on-pointer-up
@ -210,7 +211,8 @@
:style {:stroke "white"
:stroke-width (/ 0.15 zoom)}}]])
(when show-h-scroll?
[:g.h-scroll {:fill clr/black}
[:g.h-scroll {:fill clr/black
:data-testid "horizontal-scrollbar"}
[:rect {:on-pointer-move #(on-pointer-move % :x)
:on-pointer-down #(on-pointer-down % :x)
:on-pointer-up on-pointer-up

View file

@ -67,6 +67,7 @@
[:rect.selection-rect
{:x (:x data)
:y (:y data)
:data-testid "workspace-selection-rect"
:width (:width data)
:height (:height data)
:style {;; Primary with 0.1 opacity