diff --git a/frontend/src/app/main/data/workspace/path/drawing.cljs b/frontend/src/app/main/data/workspace/path/drawing.cljs index b85ac2edd7..ce2f2ab240 100644 --- a/frontend/src/app/main/data/workspace/path/drawing.cljs +++ b/frontend/src/app/main/data/workspace/path/drawing.cljs @@ -31,8 +31,23 @@ [beicon.v2.core :as rx] [potok.v2.core :as ptk])) +(declare close-path-drag-end) +(declare check-changed-content) (declare change-edit-mode) +(defn- end-path-event? + [event] + (let [type (ptk/type event)] + (or + (= type ::common/finish-path) + (= type :app.main.data.workspace.path.shortcuts/esc-pressed) + (= type :app.main.data.workspace.common/clear-edition-mode) + (= type :app.main.data.workspace.edition/clear-edition-mode) + (= type :app.main.data.workspace/finalize-page) + (= event :interrupt) ;; ESC + (and ^boolean (mse/mouse-event? event) + ^boolean (mse/mouse-double-click-event? event))))) + (defn preview-next-point [{:keys [x y shift?]}] (ptk/reify ::preview-next-point @@ -126,8 +141,6 @@ (rx/of (preview-next-point handler) (undo/merge-head)))))) -(declare close-path-drag-end) - (defn close-path-drag-start [position] (ptk/reify ::close-path-drag-start @@ -146,8 +159,7 @@ (rx/take-until (rx/merge (mse/drag-stopper stream) - (->> stream - (rx/filter helpers/end-path-event?)))))] + (rx/filter end-path-event? stream))))] (rx/concat (rx/of (add-node position)) @@ -171,8 +183,7 @@ (watch [_ state stream] (let [stopper (rx/merge (mse/drag-stopper stream) - (->> stream - (rx/filter helpers/end-path-event?))) + (rx/filter end-path-event? stream)) drag-events (->> (streams/position-stream state) (rx/map #(drag-handler %)) @@ -199,8 +210,7 @@ (let [stopper (rx/merge (mse/drag-stopper stream) - (->> stream - (rx/filter helpers/end-path-event?))) + (rx/filter end-path-event? stream)) drag-events (->> (streams/position-stream state) @@ -230,7 +240,7 @@ end-stream (->> stream - (rx/filter helpers/end-path-event?) + (rx/filter end-path-event?) (rx/share)) stoper-stream @@ -241,8 +251,7 @@ ;; Mouse move preview mousemove-events (->> (streams/position-stream state) - (rx/map #(preview-next-point %)) - (rx/take-until end-stream)) + (rx/map #(preview-next-point %))) ;; From mouse down we can have: click, drag and double click mousedown-events @@ -256,18 +265,15 @@ (make-drag-stream state stream %))) (rx/take-until end-stream))] - (rx/concat - (rx/of (undo/start-path-undo)) - (rx/of (common/init-path)) - (->> (rx/merge mousemove-events - mousedown-events) - (rx/take-until stoper-stream)) + (->> (rx/concat + (rx/of (undo/start-path-undo)) + (->> (rx/merge mousemove-events + mousedown-events) + (rx/take-until stoper-stream)) + (rx/of (ptk/data-event ::end-edition)))))))) - ;; This step implicitly finish path - (rx/of (common/finish-path) - (change-edit-mode :draw))))))) - -(defn setup-frame [] +(defn setup-frame + [] (ptk/reify ::setup-frame ptk/UpdateEvent (update [_ state] @@ -332,14 +338,15 @@ (rx/concat (rx/of (start-edition shape-id)) (->> stream - (rx/filter (ptk/type? ::common/finish-path)) + (rx/filter (ptk/type? ::end-edition)) (rx/take 1) (rx/observe-on :async) (rx/map (partial handle-drawing-end shape-id)))))))) -(declare check-changed-content) +(declare start-draw-mode*) -(defn start-draw-mode [] +(defn start-draw-mode + [] (ptk/reify ::start-draw-mode ptk/UpdateEvent (update [_ state] @@ -350,36 +357,31 @@ (update-in state [:workspace-local :edit-path id] assoc :old-content content) state))) + ptk/WatchEvent + (watch [_ _ _] + (rx/of (start-draw-mode*))))) + +(defn start-draw-mode* + [] + (ptk/reify ::start-draw-mode* ptk/WatchEvent (watch [_ state stream] - (let [id (get-in state [:workspace-local :edition]) - edit-mode (get-in state [:workspace-local :edit-path id :edit-mode])] - (if (= :draw edit-mode) + (let [local (get state :workspace-local) + id (get local :edition) + mode (dm/get-in local [:edit-path id :edit-mode])] + + (if (= :draw mode) (rx/concat (rx/of (dwsh/update-shapes [id] path/convert-to-path)) (rx/of (start-edition id)) (->> stream - (rx/filter (ptk/type? ::common/finish-path)) + (rx/filter (ptk/type? ::end-edition)) (rx/take 1) - (rx/map check-changed-content))) + (rx/mapcat (fn [_] + (rx/of (check-changed-content) + (start-draw-mode*)))))) (rx/empty)))))) -(defn check-changed-content [] - (ptk/reify ::check-changed-content - ptk/WatchEvent - (watch [_ state _] - (let [id (st/get-path-id state) - content (st/get-path state :content) - old-content (get-in state [:workspace-local :edit-path id :old-content]) - mode (get-in state [:workspace-local :edit-path id :edit-mode]) - empty-content? (empty? content)] - (cond - (and (not= content old-content) (not empty-content?)) (rx/of (changes/save-path-content)) - (= mode :draw) (rx/of :interrupt) - :else (rx/of - (common/finish-path) - (dwdc/clear-drawing))))))) - (defn change-edit-mode [mode] (ptk/reify ::change-edit-mode @@ -406,3 +408,25 @@ (let [id (st/get-path-id state)] (assoc-in state [:workspace-local :edit-path id :prev-handler] nil))))) +(defn check-changed-content + [] + (ptk/reify ::check-changed-content + ptk/WatchEvent + (watch [_ state _] + (let [id (st/get-path-id state) + content (st/get-path state :content) + old-content (get-in state [:workspace-local :edit-path id :old-content]) + mode (get-in state [:workspace-local :edit-path id :edit-mode]) + empty-content? (empty? content)] + + (cond + (and (not= content old-content) (not empty-content?)) + (rx/of (changes/save-path-content)) + + (= mode :draw) + (rx/of :interrupt) + + :else + (rx/of + (common/finish-path) + (dwdc/clear-drawing))))))) diff --git a/frontend/src/app/main/data/workspace/path/helpers.cljs b/frontend/src/app/main/data/workspace/path/helpers.cljs index 6c697a87d3..c904e388f5 100644 --- a/frontend/src/app/main/data/workspace/path/helpers.cljs +++ b/frontend/src/app/main/data/workspace/path/helpers.cljs @@ -10,22 +10,7 @@ [app.common.math :as mth] [app.common.types.path :as path] [app.common.types.path.helpers :as path.helpers] - [app.common.types.path.segment :as path.segment] - [app.main.data.workspace.path.common :as common] - [app.util.mouse :as mse] - [potok.v2.core :as ptk])) - -(defn end-path-event? - [event] - (let [type (ptk/type event)] - (or (= type ::common/finish-path) - (= type :app.main.data.workspace.path.shortcuts/esc-pressed) - (= type :app.main.data.workspace.common/clear-edition-mode) - (= type :app.main.data.workspace.edition/clear-edition-mode) - (= type :app.main.data.workspace/finalize-page) - (= event :interrupt) ;; ESC - (and ^boolean (mse/mouse-event? event) - ^boolean (mse/mouse-double-click-event? event))))) + [app.common.types.path.segment :as path.segment])) (defn append-node "Creates a new node in the path. Usually used when drawing." diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index a9832ffbc4..87f4504c84 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -51,7 +51,7 @@ [app.main.ui.workspace.viewport.selection :as selection] [app.main.ui.workspace.viewport.snap-distances :as snap-distances] [app.main.ui.workspace.viewport.snap-points :as snap-points] - [app.main.ui.workspace.viewport.top-bar :refer [edition-bar*]] + [app.main.ui.workspace.viewport.top-bar :refer [path-edition-bar* grid-edition-bar* view-only-bar*]] [app.main.ui.workspace.viewport.utils :as utils] [app.main.ui.workspace.viewport.viewport-ref :refer [create-viewport-ref]] [app.main.ui.workspace.viewport.widgets :as widgets] @@ -302,17 +302,21 @@ [:div {:class (stl/css :viewport) :style #js {"--zoom" zoom} :data-testid "viewport"} (when (:can-edit permissions) - [:* - (when-not hide-ui? - [:> top-toolbar* {:layout layout}]) + (if read-only? + [:> view-only-bar* {}] + [:* + (when-not hide-ui? + [:> top-toolbar* {:layout layout}]) - (when single-select? - [:> edition-bar* {:shape editing-shape - :is-path-edition path-editing? - :is-grid-edition grid-editing? - :is-read-only read-only? - :edit-path-state edit-path-state - :layout layout}])]) + (when (and ^boolean path-editing? + ^boolean single-select?) + [:> path-edition-bar* {:shape editing-shape + :edit-path-state edit-path-state + :layout layout}]) + + (when (and ^boolean grid-editing? + ^boolean single-select?) + [:> grid-edition-bar* {:shape editing-shape}])])) [:div {:class (stl/css :viewport-overlays)} ;; The behaviour inside a foreign object is a bit different that in plain HTML so we wrap @@ -637,7 +641,7 @@ (when show-selection-handlers? [:g.selection-handlers {:clipPath "url(#clip-handlers)"} (when-not text-editing? - (if editing-shape + (if (and editing-shape path-editing?) [:> path-editor* {:shape editing-shape :state edit-path-state :zoom zoom}] diff --git a/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs b/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs index 1c91d3c656..b9f4f69cb4 100644 --- a/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/top_bar.cljs @@ -19,7 +19,7 @@ ;; should also be renamed. But this should be done on development ;; branch. -(mf/defc view-only-actions* +(mf/defc view-only-bar* {::mf/private true} [] (let [handle-close-view-mode @@ -38,22 +38,15 @@ :on-click handle-close-view-mode} (tr "workspace.top-bar.read-only.done")]]])) -(mf/defc edition-bar* - [{:keys [layout is-read-only edit-path-state is-grid-edition is-path-edition shape]}] - (cond - ^boolean - is-read-only - [:> view-only-actions*] +(mf/defc path-edition-bar* + [{:keys [layout edit-path-state shape]}] + (let [rulers? (contains? layout :rulers) + class (stl/css-case + :viewport-actions-path true + :viewport-actions-no-rulers (not rulers?))] + [:div {:class class} + [:> path-actions* {:shape shape :state edit-path-state}]])) - ^boolean - is-path-edition - - (let [rulers? (contains? layout :rulers) - class (stl/css-case - :viewport-actions-path true - :viewport-actions-no-rulers (not rulers?))] - [:div {:class class} - [:> path-actions* {:shape shape :state edit-path-state}]]) - - is-grid-edition - [:& grid-edition-actions {:shape shape}])) +(mf/defc grid-edition-bar* + [{:keys [shape]}] + [:& grid-edition-actions {:shape shape}]) diff --git a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs index 91f0ab70bc..02070b1a94 100644 --- a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs +++ b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs @@ -47,7 +47,7 @@ [app.main.ui.workspace.viewport.selection :as selection] [app.main.ui.workspace.viewport.snap-distances :as snap-distances] [app.main.ui.workspace.viewport.snap-points :as snap-points] - [app.main.ui.workspace.viewport.top-bar :refer [edition-bar*]] + [app.main.ui.workspace.viewport.top-bar :refer [path-edition-bar* grid-edition-bar* view-only-bar*]] [app.main.ui.workspace.viewport.utils :as utils] [app.main.ui.workspace.viewport.viewport-ref :refer [create-viewport-ref]] [app.main.ui.workspace.viewport.widgets :as widgets] @@ -349,16 +349,22 @@ [:div {:class (stl/css :viewport) :style #js {"--zoom" zoom} :data-testid "viewport"} (when (:can-edit permissions) - [:* - (when-not hide-ui? - [:> top-toolbar* {:layout layout}]) + (if read-only? + [:> view-only-bar* {}] + [:* + (when-not hide-ui? + [:> top-toolbar* {:layout layout}]) + + (when (and ^boolean path-editing? + ^boolean single-select?) + [:> path-edition-bar* {:shape editing-shape + :edit-path-state edit-path-state + :layout layout}]) + + (when (and ^boolean grid-editing? + ^boolean single-select?) + [:> grid-edition-bar* {:shape editing-shape}])])) - [:> edition-bar* {:layout layout - :selected selected-shapes - :edit-path edit-path-state - :drawing drawing - :edition edition - :is-read-only read-only?}]]) [:div {:class (stl/css :viewport-overlays)} (when show-comments? [:> comments/comments-layer* {:vbox vbox @@ -627,7 +633,7 @@ (when show-selection-handlers? [:g.selection-handlers {:clipPath "url(#clip-handlers)"} (when-not text-editing? - (if editing-shape + (if (and editing-shape path-editing?) [:> path-editor* {:shape editing-shape :state edit-path-state :zoom zoom}]