mirror of
https://github.com/penpot/penpot.git
synced 2026-07-28 17:06:21 +00:00
🐛 Fix workspace crash and cleanup viewport_ref event/resize handling (#10721)
Replace `globals/document` and `globals/window` with `js/document` and `js/window` in workspace.cljs, removing the unused `app.util.globals` import. This avoids "can't access dead object" errors in Firefox when navigating between pages/files, matching the existing pattern used in viewport/hooks.cljs. Fix a leaked MOUSELEAVE listener in viewport_ref.cljs — the ref callback added a new listener on every mount but never unregistered the previous one. Now uses standard .addEventListener/.removeEventListener with a React ref to track the handler for proper cleanup. Fix ResizeObserver cleanup in viewport_ref.cljs — `init-observer` is now a private function that only creates an observer when a node is provided, and cleanup is handled via the ref callback on unmount. AI-assisted-by: mimo-v2.5-pro
This commit is contained in:
parent
5a0cee44b1
commit
af120feb1f
@ -44,7 +44,6 @@
|
||||
[app.main.ui.workspace.webgl-unavailable-modal]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as globals]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[goog.events :as events]
|
||||
[okulary.core :as l]
|
||||
@ -177,7 +176,7 @@
|
||||
|
||||
(mf/with-effect []
|
||||
(let [focus-out #(st/emit! (dw/workspace-focus-lost))
|
||||
key (events/listen globals/window "blur" focus-out)]
|
||||
key (events/listen js/window "blur" focus-out)]
|
||||
(partial events/unlistenByKey key)))
|
||||
|
||||
(mf/with-effect [file-id page-id]
|
||||
@ -252,7 +251,7 @@
|
||||
(let [handle-wasm-render
|
||||
(fn [_]
|
||||
(reset! first-frame-rendered? true))
|
||||
listener-key (events/listen globals/document "penpot:wasm:render" handle-wasm-render)]
|
||||
listener-key (events/listen js/document "penpot:wasm:render" handle-wasm-render)]
|
||||
(fn []
|
||||
(events/unlistenByKey listener-key))))
|
||||
|
||||
|
||||
@ -7,62 +7,75 @@
|
||||
(ns app.main.ui.workspace.viewport.viewport-ref
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.mouse :as mse]
|
||||
[goog.events :as events]
|
||||
[rumext.v2 :as mf])
|
||||
(:import goog.events.EventType))
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defonce viewport-ref (atom nil))
|
||||
(defonce current-observer (atom nil))
|
||||
(defonce viewport-brect (atom nil))
|
||||
|
||||
(defn init-observer
|
||||
[node on-change-bounds]
|
||||
(defn- init-observer
|
||||
[node]
|
||||
(let [on-change-bounds
|
||||
(fn [_]
|
||||
(let [brect (dom/get-bounding-rect node)
|
||||
brect (gpt/point (d/parse-integer (:left brect))
|
||||
(d/parse-integer (:top brect)))]
|
||||
(reset! viewport-brect brect)))
|
||||
|
||||
(let [observer (js/ResizeObserver. on-change-bounds)]
|
||||
(when (some? @current-observer)
|
||||
(.disconnect @current-observer))
|
||||
observer
|
||||
(js/ResizeObserver. on-change-bounds)]
|
||||
|
||||
(reset! current-observer observer)
|
||||
|
||||
(when (some? node)
|
||||
(.observe observer node))))
|
||||
|
||||
(defn on-change-bounds
|
||||
[_]
|
||||
(when @viewport-ref
|
||||
(let [brect (dom/get-bounding-rect @viewport-ref)
|
||||
brect (gpt/point (d/parse-integer (:left brect))
|
||||
(d/parse-integer (:top brect)))]
|
||||
(reset! viewport-brect brect))))
|
||||
(.observe observer node)
|
||||
observer))
|
||||
|
||||
(defn create-viewport-ref
|
||||
[]
|
||||
(let [ref (mf/use-ref nil)]
|
||||
[ref
|
||||
(mf/use-memo
|
||||
#(fn [node]
|
||||
(mf/set-ref-val! ref node)
|
||||
(reset! viewport-ref node)
|
||||
(when (some? node)
|
||||
(events/listen node EventType.MOUSELEAVE (fn [] (st/emit! (mse/->BlurEvent)))))
|
||||
(init-observer node on-change-bounds)))]))
|
||||
(let [node-ref (mf/use-ref nil)
|
||||
handler-ref (mf/use-ref nil)
|
||||
observer-ref (mf/use-ref nil)
|
||||
callback (mf/use-fn
|
||||
(fn [node]
|
||||
;; Dispose all previous resources
|
||||
(when-let [observer (mf/ref-val observer-ref)]
|
||||
(.disconnect ^js observer)
|
||||
(mf/set-ref-val! observer-ref nil))
|
||||
|
||||
|
||||
(when-let [handler (mf/ref-val handler-ref)]
|
||||
(when-let [node (mf/ref-val node-ref)]
|
||||
(.removeEventListener ^js node "mouseleave" handler)
|
||||
(mf/set-ref-val! handler-ref nil)))
|
||||
|
||||
;; Reset the ref values to the current node (can be nil)
|
||||
(mf/set-ref-val! node-ref node)
|
||||
(reset! viewport-ref node)
|
||||
|
||||
(when (some? node)
|
||||
(let [handler (fn [] (st/emit! (mse/->BlurEvent)))
|
||||
observer (init-observer node)]
|
||||
(.addEventListener ^js node "mouseleave" handler)
|
||||
|
||||
(mf/set-ref-val! handler-ref handler)
|
||||
(mf/set-ref-val! observer-ref observer)))))]
|
||||
[node-ref callback]))
|
||||
|
||||
(defn point->viewport
|
||||
[pt]
|
||||
(let [zoom (dm/get-in @st/state [:workspace-local :zoom] 1)]
|
||||
(when (and (some? @viewport-ref)
|
||||
(some? @viewport-brect))
|
||||
(let [vbox (.. ^js @viewport-ref -viewBox -baseVal)
|
||||
brect @viewport-brect
|
||||
box (gpt/point (.-x vbox) (.-y vbox))
|
||||
zoom (gpt/point zoom)]
|
||||
(let [zoom (d/nilv @refs/selected-zoom 1)
|
||||
viewport-node @viewport-ref
|
||||
viewport-brect @viewport-brect]
|
||||
|
||||
(-> (gpt/subtract pt brect)
|
||||
(when (and (some? viewport-brect)
|
||||
(some? viewport-node))
|
||||
(let [vbox (.. ^js viewport-node -viewBox -baseVal)
|
||||
box (gpt/point (.-x vbox) (.-y vbox))
|
||||
zoom (gpt/point zoom)]
|
||||
|
||||
(-> (gpt/subtract pt viewport-brect)
|
||||
(gpt/divide zoom)
|
||||
(gpt/add box))))))
|
||||
|
||||
@ -71,8 +84,8 @@
|
||||
Unlike point->viewport, this does NOT convert to canvas coordinates -
|
||||
it just subtracts the viewport's bounding rect offset."
|
||||
[pt]
|
||||
(when (some? @viewport-brect)
|
||||
(gpt/subtract pt @viewport-brect)))
|
||||
(when-let [brect @viewport-brect]
|
||||
(gpt/subtract pt brect)))
|
||||
|
||||
(defn inside-viewport?
|
||||
[target]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user