mirror of
https://github.com/penpot/penpot.git
synced 2025-06-02 20:51:38 +02:00
♻️ Major refactor of page data structure.
In preparation to future collaborative edition.
This commit is contained in:
parent
8c4bdc3f31
commit
af62d949d8
33 changed files with 1025 additions and 1124 deletions
|
@ -29,9 +29,8 @@
|
|||
(ptk/reify ::start-move-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
flags (get-in state [:workspace pid :flags])
|
||||
selected (get-in state [:workspace pid :selected])
|
||||
(let [flags (get-in state [:workspace-local :flags])
|
||||
selected (get-in state [:workspace-local :selected])
|
||||
stoper (rx/filter uws/mouse-up? stream)
|
||||
position @uws/mouse-position]
|
||||
(rx/concat
|
||||
|
@ -40,7 +39,8 @@
|
|||
(->> (uws/mouse-position-deltas position)
|
||||
(rx/map #(dw/apply-temporal-displacement-in-bulk selected %))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (dw/materialize-current-modifier-in-bulk selected)))))))
|
||||
(rx/of (dw/materialize-current-modifier-in-bulk selected)
|
||||
::dw/page-data-update))))))
|
||||
|
||||
(defn on-mouse-down
|
||||
[event {:keys [id type] :as shape} selected]
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
[lentes.core :as l]
|
||||
[rumext.core :as mx]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.main.data.shapes :as uds]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.refs :as refs]
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
[uxbox.main.data.history :as udh]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.undo :as udu]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.confirm]
|
||||
|
@ -22,9 +22,9 @@
|
|||
[uxbox.main.ui.messages :refer [messages-widget]]
|
||||
[uxbox.main.ui.workspace.viewport :refer [viewport]]
|
||||
[uxbox.main.ui.workspace.colorpalette :refer [colorpalette]]
|
||||
[uxbox.main.ui.workspace.download]
|
||||
;; [uxbox.main.ui.workspace.download]
|
||||
[uxbox.main.ui.workspace.header :refer [header]]
|
||||
[uxbox.main.ui.workspace.images]
|
||||
;; [uxbox.main.ui.workspace.images]
|
||||
[uxbox.main.ui.workspace.rules :refer [horizontal-rule vertical-rule]]
|
||||
[uxbox.main.ui.workspace.scroll :as scroll]
|
||||
[uxbox.main.ui.workspace.shortcuts :as shortcuts]
|
||||
|
@ -55,47 +55,20 @@
|
|||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(if (pos? (.-deltaY event))
|
||||
(st/emit! (dw/decrease-zoom))
|
||||
(st/emit! (dw/increase-zoom)))
|
||||
(st/emit! (udw/decrease-zoom))
|
||||
(st/emit! (udw/increase-zoom)))
|
||||
(scroll/scroll-to-point dom mouse-point scroll-position))))
|
||||
|
||||
(defn- subscribe
|
||||
[canvas page]
|
||||
(st/emit! (udp/watch-page-changes (:id page))
|
||||
(udu/watch-page-changes (:id page))
|
||||
;; TODO: temporary commented
|
||||
;; (udh/initialize (:id page))
|
||||
;; (udh/watch-page-changes (:id page))
|
||||
(dw/start-shapes-watcher (:id page)))
|
||||
(let [sub (shortcuts/init)]
|
||||
#(do (st/emit! ::udp/stop-page-watcher
|
||||
::udh/stop-page-watcher
|
||||
::dw/stop-shapes-watcher)
|
||||
(rx/cancel! sub))))
|
||||
|
||||
(mf/defc workspace
|
||||
[{:keys [page] :as props}]
|
||||
(let [flags (or (mf/deref refs/flags) #{})
|
||||
canvas (mf/use-ref nil)
|
||||
left-sidebar? (not (empty? (keep flags [:layers :sitemap
|
||||
(mf/defc workspace-content
|
||||
[{:keys [layout page] :as params}]
|
||||
(let [canvas (mf/use-ref nil)
|
||||
left-sidebar? (not (empty? (keep layout [:layers :sitemap
|
||||
:document-history])))
|
||||
right-sidebar? (not (empty? (keep flags [:icons :drawtools
|
||||
right-sidebar? (not (empty? (keep layout [:icons :drawtools
|
||||
:element-options])))
|
||||
classes (classnames
|
||||
:no-tool-bar-right (not right-sidebar?)
|
||||
:no-tool-bar-left (not left-sidebar?)
|
||||
:scrolling (:viewport-positionig workspace))]
|
||||
|
||||
(mf/use-effect #(subscribe canvas page)
|
||||
#js [(:id page)])
|
||||
[:*
|
||||
[:& messages-widget]
|
||||
[:& header {:page page
|
||||
:flags flags
|
||||
:key (:id page)}]
|
||||
|
||||
(when (:colorpalette flags)
|
||||
[:& colorpalette])
|
||||
:no-tool-bar-left (not left-sidebar?))]
|
||||
|
||||
[:main.main-content
|
||||
[:section.workspace-content
|
||||
|
@ -106,32 +79,45 @@
|
|||
[:& history-dialog]
|
||||
|
||||
;; Rules
|
||||
(when (contains? flags :rules)
|
||||
[:& horizontal-rule])
|
||||
|
||||
(when (contains? flags :rules)
|
||||
[:& vertical-rule])
|
||||
(when (contains? layout :rules)
|
||||
[:*
|
||||
[:& horizontal-rule]
|
||||
[:& vertical-rule]])
|
||||
|
||||
[:section.workspace-viewport {:id "workspace-viewport" :ref canvas}
|
||||
[:& viewport {:page page :key (:id page)}]]]
|
||||
[:& viewport {:page page}]]]
|
||||
|
||||
;; Aside
|
||||
(when left-sidebar?
|
||||
[:& left-sidebar {:page page :flags flags}])
|
||||
[:& left-sidebar {:page page :layout layout}])
|
||||
(when right-sidebar?
|
||||
[:& right-sidebar {:page page :flags flags}])]]))
|
||||
[:& right-sidebar {:page page :layout layout}])]))
|
||||
|
||||
(mf/defc workspace
|
||||
[{:keys [page-id] :as props}]
|
||||
(let [layout (mf/deref refs/workspace-layout)
|
||||
flags (mf/deref refs/selected-flags)
|
||||
page (mf/deref refs/workspace-page)]
|
||||
|
||||
[:*
|
||||
[:& messages-widget]
|
||||
[:& header {:page page :flags flags}]
|
||||
|
||||
(when (:colorpalette flags)
|
||||
[:& colorpalette])
|
||||
|
||||
(when (and layout page)
|
||||
[:& workspace-content {:layout layout :page page}])]))
|
||||
|
||||
(mf/defc workspace-page
|
||||
[{:keys [project-id page-id] :as props}]
|
||||
(let [page-iref (mf/use-memo {:deps #js [project-id page-id]
|
||||
:fn #(-> (l/in [:pages page-id])
|
||||
(l/derive st/state))})
|
||||
page (mf/deref page-iref)]
|
||||
|
||||
(mf/use-effect
|
||||
{:deps #js [project-id page-id]
|
||||
:fn #(st/emit! (dw/initialize project-id page-id))})
|
||||
(mf/use-effect
|
||||
{:deps #js [page-id]
|
||||
:fn (fn []
|
||||
(let [sub (shortcuts/init)]
|
||||
(st/emit! (udw/initialize project-id page-id))
|
||||
#(rx/cancel! sub)))})
|
||||
|
||||
[:> rdnd/provider {:backend rdnd/html5}
|
||||
(when page
|
||||
[:& workspace {:page page}])]))
|
||||
[:> rdnd/provider {:backend rdnd/html5}
|
||||
[:& workspace {:page-id page-id :key page-id}]])
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.data.shapes :as ds]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
|
@ -73,17 +72,16 @@
|
|||
(ptk/reify ::start-drawing
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:workspace :drawing-lock] #(if (nil? %) id %)))
|
||||
(update-in state [:workspace-local :drawing-lock] #(if (nil? %) id %)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
lock (get-in state [:workspace :drawing-lock])]
|
||||
(let [lock (get-in state [:workspace-local :drawing-lock])]
|
||||
(if (= lock id)
|
||||
(rx/merge
|
||||
(->> (rx/filter #(= % handle-finish-drawing) stream)
|
||||
(rx/take 1)
|
||||
(rx/map (fn [_] #(update % :workspace dissoc :drawing-lock))))
|
||||
(rx/map (fn [_] #(update % :workspace-local dissoc :drawing-lock))))
|
||||
(rx/of (handle-drawing type)))
|
||||
(rx/empty)))))))
|
||||
|
||||
|
@ -98,9 +96,8 @@
|
|||
(ptk/reify ::handle-drawing
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
data (make-minimal-shape type)]
|
||||
(update-in state [:workspace pid :drawing] merge data)))
|
||||
(let [data (make-minimal-shape type)]
|
||||
(update-in state [:workspace-local :drawing] merge data)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
@ -111,13 +108,12 @@
|
|||
|
||||
(def handle-drawing-generic
|
||||
(letfn [(initialize-drawing [state point]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
shape (get-in state [:workspace pid :drawing])
|
||||
(let [shape (get-in state [:workspace-local :drawing])
|
||||
shape (geom/setup shape {:x1 (:x point)
|
||||
:y1 (:y point)
|
||||
:x2 (+ (:x point) 2)
|
||||
:y2 (+ (:y point) 2)})]
|
||||
(assoc-in state [:workspace pid :drawing] (assoc shape ::initialized? true))))
|
||||
(assoc-in state [:workspace-local :drawing] (assoc shape ::initialized? true))))
|
||||
|
||||
(resize-shape [shape point lock?]
|
||||
(let [shape (-> (geom/shape->rect-shape shape)
|
||||
|
@ -128,14 +124,12 @@
|
|||
(assoc shape :modifier-mtx mtx)))
|
||||
|
||||
(update-drawing [state point lock?]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(update-in state [:workspace pid :drawing] resize-shape point lock?)))]
|
||||
(update-in state [:workspace-local :drawing] resize-shape point lock?))]
|
||||
|
||||
(ptk/reify ::handle-drawing-generic
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
{:keys [zoom flags]} (get-in state [:workspace pid])
|
||||
(let [{:keys [zoom flags]} (:workspace-local state)
|
||||
align? (refs/alignment-activated? flags)
|
||||
|
||||
stoper? #(or (uws/mouse-up? %) (= % :interrupt))
|
||||
|
@ -165,30 +159,26 @@
|
|||
(= 13 (:key event)))))
|
||||
|
||||
(initialize-drawing [state point]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(-> state
|
||||
(assoc-in [:workspace pid :drawing :segments] [point point])
|
||||
(assoc-in [:workspace pid :drawing ::initialized?] true))))
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :drawing :segments] [point point])
|
||||
(assoc-in [:workspace-local :drawing ::initialized?] true)))
|
||||
|
||||
(insert-point-segment [state point]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(update-in state [:workspace pid :drawing :segments] (fnil conj []) point)))
|
||||
(update-in state [:workspace-local :drawing :segments] (fnil conj []) point))
|
||||
|
||||
(update-point-segment [state index point]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
segments (count (get-in state [:workspace pid :drawing :segments]))
|
||||
(let [segments (count (get-in state [:workspace-local :drawing :segments]))
|
||||
exists? (< -1 index segments)]
|
||||
(cond-> state
|
||||
exists? (assoc-in [:workspace pid :drawing :segments index] point))))
|
||||
exists? (assoc-in [:workspace-local :drawing :segments index] point))))
|
||||
|
||||
(remove-dangling-segmnet [state]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(update-in state [:workspace pid :drawing :segments] #(vec (butlast %)))))]
|
||||
(update-in state [:workspace-local :drawing :segments] #(vec (butlast %))))]
|
||||
|
||||
(ptk/reify ::handle-drawing-path
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
{:keys [zoom flags]} (get-in state [:workspace pid])
|
||||
(let [{:keys [zoom flags]} (:workspace-local state)
|
||||
|
||||
align? (refs/alignment-activated? flags)
|
||||
last-point (volatile! (gpt/divide @uws/mouse-position zoom))
|
||||
|
@ -252,29 +242,23 @@
|
|||
(and (uws/mouse-event? event) (= type :up))))
|
||||
|
||||
(initialize-drawing [state]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(assoc-in state [:workspace pid :drawing ::initialized?] true)))
|
||||
(assoc-in state [:workspace-local :drawing ::initialized?] true))
|
||||
|
||||
(insert-point-segment [state point]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(update-in state [:workspace pid :drawing :segments] (fnil conj []) point)))
|
||||
(update-in state [:workspace-local :drawing :segments] (fnil conj []) point))
|
||||
|
||||
(simplify-drawing-path [state tolerance]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(update-in state [:workspace pid :drawing :segments] path/simplify tolerance)))]
|
||||
(update-in state [:workspace-local :drawing :segments] path/simplify tolerance))]
|
||||
|
||||
(ptk/reify ::handle-drawing-curve
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
{:keys [zoom flags]} (get-in state [:workspace pid])
|
||||
|
||||
(let [{:keys [zoom flags]} (:workspace-local state)
|
||||
align? (refs/alignment-activated? flags)
|
||||
stoper (rx/filter stoper-event? stream)
|
||||
mouse (->> (rx/sample 10 uws/mouse-position)
|
||||
(rx/mapcat #(conditional-align % align?))
|
||||
(rx/map #(gpt/divide % zoom)))]
|
||||
|
||||
(rx/concat
|
||||
(rx/of initialize-drawing)
|
||||
(->> mouse
|
||||
|
@ -287,8 +271,7 @@
|
|||
(ptk/reify ::handle-finish-drawing
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [pid (get-in state [:workspace :current])
|
||||
shape (get-in state [:workspace pid :drawing])]
|
||||
(let [shape (get-in state [:workspace-local :drawing])]
|
||||
(rx/concat
|
||||
(rx/of dw/clear-drawing)
|
||||
(when (::initialized? shape)
|
||||
|
@ -305,8 +288,7 @@
|
|||
(ptk/reify ::close-drawing-path
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [pid (get-in state [:workspace :current])]
|
||||
(assoc-in state [:workspace pid :drawing :close?] true)))))
|
||||
(assoc-in state [:workspace-local :drawing :close?] true))))
|
||||
|
||||
;; --- Components
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@
|
|||
[:ul.options-btn
|
||||
[:li.tooltip.tooltip-bottom.view-mode
|
||||
{:alt (tr "header.view-mode")
|
||||
:on-click #(st/emit! (dw/->OpenView (:id page)))
|
||||
;; :on-click #(st/emit! (dw/->OpenView (:id page)))
|
||||
}
|
||||
i/play]]
|
||||
[:& zoom-widget]]
|
||||
|
|
|
@ -72,7 +72,8 @@
|
|||
(rx/map normalize-proportion-lock)
|
||||
(rx/mapcat (partial resize shape))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (dw/materialize-current-modifier-in-bulk ids))))))))
|
||||
(rx/of (dw/materialize-current-modifier-in-bulk ids)
|
||||
::dw/page-data-update)))))))
|
||||
|
||||
;; --- Controls (Component)
|
||||
|
||||
|
@ -221,21 +222,18 @@
|
|||
[:& controls {:shape shape :zoom zoom :on-click on-click}]))
|
||||
|
||||
(mf/defc selection-handlers
|
||||
[{:keys [wst] :as props}]
|
||||
(let [shapes-map (mf/deref refs/shapes-by-id)
|
||||
shapes (map #(get shapes-map %) (:selected wst))
|
||||
edition (:edition wst)
|
||||
zoom (:zoom wst 1)
|
||||
[{:keys [selected edition zoom] :as props}]
|
||||
(let [data (mf/deref refs/workspace-data)
|
||||
shapes (map #(get-in data [:shapes-by-id %]) selected)
|
||||
num (count shapes)
|
||||
{:keys [id type] :as shape} (first shapes)]
|
||||
|
||||
(cond
|
||||
(zero? num)
|
||||
nil
|
||||
|
||||
(> num 1)
|
||||
[:& multiple-selection-handlers {:shapes shapes
|
||||
:selected (:selected wst)
|
||||
:selected selected
|
||||
:zoom zoom}]
|
||||
|
||||
(and (= type :text)
|
||||
|
|
|
@ -20,27 +20,27 @@
|
|||
|
||||
(mf/defc left-sidebar
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[{:keys [flags page] :as props}]
|
||||
[{:keys [layout page] :as props}]
|
||||
[:aside.settings-bar.settings-bar-left
|
||||
[:div.settings-bar-inside
|
||||
(when (contains? flags :sitemap)
|
||||
(when (contains? layout :sitemap)
|
||||
[:& sitemap-toolbox {:project-id (:project-id page)
|
||||
:current-page-id (:id page)
|
||||
:page page}])
|
||||
(when (contains? flags :document-history)
|
||||
(when (contains? layout :document-history)
|
||||
[:& history-toolbox])
|
||||
(when (contains? flags :layers)
|
||||
(when (contains? layout :layers)
|
||||
[:& layers-toolbox {:page page}])]])
|
||||
|
||||
;; --- Right Sidebar (Component)
|
||||
|
||||
(mf/defc right-sidebar
|
||||
[{:keys [flags page] :as props}]
|
||||
[{:keys [layout page] :as props}]
|
||||
[:aside#settings-bar.settings-bar
|
||||
[:div.settings-bar-inside
|
||||
(when (contains? flags :drawtools)
|
||||
[:& draw-toolbox {:flags flags}])
|
||||
(when (contains? flags :element-options)
|
||||
(when (contains? layout :drawtools)
|
||||
[:& draw-toolbox {:layout layout}])
|
||||
(when (contains? layout :element-options)
|
||||
[:& options-toolbox {:page page}])
|
||||
#_(when (contains? flags :icons)
|
||||
#_(when (contains? layout :icons)
|
||||
(icons-toolbox))]])
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
|
||||
(mf/defc layer-item
|
||||
[{:keys [shape selected index] :as props}]
|
||||
;; (prn "layer-item" index (:name shape))
|
||||
(letfn [(toggle-blocking [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [{:keys [id blocked]} shape]
|
||||
|
@ -107,7 +108,7 @@
|
|||
(dw/select-shape id)))))
|
||||
|
||||
(on-drop [item monitor]
|
||||
(st/emit! (udp/persist-page (:page shape))))
|
||||
(st/emit! ::dw/page-data-update))
|
||||
|
||||
(on-hover [item monitor]
|
||||
(st/emit! (dw/change-shape-order {:id (:shape-id item)
|
||||
|
@ -168,10 +169,9 @@
|
|||
(dw/select-shape id)))))
|
||||
|
||||
(on-drop [item monitor]
|
||||
(st/emit! (udp/persist-page (:page canvas))))
|
||||
(st/emit! ::dw/page-data-update))
|
||||
|
||||
(on-hover [item monitor]
|
||||
(prn "canvas-item$hover" (:id canvas))
|
||||
(st/emit! (dw/change-canvas-order {:id (:canvas-id item)
|
||||
:index index})))]
|
||||
(let [selected? (contains? selected (:id canvas))
|
||||
|
@ -236,21 +236,25 @@
|
|||
;; --- Layers Toolbox
|
||||
|
||||
(mf/defc layers-toolbox
|
||||
[{:keys [page selected] :as props}]
|
||||
[{:keys [page] :as props}]
|
||||
(let [on-click #(st/emit! (dw/toggle-flag :layers))
|
||||
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
shapes-by-id (mf/deref shapes-iref)
|
||||
canvas (->> (:canvas page)
|
||||
data (mf/deref refs/workspace-data)
|
||||
|
||||
shapes-by-id (:shapes-by-id data)
|
||||
|
||||
canvas (->> (:canvas data)
|
||||
(map #(get shapes-by-id %))
|
||||
(enumerate))
|
||||
all-shapes (->> (:shapes page)
|
||||
(map #(get shapes-by-id %)))
|
||||
|
||||
shapes (->> all-shapes
|
||||
(filter #(not (:canvas %)))
|
||||
(enumerate))
|
||||
shapes (->> (:shapes data)
|
||||
(map #(get shapes-by-id %)))
|
||||
|
||||
all-shapes (enumerate all-shapes)]
|
||||
all-shapes (enumerate shapes)
|
||||
unc-shapes (->> shapes
|
||||
(filter #(nil? (:canvas %)))
|
||||
(enumerate))]
|
||||
|
||||
[:div#layers.tool-window
|
||||
[:div.tool-window-bar
|
||||
|
@ -261,5 +265,5 @@
|
|||
[:& canvas-list {:canvas canvas
|
||||
:shapes all-shapes
|
||||
:selected selected}]
|
||||
[:& layers-list {:shapes shapes
|
||||
[:& layers-list {:shapes unc-shapes
|
||||
:selected selected}]]]))
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
[rumext.alpha :as mf]
|
||||
[rumext.core :as mx]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.shapes :as uds]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.store :as st]
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.shapes :as uds]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.store :as st]
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.shapes :as uds]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.store :as st]
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.data.shapes :as uds]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.store :as st]
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
[uxbox.main.store :as st]
|
||||
[uxbox.main.geom :as geom]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.data.shapes :as uds]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.util.i18n :refer (tr)]
|
||||
[uxbox.util.router :as r]
|
||||
|
|
|
@ -15,11 +15,12 @@
|
|||
[uxbox.main.data.projects :as dp]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.ui.confirm :refer [confirm-dialog]]
|
||||
[uxbox.main.ui.modal :as modal]
|
||||
[uxbox.main.ui.workspace.sidebar.sitemap-forms :refer [page-form-dialog]]
|
||||
[uxbox.main.ui.workspace.sortable :refer [use-sortable]]
|
||||
[uxbox.util.data :refer [classnames]]
|
||||
[uxbox.util.data :refer [classnames enumerate]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.i18n :refer [tr]]
|
||||
[uxbox.util.router :as rt]))
|
||||
|
@ -37,14 +38,12 @@
|
|||
(dom/stop-propagation event)
|
||||
(modal/show! confirm-dialog {:on-accept delete}))
|
||||
(on-drop [item monitor]
|
||||
(st/emit! (udp/rehash-pages (:project-id page))))
|
||||
(prn "TODO"))
|
||||
(on-hover [item monitor]
|
||||
(st/emit! (udp/move-page {:project-id (:project-id item)
|
||||
:page-id (:page-id item)
|
||||
:index index})))]
|
||||
(st/emit! (dw/change-page-order {:id (:id item)
|
||||
:index index})))]
|
||||
(let [[dprops ref] (use-sortable {:type "page-item"
|
||||
:data {:page-id (:id page)
|
||||
:project-id (:project-id page)
|
||||
:data {:id (:id page)
|
||||
:index index}
|
||||
:on-hover on-hover
|
||||
:on-drop on-drop})]
|
||||
|
@ -64,40 +63,52 @@
|
|||
(when deletable?
|
||||
[:a {:on-click on-delete} i/trash])]]])))
|
||||
|
||||
;; --- Pages List
|
||||
|
||||
(defn- make-pages-iref
|
||||
[{:keys [id pages] :as project}]
|
||||
(-> (l/lens (fn [s] (into [] (map #(get-in s [:pages %])) pages)))
|
||||
(l/derive st/state {:equals? =})))
|
||||
;; --- Page Item Wrapper
|
||||
|
||||
(def ^:private pages-map-iref
|
||||
(-> (l/key :pages)
|
||||
(defn- make-page-ref
|
||||
[page-id]
|
||||
(-> (l/in [:pages page-id])
|
||||
(l/derive st/state)))
|
||||
|
||||
(mf/defc page-item-wrapper
|
||||
[{:keys [page-id index deletable? selected?] :as props}]
|
||||
(let [page-ref (mf/use-memo {:deps #js [page-id]
|
||||
:fn #(make-page-ref page-id)})
|
||||
page (mf/deref page-ref)]
|
||||
[:& page-item {:page page
|
||||
:index index
|
||||
:deletable? deletable?
|
||||
:selected? selected?}]))
|
||||
|
||||
;; --- Pages List
|
||||
|
||||
(mf/defc pages-list
|
||||
[{:keys [project current-page-id] :as props}]
|
||||
(let [pages-map (mf/deref pages-map-iref)
|
||||
pages (->> (vals pages-map)
|
||||
(filter #(= (:project-id %) (:id project))))
|
||||
(let [pages (enumerate (:pages project))
|
||||
deletable? (> (count pages) 1)]
|
||||
[:ul.element-list
|
||||
(for [[index item] (map-indexed vector pages)]
|
||||
[:& page-item {:page item
|
||||
:index index
|
||||
:deletable? deletable?
|
||||
:selected? (= (:id item) current-page-id)
|
||||
:key (:id item)}])]))
|
||||
(for [[index page-id] pages]
|
||||
[:& page-item-wrapper
|
||||
{:page-id page-id
|
||||
:index index
|
||||
:deletable? deletable?
|
||||
:selected? (= page-id current-page-id)
|
||||
:key page-id}])]))
|
||||
|
||||
;; --- Sitemap Toolbox
|
||||
|
||||
(def ^:private workspace-project
|
||||
(letfn [(selector [state]
|
||||
(let [project-id (get-in state [:workspace-page :project-id])]
|
||||
(get-in state [:projects project-id])))]
|
||||
(-> (l/lens selector)
|
||||
(l/derive st/state))))
|
||||
|
||||
(mf/defc sitemap-toolbox
|
||||
[{:keys [project-id current-page-id] :as props}]
|
||||
(let [project-iref (mf/use-memo {:deps #js [project-id]
|
||||
:fn #(-> (l/in [:projects project-id])
|
||||
(l/derive st/state))})
|
||||
project (mf/deref project-iref)
|
||||
create #(modal/show! page-form-dialog {:page {:project project-id}})
|
||||
(let [project (mf/deref workspace-project)
|
||||
create #(modal/show! page-form-dialog {:page {:project-id project-id}})
|
||||
close #(st/emit! (dw/toggle-flag :sitemap))]
|
||||
[:div.sitemap.tool-window
|
||||
[:div.tool-window-bar
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.pages :as udp]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.modal :as modal]
|
||||
[uxbox.util.dom :as dom]
|
||||
|
@ -20,22 +21,12 @@
|
|||
[uxbox.util.i18n :refer [tr]]))
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::project ::us/uuid)
|
||||
(s/def ::project-id ::us/uuid)
|
||||
(s/def ::name ::us/not-empty-string)
|
||||
(s/def ::width ::us/number-str)
|
||||
(s/def ::height ::us/number-str)
|
||||
|
||||
(s/def ::page-form
|
||||
(s/keys :req-un [::id
|
||||
::project
|
||||
::name
|
||||
::width
|
||||
::height]))
|
||||
|
||||
(def defaults
|
||||
{:name ""
|
||||
:width "1366"
|
||||
:height "768"})
|
||||
(s/keys :req-un [::project-id ::name]
|
||||
:opt-un [::id]))
|
||||
|
||||
(defn- on-submit
|
||||
[event form]
|
||||
|
@ -43,20 +34,13 @@
|
|||
(modal/hide!)
|
||||
(let [data (:clean-data form)]
|
||||
(if (nil? (:id data))
|
||||
(st/emit! (udp/form->create-page data))
|
||||
(st/emit! (udp/form->update-page data)))))
|
||||
|
||||
(defn- swap-size
|
||||
[event {:keys [data] :as form}]
|
||||
(swap! data assoc
|
||||
:width (:height data)
|
||||
:height (:width data)))
|
||||
(st/emit! (udp/create-page data))
|
||||
(st/emit! (udp/rename-page data)))))
|
||||
|
||||
(defn- initial-data
|
||||
[page]
|
||||
(merge {:name "" :width "1366" :height "768"}
|
||||
(select-keys page [:name :id :project])
|
||||
(select-keys (:metadata page) [:width :height])))
|
||||
(merge {:name ""}
|
||||
(select-keys page [:name :id :project-id])))
|
||||
|
||||
(mf/defc page-form
|
||||
[{:keys [page] :as props}]
|
||||
|
@ -71,32 +55,6 @@
|
|||
:on-change (fm/on-input-change form :name)
|
||||
:value (:name data)
|
||||
:auto-focus true}]
|
||||
[:div.project-size
|
||||
[:div.input-element.pixels
|
||||
[:span (tr "ds.width")]
|
||||
[:input#project-witdh.input-text
|
||||
{:placeholder (tr "ds.width")
|
||||
:name "width"
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 5000
|
||||
:class (fm/error-class form :width)
|
||||
:on-blur (fm/on-input-blur form :width)
|
||||
:on-change (fm/on-input-change form :width)
|
||||
:value (:width data)}]]
|
||||
[:a.toggle-layout {:on-click #(swap-size % form)} i/toggle]
|
||||
[:div.input-element.pixels
|
||||
[:span (tr "ds.height")]
|
||||
[:input#project-height.input-text
|
||||
{:placeholder (tr "ds.height")
|
||||
:name "height"
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 5000
|
||||
:class (fm/error-class form :height)
|
||||
:on-blur (fm/on-input-blur form :height)
|
||||
:on-change (fm/on-input-change form :height)
|
||||
:value (:height data)}]]]
|
||||
[:input.btn-primary
|
||||
{:value (tr "ds.go")
|
||||
:type "submit"
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
[uxbox.main.ui.workspace.streams :as uws]
|
||||
[uxbox.main.ui.workspace.drawarea :refer [start-drawing]]
|
||||
|
||||
[uxbox.main.ui.shapes :as uus]
|
||||
[uxbox.main.ui.shapes :refer [shape-wrapper]]
|
||||
[uxbox.main.ui.workspace.drawarea :refer [draw-area]]
|
||||
[uxbox.main.ui.workspace.selection :refer [selection-handlers]]
|
||||
|
||||
|
@ -74,17 +74,15 @@
|
|||
|
||||
(def ^:private handle-selrect
|
||||
(letfn [(update-state [state position]
|
||||
(let [id (get-in state [:workspace :current])
|
||||
selrect (get-in state [:workspace id :selrect])]
|
||||
(let [selrect (get-in state [:workspace-local :selrect])]
|
||||
(if selrect
|
||||
(assoc-in state [:workspace id :selrect]
|
||||
(assoc-in state [:workspace-local :selrect]
|
||||
(dw/selection->rect (assoc selrect :stop position)))
|
||||
(assoc-in state [:workspace id :selrect]
|
||||
(assoc-in state [:workspace-local :selrect]
|
||||
(dw/selection->rect {:start position :stop position})))))
|
||||
|
||||
(clear-state [state]
|
||||
(let [id (get-in state [:workspace :current])]
|
||||
(update-in state [:workspace id] dissoc :selrect)))]
|
||||
(update state :workspace-local dissoc :selrect))]
|
||||
(ptk/reify ::handle-selrect
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
@ -129,11 +127,28 @@
|
|||
|
||||
;; --- Viewport
|
||||
|
||||
(mf/defc canvas-and-shapes
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[props]
|
||||
(let [data (mf/deref refs/workspace-data)
|
||||
shapes-by-id (:shapes-by-id data)
|
||||
shapes (map #(get shapes-by-id %) (:shapes data []))
|
||||
canvas (map #(get shapes-by-id %) (:canvas data []))]
|
||||
[:*
|
||||
(for [item canvas]
|
||||
[:& shape-wrapper {:shape item :key (:id item)}])
|
||||
(for [item (reverse shapes)]
|
||||
[:& shape-wrapper {:shape item :key (:id item)}])]))
|
||||
|
||||
(mf/defc viewport
|
||||
[{:keys [page] :as props}]
|
||||
(let [{:keys [drawing-tool tooltip zoom flags edition] :as wst} (mf/deref refs/workspace)
|
||||
(let [{:keys [drawing-tool
|
||||
zoom
|
||||
flags
|
||||
edition
|
||||
selected]
|
||||
:as local} (mf/deref refs/workspace-local)
|
||||
viewport-ref (mf/use-ref nil)
|
||||
tooltip (or tooltip (get-shape-tooltip drawing-tool))
|
||||
zoom (or zoom 1)]
|
||||
(letfn [(on-mouse-down [event]
|
||||
(dom/stop-propagation event)
|
||||
|
@ -230,9 +245,6 @@
|
|||
;; (prn "viewport$render")
|
||||
[:*
|
||||
[:& coordinates {:zoom zoom}]
|
||||
#_[:div.tooltip-container
|
||||
(when tooltip
|
||||
[:& cursor-tooltip {:tooltip tooltip}])]
|
||||
[:svg.viewport {:width (* c/viewport-width zoom)
|
||||
:height (* c/viewport-height zoom)
|
||||
:ref viewport-ref
|
||||
|
@ -244,23 +256,23 @@
|
|||
:on-mouse-down on-mouse-down
|
||||
:on-mouse-up on-mouse-up}
|
||||
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
||||
(when page
|
||||
[:*
|
||||
[:& uus/canvas-and-shapes {:page page}]
|
||||
|
||||
(when (seq (:selected wst))
|
||||
[:& selection-handlers {:wst wst}])
|
||||
|
||||
(when-let [dshape (:drawing wst)]
|
||||
[:& draw-area {:shape dshape
|
||||
:zoom (:zoom wst)
|
||||
:modifiers (:modifiers wst)}])])
|
||||
[:*
|
||||
[:& canvas-and-shapes]
|
||||
|
||||
(when (seq selected)
|
||||
[:& selection-handlers {:selected selected
|
||||
:zoom zoom
|
||||
:edition edition}])
|
||||
|
||||
(when-let [drawing-shape (:drawing local)]
|
||||
[:& draw-area {:shape drawing-shape
|
||||
:zoom zoom
|
||||
:modifiers (:modifiers local)}])]
|
||||
|
||||
(if (contains? flags :grid)
|
||||
[:& grid {:page page}])]
|
||||
(when (contains? flags :ruler)
|
||||
[:& ruler {:zoom zoom :ruler (:ruler wst)}])
|
||||
[:& selrect {:data (:selrect wst)}]]])))
|
||||
|
||||
(when (contains? flags :ruler)
|
||||
[:& ruler {:zoom zoom :ruler (:ruler local)}])
|
||||
|
||||
[:& selrect {:data (:selrect local)}]]])))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue