0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-23 23:18:48 -05:00

🐛 Fix problems with fixed overlays

This commit is contained in:
alonso.torres 2024-01-22 13:12:13 +01:00 committed by Andrey Antukh
parent f9fe4cd0a5
commit b6b2a3ec53
5 changed files with 131 additions and 60 deletions

View file

@ -753,3 +753,15 @@
[frame-id (get-parent-ids objects frame-id)]))] [frame-id (get-parent-ids objects frame-id)]))]
(recur frame-id frame-parents (rest selected)))))) (recur frame-id frame-parents (rest selected))))))
(defn fixed?
[objects shape-id]
(let [ids-to-check
(concat
[shape-id]
(get-children-ids objects shape-id)
(->> (get-parent-ids objects shape-id)
(take-while #(and (not= % uuid/zero) (not (root-frame? objects %))))))]
(boolean
(->> ids-to-check
(d/seek (fn [id] (dm/get-in objects [id :fixed-scroll])))))))

View file

@ -558,7 +558,7 @@
;; --- Overlays ;; --- Overlays
(defn- open-overlay* (defn- open-overlay*
[state frame position snap-to close-click-outside background-overlay animation] [state frame position snap-to close-click-outside background-overlay animation fixed-source?]
(cond-> state (cond-> state
:always :always
(update :viewer-overlays conj (update :viewer-overlays conj
@ -568,7 +568,8 @@
:snap-to snap-to :snap-to snap-to
:close-click-outside close-click-outside :close-click-outside close-click-outside
:background-overlay background-overlay :background-overlay background-overlay
:animation animation}) :animation animation
:fixed-source? fixed-source?})
(some? animation) (some? animation)
(assoc-in [:viewer-animations (:id frame)] (assoc-in [:viewer-animations (:id frame)]
@ -588,7 +589,7 @@
:animation animation}))) :animation animation})))
(defn open-overlay (defn open-overlay
[frame-id position snap-to close-click-outside background-overlay animation] [frame-id position snap-to close-click-outside background-overlay animation fixed-source?]
(dm/assert! (uuid? frame-id)) (dm/assert! (uuid? frame-id))
(dm/assert! (gpt/point? position)) (dm/assert! (gpt/point? position))
(dm/assert! (or (nil? close-click-outside) (dm/assert! (or (nil? close-click-outside)
@ -613,12 +614,13 @@
snap-to snap-to
close-click-outside close-click-outside
background-overlay background-overlay
animation) animation
fixed-source?)
state))))) state)))))
(defn toggle-overlay (defn toggle-overlay
[frame-id position snap-to close-click-outside background-overlay animation] [frame-id position snap-to close-click-outside background-overlay animation fixed-source?]
(dm/assert! (uuid? frame-id)) (dm/assert! (uuid? frame-id))
(dm/assert! (gpt/point? position)) (dm/assert! (gpt/point? position))
(dm/assert! (or (nil? close-click-outside) (dm/assert! (or (nil? close-click-outside)
@ -644,7 +646,8 @@
snap-to snap-to
close-click-outside close-click-outside
background-overlay background-overlay
animation) animation
fixed-source?)
(close-overlay* state (close-overlay* state
(:id frame) (:id frame)
(ctsi/invert-direction animation))))))) (ctsi/invert-direction animation)))))))

View file

