0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-13 23:41:24 -05:00

🚧 Minor reimplementation on how workspace initialization.

This commit is contained in:
Andrey Antukh 2019-11-27 15:33:53 +01:00
parent 59bab376cd
commit 426677935e
8 changed files with 243 additions and 221 deletions

View file

@ -10,7 +10,7 @@
[beicon.core :as rx]
[cuerdas.core :as str]
[potok.core :as ptk]
[uxbox.main.repo :as rp]
[uxbox.main.repo.core :as rp]
[uxbox.util.data :refer [index-by-id concatv]]
[uxbox.util.spec :as us]
[uxbox.util.timers :as ts]
@ -159,7 +159,7 @@
[id pages]
(s/assert ::us/uuid id)
(s/assert ::us/coll pages)
(ptk/reify ::page-fetched
(ptk/reify ::pages-fetched
IDeref
(-deref [_] (list id pages))
@ -175,7 +175,7 @@
(defn pages-fetched?
[v]
(= ::page-fetched (ptk/type v)))
(= ::pages-fetched (ptk/type v)))
;; --- Fetch Pages (by project id)
@ -185,10 +185,41 @@
(reify
ptk/WatchEvent
(watch [_ state s]
(->> (rp/req :fetch/pages-by-project {:project id})
(rx/map :payload)
(->> (rp/query :pages-by-project {:project-id id})
(rx/map #(pages-fetched id %))))))
;; --- Page Fetched
(defn page-fetched
[data]
(s/assert any? data) ;; TODO: minimal validate
(ptk/reify ::page-fetched
IDeref
(-deref [_] data)
ptk/UpdateEvent
(update [_ state]
(-> state
(unpack-page data)
(assoc-packed-page data)))))
(defn page-fetched?
[v]
(= ::page-fetched (ptk/type v)))
;; --- Fetch Pages (by project id)
(defn fetch-page
"Fetch page by id."
[id]
(s/assert ::us/uuid id)
(reify
ptk/WatchEvent
(watch [_ state s]
(->> (rp/query :page {:id id})
(rx/map page-fetched)))))
;; --- Page Created
(declare rehash-pages)

View file

@ -67,36 +67,32 @@
;; --- Projects Fetched
(defrecord ProjectsFetched [projects]
ptk/UpdateEvent
(update [_ state]
(reduce assoc-project state projects))
ptk/WatchEvent
(watch [_ state stream]
(->> (rx/from-coll (map :id projects))
(rx/map udp/fetch-pages))))
(defn projects-fetched
[projects]
{:pre [(us/valid? (s/every ::project-entity) projects)]}
(ProjectsFetched. projects))
(s/assert (s/every ::project-entity) projects)
(ptk/reify ::projects-fetched
ptk/UpdateEvent
(update [_ state]
(reduce assoc-project state projects))))
;; ptk/WatchEvent
;; (watch [_ state stream]
;; (->> (rx/from-coll (map :id projects))
;; (rx/map udp/fetch-pages))))
(defn projects-fetched?
[v]
(instance? ProjectsFetched v))
(= ::projects-fetched (ptk/type v)))
;; --- Fetch Projects
(defrecord FetchProjects []
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query :projects)
(rx/map projects-fetched))))
(defn fetch-projects
[]
(FetchProjects.))
(ptk/reify ::fetch-projects
ptk/WatchEvent
(watch [_ state stream]
(->> (rp/query :projects)
(rx/map projects-fetched)))))
;; --- Project Persisted
@ -177,14 +173,13 @@
(defn go-to
[id]
{:pre [(uuid? id)]}
(reify
(s/assert ::us/uuid id)
(ptk/reify ::go-to
ptk/WatchEvent
(watch [_ state stream]
(let [[page & rest-pages] (get-in state [:projects id :pages])]
(when page
(let [params {:project id :page page}]
(rx/of (rt/nav :workspace/page params))))))))
(let [page-id (get-in state [:projects id :ref-page-id])]
(let [params {:project id :page page-id}]
(rx/of (rt/nav :workspace/page params)))))))
;; --- Update Opts (Filtering & Ordering)

View file

