mirror of
https://github.com/penpot/penpot.git
synced 2025-03-28 15:41:25 -05:00
🎉 Namespace workspace data with page id.
This commit is contained in:
parent
38f675d7f9
commit
fc734328cb
13 changed files with 419 additions and 440 deletions
|
@ -112,17 +112,20 @@
|
|||
|
||||
(s/def ::attr keyword?)
|
||||
(s/def ::val any?)
|
||||
(s/def ::parent-id uuid?)
|
||||
(s/def ::frame-id uuid?)
|
||||
(s/def ::loc #{:top :bottom :up :down})
|
||||
|
||||
(defmulti operation-spec-impl :type)
|
||||
|
||||
(defmethod operation-spec-impl :set [_]
|
||||
(s/keys :req-un [::attr ::val]))
|
||||
|
||||
(defmethod operation-spec-impl :order [_]
|
||||
(defmethod operation-spec-impl :abs-order [_]
|
||||
(s/keys :req-un [::id ::index]))
|
||||
|
||||
(defmethod operation-spec-impl :rel-order [_]
|
||||
(s/keys :req-un [::id ::loc]))
|
||||
|
||||
(s/def ::operation (s/multi-spec operation-spec-impl :type))
|
||||
(s/def ::operations (s/coll-of ::operation))
|
||||
|
||||
|
@ -226,7 +229,7 @@
|
|||
(dissoc shape attr)
|
||||
(assoc shape attr val))))
|
||||
|
||||
(defmethod process-operation :order
|
||||
(defmethod process-operation :abs-order
|
||||
[obj {:keys [id index]}]
|
||||
(assert (vector? (:shapes obj)) ":shapes should be a vector")
|
||||
(update obj :shapes (fn [items]
|
||||
|
@ -234,6 +237,24 @@
|
|||
(split-at index))]
|
||||
(vec (concat b [id] a))))))
|
||||
|
||||
|
||||
(defmethod process-operation :rel-order
|
||||
[obj {:keys [id loc] :as change}]
|
||||
(assert (vector? (:shapes obj)) ":shapes should be a vector")
|
||||
(let [shapes (:shapes obj)
|
||||
cindex (d/index-of shapes id)
|
||||
nindex (case loc
|
||||
:top 0
|
||||
:down (min (- (count shapes) 1) (inc cindex))
|
||||
:up (max 0 (- cindex 1))
|
||||
:bottom (- (count shapes) 1))]
|
||||
(update obj :shapes
|
||||
(fn [shapes]
|
||||
(let [[fst snd] (->> (remove #(= % id) shapes)
|
||||
(split-at nindex))]
|
||||
(d/concat [] fst [id] snd))))))
|
||||
|
||||
|
||||
(defmethod process-operation :default
|
||||
[shape op]
|
||||
(ex/raise :type :operation-not-implemented
|
||||
|
|
|
@ -48,7 +48,7 @@ This is a potential list of persistent ops:
|
|||
|
||||
{:type :mov-obj
|
||||
:id <uuid>
|
||||
:dest <uuid>}
|
||||
:frame-id <uuid>}
|
||||
|
||||
{:type :del-obj
|
||||
:id <uuid>}
|
||||
|
@ -61,9 +61,13 @@ This is a potential list of operations:
|
|||
:attr <any>
|
||||
:val <any>}
|
||||
|
||||
{:type :mov
|
||||
{:type :abs-order
|
||||
:id <uuid>
|
||||
:index <int>}
|
||||
|
||||
{:type :rel-order
|
||||
:id <uuid>
|
||||
:loc <one-of:up,down,top,bottom>}
|
||||
```
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -47,7 +47,9 @@
|
|||
(l/derive st/state)))
|
||||
|
||||
(def workspace-data
|
||||
(-> (l/key :workspace-data)
|
||||
(-> (l/lens (fn [state]
|
||||
(let [page-id (get-in state [:workspace-page :id])]
|
||||
(get-in state [:workspace-data page-id]))))
|
||||
(l/derive st/state)))
|
||||
|
||||
(def selected-shapes
|
||||
|
@ -68,14 +70,6 @@
|
|||
(l/derive workspace-local)))
|
||||
|
||||
;; DEPRECATED
|
||||
(def flags
|
||||
(-> (l/key :flags)
|
||||
(l/derive workspace-local)))
|
||||
|
||||
(def selected-flags
|
||||
(-> (l/key :flags)
|
||||
(l/derive workspace-local)))
|
||||
|
||||
(def selected-zoom
|
||||
(-> (l/key :zoom)
|
||||
(l/derive workspace-local)))
|
||||
|
|
|
@ -35,26 +35,30 @@
|
|||
(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]
|
||||
zero-point? #(= % (gpt/point 0 0))
|
||||
position @uws/mouse-position
|
||||
deltas (atom 0)]
|
||||
(rx/concat
|
||||
(->> (uws/mouse-position-deltas position)
|
||||
(rx/filter (complement zero-point?))
|
||||
(rx/tap #(swap! deltas inc))
|
||||
(rx/map #(dw/apply-displacement-in-bulk selected %))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (dw/materialize-displacement-in-bulk selected)
|
||||
::dw/page-data-update))))))
|
||||
(rx/of (dw/materialize-displacement-in-bulk selected)))))))
|
||||
|
||||
(def start-move-frame
|
||||
(ptk/reify ::start-move-selected
|
||||
(ptk/reify ::start-move-frame
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [flags (get-in state [:workspace-local :flags])
|
||||
selected (get-in state [:workspace-local :selected])
|
||||
stoper (rx/filter uws/mouse-up? stream)
|
||||
zero-point? #(= % (gpt/point 0 0))
|
||||
frame-id (first selected)
|
||||
position @uws/mouse-position]
|
||||
|
||||
(rx/concat
|
||||
(->> (uws/mouse-position-deltas position)
|
||||
(rx/filter (complement zero-point?))
|
||||
(rx/map #(dw/apply-frame-displacement frame-id %))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (dw/materialize-frame-displacement frame-id)))))))
|
||||
|
|
|
@ -58,9 +58,8 @@
|
|||
(scroll/scroll-to-point dom mouse-point scroll-position))))
|
||||
|
||||
(mf/defc workspace-content
|
||||
[{:keys [page file flags] :as params}]
|
||||
[{:keys [page file layout] :as params}]
|
||||
(let [frame (mf/use-ref nil)
|
||||
layout (mf/deref refs/workspace-layout)
|
||||
left-sidebar? (not (empty? (keep layout [:layers :sitemap
|
||||
:document-history])))
|
||||
right-sidebar? (not (empty? (keep layout [:icons :drawtools
|
||||
|
@ -87,7 +86,7 @@
|
|||
[:& vertical-rule]])
|
||||
|
||||
[:section.workspace-viewport {:id "workspace-viewport" :ref frame}
|
||||
[:& viewport {:page page}]]]
|
||||
[:& viewport {:page page :file file}]]]
|
||||
|
||||
;; Aside
|
||||
(when left-sidebar?
|
||||
|
@ -95,6 +94,7 @@
|
|||
(when right-sidebar?
|
||||
[:& right-sidebar {:page page :layout layout}])]]))
|
||||
|
||||
|
||||
(mf/defc workspace
|
||||
[{:keys [file-id page-id] :as props}]
|
||||
(mf/use-effect
|
||||
|
@ -109,6 +109,9 @@
|
|||
(st/emit! (dw/initialize-ws file-id))
|
||||
#(st/emit! (dw/finalize-ws file-id)))})
|
||||
|
||||
(mf/use-effect
|
||||
{:fn #(st/emit! dw/initialize-layout)})
|
||||
|
||||
(mf/use-effect
|
||||
{:deps (mf/deps file-id page-id)
|
||||
:fn (fn []
|
||||
|
@ -116,11 +119,15 @@
|
|||
#(rx/cancel! sub)))})
|
||||
|
||||
(let [file (mf/deref refs/workspace-file)
|
||||
page (mf/deref refs/workspace-page)]
|
||||
page (mf/deref refs/workspace-page)
|
||||
layout (mf/deref refs/workspace-layout)]
|
||||
[:> rdnd/provider {:backend rdnd/html5}
|
||||
[:& messages-widget]
|
||||
[:& header {:page page}]
|
||||
[:& header {:page page
|
||||
:file file
|
||||
:layout layout}]
|
||||
|
||||
(when page
|
||||
[:& workspace-content {:file file
|
||||
:page page}])]))
|
||||
:page page
|
||||
:layout layout}])]))
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
:fill-opacity 0
|
||||
:segments []}
|
||||
{:type :frame
|
||||
:name "Canvas"}
|
||||
:name "Artboard"}
|
||||
{:type :curve
|
||||
:name "Path"
|
||||
:stroke-style :solid
|
||||
|
|
|
@ -63,19 +63,15 @@
|
|||
;; --- Header Component
|
||||
|
||||
(mf/defc header
|
||||
[{:keys [page] :as props}]
|
||||
(let [toggle #(st/emit! (dw/toggle-flag %))
|
||||
toggle-layout #(st/emit! (dw/toggle-layout-flag %))
|
||||
on-undo (constantly nil)
|
||||
on-redo (constantly nil)
|
||||
[{:keys [page file layout] :as props}]
|
||||
(let [toggle-layout #(st/emit! (dw/toggle-layout-flag %))
|
||||
on-undo #(st/emit! (udu/undo))
|
||||
on-redo #(st/emit! (udu/redo))
|
||||
on-image #(modal/show! import-image-modal {})
|
||||
;;on-download #(udl/open! :download)
|
||||
layout (mf/deref refs/workspace-layout)
|
||||
flags (mf/deref refs/selected-flags)
|
||||
file (mf/deref refs/workspace-file)
|
||||
selected-drawtool (mf/deref refs/selected-drawing-tool)
|
||||
select-drawtool #(st/emit! :interrupt
|
||||
(dw/deactivate-ruler)
|
||||
#_(dw/deactivate-ruler)
|
||||
(dw/select-for-drawing %))]
|
||||
|
||||
[:header#workspace-bar.workspace-bar
|
||||
|
@ -173,13 +169,13 @@
|
|||
i/ruler]
|
||||
[:li.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.header.grid")
|
||||
:class (when (contains? flags :grid) "selected")
|
||||
:on-click (partial toggle :grid)}
|
||||
:class (when (contains? layout :grid) "selected")
|
||||
:on-click (partial toggle-layout :grid)}
|
||||
i/grid]
|
||||
[:li.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.header.grid-snap")
|
||||
:class (when (contains? flags :grid-snap) "selected")
|
||||
:on-click (partial toggle :grid-snap)}
|
||||
:class (when (contains? layout :grid-snap) "selected")
|
||||
:on-click (partial toggle-layout :grid-snap)}
|
||||
i/grid-snap]]]
|
||||
;; [:li.tooltip.tooltip-bottom
|
||||
;; {:alt (tr "header.align")}
|
||||
|
|
|
@ -39,10 +39,10 @@
|
|||
:ctrl+t #(st/emit! (dw/select-for-drawing :text))
|
||||
:esc #(st/emit! :interrupt dw/deselect-all)
|
||||
:delete #(st/emit! dw/delete-selected)
|
||||
:ctrl+up #(st/emit! (dw/order-selected-shapes :up))
|
||||
:ctrl+down #(st/emit! (dw/order-selected-shapes :down))
|
||||
:ctrl+shift+up #(st/emit! (dw/order-selected-shapes :top))
|
||||
:ctrl+shift+down #(st/emit! (dw/order-selected-shapes :bottom))
|
||||
:ctrl+up #(st/emit! (dw/vertical-order-selected :up))
|
||||
:ctrl+down #(st/emit! (dw/vertical-order-selected :down))
|
||||
:ctrl+shift+up #(st/emit! (dw/vertical-order-selected :top))
|
||||
:ctrl+shift+down #(st/emit! (dw/vertical-order-selected :bottom))
|
||||
:shift+up #(st/emit! (dw/move-selected :up true))
|
||||
:shift+down #(st/emit! (dw/move-selected :down true))
|
||||
:shift+right #(st/emit! (dw/move-selected :right true))
|
||||
|
@ -66,7 +66,7 @@
|
|||
|
||||
;; Initialize shortcut listener.
|
||||
(let [event KeyboardShortcutHandler.EventType.SHORTCUT_TRIGGERED
|
||||
callback #(sink (keyword (.-identifier %)))
|
||||
callback #(sink (keyword (.-identifier %)))
|
||||
key (events/listen handler event callback)]
|
||||
(fn []
|
||||
(events/unlistenByKey key)
|
||||
|
|
|
@ -75,7 +75,8 @@
|
|||
[props]
|
||||
(let [history (mf/deref refs/history)
|
||||
section (mf/use-state :main)
|
||||
close #(st/emit! (dw/toggle-flag :history))
|
||||
;; close #(st/emit! (dw/toggle-flag :history))
|
||||
close (constantly nil)
|
||||
main? (= @section :main)
|
||||
pinned? (= @section :pinned)
|
||||
show-main #(st/emit! (udh/select-section :main))
|
||||
|
|
|
@ -118,14 +118,14 @@
|
|||
(st/emit! dw/deselect-all
|
||||
(dw/select-shape id)))))
|
||||
|
||||
on-drop
|
||||
(fn [item monitor]
|
||||
(st/emit! (dw/commit-shape-order-change (:obj-id item))))
|
||||
|
||||
on-hover
|
||||
(fn [item monitor]
|
||||
(st/emit! (dw/shape-order-change (:obj-id item) index)))
|
||||
|
||||
on-drop
|
||||
(fn [item monitor]
|
||||
(st/emit! (dw/commit-shape-order-change (:obj-id item))))
|
||||
|
||||
[dprops dnd-ref] (use-sortable
|
||||
{:type (str "layer-item" (:frame-id item))
|
||||
:data {:obj-id (:id item)
|
||||
|
|
|
@ -40,10 +40,10 @@
|
|||
nil)])
|
||||
|
||||
(mf/defc shape-options-wrapper
|
||||
[{:keys [shape-id] :as props}]
|
||||
[{:keys [shape-id page-id] :as props}]
|
||||
(let [shape-iref (mf/use-memo
|
||||
{:deps (mf/deps shape-id)
|
||||
:fn #(-> (l/in [:workspace-data :objects shape-id])
|
||||
{:deps (mf/deps shape-id page-id)
|
||||
:fn #(-> (l/in [:workspace-data page-id :objects shape-id])
|
||||
(l/derive st/state))})
|
||||
shape (mf/deref shape-iref)]
|
||||
[:& shape-options {:shape shape}]))
|
||||
|
@ -61,5 +61,6 @@
|
|||
[:div.tool-window-content
|
||||
[:div.element-options
|
||||
(if (= (count selected) 1)
|
||||
[:& shape-options-wrapper {:shape-id (first selected)}]
|
||||
[:& shape-options-wrapper {:shape-id (first selected)
|
||||
:page-id (:id page)}]
|
||||
[:& page/options {:page page}])]]]))
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
(:require
|
||||
[beicon.core :as rx]
|
||||
[goog.events :as events]
|
||||
[goog.object :as gobj]
|
||||
[potok.core :as ptk]
|
||||
[lentes.core :as l]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.builtins.icons :as i]
|
||||
[uxbox.main.constants :as c]
|
||||
|
@ -141,12 +143,28 @@
|
|||
;; --- Viewport
|
||||
|
||||
(declare remote-user-cursors)
|
||||
(declare frames)
|
||||
|
||||
(mf/defc frame-and-shapes
|
||||
{:wrap [mf/wrap-memo]}
|
||||
(defn- build-workspace-data-iref
|
||||
[page-id]
|
||||
(-> (l/in [:workspace-data page-id])
|
||||
(l/derive st/state)))
|
||||
|
||||
(mf/defrc frames-wrapper
|
||||
;; {:wrap [mf/wrap-memo]}
|
||||
[props]
|
||||
(let [data (mf/deref refs/workspace-data)
|
||||
objects (:objects data)
|
||||
(let [page (gobj/get props "page")
|
||||
page-id (:id page)
|
||||
data-ref (mf/use-memo {:fn #(-> (l/in [:workspace-data page-id])
|
||||
(l/derive st/state))
|
||||
:deps (mf/deps page-id)})
|
||||
data (mf/deref data-ref)]
|
||||
[:& frames {:data data}]))
|
||||
|
||||
(mf/defc frames
|
||||
{:wrap [mf/wrap-memo]}
|
||||
[{:keys [data] :as props}]
|
||||
(let [objects (:objects data)
|
||||
root (get objects uuid/zero)
|
||||
shapes (->> (:shapes root)
|
||||
(map #(get objects %)))]
|
||||
|
@ -298,7 +316,7 @@
|
|||
;; {:id "foobar"
|
||||
;; :on-render (perf/react-on-profile)}
|
||||
;; [:& frame-and-shapes]]
|
||||
[:& frame-and-shapes]
|
||||
[:& frames-wrapper {:page page}]
|
||||
|
||||
(when (seq selected)
|
||||
[:& selection-handlers {:selected selected
|
||||
|
|
Loading…
Add table
Reference in a new issue