@ -139,6 +139,7 @@
background-overlay? (:background-overlay overlay) background-overlay? (:background-overlay overlay)
overlay-frame (:frame overlay) overlay-frame (:frame overlay)
overlay-position (:position overlay) overlay-position (:position overlay)
fixed-base? (:fixed-source? overlay)
size size
(mf/with-memo [page overlay zoom] (mf/with-memo [page overlay zoom]
@ -168,21 +169,42 @@
:top 0} :top 0}
:on-click on-click}]) :on-click on-click}])
[:div {:class (stl/css :viewer-overlay :viewport-container) (if fixed-base?
:id (dm/str "overlay-" (:id overlay-frame)) [:div {:class (stl/css :viewport-container-wrapper)
:style {:width (:width size) :style {:position "absolute"
:height (:height size) :left (* (:x overlay-position) zoom)
:left (* (:x overlay-position) zoom) :top (* (:y overlay-position) zoom)
:top (* (:y overlay-position) zoom)}} :width (:width size)
:height (:height size)
:z-index 2}}
[:div {:class (stl/css :viewer-overlay :viewport-container)
:id (dm/str "overlay-" (:id overlay-frame))
:style {:width (:width size)
:height (:height size)
:position "fixed"}}
[:& interactions/viewport
{:frame overlay-frame
:base-frame frame
:frame-offset overlay-position
:size size
:delta delta
:page page
:interactions-mode interactions-mode}]]]
[:& interactions/viewport [:div {:class (stl/css :viewer-overlay :viewport-container)
{:frame overlay-frame :id (dm/str "overlay-" (:id overlay-frame))
:base-frame frame :style {:width (:width size)
:frame-offset overlay-position :height (:height size)
:size size :left (* (:x overlay-position) zoom)
:delta delta :top (* (:y overlay-position) zoom)}}
:page page [:& interactions/viewport
:interactions-mode interactions-mode}]]])) {:frame overlay-frame
:base-frame frame
:frame-offset overlay-position
:size size
:delta delta
:page page
:interactions-mode interactions-mode}]])]))
(mf/defc viewer-wrapper (mf/defc viewer-wrapper
{::mf/wrap-props false} {::mf/wrap-props false}

View file

@ -39,6 +39,23 @@
(into [frame-id]) (into [frame-id])
(reduce update-fn objects)))) (reduce update-fn objects))))
(defn get-fixed-ids
[objects]
(let [fixed-ids (filter :fixed-scroll (vals objects))
;; we have to consider the children if the fixed element is a group
fixed-children-ids
(into #{} (mapcat #(cfh/get-children-ids objects (:id %)) fixed-ids))
parent-children-ids
(->> fixed-ids
(mapcat #(cons (:id %) (cfh/get-parent-ids objects (:id %))))
(remove #(= % uuid/zero)))
fixed-ids
(concat fixed-children-ids parent-children-ids)]
fixed-ids))
(mf/defc viewport-svg (mf/defc viewport-svg
{::mf/wrap [mf/memo] {::mf/wrap [mf/memo]
::mf/wrap-props false} ::mf/wrap-props false}
@ -48,31 +65,25 @@
base (unchecked-get props "base") base (unchecked-get props "base")
offset (unchecked-get props "offset") offset (unchecked-get props "offset")
size (unchecked-get props "size") size (unchecked-get props "size")
fixed? (unchecked-get props "fixed?")
delta (or (unchecked-get props "delta") (gpt/point 0 0)) delta (or (unchecked-get props "delta") (gpt/point 0 0))
vbox (:vbox size) vbox (:vbox size)
fixed-ids (filter :fixed-scroll (vals (:objects page))) frame (cond-> frame fixed? (assoc :fixed-scroll true))
;; we have con consider the children if the fixed element is a group objects (:objects page)
fixed-children-ids objects (cond-> objects fixed? (assoc-in [(:id frame) :fixed-scroll] true))
(into #{} (mapcat #(cfh/get-children-ids (:objects page) (:id %)) fixed-ids))
parent-children-ids fixed-ids (get-fixed-ids objects)
(->> fixed-ids
(mapcat #(cons (:id %) (cfh/get-parent-ids (:objects page) (:id %))))
(remove #(= % uuid/zero)))
fixed-ids
(concat fixed-children-ids parent-children-ids)
not-fixed-ids not-fixed-ids
(->> (remove (set fixed-ids) (keys (:objects page))) (->> (remove (set fixed-ids) (keys objects))
(remove #(= % uuid/zero))) (remove #(= % uuid/zero)))
calculate-objects calculate-objects
(fn [ids] (fn [ids]
(->> ids (->> ids
(map (d/getf (:objects page))) (map (d/getf objects))
(concat [frame]) (concat [frame])
(d/index-by :id) (d/index-by :id)
(prepare-objects frame size delta))) (prepare-objects frame size delta)))
@ -112,28 +123,41 @@
[:& (mf/provider shapes/base-frame-ctx) {:value base} [:& (mf/provider shapes/base-frame-ctx) {:value base}
[:& (mf/provider shapes/frame-offset-ctx) {:value offset} [:& (mf/provider shapes/frame-offset-ctx) {:value offset}
;; We have two different svgs for fixed and not fixed elements so we can emulate the sticky css attribute in svg (if fixed?
[:svg {:class (stl/css :fixed) [:svg {:class (stl/css :fixed)
:view-box vbox :view-box vbox
:width (:width size) :width (:width size)
:height (:height size) :height (:height size)
:version "1.1" :version "1.1"
:xmlnsXlink "http://www.w3.org/1999/xlink" :xmlnsXlink "http://www.w3.org/1999/xlink"
:xmlns "http://www.w3.org/2000/svg" :xmlns "http://www.w3.org/2000/svg"
:fill "none" :fill "none"}
:style {:width (:width size) [:& wrapper-not-fixed {:shape frame :view-box vbox}]]
:height (:height size)}}
[:& wrapper-fixed {:shape fixed-frame :view-box vbox}]]
[:svg {:class (stl/css :not-fixed) [:*
:view-box vbox ;; We have two different svgs for fixed and not fixed elements so we can emulate the sticky css attribute in svg
:width (:width size) [:svg {:class (stl/css :fixed)
:height (:height size) :view-box vbox
:version "1.1" :width (:width size)
:xmlnsXlink "http://www.w3.org/1999/xlink" :height (:height size)
:xmlns "http://www.w3.org/2000/svg" :version "1.1"
:fill "none"} :xmlnsXlink "http://www.w3.org/1999/xlink"
[:& wrapper-not-fixed {:shape frame :view-box vbox}]]]])) :xmlns "http://www.w3.org/2000/svg"
:fill "none"
:style {:width (:width size)
:height (:height size)
:z-index 1}}
[:& wrapper-fixed {:shape fixed-frame :view-box vbox}]]
[:svg {:class (stl/css :not-fixed)
:view-box vbox
:width (:width size)
:height (:height size)
:version "1.1"
:xmlnsXlink "http://www.w3.org/1999/xlink"
:xmlns "http://www.w3.org/2000/svg"
:fill "none"}
[:& wrapper-not-fixed {:shape frame :view-box vbox}]]])]]))
(mf/defc viewport (mf/defc viewport
{::mf/wrap [mf/memo] {::mf/wrap [mf/memo]
@ -150,7 +174,8 @@
page (unchecked-get props "page") page (unchecked-get props "page")
frame (unchecked-get props "frame") frame (unchecked-get props "frame")
base (unchecked-get props "base-frame")] base (unchecked-get props "base-frame")
fixed? (unchecked-get props "fixed?")]
(mf/with-effect [mode] (mf/with-effect [mode]
(let [on-click (let [on-click
@ -190,7 +215,8 @@
:base base :base base
:offset offset :offset offset
:size size :size size
:delta delta}])) :delta delta
:fixed? fixed?}]))
(mf/defc flows-menu (mf/defc flows-menu
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}

View file

@ -70,6 +70,7 @@
background-overlay (:background-overlay interaction) background-overlay (:background-overlay interaction)
overlays-ids (set (map :id overlays)) overlays-ids (set (map :id overlays))
relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame) relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame)
fixed-base? (cfh/fixed? objects relative-to-id)
[position snap-to] (ctsi/calc-overlay-position interaction [position snap-to] (ctsi/calc-overlay-position interaction
shape shape
objects objects
@ -83,7 +84,8 @@
snap-to snap-to
close-click-outside close-click-outside
background-overlay background-overlay
(:animation interaction))))) (:animation interaction)
fixed-base?))))
:toggle-overlay :toggle-overlay
(let [dest-frame-id (:destination interaction) (let [dest-frame-id (:destination interaction)
@ -96,6 +98,7 @@
relative-to-shape (or (get objects relative-to-id) base-frame) relative-to-shape (or (get objects relative-to-id) base-frame)
overlays-ids (set (map :id overlays)) overlays-ids (set (map :id overlays))
relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame) relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame)
fixed-base? (cfh/fixed? objects (:id base-frame))
[position snap-to] (ctsi/calc-overlay-position interaction [position snap-to] (ctsi/calc-overlay-position interaction
shape shape
objects objects
@ -112,7 +115,8 @@
snap-to snap-to
close-click-outside close-click-outside
background-overlay background-overlay
(:animation interaction))))) (:animation interaction)
fixed-base?))))
:close-overlay :close-overlay
(let [dest-frame-id (or (:destination interaction) (let [dest-frame-id (or (:destination interaction)
@ -152,6 +156,7 @@
relative-to-shape (or (get objects relative-to-id) base-frame) relative-to-shape (or (get objects relative-to-id) base-frame)
overlays-ids (set (map :id overlays)) overlays-ids (set (map :id overlays))
relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame) relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame)
fixed-base? (cfh/fixed? objects (:id base-frame))
[position snap-to] (ctsi/calc-overlay-position interaction [position snap-to] (ctsi/calc-overlay-position interaction
shape shape
objects objects
@ -168,7 +173,8 @@
snap-to snap-to
close-click-outside close-click-outside
background-overlay background-overlay
(:animation interaction))))) (:animation interaction)
fixed-base?))))
:close-overlay :close-overlay
@ -184,6 +190,7 @@
background-overlay (:background-overlay interaction) background-overlay (:background-overlay interaction)
overlays-ids (set (map :id overlays)) overlays-ids (set (map :id overlays))
relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame) relative-to-base-frame (find-relative-to-base-frame relative-to-shape objects overlays-ids base-frame)
fixed-base? (cfh/fixed? objects (:id base-frame))
[position snap-to] (ctsi/calc-overlay-position interaction [position snap-to] (ctsi/calc-overlay-position interaction
shape shape
objects objects
@ -197,7 +204,8 @@
snap-to snap-to
close-click-outside close-click-outside
background-overlay background-overlay
(:animation interaction))))) (:animation interaction)
fixed-base?))))
nil)) nil))
(defn- on-pointer-down (defn- on-pointer-down