@ -46,6 +46,15 @@
(declare initialize-alignment)
(def workspace-default-data
{:initialized true
:zoom 1
:flags #{:sitemap :drawtools :layers :element-options :rules}
:selected #{}
:drawing nil
:drawing-tool nil
:tooltip nil})
(defn initialize
"Initialize the workspace state."
[project-id page-id]
@ -54,22 +63,15 @@
(ptk/reify ::initialize
ptk/UpdateEvent
(update [_ state]
(let [default-flags #{:sitemap :drawtools :layers :element-options :rules}
initial-workspace {:project-id project-id
:initialized true
:page-id page-id
:zoom 1
:flags default-flags
:selected #{}
:drawing nil
:drawing-tool nil
:tooltip nil}]
(let [data (assoc workspace-default-data
:project-id project-id
:page-id page-id)]
(-> state
(update-in [:workspace page-id]
(fn [wsp]
(if (:initialized wsp)
wsp
(merge wsp initial-workspace))))
(merge wsp data))))
(assoc-in [:workspace :current] page-id))))
ptk/WatchEvent
@ -77,17 +79,16 @@
(let [page (get-in state [:pages page-id])]
;; Activate loaded if page is not fetched.
(when-not page (reset! st/loader true))
(if page
(rx/of (initialize-alignment page-id))
(rx/merge
(rx/of (udp/fetch-pages project-id))
(->> stream
(rx/filter udp/pages-fetched?)
(rx/take 1)
(rx/do #(reset! st/loader false))
(rx/map #(initialize-alignment page-id)))))))
(rx/merge
;; TODO: the `fetch-pages` should fetch a limited set of attrs
(rx/of (udp/fetch-page page-id))
(rx/of (udp/fetch-pages project-id))
(->> stream
(rx/filter udp/page-fetched?)
(rx/take 1)
(rx/mapcat (fn [event]
(reset! st/loader false)
(rx/of (initialize-alignment page-id))))))))
ptk/EffectEvent
(effect [_ state stream]
;; Optimistic prefetch of projects if them are not already fetched
@ -307,27 +308,21 @@
;; --- Grid Alignment
(defrecord InitializeAlignment [id]
ptk/WatchEvent
(watch [_ state stream]
(let [{:keys [metadata] :as page} (get-in state [:pages id])
params {:width c/viewport-width
:height c/viewport-height
:x-axis (:grid-x-axis metadata c/grid-x-axis)
:y-axis (:grid-y-axis metadata c/grid-y-axis)}]
(rx/concat
(rx/of (deactivate-flag :grid-indexed))
(->> (uwrk/initialize-alignment params)
(rx/map #(activate-flag :grid-indexed)))))))
(defn initialize-alignment?
[v]
(instance? InitializeAlignment v))
(defn initialize-alignment
[id]
{:pre [(uuid? id)]}
(InitializeAlignment. id))
(s/assert ::us/uuid id)
(ptk/reify ::initialize-alignment
ptk/WatchEvent
(watch [_ state stream]
(let [metadata (get-in state [:pages id :metadata])
params {:width c/viewport-width
:height c/viewport-height
:x-axis (:grid-x-axis metadata c/grid-x-axis)
:y-axis (:grid-y-axis metadata c/grid-y-axis)}]
(rx/concat
(rx/of (deactivate-flag :grid-indexed))
(->> (uwrk/initialize-alignment params)
(rx/map #(activate-flag :grid-indexed))))))))
;; --- Duplicate Selected

View file

@ -9,16 +9,16 @@
(:require
[rumext.alpha :as mf]
[uxbox.main.store :as st]
[uxbox.main.ui.shapes.circle :refer [circle-shape]]
[uxbox.main.ui.shapes.group :refer [group-shape]]
[uxbox.main.ui.shapes.icon :refer [icon-shape]]
[uxbox.main.ui.shapes.image :refer [image-shape]]
[uxbox.main.ui.shapes.path :refer [path-shape]]
[uxbox.main.ui.shapes.rect :refer [rect-shape]]
[uxbox.main.ui.shapes.text :refer [text-shape]]
;; [uxbox.main.ui.shapes.circle :refer [circle-shape]]
;; [uxbox.main.ui.shapes.group :refer [group-shape]]
;; [uxbox.main.ui.shapes.icon :refer [icon-shape]]
;; [uxbox.main.ui.shapes.image :refer [image-shape]]
;; [uxbox.main.ui.shapes.path :refer [path-shape]]
;; [uxbox.main.ui.shapes.rect :refer [rect-shape]]
;; [uxbox.main.ui.shapes.text :refer [text-shape]]
[uxbox.util.dom :as dom]))
(def ^:dynamic *state* st/state)
;; (def ^:dynamic *state* st/state)
(mf/defc background
[]
@ -33,7 +33,7 @@
(defn- make-shape-element
[state shape]
(mf/html
#_(mf/html
(case (:type shape)
;; :text [:& text-shape {:shape shape}]
:icon [:& icon-shape {:shape shape}]
@ -46,7 +46,7 @@
(mf/defc page-svg
[{:keys [page state] :as props}]
(let [{:keys [width height]} (:metadata page)]
#_(let [{:keys [width height]} (:metadata page)]
[:svg {:width width
:height height
:view-box (str "0 0 " width " " height)
@ -61,7 +61,7 @@
(defn render-page
[id]
(try
#_(try
(let [state (deref st/state)
page (get-in state [:pages id])]
(when (:shapes page)

View file

@ -5,7 +5,7 @@
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.main.ui.shapes.group
(:require
#_(:require
[lentes.core :as l]
[rumext.core :as mx]
[uxbox.main.geom :as geom]
@ -24,64 +24,64 @@
;; --- Helpers
(declare group-component)
;; (declare group-component)
(defn- focus-shape
[id]
(-> (l/in [:shapes id])
(l/derive st/state)))
;; (defn- focus-shape
;; [id]
;; (-> (l/in [:shapes id])
;; (l/derive st/state)))
(defn render-component
[shape]
(case (:type shape)
:group (group-component shape)
:text (text/text-component shape)
:icon (icon/icon-component shape)
:rect (rect/rect-component shape)
:path (path/path-component shape)
:image (image/image-component shape)
:circle (circle/circle-component shape)))
;; (defn render-component
;; [shape]
;; (case (:type shape)
;; :group (group-component shape)
;; :text (text/text-component shape)
;; :icon (icon/icon-component shape)
;; :rect (rect/rect-component shape)
;; :path (path/path-component shape)
;; :image (image/image-component shape)
;; :circle (circle/circle-component shape)))
(mx/defc component-container
{:mixins [mx/reactive mx/static]}
[id]
(when-let [shape (mx/react (focus-shape id))]
(when-not (:hidden shape)
(render-component shape))))
;; (mx/defc component-container
;; {:mixins [mx/reactive mx/static]}
;; [id]
;; (when-let [shape (mx/react (focus-shape id))]
;; (when-not (:hidden shape)
;; (render-component shape))))
;; --- Group Component
;; ;; --- Group Component
(declare group-shape)
;; (declare group-shape)
(mx/defc group-component
{:mixins [mx/static mx/reactive]}
[{:keys [id x y width height group] :as shape}]
(let [modifiers (mx/react (refs/selected-modifiers id))
selected (mx/react refs/selected-shapes)
selected? (contains? selected id)
on-mouse-down #(common/on-mouse-down % shape selected)
shape (assoc shape :modifiers modifiers)]
[:g.shape.group-shape
{:class (when selected? "selected")
:on-mouse-down on-mouse-down}
(group-shape shape component-container)]))
;; (mx/defc group-component
;; {:mixins [mx/static mx/reactive]}
;; [{:keys [id x y width height group] :as shape}]
;; (let [modifiers (mx/react (refs/selected-modifiers id))
;; selected (mx/react refs/selected-shapes)
;; selected? (contains? selected id)
;; on-mouse-down #(common/on-mouse-down % shape selected)
;; shape (assoc shape :modifiers modifiers)]
;; [:g.shape.group-shape
;; {:class (when selected? "selected")
;; :on-mouse-down on-mouse-down}
;; (group-shape shape component-container)]))
;; --- Group Shape
;; ;; --- Group Shape
(mx/defc group-shape
{:mixins [mx/static mx/reactive]}
[{:keys [id items modifiers] :as shape} factory]
(let [{:keys [resize displacement]} modifiers
;; (mx/defc group-shape
;; {:mixins [mx/static mx/reactive]}
;; [{:keys [id items modifiers] :as shape} factory]
;; (let [{:keys [resize displacement]} modifiers
xfmt (cond-> (gmt/matrix)
resize (gmt/multiply resize)
displacement (gmt/multiply displacement))
;; xfmt (cond-> (gmt/matrix)
;; resize (gmt/multiply resize)
;; displacement (gmt/multiply displacement))
moving? (boolean displacement)]
[:g {:id (str "shape-" id)
:class (classnames :move-cursor moving?)
:transform (str xfmt)}
(for [item (reverse items)]
(-> (factory item)
(mx/with-key (str item))))]))
;; moving? (boolean displacement)]
;; [:g {:id (str "shape-" id)
;; :class (classnames :move-cursor moving?)
;; :transform (str xfmt)}
;; (for [item (reverse items)]
;; (-> (factory item)
;; (mx/with-key (str item))))]))

View file

@ -2,7 +2,7 @@
;; 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) 2015-2016 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2015-2019 Andrey Antukh <niwi@niwi.nz>
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
(ns uxbox.main.ui.workspace.sidebar.sitemap
@ -78,7 +78,8 @@
(mf/defc pages-list
[{:keys [project current-page-id] :as props}]
(let [pages-map (mf/deref pages-map-iref)
pages (map #(get pages-map %) (:pages project))
pages (->> (vals pages-map)
(filter #(= (:project-id %) (:id project))))
deletable? (> (count pages) 1)]
[:ul.element-list
(for [[index item] (map-indexed vector pages)]

View file

@ -15,7 +15,7 @@
(mf/defc background
{:wrap [mf/wrap-memo]}
[{:keys [background] :as metadata}]
[:rect
#_[:rect
{:x 0 :y 0
:width "100%"
:height "100%"
@ -28,7 +28,7 @@
(mf/defc canvas
{:wrap [mf/wrap-memo]}
[{:keys [page] :as props}]
(let [{:keys [metadata id]} page
#_(let [{:keys [metadata id]} page
{:keys [width height]} metadata]
[:div.view-canvas
[:svg.page-layout {:width width

View file

@ -5,7 +5,7 @@
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.view.ui.viewer.shapes
(:require [goog.events :as events]
#_(:require [goog.events :as events]
[lentes.core :as l]
[uxbox.builtins.icons :as i]
[uxbox.view.store :as st]
@ -15,104 +15,104 @@
[uxbox.main.ui.shapes.rect :refer [rect-shape]]
[uxbox.main.ui.shapes.icon :refer [icon-shape]]
[uxbox.main.ui.shapes.text :refer [text-shape]]
[uxbox.main.ui.shapes.group :refer [group-shape]]
;; [uxbox.main.ui.shapes.group :refer [group-shape]]
[uxbox.main.ui.shapes.path :refer [path-shape]]
[uxbox.main.ui.shapes.circle :refer [circle-shape]]
[uxbox.main.ui.shapes.image :refer [image-shape]]
[rumext.core :as mx :include-macros true])
(:import goog.events.EventType))
#_(:import goog.events.EventType))
(def itx-flag-ref
(-> (comp (l/key :flags) (l/lens :interactions))
(l/derive st/state)))
;; (def itx-flag-ref
;; (-> (comp (l/key :flags) (l/lens :interactions))
;; (l/derive st/state)))
(defn image-ref
[id]
(-> (l/in [:images id])
(l/derive st/state)))
;; (defn image-ref
;; [id]
;; (-> (l/in [:images id])
;; (l/derive st/state)))
;; --- Interactions Wrapper
;; ;; --- Interactions Wrapper
(defn- interactions-wrapper-did-mount
[own]
(let [dom (mx/dom-node own)
shape (first (::mx/args own))
evnts (itx/build-events shape)
keys (reduce (fn [acc [evt callback]]
(conj acc (events/listen dom evt callback)))
[]
evnts)]
(assoc own ::keys keys)))
;; (defn- interactions-wrapper-did-mount
;; [own]
;; (let [dom (mx/dom-node own)
;; shape (first (::mx/args own))
;; evnts (itx/build-events shape)
;; keys (reduce (fn [acc [evt callback]]
;; (conj acc (events/listen dom evt callback)))
;; []
;; evnts)]
;; (assoc own ::keys keys)))
(defn- interactions-wrapper-will-unmount
[own]
(let [keys (::keys own)]
(run! #(events/unlistenByKey %) keys)
(dissoc own ::keys)))
;; (defn- interactions-wrapper-will-unmount
;; [own]
;; (let [keys (::keys own)]
;; (run! #(events/unlistenByKey %) keys)
;; (dissoc own ::keys)))
(mx/defc interactions-wrapper
{:did-mount interactions-wrapper-did-mount
:will-unmount interactions-wrapper-will-unmount
:mixins [mx/reactive mx/static]}
[shape factory]
{:pre [(map? shape)]}
(let [show-itx? (and (mx/react itx-flag-ref)
(not (empty? (:interactions shape))))
rect (geom/shape->rect-shape shape)]
[:g {:id (str "itx-" (:id shape))
:style {:cursor "pointer"}}
(factory shape)
(when show-itx?
[:circle {:class "interaction-bullet"
:cx (:x1 rect)
:cy (:y1 rect)
:r 5}])]))
;; (mx/defc interactions-wrapper
;; {:did-mount interactions-wrapper-did-mount
;; :will-unmount interactions-wrapper-will-unmount
;; :mixins [mx/reactive mx/static]}
;; [shape factory]
;; {:pre [(map? shape)]}
;; (let [show-itx? (and (mx/react itx-flag-ref)
;; (not (empty? (:interactions shape))))
;; rect (geom/shape->rect-shape shape)]
;; [:g {:id (str "itx-" (:id shape))
;; :style {:cursor "pointer"}}
;; (factory shape)
;; (when show-itx?
;; [:circle {:class "interaction-bullet"
;; :cx (:x1 rect)
;; :cy (:y1 rect)
;; :r 5}])]))
;; [:rect {:class "interaction-hightlight"
;; :x (:x1 rect)
;; :y (:y1 rect)
;; :width (:width rect)
;; :height (:height rect)}]
;; ;; [:rect {:class "interaction-hightlight"
;; ;; :x (:x1 rect)
;; ;; :y (:y1 rect)
;; ;; :width (:width rect)
;; ;; :height (:height rect)}]
;; --- Image Shape Wrapper
;;
;; NOTE: This wrapper is needed for preload the referenced
;; image object which is need for properly show the shape.
;; ;; --- Image Shape Wrapper
;; ;;
;; ;; NOTE: This wrapper is needed for preload the referenced
;; ;; image object which is need for properly show the shape.
(mx/defc image-shape-wrapper
{:mixins [mx/static mx/reactive]
:init (fn [own]
(when-let [image-id (-> own ::mx/args first :image)]
(st/emit! (udv/fetch-image image-id)))
own)}
[{:keys [image] :as item}]
(when-let [image (mx/react (image-ref image))]
(image-shape (assoc item :image image))))
;; (mx/defc image-shape-wrapper
;; {:mixins [mx/static mx/reactive]
;; :init (fn [own]
;; (when-let [image-id (-> own ::mx/args first :image)]
;; (st/emit! (udv/fetch-image image-id)))
;; own)}
;; [{:keys [image] :as item}]
;; (when-let [image (mx/react (image-ref image))]
;; (image-shape (assoc item :image image))))
;; --- Text Shape Wrapper
;; ;; --- Text Shape Wrapper
(mx/defc text-shape-wrapper
{:mixins [mx/static]}
[item]
(text-shape (assoc item :user-select true)))
;; (mx/defc text-shape-wrapper
;; {:mixins [mx/static]}
;; [item]
;; (text-shape (assoc item :user-select true)))
;; --- Shapes
;; ;; --- Shapes
(declare shape)
;; (declare shape)
(mx/defc shape*
[{:keys [type] :as item}]
(case type
:group (group-shape item shape)
:image (image-shape-wrapper item)
:text (text-shape-wrapper item)
:icon (icon-shape item)
:rect (rect-shape item)
:path (path-shape item)
:circle (circle-shape item)))
;; (mx/defc shape*
;; [{:keys [type] :as item}]
;; (case type
;; ;; :group (group-shape item shape)
;; :image (image-shape-wrapper item)
;; :text (text-shape-wrapper item)
;; :icon (icon-shape item)
;; :rect (rect-shape item)
;; :path (path-shape item)
;; :circle (circle-shape item)))
(mx/defc shape
[sid]
{:pre [(uuid? sid)]}
(let [item (get-in @st/state [:shapes sid])]
(interactions-wrapper item shape*)))
;; (mx/defc shape
;; [sid]
;; {:pre [(uuid? sid)]}
;; (let [item (get-in @st/state [:shapes sid])]
;; (interactions-wrapper item shape*)))