🐛 Fix calculate zoom to avoid bubbles to get outside viewbox (#6138)

* 🐛 Fix calculate zoom to avoid bubbles to get outside vbox

* 📎 PR changes
This commit is contained in:
luisδμ 2025-03-25 15:39:47 +01:00 committed by GitHub
parent e81adb241b
commit dc84ab3e41
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 55 additions and 11 deletions

View file

@ -10,6 +10,7 @@
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
[app.common.geom.align :as gal]
[app.common.geom.point :as gpt]
[app.common.geom.rect :as gpr]
[app.common.geom.shapes :as gsh]
[app.common.math :as mth]
@ -83,6 +84,25 @@
(fn [local]
(setup state local)))))))
(defn calculate-centered-viewbox
"Updates the viewbox coordinates for a given center position"
[local position]
(let [vbox (:vbox local)
nw (/ (:width vbox) 2)
nh (/ (:height vbox) 2)
nx (- (:x position) nw)
ny (- (:y position) nh)]
(update local :vbox assoc :x nx :y ny)))
(defn update-viewport-position-center
[position]
(assert (gpt/point? position) "expected a point instance for `position` param")
(ptk/reify ::update-viewport-position-center
ptk/UpdateEvent
(update [_ state]
(update state :workspace-local calculate-centered-viewbox position))))
(defn update-viewport-position
[{:keys [x y] :or {x identity y identity}}]

View file

@ -20,7 +20,7 @@
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
(defn- impl-update-zoom
(defn impl-update-zoom
[{:keys [vbox] :as local} center zoom]
(let [new-zoom (if (fn? zoom) (zoom (:zoom local)) zoom)
old-zoom (:zoom local)

View file

@ -17,6 +17,7 @@
[app.main.data.comments :as dcm]
[app.main.data.modal :as modal]
[app.main.data.workspace.comments :as dwcm]
[app.main.data.workspace.viewport :as dwv]
[app.main.data.workspace.zoom :as dwz]
[app.main.refs :as refs]
[app.main.store :as st]
@ -1097,15 +1098,35 @@
groups))
(group-bubbles zoom remaining visited (cons [current] groups)))))))
(defn- calculate-zoom-scale-to-ungroup-bubbles
"Calculate the minimum zoom scale needed for a group of bubbles to avoid overlap among them"
[zoom threads]
(defn- inside-vbox?
"Checks if a bubble or a bubble group is inside a viewbox"
[thread-group wl]
(let [vbox (:vbox wl)
positions (mapv :position thread-group)
position (gpt/center-points positions)
pos-x (:x position)
pos-y (:y position)
x1 (:x vbox)
y1 (:y vbox)
x2 (+ x1 (:width vbox))
y2 (+ y1 (:height vbox))]
(and (> x2 pos-x x1) (> y2 pos-y y1))))
(defn- calculate-zoom-scale
"Calculates the zoom level needed to ungroup the largest number of bubbles while
keeping them all visible in the viewbox."
[position zoom threads wl]
(let [num-threads (count threads)
num-grouped-threads (count (group-bubbles zoom threads))
zoom-scale-step 1.75]
(if (= num-threads num-grouped-threads)
grouped-threads (group-bubbles zoom threads)
num-grouped-threads (count grouped-threads)
zoom-scale-step 1.75
scaled-zoom (* zoom zoom-scale-step)
zoomed-wl (dwz/impl-update-zoom wl position scaled-zoom)
outside-vbox? (complement inside-vbox?)]
(if (or (= num-threads num-grouped-threads)
(some #(outside-vbox? % zoomed-wl) grouped-threads))
zoom
(calculate-zoom-scale-to-ungroup-bubbles (* zoom zoom-scale-step) threads))))
(calculate-zoom-scale position scaled-zoom threads zoomed-wl))))
(mf/defc comment-floating-group*
{::mf/wrap [mf/memo]}
@ -1126,11 +1147,14 @@
on-click
(mf/use-fn
(mf/deps thread-group position)
(mf/deps thread-group position zoom)
(fn []
(let [updated-zoom (calculate-zoom-scale-to-ungroup-bubbles zoom thread-group)
(let [wl (deref refs/workspace-local)
centered-wl (dwv/calculate-centered-viewbox wl position)
updated-zoom (calculate-zoom-scale position zoom thread-group centered-wl)
scale-zoom (/ updated-zoom zoom)]
(st/emit! (dwz/set-zoom position scale-zoom)))))]
(st/emit! (dwv/update-viewport-position-center position)
(dwz/set-zoom position scale-zoom)))))]
[:div {:style {:top (dm/str pos-y "px")
:left (dm/str pos-x "px")}