0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-24 23:49:45 -05:00

♻️ Refactor viewer comments related components

This commit is contained in:
Andrey Antukh 2022-08-23 07:23:39 +02:00 committed by Andrés Moya
parent 50d371c14b
commit a37c1f7fca
2 changed files with 162 additions and 132 deletions

View file

@ -6,6 +6,7 @@
(ns app.main.ui.comments (ns app.main.ui.comments
(:require (:require
[app.common.geom.point :as gpt]
[app.config :as cfg] [app.config :as cfg]
[app.main.data.comments :as dcm] [app.main.data.comments :as dcm]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
@ -110,8 +111,10 @@
[:input.btn-secondary {:type "button" :value "Cancel" :on-click on-cancel}]])])) [:input.btn-secondary {:type "button" :value "Cancel" :on-click on-cancel}]])]))
(mf/defc draft-thread (mf/defc draft-thread
[{:keys [draft zoom on-cancel on-submit] :as props}] [{:keys [draft zoom on-cancel on-submit position-modifier]}]
(let [position (:position draft) (let [position (cond-> (:position draft)
(some? position-modifier)
(gpt/transform position-modifier))
content (:content draft) content (:content draft)
pos-x (* (:x position) zoom) pos-x (* (:x position) zoom)
pos-y (* (:y position) zoom) pos-y (* (:y position) zoom)
@ -281,9 +284,12 @@
(l/derived (l/in [:comments id]) st/state)) (l/derived (l/in [:comments id]) st/state))
(mf/defc thread-comments (mf/defc thread-comments
[{:keys [thread zoom users origin]}] {::mf/wrap [mf/memo]}
[{:keys [thread zoom users origin position-modifier]}]
(let [ref (mf/use-ref) (let [ref (mf/use-ref)
pos (:position thread) pos (cond-> (:position thread)
(some? position-modifier)
(gpt/transform position-modifier))
pos-x (+ (* (:x pos) zoom) 14) pos-x (+ (* (:x pos) zoom) 14)
pos-y (- (* (:y pos) zoom) 14) pos-y (- (* (:y pos) zoom) 14)
@ -384,9 +390,12 @@
(mf/defc thread-bubble (mf/defc thread-bubble
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [thread zoom open? on-click origin]}] [{:keys [thread zoom open? on-click origin position-modifier]}]
(let [pos (:position thread) (let [pos (cond-> (:position thread)
drag? (mf/use-ref nil) (some? position-modifier)
(gpt/transform position-modifier))
drag? (mf/use-ref nil)
was-open? (mf/use-ref nil) was-open? (mf/use-ref nil)
{:keys [on-pointer-down {:keys [on-pointer-down
@ -398,41 +407,45 @@
pos-x (* (or (:new-position-x @state) (:x pos)) zoom) pos-x (* (or (:new-position-x @state) (:x pos)) zoom)
pos-y (* (or (:new-position-y @state) (:y pos)) zoom) pos-y (* (or (:new-position-y @state) (:y pos)) zoom)
on-pointer-down* (mf/use-callback on-pointer-down*
(mf/deps origin was-open? open? drag? on-pointer-down) (mf/use-callback
(fn [event] (mf/deps origin was-open? open? drag? on-pointer-down)
(when (not= origin :viewer) (fn [event]
(mf/set-ref-val! was-open? open?) (when (not= origin :viewer)
(when open? (st/emit! (dcm/close-thread))) (mf/set-ref-val! was-open? open?)
(mf/set-ref-val! drag? false) (when open? (st/emit! (dcm/close-thread)))
(dom/stop-propagation event) (mf/set-ref-val! drag? false)
(on-pointer-down event)))) (dom/stop-propagation event)
(on-pointer-down event))))
on-pointer-up* (mf/use-callback on-pointer-up*
(mf/deps origin thread was-open? drag? on-pointer-up) (mf/use-callback
(fn [event] (mf/deps origin thread was-open? drag? on-pointer-up)
(when (not= origin :viewer) (fn [event]
(dom/stop-propagation event) (when (not= origin :viewer)
(on-pointer-up event thread) (dom/stop-propagation event)
(on-pointer-up event thread)
(when (or (and (mf/ref-val was-open?) (mf/ref-val drag?)) (when (or (and (mf/ref-val was-open?) (mf/ref-val drag?))
(and (not (mf/ref-val was-open?)) (not (mf/ref-val drag?)))) (and (not (mf/ref-val was-open?)) (not (mf/ref-val drag?))))
(st/emit! (dcm/open-thread thread)))))) (st/emit! (dcm/open-thread thread))))))
on-mouse-move* (mf/use-callback on-mouse-move*
(mf/deps origin drag? on-mouse-move) (mf/use-callback
(fn [event] (mf/deps origin drag? on-mouse-move)
(when (not= origin :viewer) (fn [event]
(mf/set-ref-val! drag? true) (when (not= origin :viewer)
(dom/stop-propagation event) (mf/set-ref-val! drag? true)
(on-mouse-move event)))) (dom/stop-propagation event)
(on-mouse-move event))))
on-click* (mf/use-callback on-click*
(mf/deps origin thread on-click) (mf/use-callback
(fn [event] (mf/deps origin thread on-click)
(dom/stop-propagation event) (fn [event]
(when (= origin :viewer) (dom/stop-propagation event)
(on-click thread))))] (when (= origin :viewer)
(on-click thread))))]
[:div.thread-bubble [:div.thread-bubble
{:style {:top (str pos-y "px") {:style {:top (str pos-y "px")
@ -448,7 +461,7 @@
[:span (:seqn thread)]])) [:span (:seqn thread)]]))
(mf/defc comment-thread (mf/defc comment-thread
[{:keys [item users on-click] :as props}] [{:keys [item users on-click]}]
(let [owner (get users (:owner-id item)) (let [owner (get users (:owner-id item))
on-click* on-click*
(mf/use-callback (mf/use-callback

View file

@ -6,6 +6,8 @@
(ns app.main.ui.viewer.comments (ns app.main.ui.viewer.comments
(:require (:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.matrix :as gmt] [app.common.geom.matrix :as gmt]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
@ -23,132 +25,145 @@
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
(mf/defc comments-menu (mf/defc comments-menu
{::mf/wrap [mf/memo]
::mf/wrap-props false}
[] []
(let [{cmode :mode cshow :show clist :list} (mf/deref refs/comments-local) (let [local (mf/deref refs/comments-local)
owner-filter (:owner-filter local)
status-filter (:status-filter local)
show-sidebar? (:show-sidebar? local)
show-dropdown? (mf/use-state false) show-dropdown? (mf/use-state false)
toggle-dropdown (mf/use-fn #(swap! show-dropdown? not)) toggle-dropdown (mf/use-fn #(swap! show-dropdown? not))
hide-dropdown (mf/use-fn #(reset! show-dropdown? false)) hide-dropdown (mf/use-fn #(reset! show-dropdown? false))
update-mode update-option (mf/use-fn
(mf/use-callback (fn [event]
(fn [mode] (let [target (dom/get-current-target event)
(st/emit! (dcm/update-filters {:mode mode})))) key (d/read-string (dom/get-attribute target "data-key"))
val (d/read-string (dom/get-attribute target "data-val"))]
update-show (st/emit! (dcm/update-options {key val})))))]
(mf/use-callback
(fn [mode]
(st/emit! (dcm/update-filters {:show mode}))))
update-list
(mf/use-callback
(fn [show-list]
(st/emit! (dcm/update-filters {:list show-list}))))]
[:div.view-options {:on-click toggle-dropdown} [:div.view-options {:on-click toggle-dropdown}
[:span.label (tr "labels.comments")] [:span.label (tr "labels.comments")]
[:span.icon i/arrow-down] [:span.icon i/arrow-down]
[:& dropdown {:show @show-dropdown? [:& dropdown {:show @show-dropdown?
:on-close hide-dropdown} :on-close hide-dropdown}
[:ul.dropdown.with-check [:ul.dropdown.with-check
[:li {:class (dom/classnames :selected (= :all cmode)) [:li {:class (dom/classnames :selected (= :all owner-filter))
:on-click #(update-mode :all)} :data-key ":owner-filter"
:data-val ":all"
:on-click update-option}
[:span.icon i/tick] [:span.icon i/tick]
[:span.label (tr "labels.show-all-comments")]] [:span.label (tr "labels.show-all-comments")]]
[:li {:class (dom/classnames :selected (= :yours cmode)) [:li {:class (dom/classnames :selected (= :yours owner-filter))
:on-click #(update-mode :yours)} :data-key ":owner-filter"
:data-val ":yours"
:on-click update-option}
[:span.icon i/tick] [:span.icon i/tick]
[:span.label (tr "labels.show-your-comments")]] [:span.label (tr "labels.show-your-comments")]]
[:hr] [:hr]
[:li {:class (dom/classnames :selected (= :pending cshow)) [:li {:class (dom/classnames :selected (= :pending status-filter))
:on-click #(update-show (if (= :pending cshow) :all :pending))} :data-key ":status-filter"
:data-val (if (= :pending status-filter) ":all" ":pending")
:on-click update-option}
[:span.icon i/tick] [:span.icon i/tick]
[:span.label (tr "labels.hide-resolved-comments")]] [:span.label (tr "labels.hide-resolved-comments")]]
[:hr] [:hr]
[:li {:class (dom/classnames :selected show-sidebar?)
[:li {:class (dom/classnames :selected (= :show clist)) :data-key ":show-sidebar?"
:on-click #(update-list (if (= :show clist) :hide :show))} :data-val (if show-sidebar? "false" "true")
:on-click update-option}
[:span.icon i/tick] [:span.icon i/tick]
[:span.label (tr "labels.show-comments-list")]]]]])) [:span.label (tr "labels.show-comments-list")]]]]]))
(def threads-ref (defn- update-thread-position [positions {:keys [id] :as thread}]
(l/derived :comment-threads st/state)) (if-let [data (get positions id)]
(-> thread
(def comments-local-ref (assoc :position (:position data))
(l/derived :comments-local st/state)) (assoc :frame-id (:frame-id data)))
thread))
(mf/defc comments-layer (mf/defc comments-layer
[{:keys [zoom file users frame page] :as props}] [{:keys [zoom file users frame page] :as props}]
(let [profile (mf/deref refs/profile) (prn "comments-layer")
threads-position-ref (l/derived (l/in [:viewer :pages (:id page) :options :comment-threads-position]) st/state) (let [profile (mf/deref refs/profile)
threads-position-map (mf/deref threads-position-ref) local (mf/deref refs/comments-local)
threads-map (mf/deref threads-ref)
frame-corner (-> frame :points gsh/points->selrect gpt/point) open-thread-id (:open local)
modifier1 (-> (gmt/matrix) page-id (:id page)
(gmt/translate (gpt/negate frame-corner))) file-id (:id file)
frame-id (:id frame)
modifier2 (-> (gpt/point frame-corner) tpos-ref (mf/with-memo [page-id]
(gmt/translate-matrix)) (-> (l/in [:pages page-id :options :comment-threads-position])
(l/derived refs/viewer-data)))
cstate (mf/deref refs/comments-local) positions (mf/deref tpos-ref)
threads-map (mf/deref refs/comment-threads)
update-thread-position (fn update-thread-position [thread] frame-corner (mf/with-memo [frame]
(if (contains? threads-position-map (:id thread)) (-> frame :points gsh/points->selrect gpt/point))
(-> thread
(assoc :position (get-in threads-position-map [(:id thread) :position])) modifier1 (mf/with-memo [frame-corner]
(assoc :frame-id (get-in threads-position-map [(:id thread) :frame-id]))) (-> (gmt/matrix)
thread)) (gmt/translate (gpt/negate frame-corner))))
modifier2 (mf/with-memo [frame-corner]
(-> (gpt/point frame-corner)
(gmt/translate-matrix)))
threads (mf/with-memo [threads-map positions]
(->> (vals threads-map)
(map (partial update-thread-position positions))
(filter #(= (:frame-id %) (:id frame)))
(dcm/apply-filters local profile)
(filter (fn [{:keys [position]}]
(gsh/has-point? frame position)))))
threads (->> (vals threads-map)
(map update-thread-position)
(filter #(= (:frame-id %) (:id frame)))
(dcm/apply-filters cstate profile)
(filter (fn [{:keys [position]}]
(gsh/has-point? frame position))))
on-bubble-click on-bubble-click
(mf/use-callback (mf/use-fn
(mf/deps cstate) (mf/deps open-thread-id)
(fn [thread] (fn [{:keys [id] :as thread}]
(if (= (:open cstate) (:id thread)) (st/emit! (if (= open-thread-id id)
(st/emit! (dcm/close-thread)) (dcm/close-thread)
(st/emit! (-> (dcm/open-thread thread) (-> (dcm/open-thread thread)
(with-meta {::ev/origin "viewer"})))))) (with-meta {::ev/origin "viewer"}))))))
on-click on-click
(mf/use-callback (mf/use-fn
(mf/deps cstate frame page file zoom) (mf/deps open-thread-id zoom page-id file-id modifier2)
(fn [event] (fn [event]
(dom/stop-propagation event) (dom/stop-propagation event)
(if (some? (:open cstate)) (if (some? open-thread-id)
(st/emit! (dcm/close-thread)) (st/emit! (dcm/close-thread))
(let [event (.-nativeEvent ^js event) (let [event (dom/event->native-event event)
viewport-point (dom/get-offset-position event) position (-> (dom/get-offset-position event)
viewport-point (-> viewport-point (update :x #(/ % zoom)) (update :y #(/ % zoom))) (update :x #(/ % zoom))
position (gpt/transform viewport-point modifier2) (update :y #(/ % zoom))
(gpt/transform modifier2))
params {:position position params {:position position
:page-id (:id page) :page-id (:id page)
:file-id (:id file)}] :file-id (:id file)}]
(st/emit! (dcm/create-draft params)))))) (st/emit! (dcm/create-draft params))))))
on-draft-cancel on-draft-cancel
(mf/use-callback (mf/use-fn #(st/emit! (dcm/close-thread)))
(mf/deps cstate)
#(st/emit! (dcm/close-thread)))
on-draft-submit on-draft-submit
(mf/use-callback (mf/use-fn
(mf/deps frame) (mf/deps frame-id modifier2)
(fn [draft] (fn [draft]
(let [params (-> draft (let [params (-> draft
(update :position gpt/transform modifier2) (update :position gpt/transform modifier2)
(assoc :frame-id (:id frame)))] (assoc :frame-id frame-id))]
(st/emit! (dcm/create-thread-on-viewer params) (st/emit! (dcm/create-thread-on-viewer params)
(dcm/close-thread)))))] (dcm/close-thread)))))]
@ -156,35 +171,37 @@
[:div.viewer-comments-container [:div.viewer-comments-container
[:div.threads [:div.threads
(for [item threads] (for [item threads]
(let [item (update item :position gpt/transform modifier1)] [:& cmt/thread-bubble
[:& cmt/thread-bubble {:thread item {:thread item
:zoom zoom :position-modifier modifier1
:on-click on-bubble-click :zoom zoom
:open? (= (:id item) (:open cstate)) :on-click on-bubble-click
:key (:seqn item) :open? (= (:id item) (:open local))
:origin :viewer}])) :key (:seqn item)
:origin :viewer}])
(when-let [id (:open cstate)] (when-let [thread (get threads-map open-thread-id)]
(when-let [thread (as-> (get threads-map id) $ [:& cmt/thread-comments
(when (some? $) {:thread thread
(update $ :position gpt/transform modifier1)))] :position-modifier modifier1
[:& cmt/thread-comments {:thread thread :users users
:users users :zoom zoom}])
:zoom zoom}]))
(when-let [draft (:draft cstate)] (when-let [draft (:draft local)]
[:& cmt/draft-thread {:draft (update draft :position gpt/transform modifier1) [:& cmt/draft-thread
:on-cancel on-draft-cancel {:draft draft
:on-submit on-draft-submit :position-modifier modifier1
:zoom zoom}])]]])) :on-cancel on-draft-cancel
:on-submit on-draft-submit
:zoom zoom}])]]]))
(mf/defc comments-sidebar (mf/defc comments-sidebar
[{:keys [users frame page]}] [{:keys [users frame page]}]
(let [profile (mf/deref refs/profile) (let [profile (mf/deref refs/profile)
cstate (mf/deref refs/comments-local) local (mf/deref refs/comments-local)
threads-map (mf/deref threads-ref) threads-map (mf/deref refs/comment-threads)
threads (->> (vals threads-map) threads (->> (vals threads-map)
(dcm/apply-filters cstate profile) (dcm/apply-filters local profile)
(filter (fn [{:keys [position]}] (filter (fn [{:keys [position]}]
(gsh/has-point? frame position))))] (gsh/has-point? frame position))))]
[:aside.settings-bar.settings-bar-right.comments-right-sidebar [:aside.settings-bar.settings-bar-right.comments-right-sidebar