♻️ Refactor viewer state management (partial)

This commit is contained in:
Andrey Antukh 2022-08-23 07:22:52 +02:00 committed by Andrés Moya
parent 48de242a2d
commit 50d371c14b
11 changed files with 434 additions and 297 deletions

View file

@ -18,93 +18,122 @@
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.icons :as i]
[app.main.ui.hooks :as h]
[app.main.ui.viewer.shapes :as shapes]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as kbd]
[app.util.object :as obj]
[goog.events :as events]
[rumext.alpha :as mf]))
(defn prepare-objects
[page frame size]
(fn []
(let [objects (:objects page)
frame-id (:id frame)
modifier (-> (gpt/point (:x size) (:y size))
(gpt/negate)
(gmt/translate-matrix))
(let [objects (:objects page)
frame-id (:id frame)
modifier (-> (gpt/point (:x size) (:y size))
(gpt/negate)
(gmt/translate-matrix))
update-fn #(d/update-when %1 %2 assoc-in [:modifiers :displacement] modifier)]
update-fn #(d/update-when %1 %2 assoc-in [:modifiers :displacement] modifier)]
(->> (cph/get-children-ids objects frame-id)
(into [frame-id])
(reduce update-fn objects)))))
(->> (cph/get-children-ids objects frame-id)
(into [frame-id])
(reduce update-fn objects))))
(mf/defc viewport
{::mf/wrap [mf/memo]}
[{:keys [page interactions-mode frame base-frame frame-offset size]}]
(let [objects (mf/use-memo
(mf/deps page frame size)
(prepare-objects page frame size))
(mf/defc viewport-svg
{::mf/wrap [mf/memo]
::mf/wrap-props false}
[props]
(let [page (unchecked-get props "page")
frame (unchecked-get props "frame")
base (unchecked-get props "base")
offset (unchecked-get props "offset")
size (unchecked-get props "size")
wrapper (mf/use-memo
(mf/deps objects)
#(shapes/frame-container-factory objects))
vbox (:vbox size)
objects (mf/with-memo [page frame size]
(prepare-objects page frame size))
wrapper (mf/with-memo [objects]
(shapes/frame-container-factory objects))
;; Retrieve frames again with correct modifier
frame (get objects (:id frame))
base-frame (get objects (:id base-frame))
frame (get objects (:id frame))
base (get objects (:id base))]
on-click
(fn [_]
(when (= interactions-mode :show-on-click)
(st/emit! dv/flash-interactions)))
on-mouse-wheel
(fn [event]
(when (kbd/mod? event)
(dom/prevent-default event)
(let [event (.getBrowserEvent ^js event)
delta (+ (.-deltaY ^js event) (.-deltaX ^js event))]
(if (pos? delta)
(st/emit! dv/decrease-zoom)
(st/emit! dv/increase-zoom)))))
on-key-down
(fn [event]
(when (kbd/esc? event)
(st/emit! (dcm/close-thread))))]
(mf/use-effect
(mf/deps interactions-mode) ;; on-click event depends on interactions-mode
(fn []
;; bind with passive=false to allow the event to be cancelled
;; https://stackoverflow.com/a/57582286/3219895
(let [key1 (events/listen goog/global "wheel" on-mouse-wheel #js {"passive" false})
key2 (events/listen js/window "keydown" on-key-down)
key3 (events/listen js/window "click" on-click)]
(fn []
(events/unlistenByKey key1)
(events/unlistenByKey key2)
(events/unlistenByKey key3)))))
[:& (mf/provider shapes/base-frame-ctx) {:value base-frame}
[:& (mf/provider shapes/frame-offset-ctx) {:value frame-offset}
[:svg {:view-box (:vbox size)
[:& (mf/provider shapes/base-frame-ctx) {:value base}
[:& (mf/provider shapes/frame-offset-ctx) {:value offset}
[:svg {: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 {:shape frame
:view-box (:vbox size)}]]]]))
[:& wrapper {:shape frame :view-box vbox}]]]]))
(mf/defc viewport
{
::mf/wrap [mf/memo]
::mf/wrap-props false}
[props]
(let [;; NOTE: with `use-equal-memo` hook we ensure that all values
;; conserves the reference identity for avoid unnecesary dummy
;; rerenders.
mode (h/use-equal-memo (unchecked-get props "interactions-mode"))
offset (h/use-equal-memo (unchecked-get props "frame-offset"))
size (h/use-equal-memo (unchecked-get props "size"))
page (unchecked-get props "page")
frame (unchecked-get props "frame")
base (unchecked-get props "base-frame")]
(mf/with-effect [mode]
(let [on-click
(fn [_]
(when (= mode :show-on-click)
(st/emit! (dv/flash-interactions))))
on-mouse-wheel
(fn [event]
(when (kbd/mod? event)
(dom/prevent-default event)
(let [event (dom/event->browser-event event)
delta (+ (.-deltaY ^js event)
(.-deltaX ^js event))]
(if (pos? delta)
(st/emit! dv/decrease-zoom)
(st/emit! dv/increase-zoom)))))
on-key-down
(fn [event]
(when (kbd/esc? event)
(st/emit! (dcm/close-thread))))
;; bind with passive=false to allow the event to be cancelled
;; https://stackoverflow.com/a/57582286/3219895
key1 (events/listen goog/global "wheel" on-mouse-wheel #js {"passive" false})
key2 (events/listen goog/global "keydown" on-key-down)
key3 (events/listen goog/global "click" on-click)]
(fn []
(events/unlistenByKey key1)
(events/unlistenByKey key2)
(events/unlistenByKey key3))))
[:& viewport-svg {:page page
:frame frame
:base base
:offset offset
:size size}]))
(mf/defc flows-menu
{::mf/wrap [mf/memo]}
[{:keys [page index]}]
(let [flows (get-in page [:options :flows])
(let [flows (dm/get-in page [:options :flows])
frames (:frames page)
frame (get frames index)
current-flow (mf/use-state
@ -135,7 +164,6 @@
[:span.icon i/tick]
[:span.label (:name flow)]])]]])))
(mf/defc interactions-menu
[]
(let [local (mf/deref refs/viewer-local)