From b6b2a3ec53dfa281ba177a6c475e542cd5f7d3c1 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 22 Jan 2024 13:12:13 +0100 Subject: [PATCH] :bug: Fix problems with fixed overlays --- common/src/app/common/files/helpers.cljc | 12 +++ frontend/src/app/main/data/viewer.cljs | 15 +-- frontend/src/app/main/ui/viewer.cljs | 50 +++++++--- .../src/app/main/ui/viewer/interactions.cljs | 98 ++++++++++++------- frontend/src/app/main/ui/viewer/shapes.cljs | 16 ++- 5 files changed, 131 insertions(+), 60 deletions(-) diff --git a/common/src/app/common/files/helpers.cljc b/common/src/app/common/files/helpers.cljc index dce09d5dd..05ceca6b2 100644 --- a/common/src/app/common/files/helpers.cljc +++ b/common/src/app/common/files/helpers.cljc @@ -753,3 +753,15 @@ [frame-id (get-parent-ids objects frame-id)]))] (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]))))))) diff --git a/frontend/src/app/main/data/viewer.cljs b/frontend/src/app/main/data/viewer.cljs index ae361f3e1..af8401d8a 100644 --- a/frontend/src/app/main/data/viewer.cljs +++ b/frontend/src/app/main/data/viewer.cljs @@ -558,7 +558,7 @@ ;; --- Overlays (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 :always (update :viewer-overlays conj @@ -568,7 +568,8 @@ :snap-to snap-to :close-click-outside close-click-outside :background-overlay background-overlay - :animation animation}) + :animation animation + :fixed-source? fixed-source?}) (some? animation) (assoc-in [:viewer-animations (:id frame)] @@ -588,7 +589,7 @@ :animation animation}))) (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! (gpt/point? position)) (dm/assert! (or (nil? close-click-outside) @@ -613,12 +614,13 @@ snap-to close-click-outside background-overlay - animation) + animation + fixed-source?) state))))) (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! (gpt/point? position)) (dm/assert! (or (nil? close-click-outside) @@ -644,7 +646,8 @@ snap-to close-click-outside background-overlay - animation) + animation + fixed-source?) (close-overlay* state (:id frame) (ctsi/invert-direction animation))))))) diff --git a/frontend/src/app/main/ui/viewer.cljs b/frontend/src/app/main/ui/viewer.cljs index 899dee386..647248651 100644 --- a/frontend/src/app/main/ui/viewer.cljs +++ b/frontend/src/app/main/ui/viewer.cljs @@ -139,6 +139,7 @@ background-overlay? (:background-overlay overlay) overlay-frame (:frame overlay) overlay-position (:position overlay) + fixed-base? (:fixed-source? overlay) size (mf/with-memo [page overlay zoom] @@ -168,21 +169,42 @@ :top 0} :on-click on-click}]) - [:div {:class (stl/css :viewer-overlay :viewport-container) - :id (dm/str "overlay-" (:id overlay-frame)) - :style {:width (:width size) - :height (:height size) - :left (* (:x overlay-position) zoom) - :top (* (:y overlay-position) zoom)}} + (if fixed-base? + [:div {:class (stl/css :viewport-container-wrapper) + :style {:position "absolute" + :left (* (:x 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 - {:frame overlay-frame - :base-frame frame - :frame-offset overlay-position - :size size - :delta delta - :page page - :interactions-mode interactions-mode}]]])) + [:div {:class (stl/css :viewer-overlay :viewport-container) + :id (dm/str "overlay-" (:id overlay-frame)) + :style {:width (:width size) + :height (:height size) + :left (* (:x overlay-position) zoom) + :top (* (:y overlay-position) zoom)}} + [:& interactions/viewport + {: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/wrap-props false} diff --git a/frontend/src/app/main/ui/viewer/interactions.cljs b/frontend/src/app/main/ui/viewer/interactions.cljs index 60f1928c4..dc4f30ef1 100644 --- a/frontend/src/app/main/ui/viewer/interactions.cljs +++ b/frontend/src/app/main/ui/viewer/interactions.cljs @@ -39,6 +39,23 @@ (into [frame-id]) (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/wrap [mf/memo] ::mf/wrap-props false} @@ -48,31 +65,25 @@ base (unchecked-get props "base") offset (unchecked-get props "offset") size (unchecked-get props "size") + fixed? (unchecked-get props "fixed?") delta (or (unchecked-get props "delta") (gpt/point 0 0)) 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 - fixed-children-ids - (into #{} (mapcat #(cfh/get-children-ids (:objects page) (:id %)) fixed-ids)) + objects (:objects page) + objects (cond-> objects fixed? (assoc-in [(:id frame) :fixed-scroll] true)) - parent-children-ids - (->> fixed-ids - (mapcat #(cons (:id %) (cfh/get-parent-ids (:objects page) (:id %)))) - (remove #(= % uuid/zero))) - - fixed-ids - (concat fixed-children-ids parent-children-ids) + fixed-ids (get-fixed-ids objects) not-fixed-ids - (->> (remove (set fixed-ids) (keys (:objects page))) + (->> (remove (set fixed-ids) (keys objects)) (remove #(= % uuid/zero))) calculate-objects (fn [ids] (->> ids - (map (d/getf (:objects page))) + (map (d/getf objects)) (concat [frame]) (d/index-by :id) (prepare-objects frame size delta))) @@ -112,28 +123,41 @@ [:& (mf/provider shapes/base-frame-ctx) {:value base} [:& (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 - [:svg {:class (stl/css :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" - :style {:width (:width size) - :height (:height size)}} - [:& wrapper-fixed {:shape fixed-frame :view-box vbox}]] + (if fixed? + [:svg {:class (stl/css :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}]] - [: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}]]]])) + [:* + ;; We have two different svgs for fixed and not fixed elements so we can emulate the sticky css attribute in svg + [:svg {:class (stl/css :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" + :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/wrap [mf/memo] @@ -150,7 +174,8 @@ page (unchecked-get props "page") 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] (let [on-click @@ -190,7 +215,8 @@ :base base :offset offset :size size - :delta delta}])) + :delta delta + :fixed? fixed?}])) (mf/defc flows-menu {::mf/wrap [mf/memo]} diff --git a/frontend/src/app/main/ui/viewer/shapes.cljs b/frontend/src/app/main/ui/viewer/shapes.cljs index d976fbc74..6a739d320 100644 --- a/frontend/src/app/main/ui/viewer/shapes.cljs +++ b/frontend/src/app/main/ui/viewer/shapes.cljs @@ -70,6 +70,7 @@ background-overlay (:background-overlay interaction) overlays-ids (set (map :id overlays)) 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 shape objects @@ -83,7 +84,8 @@ snap-to close-click-outside background-overlay - (:animation interaction))))) + (:animation interaction) + fixed-base?)))) :toggle-overlay (let [dest-frame-id (:destination interaction) @@ -96,6 +98,7 @@ relative-to-shape (or (get objects relative-to-id) base-frame) overlays-ids (set (map :id overlays)) 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 shape objects @@ -112,7 +115,8 @@ snap-to close-click-outside background-overlay - (:animation interaction))))) + (:animation interaction) + fixed-base?)))) :close-overlay (let [dest-frame-id (or (:destination interaction) @@ -152,6 +156,7 @@ relative-to-shape (or (get objects relative-to-id) base-frame) overlays-ids (set (map :id overlays)) 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 shape objects @@ -168,7 +173,8 @@ snap-to close-click-outside background-overlay - (:animation interaction))))) + (:animation interaction) + fixed-base?)))) :close-overlay @@ -184,6 +190,7 @@ background-overlay (:background-overlay interaction) overlays-ids (set (map :id overlays)) 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 shape objects @@ -197,7 +204,8 @@ snap-to close-click-outside background-overlay - (:animation interaction))))) + (:animation interaction) + fixed-base?)))) nil)) (defn- on-pointer-down