mirror of
https://github.com/penpot/penpot.git
synced 2026-05-31 20:58:08 +00:00
193 lines
7.3 KiB
Clojure
193 lines
7.3 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; Copyright (c) UXBOX Labs SL
|
|
|
|
(ns app.main.ui.viewer.comments
|
|
(:require
|
|
[app.common.geom.matrix :as gmt]
|
|
[app.common.geom.point :as gpt]
|
|
[app.common.geom.shapes :as gsh]
|
|
[app.main.data.comments :as dcm]
|
|
[app.main.data.events :as ev]
|
|
[app.main.refs :as refs]
|
|
[app.main.store :as st]
|
|
[app.main.ui.comments :as cmt]
|
|
[app.main.ui.components.dropdown :refer [dropdown]]
|
|
[app.main.ui.icons :as i]
|
|
[app.main.ui.workspace.comments :as wc]
|
|
[app.util.dom :as dom]
|
|
[app.util.i18n :as i18n :refer [tr]]
|
|
[okulary.core :as l]
|
|
[rumext.alpha :as mf]))
|
|
|
|
(mf/defc comments-menu
|
|
[]
|
|
(let [{cmode :mode cshow :show clist :list} (mf/deref refs/comments-local)
|
|
|
|
show-dropdown? (mf/use-state false)
|
|
toggle-dropdown (mf/use-fn #(swap! show-dropdown? not))
|
|
hide-dropdown (mf/use-fn #(reset! show-dropdown? false))
|
|
|
|
update-mode
|
|
(mf/use-callback
|
|
(fn [mode]
|
|
(st/emit! (dcm/update-filters {:mode mode}))))
|
|
|
|
update-show
|
|
(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}
|
|
[:span.label (tr "labels.comments")]
|
|
[:span.icon i/arrow-down]
|
|
[:& dropdown {:show @show-dropdown?
|
|
:on-close hide-dropdown}
|
|
[:ul.dropdown.with-check
|
|
[:li {:class (dom/classnames :selected (= :all cmode))
|
|
:on-click #(update-mode :all)}
|
|
[:span.icon i/tick]
|
|
[:span.label (tr "labels.show-all-comments")]]
|
|
|
|
[:li {:class (dom/classnames :selected (= :yours cmode))
|
|
:on-click #(update-mode :yours)}
|
|
[:span.icon i/tick]
|
|
[:span.label (tr "labels.show-your-comments")]]
|
|
|
|
[:hr]
|
|
|
|
[:li {:class (dom/classnames :selected (= :pending cshow))
|
|
:on-click #(update-show (if (= :pending cshow) :all :pending))}
|
|
[:span.icon i/tick]
|
|
[:span.label (tr "labels.hide-resolved-comments")]]
|
|
|
|
[:hr]
|
|
|
|
[:li {:class (dom/classnames :selected (= :show clist))
|
|
:on-click #(update-list (if (= :show clist) :hide :show))}
|
|
[:span.icon i/tick]
|
|
[:span.label (tr "labels.show-comments-list")]]]]]))
|
|
|
|
|
|
(def threads-ref
|
|
(l/derived :comment-threads st/state))
|
|
|
|
(def comments-local-ref
|
|
(l/derived :comments-local st/state))
|
|
|
|
(mf/defc comments-layer
|
|
[{:keys [zoom file users frame page] :as props}]
|
|
(let [profile (mf/deref refs/profile)
|
|
threads-position-ref (l/derived (l/in [:viewer :pages (:id page) :options :comment-threads-position]) st/state)
|
|
threads-position-map (mf/deref threads-position-ref)
|
|
threads-map (mf/deref threads-ref)
|
|
|
|
frame-corner (-> frame :points gsh/points->selrect gpt/point)
|
|
modifier1 (-> (gmt/matrix)
|
|
(gmt/translate (gpt/negate frame-corner)))
|
|
|
|
modifier2 (-> (gpt/point frame-corner)
|
|
(gmt/translate-matrix))
|
|
|
|
cstate (mf/deref refs/comments-local)
|
|
|
|
update-thread-position (fn update-thread-position [thread]
|
|
(if (contains? threads-position-map (:id thread))
|
|
(-> thread
|
|
(assoc :position (get-in threads-position-map [(:id thread) :position]))
|
|
(assoc :frame-id (get-in threads-position-map [(:id thread) :frame-id])))
|
|
thread))
|
|
|
|
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
|
|
(mf/use-callback
|
|
(mf/deps cstate)
|
|
(fn [thread]
|
|
(if (= (:open cstate) (:id thread))
|
|
(st/emit! (dcm/close-thread))
|
|
(st/emit! (-> (dcm/open-thread thread)
|
|
(with-meta {::ev/origin "viewer"}))))))
|
|
|
|
on-click
|
|
(mf/use-callback
|
|
(mf/deps cstate frame page file zoom)
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(if (some? (:open cstate))
|
|
(st/emit! (dcm/close-thread))
|
|
(let [event (.-nativeEvent ^js event)
|
|
viewport-point (dom/get-offset-position event)
|
|
viewport-point (-> viewport-point (update :x #(/ % zoom)) (update :y #(/ % zoom)))
|
|
position (gpt/transform viewport-point modifier2)
|
|
params {:position position
|
|
:page-id (:id page)
|
|
:file-id (:id file)}]
|
|
(st/emit! (dcm/create-draft params))))))
|
|
|
|
on-draft-cancel
|
|
(mf/use-callback
|
|
(mf/deps cstate)
|
|
#(st/emit! (dcm/close-thread)))
|
|
|
|
on-draft-submit
|
|
(mf/use-callback
|
|
(mf/deps frame)
|
|
(fn [draft]
|
|
(let [params (-> draft
|
|
(update :position gpt/transform modifier2)
|
|
(assoc :frame-id (:id frame)))]
|
|
(st/emit! (dcm/create-thread-on-viewer params)
|
|
(dcm/close-thread)))))]
|
|
|
|
[:div.comments-section {:on-click on-click}
|
|
[:div.viewer-comments-container
|
|
[:div.threads
|
|
(for [item threads]
|
|
(let [item (update item :position gpt/transform modifier1)]
|
|
[:& cmt/thread-bubble {:thread item
|
|
:zoom zoom
|
|
:on-click on-bubble-click
|
|
:open? (= (:id item) (:open cstate))
|
|
:key (:seqn item)
|
|
:origin :viewer}]))
|
|
|
|
(when-let [id (:open cstate)]
|
|
(when-let [thread (as-> (get threads-map id) $
|
|
(when (some? $)
|
|
(update $ :position gpt/transform modifier1)))]
|
|
[:& cmt/thread-comments {:thread thread
|
|
:users users
|
|
:zoom zoom}]))
|
|
|
|
(when-let [draft (:draft cstate)]
|
|
[:& cmt/draft-thread {:draft (update draft :position gpt/transform modifier1)
|
|
:on-cancel on-draft-cancel
|
|
:on-submit on-draft-submit
|
|
:zoom zoom}])]]]))
|
|
|
|
(mf/defc comments-sidebar
|
|
[{:keys [users frame page]}]
|
|
(let [profile (mf/deref refs/profile)
|
|
cstate (mf/deref refs/comments-local)
|
|
threads-map (mf/deref threads-ref)
|
|
threads (->> (vals threads-map)
|
|
(dcm/apply-filters cstate profile)
|
|
(filter (fn [{:keys [position]}]
|
|
(gsh/has-point? frame position))))]
|
|
[:aside.settings-bar.settings-bar-right.comments-right-sidebar
|
|
[:div.settings-bar-inside
|
|
[:& wc/comments-sidebar {:users users :threads threads :page-id (:id page)}]]]))
|