diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 2de105031e..0a52acdda8 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -9,7 +9,6 @@ (ns app.main.data.workspace (:require - [cuerdas.core :as str] [app.common.data :as d] [app.common.exceptions :as ex] [app.common.geom.matrix :as gmt] @@ -22,6 +21,7 @@ [app.common.uuid :as uuid] [app.config :as cfg] [app.main.constants :as c] + [app.main.data.colors :as mdc] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.notifications :as dwn] @@ -29,11 +29,11 @@ [app.main.data.workspace.selection :as dws] [app.main.data.workspace.texts :as dwtxt] [app.main.data.workspace.transforms :as dwt] - [app.main.data.colors :as mdc] [app.main.repo :as rp] [app.main.store :as st] [app.main.streams :as ms] [app.main.worker :as uw] + [app.util.logging :as log] [app.util.router :as rt] [app.util.timers :as ts] [app.util.transit :as t] @@ -41,8 +41,11 @@ [beicon.core :as rx] [cljs.spec.alpha :as s] [clojure.set :as set] + [clojure.set :as set] + [cuerdas.core :as str] [potok.core :as ptk])) +;; (log/set-level! :trace) ;; --- Specs (s/def ::shape-attrs ::cp/shape-attrs) @@ -59,7 +62,6 @@ (s/def ::layout-flag #{:sitemap - :sitemap-pages :layers :comments :assets @@ -75,7 +77,6 @@ (def default-layout #{:sitemap - :sitemap-pages :layers :element-options :rules @@ -381,59 +382,47 @@ ;; --- Toggle layout flag -(defn- toggle-layout-flag - [state flag] - (us/assert ::layout-flag flag) - (update state :workspace-layout - (fn [flags] - (if (contains? flags flag) - (disj flags flag) - (conj flags flag))))) +(def layout-flags + {:assets + {:del #{:sitemap :layers :document-history } + :add #{:assets}} -(defn- check-sidebars - [state] - (let [layout (:workspace-layout state) - left? (seq (keep layout [:layers :sitemap :document-history :assets])) - right? (seq (keep layout [:element-options :comments]))] + :document-history + {:del #{:assets :layers :sitemap} + :add #{:document-history}} - (update state :workspace-local - assoc :left-sidebar? (boolean left?) - :right-sidebar? (boolean right?)))) + :layers + {:del #{:document-history :assets} + :add #{:sitemap :layers}}}) -(defn- check-auto-flags - [state flags-to-toggle] - (update state :workspace-layout - (fn [flags] - (cond-> flags - (contains? flags-to-toggle :assets) - (disj :sitemap :layers :document-history) +(defn- ensure-layout + [layout] + (assert (contains? layout-flags layout) + (str "unexpected layout name: " layout)) + (ptk/reify ::ensure-layout + ptk/UpdateEvent + (update [_ state] + (update state :workspace-layout + (fn [stored] + (let [todel (get-in layout-flags [layout :del] #{}) + toadd (get-in layout-flags [layout :add] #{})] + (-> stored + (set/difference todel) + (set/union toadd)))))))) - (contains? flags-to-toggle :sitemap) - (disj :assets :document-history) - - (contains? flags-to-toggle :document-history) - (disj :assets :sitemap :layers) - - (contains? flags-to-toggle :document-history) - (disj :assets :sitemap :layers) - - (contains? flags-to-toggle :comments) - (as-> $ (if (contains? flags :comments) - (disj $ :element-options) - (conj $ :element-options))) - - (contains? flags-to-toggle :element-options) - (disj :comments))))) - -(defn toggle-layout-flags +(defn- toggle-layout-flags [& flags] - (let [flags (into #{} flags)] - (ptk/reify ::toggle-layout-flags - ptk/UpdateEvent - (update [_ state] - (-> (reduce toggle-layout-flag state flags) - (check-auto-flags flags) - (check-sidebars)))))) + (ptk/reify ::toggle-layout-flags + ptk/UpdateEvent + (update [_ state] + (update state :workspace-layout + (fn [stored] + (reduce (fn [flags flag] + (if (contains? flags flag) + (disj flags flag) + (conj flags flag))) + stored + (into #{} flags))))))) ;; --- Set element options mode @@ -1057,8 +1046,6 @@ (update [_ state] (update state :workspace-drawing dissoc :tool :object)))) -(declare toggle-layout-flags) - (defn select-for-drawing ([tool] (select-for-drawing tool nil)) ([tool data] @@ -1071,12 +1058,16 @@ (watch [_ state stream] (let [stoper (rx/filter (ptk/type? ::clear-drawing) stream)] (rx/merge - (rx/of (toggle-layout-flags :element-options)) - (->> stream - (rx/filter dwc/interrupt?) - (rx/take 1) - (rx/map (constantly clear-drawing)) - (rx/take-until stoper)))))))) + (rx/of (dws/deselect-all)) + + ;; NOTE: comments are a special case and they manage they + ;; own interrupt cycle. + (when (not= tool :comments) + (->> stream + (rx/filter dwc/interrupt?) + (rx/take 1) + (rx/map (constantly clear-drawing)) + (rx/take-until stoper))))))))) ;; --- Update Dimensions diff --git a/frontend/src/app/main/data/workspace/comments.cljs b/frontend/src/app/main/data/workspace/comments.cljs index 905066f79d..b355be375d 100644 --- a/frontend/src/app/main/data/workspace/comments.cljs +++ b/frontend/src/app/main/data/workspace/comments.cljs @@ -40,7 +40,6 @@ (s/def ::comment any?) (declare create-draft-thread) -(declare clear-draft-thread) (declare retrieve-comment-threads) (declare refresh-comment-thread) (declare handle-interrupt) @@ -75,16 +74,17 @@ (ptk/reify ::handle-interrupt ptk/UpdateEvent (update [_ state] - (let [local (:workspace-comments state)] + (let [local (:workspace-comments state) + drawing (:workspace-drawing state)] (cond - (:draft local) - (update state :workspace-comments dissoc :draft) + (:comment drawing) + (update state :workspace-drawing dissoc :comment) (:open local) (update state :workspace-comments dissoc :open) :else - state))))) + (dissoc state :workspace-drawing)))))) ;; Event responsible of the what should be executed when user clicked ;; on the comments layer. An option can be create a new draft thread, @@ -98,15 +98,16 @@ (let [local (:workspace-comments state)] (if (:open local) (update state :workspace-comments dissoc :open) - (update state :workspace-comments assoc - :draft {:position position :content ""})))))) + (update state :workspace-drawing assoc + :comment {:position position :content ""})))))) (defn create-thread [data] (letfn [(created [{:keys [id comment] :as thread} state] (-> state (update :comment-threads assoc id (dissoc thread :comment)) - (update :workspace-comments assoc :draft nil :open id) + (update :workspace-comments assoc :open id) + (update :workspace-drawing dissoc :comment) (update-in [:comments id] assoc (:id comment) comment)))] (ptk/reify ::create-thread @@ -247,28 +248,25 @@ (ptk/reify ::open-thread ptk/UpdateEvent (update [_ state] - (update state :workspace-comments assoc :open id :draft nil)))) + (-> state + (update :workspace-comments assoc :open id) + (update :workspace-drawing dissoc :comment))))) (defn close-thread [] (ptk/reify ::open-thread ptk/UpdateEvent (update [_ state] - (update state :workspace-comments dissoc :open :draft)))) - - -(defn- clear-draft-thread - [state] - (update state :workspace-comments dissoc :draft)) - -;; TODO: add specs + (-> state + (update :workspace-comments dissoc :open) + (update :workspace-drawing dissoc :comment))))) (defn update-draft-thread [data] (ptk/reify ::update-draft-thread ptk/UpdateEvent (update [_ state] - (update state :workspace-comments assoc :draft data)))) + (update state :workspace-drawing assoc :comment data)))) (defn update-filters [{:keys [main resolved]}] diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index 3bc99693a5..a13eb328bd 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -21,7 +21,6 @@ [app.main.ui.keyboard :as kbd] [app.main.ui.workspace.colorpalette :refer [colorpalette]] [app.main.ui.workspace.colorpicker] - [app.main.ui.workspace.comments :refer [comments-layer]] [app.main.ui.workspace.context-menu :refer [context-menu]] [app.main.ui.workspace.header :refer [header]] [app.main.ui.workspace.left-toolbar :refer [left-toolbar]] @@ -53,14 +52,6 @@ [:section.workspace-content {:class classes} [:section.workspace-viewport - (when (contains? layout :comments) - [:& comments-layer {:vbox (:vbox local) - :vport (:vport local) - :zoom (:zoom local) - :page-id page-id - :file-id (:id file)} - ]) - (when (contains? layout :rules) [:* [:div.empty-rule-square] diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs index 8e73260982..163e0341f3 100644 --- a/frontend/src/app/main/ui/workspace/comments.cljs +++ b/frontend/src/app/main/ui/workspace/comments.cljs @@ -358,7 +358,7 @@ (l/derived :workspace-comments st/state)) (mf/defc comments-layer - [{:keys [vbox vport zoom file-id page-id] :as props}] + [{:keys [vbox vport zoom file-id page-id drawing] :as props}] (let [pos-x (* (- (:x vbox)) zoom) pos-y (* (- (:y vbox)) zoom) profile (mf/deref refs/profile) @@ -390,7 +390,7 @@ [:& thread-comments {:thread thread :zoom zoom}])) - (when-let [draft (:draft local)] + (when-let [draft (:comment drawing)] [:& draft-thread {:draft draft :zoom zoom}])]])) diff --git a/frontend/src/app/main/ui/workspace/left_toolbar.cljs b/frontend/src/app/main/ui/workspace/left_toolbar.cljs index a62bfb69bb..482f3b97df 100644 --- a/frontend/src/app/main/ui/workspace/left_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/left_toolbar.cljs @@ -25,9 +25,9 @@ [{:keys [layout] :as props}] (let [file-input (mf/use-ref nil) selected-drawtool (mf/deref refs/selected-drawing-tool) - select-drawtool #(st/emit! :interrupt - (dw/select-for-drawing %)) - file (mf/deref refs/workspace-file) + select-drawtool #(st/emit! :interrupt (dw/select-for-drawing %)) + + file (mf/deref refs/workspace-file) locale (i18n/use-locale) on-image #(dom/click (mf/ref-val file-input)) @@ -97,26 +97,25 @@ [:li.tooltip.tooltip-right {:alt (t locale "workspace.toolbar.comments") - :class (when (contains? layout :comments) "selected") - :on-click (st/emitf :interrupt (dw/toggle-layout-flags :comments)) - } + :class (when (= selected-drawtool :comments) "selected") + :on-click (partial select-drawtool :comments)} i/chat]] [:ul.left-toolbar-options.panels [:li.tooltip.tooltip-right {:alt "Layers" :class (when (contains? layout :layers) "selected") - :on-click (st/emitf (dw/toggle-layout-flags :sitemap :layers))} + :on-click (st/emitf (dw/ensure-layout :layers))} i/layers] [:li.tooltip.tooltip-right {:alt (t locale "workspace.toolbar.assets") :class (when (contains? layout :assets) "selected") - :on-click (st/emitf (dw/toggle-layout-flags :assets))} + :on-click (st/emitf (dw/ensure-layout :assets))} i/library] [:li.tooltip.tooltip-right {:alt "History" :class (when (contains? layout :document-history) "selected") - :on-click (st/emitf (dw/toggle-layout-flags :document-history))} + :on-click (st/emitf (dw/ensure-layout :document-history))} i/undo-history] [:li.tooltip.tooltip-right {:alt (t locale "workspace.toolbar.color-palette") diff --git a/frontend/src/app/main/ui/workspace/sidebar.cljs b/frontend/src/app/main/ui/workspace/sidebar.cljs index a2b60cec43..7790368cb6 100644 --- a/frontend/src/app/main/ui/workspace/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar.cljs @@ -9,14 +9,15 @@ (ns app.main.ui.workspace.sidebar (:require - [rumext.alpha :as mf] - [cuerdas.core :as str] + [app.main.refs :as refs] [app.main.ui.workspace.comments :refer [comments-sidebar]] + [app.main.ui.workspace.sidebar.assets :refer [assets-toolbox]] [app.main.ui.workspace.sidebar.history :refer [history-toolbox]] [app.main.ui.workspace.sidebar.layers :refer [layers-toolbox]] [app.main.ui.workspace.sidebar.options :refer [options-toolbox]] [app.main.ui.workspace.sidebar.sitemap :refer [sitemap]] - [app.main.ui.workspace.sidebar.assets :refer [assets-toolbox]])) + [cuerdas.core :as str] + [rumext.alpha :as mf])) ;; --- Left Sidebar (Component) @@ -26,14 +27,16 @@ [:aside.settings-bar.settings-bar-left [:div.settings-bar-inside {:data-layout (str/join "," layout)} - (when (contains? layout :sitemap) - [:& sitemap {:file file - :page-id page-id - :layout layout}]) - (when (contains? layout :document-history) - [:& history-toolbox]) (when (contains? layout :layers) - [:& layers-toolbox]) + [:* + [:& sitemap {:file file + :page-id page-id + :layout layout}] + [:& layers-toolbox]]) + + (when (contains? layout :document-history) + [:& history-toolbox]) + (when (contains? layout :assets) [:& assets-toolbox {:team-id (:team-id project) :file file}])]]) @@ -42,12 +45,12 @@ (mf/defc right-sidebar [{:keys [layout page-id file-id local] :as props}] - [:aside#settings-bar.settings-bar - [:div.settings-bar-inside - (when (contains? layout :element-options) - [:& options-toolbox - {:page-id page-id - :file-id file-id - :local local}]) - (when (contains? layout :comments) - [:& comments-sidebar])]]) + (let [drawing-tool (:tool (mf/deref refs/workspace-drawing))] + [:aside#settings-bar.settings-bar + [:div.settings-bar-inside + (if (= drawing-tool :comments) + [:& comments-sidebar] + [:& options-toolbox + {:page-id page-id + :file-id file-id + :local local}])]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs index 5bfb3952ff..cb38b6498f 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/sitemap.cljs @@ -148,16 +148,20 @@ (mf/defc sitemap [{:keys [file page-id layout] :as props}] - (let [create (mf/use-callback #(st/emit! dw/create-empty-page)) - collapse (mf/use-callback #(st/emit! (dw/toggle-layout-flags :sitemap-pages))) - locale (mf/deref i18n/locale)] + (let [create (mf/use-callback #(st/emit! dw/create-empty-page)) + locale (mf/deref i18n/locale) + show-pages? (mf/use-state true) + + toggle-pages + (mf/use-callback #(reset! show-pages? not))] + [:div.sitemap.tool-window [:div.tool-window-bar [:span (t locale "workspace.sidebar.sitemap")] [:div.add-page {:on-click create} i/close] - [:div.collapse-pages {:on-click collapse} i/arrow-slide]] + [:div.collapse-pages {:on-click toggle-pages} i/arrow-slide]] - (when (contains? layout :sitemap-pages) + (when @show-pages? [:div.tool-window-content [:& pages-list {:file file diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 1a3f8bcfc1..89f8349b7f 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -29,15 +29,16 @@ [app.main.ui.hooks :as hooks] [app.main.ui.icons :as i] [app.main.ui.keyboard :as kbd] + [app.main.ui.workspace.colorpicker.pixel-overlay :refer [pixel-overlay]] + [app.main.ui.workspace.comments :refer [comments-layer]] [app.main.ui.workspace.drawarea :refer [draw-area]] [app.main.ui.workspace.frame-grid :refer [frame-grid]] + [app.main.ui.workspace.gradients :refer [gradient-handlers]] [app.main.ui.workspace.presence :as presence] [app.main.ui.workspace.selection :refer [selection-handlers]] [app.main.ui.workspace.shapes :refer [shape-wrapper frame-wrapper]] [app.main.ui.workspace.shapes.interactions :refer [interactions]] [app.main.ui.workspace.shapes.outline :refer [outline]] - [app.main.ui.workspace.gradients :refer [gradient-handlers]] - [app.main.ui.workspace.colorpicker.pixel-overlay :refer [pixel-overlay]] [app.main.ui.workspace.snap-distances :refer [snap-distances]] [app.main.ui.workspace.snap-points :refer [snap-points]] [app.util.dom :as dom] @@ -229,7 +230,8 @@ (cond (and (= 1 (.-which event))) (if drawing-tool - (st/emit! (dd/start-drawing drawing-tool)) + (when (not= drawing-tool :comments) + (st/emit! (dd/start-drawing drawing-tool))) (st/emit! dw/handle-selection)) (and (not edition) @@ -495,6 +497,16 @@ :options options :layout layout}]) + (when (= drawing-tool :comments) + [:& comments-layer {:vbox (:vbox local) + :vport (:vport local) + :zoom (:zoom local) + :drawing drawing + :page-id page-id + :file-id (:id file)} + ]) + + [:svg.viewport {:preserveAspectRatio "xMidYMid meet" :width (:width vport 0) @@ -504,6 +516,7 @@ :class (when drawing-tool "drawing") :style {:cursor (cond panning cur/hand + (= drawing-tool :comments) cur/hand (= drawing-tool :frame) cur/create-artboard (= drawing-tool :rect) cur/create-rectangle (= drawing-tool :circle) cur/create-ellipse @@ -523,7 +536,9 @@ :on-drag-over on-drag-over :on-drop on-drop} - [:g + [:g {:style {:pointer-events (if (contains? layout :comments) + "none" + "auto")}} [:& frames {:key page-id :hover (:hover local) :selected (:selected selected)}]