mirror of
https://github.com/penpot/penpot.git
synced 2025-08-01 09:28:20 +02:00
Merge pull request #2108 from penpot/hiru-main-instance
Components v2 (first PR)
This commit is contained in:
commit
18970cb233
101 changed files with 3212 additions and 1262 deletions
|
@ -63,6 +63,11 @@
|
|||
flags (sequence (map keyword) (str/words flags))]
|
||||
(flags/parse flags/default default-flags flags)))
|
||||
|
||||
(defn- parse-features
|
||||
[global]
|
||||
(when-let [features-str (obj/get global "penpotFeatures")]
|
||||
(map keyword (str/words features-str))))
|
||||
|
||||
(defn- parse-version
|
||||
[global]
|
||||
(-> (obj/get global "penpotVersion")
|
||||
|
@ -88,6 +93,7 @@
|
|||
|
||||
(def build-date (parse-build-date global))
|
||||
(def flags (atom (parse-flags global)))
|
||||
(def features (atom (parse-features global)))
|
||||
(def version (atom (parse-version global)))
|
||||
(def target (atom (parse-target global)))
|
||||
(def browser (atom (parse-browser)))
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
[app.main.sentry :as sentry]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui :as ui]
|
||||
[app.main.ui.alert]
|
||||
[app.main.ui.confirm]
|
||||
[app.main.ui.delete-shared]
|
||||
[app.main.ui.modal :refer [modal]]
|
||||
[app.main.ui.routes :as rt]
|
||||
[app.main.worker :as worker]
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.main.data.fonts :as df]
|
||||
[app.main.data.media :as di]
|
||||
[app.main.data.users :as du]
|
||||
[app.main.features :as features]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.router :as rt]
|
||||
|
@ -246,6 +247,32 @@
|
|||
(->> (rp/query :team-shared-files {:team-id team-id})
|
||||
(rx/map shared-files-fetched))))))
|
||||
|
||||
;; --- EVENT: Get files that use this shared-file
|
||||
|
||||
(defn clean-temp-shared
|
||||
[]
|
||||
(ptk/reify ::clean-temp-shared
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:dashboard-local :files-with-shared] nil))))
|
||||
|
||||
(defn library-using-files-fetched
|
||||
[files]
|
||||
(ptk/reify ::library-using-files-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [files (d/index-by :id files)]
|
||||
(assoc-in state [:dashboard-local :files-with-shared] files)))))
|
||||
|
||||
(defn fetch-library-using-files
|
||||
[file]
|
||||
(ptk/reify ::fetch-library-using-files
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [file-id (:id file)]
|
||||
(->> (rp/query :library-using-files {:file-id file-id})
|
||||
(rx/map library-using-files-fetched))))))
|
||||
|
||||
;; --- EVENT: recent-files
|
||||
|
||||
(defn recent-files-fetched
|
||||
|
@ -718,12 +745,13 @@
|
|||
(-deref [_] {:project-id project-id})
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [it _ _]
|
||||
(watch [it state _]
|
||||
(let [{:keys [on-success on-error]
|
||||
:or {on-success identity
|
||||
on-error rx/throw}} (meta params)
|
||||
name (name (gensym (str (tr "dashboard.new-file-prefix") " ")))
|
||||
params (assoc params :name name)]
|
||||
components-v2 (features/active-feature? state :components-v2)
|
||||
params (assoc params :name name :components-v2 components-v2)]
|
||||
|
||||
(->> (rp/mutation! :create-file params)
|
||||
(rx/tap on-success)
|
||||
|
|
|
@ -10,9 +10,11 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.main.data.comments :as dcm]
|
||||
[app.main.data.fonts :as df]
|
||||
[app.main.features :as features]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.globals :as ug]
|
||||
[app.util.router :as rt]
|
||||
|
@ -99,9 +101,15 @@
|
|||
(us/assert ::fetch-bundle-params params)
|
||||
(ptk/reify ::fetch-file
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [params' (cond-> {:file-id file-id}
|
||||
(uuid? share-id) (assoc :share-id share-id))]
|
||||
(watch [_ state _]
|
||||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
params' (cond-> {:file-id file-id}
|
||||
(uuid? share-id)
|
||||
(assoc :share-id share-id)
|
||||
|
||||
:always
|
||||
(assoc :components-v2 components-v2))]
|
||||
|
||||
(->> (rp/query :view-only-bundle params')
|
||||
(rx/mapcat
|
||||
(fn [{:keys [fonts] :as bundle}]
|
||||
|
@ -116,8 +124,8 @@
|
|||
(map (fn [page-id]
|
||||
(let [data (get-in file [:data :pages-index page-id])]
|
||||
[page-id (assoc data
|
||||
:frames (cph/get-viewer-frames (:objects data))
|
||||
:all-frames (cph/get-viewer-frames (:objects data) {:all-frames? true}))])))
|
||||
:frames (ctt/get-viewer-frames (:objects data))
|
||||
:all-frames (ctt/get-viewer-frames (:objects data) {:all-frames? true}))])))
|
||||
(into {}))]
|
||||
|
||||
(ptk/reify ::bundle-fetched
|
||||
|
|
|
@ -14,13 +14,13 @@
|
|||
[app.common.geom.proportions :as gpr]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.text :as txt]
|
||||
[app.common.transit :as t]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cfg]
|
||||
[app.main.data.events :as ev]
|
||||
|
@ -59,7 +59,6 @@
|
|||
[app.util.globals :as ug]
|
||||
[app.util.http :as http]
|
||||
[app.util.i18n :as i18n]
|
||||
[app.util.names :as un]
|
||||
[app.util.router :as rt]
|
||||
[app.util.timers :as tm]
|
||||
[app.util.webapi :as wapi]
|
||||
|
@ -157,7 +156,7 @@
|
|||
:workspace-project project
|
||||
:workspace-file (assoc file :initialized true)
|
||||
:workspace-data (-> (:data file)
|
||||
(cph/start-object-indices)
|
||||
(ctst/start-object-indices)
|
||||
;; DEBUG: Uncomment this to try out migrations in local without changing
|
||||
;; the version number
|
||||
#_(assoc :version 17)
|
||||
|
@ -215,7 +214,8 @@
|
|||
(watch [_ state _]
|
||||
(if (contains? (get-in state [:workspace-data :pages-index]) page-id)
|
||||
(rx/of (dwp/preload-data-uris)
|
||||
(dwth/watch-state-changes))
|
||||
(dwth/watch-state-changes)
|
||||
(dwl/watch-component-changes))
|
||||
(let [default-page-id (get-in state [:workspace-data :pages 0])]
|
||||
(rx/of (go-to-page default-page-id)))))
|
||||
|
||||
|
@ -270,8 +270,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [pages (get-in state [:workspace-data :pages-index])
|
||||
unames (un/retrieve-used-names pages)
|
||||
name (un/generate-unique-name unames "Page-1")
|
||||
unames (ctst/retrieve-used-names pages)
|
||||
name (ctst/generate-unique-name unames "Page-1")
|
||||
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/add-empty-page id name))]
|
||||
|
@ -285,9 +285,9 @@
|
|||
(watch [it state _]
|
||||
(let [id (uuid/next)
|
||||
pages (get-in state [:workspace-data :pages-index])
|
||||
unames (un/retrieve-used-names pages)
|
||||
unames (ctst/retrieve-used-names pages)
|
||||
page (get-in state [:workspace-data :pages-index page-id])
|
||||
name (un/generate-unique-name unames (:name page))
|
||||
name (ctst/generate-unique-name unames (:name page))
|
||||
|
||||
no_thumbnails_objects (->> (:objects page)
|
||||
(d/mapm (fn [_ val] (dissoc val :use-for-thumbnail?))))
|
||||
|
@ -991,7 +991,7 @@
|
|||
(let [selected (wsh/lookup-selected state)
|
||||
pages (-> state :workspace-data :pages-index vals)
|
||||
get-frames (fn [{:keys [objects id] :as page}]
|
||||
(->> (cph/get-frames objects)
|
||||
(->> (ctst/get-frames objects)
|
||||
(sequence
|
||||
(comp (filter :use-for-thumbnail?)
|
||||
(map :id)
|
||||
|
@ -1223,7 +1223,7 @@
|
|||
;; selected and its parents
|
||||
objects (cph/selected-subtree objects selected)
|
||||
|
||||
selected (->> (cph/sort-z-index objects selected)
|
||||
selected (->> (ctst/sort-z-index objects selected)
|
||||
(into (d/ordered-set)))]
|
||||
|
||||
(assoc data :selected selected)))
|
||||
|
@ -1478,7 +1478,7 @@
|
|||
[frame-id frame-id delta])
|
||||
|
||||
(empty? page-selected)
|
||||
(let [frame-id (cph/frame-id-by-position page-objects mouse-pos)
|
||||
(let [frame-id (ctst/frame-id-by-position page-objects mouse-pos)
|
||||
delta (gpt/subtract mouse-pos orig-pos)]
|
||||
[frame-id frame-id delta])
|
||||
|
||||
|
@ -1590,8 +1590,8 @@
|
|||
height 16
|
||||
page-id (:current-page-id state)
|
||||
frame-id (-> (wsh/lookup-page-objects state page-id)
|
||||
(cph/frame-id-by-position @ms/mouse-position))
|
||||
shape (cp/setup-rect-selrect
|
||||
(ctst/frame-id-by-position @ms/mouse-position))
|
||||
shape (cts/setup-rect-selrect
|
||||
{:id id
|
||||
:type :text
|
||||
:name "Text"
|
||||
|
@ -1681,12 +1681,12 @@
|
|||
(let [srect (gsh/selection-rect selected-objs)
|
||||
frame-id (get-in objects [(first selected) :frame-id])
|
||||
parent-id (get-in objects [(first selected) :parent-id])
|
||||
shape (-> (cp/make-minimal-shape :frame)
|
||||
shape (-> (cts/make-minimal-shape :frame)
|
||||
(merge {:x (:x srect) :y (:y srect) :width (:width srect) :height (:height srect)})
|
||||
(assoc :frame-id frame-id :parent-id parent-id)
|
||||
(cond-> (not= frame-id uuid/zero)
|
||||
(assoc :fills [] :hide-in-viewer true))
|
||||
(cp/setup-rect-selrect))]
|
||||
(cts/setup-rect-selrect))]
|
||||
(rx/of
|
||||
(dwu/start-undo-transaction)
|
||||
(dwsh/add-shape shape)
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.path.shapes-to-path :as stp]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.util.names :as un]
|
||||
[beicon.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]))
|
||||
|
@ -90,8 +90,8 @@
|
|||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
base-name (-> bool-type d/name str/capital (str "-1"))
|
||||
name (-> (un/retrieve-used-names objects)
|
||||
(un/generate-unique-name base-name))
|
||||
name (-> (ctt/retrieve-used-names objects)
|
||||
(ctt/generate-unique-name base-name))
|
||||
shapes (selected-shapes state)]
|
||||
|
||||
(when-not (empty? shapes)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.common.pages.changes-spec :as pcs]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
|
@ -165,7 +166,7 @@
|
|||
(update-in state path (fn [file]
|
||||
(-> file
|
||||
(cp/process-changes redo-changes false)
|
||||
(cph/update-object-indices page-id))))
|
||||
(ctst/update-object-indices page-id))))
|
||||
|
||||
(catch :default err
|
||||
(log/error :js/error err)
|
||||
|
@ -191,6 +192,7 @@
|
|||
process-page-changes
|
||||
(fn [[page-id _changes]]
|
||||
(update-indices page-id redo-changes))]
|
||||
|
||||
(rx/concat
|
||||
(rx/from (map process-page-changes changes-by-pages))
|
||||
|
||||
|
|
|
@ -108,4 +108,3 @@
|
|||
:undo-changes []
|
||||
:origin it
|
||||
:save-undo? false})))))))))))
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
(ns app.main.data.workspace.drawing
|
||||
"Drawing interactions."
|
||||
(:require
|
||||
[app.common.pages :as cp]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.drawing.box :as box]
|
||||
|
@ -91,7 +91,7 @@
|
|||
(ptk/reify ::handle-drawing
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [data (cp/make-minimal-shape type)]
|
||||
(let [data (cts/make-minimal-shape type)]
|
||||
(update-in state [:workspace-drawing :object] merge data)))
|
||||
|
||||
ptk/WatchEvent
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.drawing.common :as common]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
|
@ -65,11 +66,11 @@
|
|||
focus (:workspace-focus-selected state)
|
||||
zoom (get-in state [:workspace-local :zoom] 1)
|
||||
|
||||
fid (cph/frame-id-by-position objects initial)
|
||||
fid (ctt/frame-id-by-position objects initial)
|
||||
|
||||
shape (get-in state [:workspace-drawing :object])
|
||||
shape (-> shape
|
||||
(cp/setup-shape {:x (:x initial)
|
||||
(cts/setup-shape {:x (:x initial)
|
||||
:y (:y initial)
|
||||
:width 0.01
|
||||
:height 0.01})
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
|
@ -55,7 +55,7 @@
|
|||
(assoc :height 17 :width 4 :grow-type :auto-width)
|
||||
|
||||
click-draw?
|
||||
(cp/setup-rect-selrect)
|
||||
(cts/setup-rect-selrect)
|
||||
|
||||
:always
|
||||
(-> (gsh/transform-shape)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
(:require
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.path :as gsp]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.main.data.workspace.drawing.common :as common]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.streams :as ms]
|
||||
|
@ -47,7 +47,7 @@
|
|||
(let [objects (wsh/lookup-page-objects state)
|
||||
content (get-in state [:workspace-drawing :object :content] [])
|
||||
position (get-in content [0 :params] nil)
|
||||
frame-id (cph/frame-id-by-position objects position)]
|
||||
frame-id (ctt/frame-id-by-position objects position)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :frame-id] frame-id))))))
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.util.names :as un]
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
|
@ -71,12 +71,12 @@
|
|||
(= (count shapes) 1)
|
||||
(= (:type (first shapes)) :group))
|
||||
(:name (first shapes))
|
||||
(-> (un/retrieve-used-names objects)
|
||||
(un/generate-unique-name base-name)))
|
||||
(-> (ctt/retrieve-used-names objects)
|
||||
(ctt/generate-unique-name base-name)))
|
||||
|
||||
selrect (gsh/selection-rect shapes)
|
||||
group (-> (cp/make-minimal-group frame-id selrect gname)
|
||||
(cp/setup-shape selrect)
|
||||
group (-> (cts/make-minimal-group frame-id selrect gname)
|
||||
(cts/setup-shape selrect)
|
||||
(assoc :shapes (mapv :id shapes)
|
||||
:parent-id parent-id
|
||||
:frame-id frame-id
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.names :as un]
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
|||
|
||||
flows (get-in page [:options :flows] [])
|
||||
unames (into #{} (map :name flows))
|
||||
name (un/generate-unique-name unames "Flow-1")
|
||||
name (ctst/generate-unique-name unames "Flow-1")
|
||||
|
||||
new-flow {:id (uuid/next)
|
||||
:name name
|
||||
|
@ -182,7 +182,7 @@
|
|||
from-frame-id (if (cph/frame-shape? from-shape)
|
||||
from-id (:frame-id from-shape))
|
||||
|
||||
target-frame (cph/frame-by-position objects position)]
|
||||
target-frame (ctst/frame-by-position objects position)]
|
||||
|
||||
(when (and (not= (:id target-frame) uuid/zero)
|
||||
(not= (:id target-frame) from-frame-id)
|
||||
|
|
|
@ -10,12 +10,15 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.logging :as log]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.changes :as ch]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.changes-spec :as pcs]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.color :as ctc]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.typography :as ctt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.dashboard :as dd]
|
||||
|
@ -27,10 +30,11 @@
|
|||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[app.util.names :as un]
|
||||
[app.util.router :as rt]
|
||||
[app.util.time :as dt]
|
||||
[beicon.core :as rx]
|
||||
|
@ -137,7 +141,7 @@
|
|||
(pcb/update-color color))]
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dch/commit-changes changes)
|
||||
(sync-file (:current-file-id state) file-id)
|
||||
(sync-file (:current-file-id state) file-id :colors (:id color))
|
||||
(dwu/commit-undo-transaction))))
|
||||
|
||||
(defn update-color
|
||||
|
@ -240,7 +244,7 @@
|
|||
(pcb/update-typography typography))]
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dch/commit-changes changes)
|
||||
(sync-file (:current-file-id state) file-id)
|
||||
(sync-file (:current-file-id state) file-id :typographies (:id typography))
|
||||
(dwu/commit-undo-transaction))))
|
||||
|
||||
(defn update-typography
|
||||
|
@ -280,7 +284,7 @@
|
|||
|
||||
(defn- add-component2
|
||||
"This is the second step of the component creation."
|
||||
[selected]
|
||||
[selected components-v2]
|
||||
(ptk/reify ::add-component2
|
||||
IDeref
|
||||
(-deref [_] {:num-shapes (count selected)})
|
||||
|
@ -293,7 +297,7 @@
|
|||
shapes (dwg/shapes-for-grouping objects selected)]
|
||||
(when-not (empty? shapes)
|
||||
(let [[group _ changes]
|
||||
(dwlh/generate-add-component it shapes objects page-id file-id)]
|
||||
(dwlh/generate-add-component it shapes objects page-id file-id components-v2)]
|
||||
(when-not (empty? (:redo-changes changes))
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dws/select-shapes (d/ordered-set (:id group)))))))))))
|
||||
|
@ -307,10 +311,11 @@
|
|||
(ptk/reify ::add-component
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
(cph/clean-loops objects))]
|
||||
(rx/of (add-component2 selected))))))
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
(cph/clean-loops objects))
|
||||
components-v2 (features/active-feature? state :components-v2)]
|
||||
(rx/of (add-component2 selected components-v2))))))
|
||||
|
||||
(defn rename-component
|
||||
"Rename the component with the given id, in the current file library."
|
||||
|
@ -352,18 +357,30 @@
|
|||
component (cph/get-component libraries id)
|
||||
all-components (-> state :workspace-data :components vals)
|
||||
unames (into #{} (map :name) all-components)
|
||||
new-name (un/generate-unique-name unames (:name component))
|
||||
new-name (ctst/generate-unique-name unames (:name component))
|
||||
|
||||
[new-shape new-shapes _updated-shapes]
|
||||
(dwlh/duplicate-component component)
|
||||
components-v2 (features/active-feature? state :components-v2)
|
||||
|
||||
changes (-> (pcb/empty-changes it nil) ;; no objects are changed
|
||||
(pcb/with-objects nil) ;; in the current page
|
||||
(pcb/add-component (:id new-shape)
|
||||
main-instance-page (when components-v2
|
||||
(wsh/lookup-page state (:main-instance-page component)))
|
||||
main-instance-shape (when components-v2
|
||||
(ctn/get-shape main-instance-page (:main-instance-id component)))
|
||||
|
||||
[new-component-shape new-component-shapes
|
||||
new-main-instance-shape new-main-instance-shapes]
|
||||
(dwlh/duplicate-component component main-instance-page main-instance-shape)
|
||||
|
||||
changes (-> (pcb/empty-changes it nil)
|
||||
(pcb/with-page main-instance-page)
|
||||
(pcb/with-objects (:objects main-instance-page))
|
||||
(pcb/add-objects new-main-instance-shapes {:ignore-touched true})
|
||||
(pcb/add-component (:id new-component-shape)
|
||||
(:path component)
|
||||
new-name
|
||||
new-shapes
|
||||
[]))]
|
||||
new-component-shapes
|
||||
[]
|
||||
(:id new-main-instance-shape)
|
||||
(:id main-instance-page)))]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
|
@ -521,7 +538,7 @@
|
|||
libraries (wsh/get-libraries state)
|
||||
|
||||
container (cph/get-container local-file :page page-id)
|
||||
shape (cph/get-shape container id)
|
||||
shape (ctn/get-shape container id)
|
||||
|
||||
changes
|
||||
(-> (pcb/empty-changes it)
|
||||
|
@ -568,13 +585,15 @@
|
|||
(ptk/reify ::update-component-sync
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [current-file-id (:current-file-id state)]
|
||||
(let [current-file-id (:current-file-id state)
|
||||
page (wsh/lookup-page state)
|
||||
shape (ctn/get-shape page shape-id)]
|
||||
(rx/of
|
||||
(dwu/start-undo-transaction)
|
||||
(update-component shape-id)
|
||||
(sync-file current-file-id file-id)
|
||||
(sync-file current-file-id file-id :components (:component-id shape))
|
||||
(when (not= current-file-id file-id)
|
||||
(sync-file file-id file-id))
|
||||
(sync-file file-id file-id :components (:component-id shape)))
|
||||
(dwu/commit-undo-transaction))))))
|
||||
|
||||
(defn update-component-in-bulk
|
||||
|
@ -593,63 +612,83 @@
|
|||
"Synchronize the given file from the given library. Walk through all
|
||||
shapes in all pages in the file that use some color, typography or
|
||||
component of the library, and copy the new values to the shapes. Do
|
||||
it also for shapes inside components of the local file library."
|
||||
[file-id library-id]
|
||||
(us/assert ::us/uuid file-id)
|
||||
(us/assert ::us/uuid library-id)
|
||||
(ptk/reify ::sync-file
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(if (not= library-id (:current-file-id state))
|
||||
(d/assoc-in-when state [:workspace-libraries library-id :synced-at] (dt/now))
|
||||
state))
|
||||
it also for shapes inside components of the local file library.
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(when (and (some? file-id) (some? library-id)) ; Prevent race conditions while navigating out of the file
|
||||
(log/info :msg "SYNC-FILE"
|
||||
:file (dwlh/pretty-file file-id state)
|
||||
:library (dwlh/pretty-file library-id state))
|
||||
(let [file (wsh/get-file state file-id)
|
||||
If it's known that only one asset has changed, you can give its
|
||||
type and id, and only shapes that use it will be synced, thus avoiding
|
||||
a lot of unneeded checks."
|
||||
([file-id library-id]
|
||||
(sync-file file-id library-id nil nil))
|
||||
([file-id library-id asset-type asset-id]
|
||||
(us/assert ::us/uuid file-id)
|
||||
(us/assert ::us/uuid library-id)
|
||||
(us/assert (s/nilable #{:colors :components :typographies}) asset-type)
|
||||
(us/assert (s/nilable ::us/uuid) asset-id)
|
||||
(ptk/reify ::sync-file
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(if (and (not= library-id (:current-file-id state))
|
||||
(nil? asset-id))
|
||||
(d/assoc-in-when state [:workspace-libraries library-id :synced-at] (dt/now))
|
||||
state))
|
||||
|
||||
library-changes (reduce
|
||||
pcb/concat-changes
|
||||
(pcb/empty-changes it)
|
||||
[(dwlh/generate-sync-library it file-id :components library-id state)
|
||||
(dwlh/generate-sync-library it file-id :colors library-id state)
|
||||
(dwlh/generate-sync-library it file-id :typographies library-id state)])
|
||||
file-changes (reduce
|
||||
pcb/concat-changes
|
||||
(pcb/empty-changes it)
|
||||
[(dwlh/generate-sync-file it file-id :components library-id state)
|
||||
(dwlh/generate-sync-file it file-id :colors library-id state)
|
||||
(dwlh/generate-sync-file it file-id :typographies library-id state)])
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(when (and (some? file-id) (some? library-id)) ; Prevent race conditions while navigating out of the file
|
||||
(log/info :msg "SYNC-FILE"
|
||||
:file (dwlh/pretty-file file-id state)
|
||||
:library (dwlh/pretty-file library-id state))
|
||||
(let [file (wsh/get-file state file-id)
|
||||
|
||||
changes (pcb/concat-changes library-changes file-changes)]
|
||||
sync-components? (or (nil? asset-type) (= asset-type :components))
|
||||
sync-colors? (or (nil? asset-type) (= asset-type :colors))
|
||||
sync-typographies? (or (nil? asset-type) (= asset-type :typographies))
|
||||
|
||||
(log/debug :msg "SYNC-FILE finished" :js/rchanges (log-changes
|
||||
(:redo-changes changes)
|
||||
file))
|
||||
(rx/concat
|
||||
(rx/of (dm/hide-tag :sync-dialog))
|
||||
(when (seq (:redo-changes changes))
|
||||
(rx/of (dch/commit-changes (assoc changes ;; TODO a ver qué pasa con esto
|
||||
:file-id file-id))))
|
||||
(when (not= file-id library-id)
|
||||
;; When we have just updated the library file, give some time for the
|
||||
;; update to finish, before marking this file as synced.
|
||||
;; TODO: look for a more precise way of syncing this.
|
||||
;; Maybe by using the stream (second argument passed to watch)
|
||||
;; to wait for the corresponding changes-committed and then proceed
|
||||
;; with the :update-sync mutation.
|
||||
(rx/concat (rx/timer 3000)
|
||||
(rp/mutation :update-sync
|
||||
{:file-id file-id
|
||||
:library-id library-id})))
|
||||
(when (seq (:redo-changes library-changes))
|
||||
(rx/of (sync-file-2nd-stage file-id library-id)))))))))
|
||||
library-changes (reduce
|
||||
pcb/concat-changes
|
||||
(pcb/empty-changes it)
|
||||
[(when sync-components?
|
||||
(dwlh/generate-sync-library it file-id :components asset-id library-id state))
|
||||
(when sync-colors?
|
||||
(dwlh/generate-sync-library it file-id :colors asset-id library-id state))
|
||||
(when sync-typographies?
|
||||
(dwlh/generate-sync-library it file-id :typographies asset-id library-id state))])
|
||||
file-changes (reduce
|
||||
pcb/concat-changes
|
||||
(pcb/empty-changes it)
|
||||
[(when sync-components?
|
||||
(dwlh/generate-sync-file it file-id :components asset-id library-id state))
|
||||
(when sync-colors?
|
||||
(dwlh/generate-sync-file it file-id :colors asset-id library-id state))
|
||||
(when sync-typographies?
|
||||
(dwlh/generate-sync-file it file-id :typographies asset-id library-id state))])
|
||||
|
||||
(defn sync-file-2nd-stage
|
||||
changes (pcb/concat-changes library-changes file-changes)]
|
||||
|
||||
(log/debug :msg "SYNC-FILE finished" :js/rchanges (log-changes
|
||||
(:redo-changes changes)
|
||||
file))
|
||||
(rx/concat
|
||||
(rx/of (dm/hide-tag :sync-dialog))
|
||||
(when (seq (:redo-changes changes))
|
||||
(rx/of (dch/commit-changes (assoc changes ;; TODO a ver qué pasa con esto
|
||||
:file-id file-id))))
|
||||
(when (not= file-id library-id)
|
||||
;; When we have just updated the library file, give some time for the
|
||||
;; update to finish, before marking this file as synced.
|
||||
;; TODO: look for a more precise way of syncing this.
|
||||
;; Maybe by using the stream (second argument passed to watch)
|
||||
;; to wait for the corresponding changes-committed and then proceed
|
||||
;; with the :update-sync mutation.
|
||||
(rx/concat (rx/timer 3000)
|
||||
(rp/mutation :update-sync
|
||||
{:file-id file-id
|
||||
:library-id library-id})))
|
||||
(when (and (seq (:redo-changes library-changes))
|
||||
sync-components?)
|
||||
(rx/of (sync-file-2nd-stage file-id library-id asset-id))))))))))
|
||||
|
||||
(defn- sync-file-2nd-stage
|
||||
"If some components have been modified, we need to launch another synchronization
|
||||
to update the instances of the changed components."
|
||||
;; TODO: this does not work if there are multiple nested components. Only the
|
||||
|
@ -658,9 +697,10 @@
|
|||
;; recursively. But for this not to cause an infinite loop, we need to
|
||||
;; implement updated-at at component level, to detect what components have
|
||||
;; not changed, and then not to apply sync and terminate the loop.
|
||||
[file-id library-id]
|
||||
[file-id library-id asset-id]
|
||||
(us/assert ::us/uuid file-id)
|
||||
(us/assert ::us/uuid library-id)
|
||||
(us/assert (s/nilable ::us/uuid) asset-id)
|
||||
(ptk/reify ::sync-file-2nd-stage
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
|
@ -671,8 +711,8 @@
|
|||
changes (reduce
|
||||
pcb/concat-changes
|
||||
(pcb/empty-changes it)
|
||||
[(dwlh/generate-sync-file it file-id :components library-id state)
|
||||
(dwlh/generate-sync-library it file-id :components library-id state)])]
|
||||
[(dwlh/generate-sync-file it file-id :components asset-id library-id state)
|
||||
(dwlh/generate-sync-library it file-id :components asset-id library-id state)])]
|
||||
(when (seq (:redo-changes changes))
|
||||
(log/debug :msg "SYNC-FILE (2nd stage) finished" :js/rchanges (log-changes
|
||||
(:redo-changes changes)
|
||||
|
@ -716,6 +756,48 @@
|
|||
:callback do-dismiss}]
|
||||
:sync-dialog))))))
|
||||
|
||||
(defn watch-component-changes
|
||||
"Watch the state for changes that affect to any main instance. If a change is detected will throw
|
||||
an update-component-sync, so changes are immediately propagated to the component and copies."
|
||||
[]
|
||||
(ptk/reify ::watch-component-changes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
|
||||
stopper
|
||||
(->> stream
|
||||
(rx/filter #(or (= :app.main.data.workspace/finalize-page (ptk/type %))
|
||||
(= ::watch-component-changes (ptk/type %)))))
|
||||
|
||||
workspace-data-s
|
||||
(->> (rx/concat
|
||||
(rx/of nil)
|
||||
(rx/from-atom refs/workspace-data {:emit-current-value? true})))
|
||||
|
||||
change-s
|
||||
(->> stream
|
||||
(rx/filter #(or (dch/commit-changes? %)
|
||||
(= (ptk/type %) :app.main.data.workspace.notifications/handle-file-change)))
|
||||
(rx/observe-on :async))
|
||||
|
||||
check-changes
|
||||
(fn [[event data]]
|
||||
(let [changes (-> event deref :changes)
|
||||
components-changed (reduce #(into %1 (ch/components-changed data %2))
|
||||
#{}
|
||||
changes)]
|
||||
(when (d/not-empty? components-changed)
|
||||
(run! st/emit!
|
||||
(map #(update-component-sync % (:id data))
|
||||
components-changed)))))]
|
||||
|
||||
(when components-v2
|
||||
(->> change-s
|
||||
(rx/with-latest-from workspace-data-s)
|
||||
(rx/map check-changes)
|
||||
(rx/take-until stopper)))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Backend interactions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -762,12 +844,13 @@
|
|||
[file-id library-id]
|
||||
(ptk/reify ::attach-library
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [fetched #(assoc-in %2 [:workspace-libraries (:id %1)] %1)
|
||||
params {:file-id file-id
|
||||
:library-id library-id}]
|
||||
(watch [_ state _]
|
||||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
fetched #(assoc-in %2 [:workspace-libraries (:id %1)] %1)
|
||||
params {:file-id file-id
|
||||
:library-id library-id}]
|
||||
(->> (rp/mutation :link-file-to-library params)
|
||||
(rx/mapcat #(rp/query :file {:id library-id}))
|
||||
(rx/mapcat #(rp/query :file {:id library-id :components-v2 components-v2}))
|
||||
(rx/map #(partial fetched %)))))))
|
||||
|
||||
(defn unlink-file-from-library
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
[app.common.spec :as us]
|
||||
[app.common.text :as txt]
|
||||
[app.common.types.color :as ctc]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.typography :as cty]
|
||||
[app.main.data.workspace.groups :as dwg]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.util.names :as un]
|
||||
[cljs.spec.alpha :as s]
|
||||
[clojure.set :as set]))
|
||||
|
||||
|
@ -55,51 +58,11 @@
|
|||
|
||||
;; ---- Components and instances creation ----
|
||||
|
||||
(defn make-component-shape
|
||||
"Clone the shape and all children. Generate new ids and detach
|
||||
from parent and frame. Update the original shapes to have links
|
||||
to the new ones."
|
||||
[shape objects file-id]
|
||||
(assert (nil? (:component-id shape)))
|
||||
(assert (nil? (:component-file shape)))
|
||||
(assert (nil? (:shape-ref shape)))
|
||||
(let [;; Ensure that the component root is not an instance and
|
||||
;; it's no longer tied to a frame.
|
||||
update-new-shape (fn [new-shape _original-shape]
|
||||
(cond-> new-shape
|
||||
true
|
||||
(-> (assoc :frame-id nil)
|
||||
(dissoc :component-root?))
|
||||
|
||||
(nil? (:parent-id new-shape))
|
||||
(dissoc :component-id
|
||||
:component-file
|
||||
:shape-ref)))
|
||||
|
||||
;; Make the original shape an instance of the new component.
|
||||
;; If one of the original shape children already was a component
|
||||
;; instance, maintain this instanceness untouched.
|
||||
update-original-shape (fn [original-shape new-shape]
|
||||
(cond-> original-shape
|
||||
(nil? (:shape-ref original-shape))
|
||||
(-> (assoc :shape-ref (:id new-shape))
|
||||
(dissoc :touched))
|
||||
|
||||
(nil? (:parent-id new-shape))
|
||||
(assoc :component-id (:id new-shape)
|
||||
:component-file file-id
|
||||
:component-root? true)
|
||||
|
||||
(some? (:parent-id new-shape))
|
||||
(dissoc :component-root?)))]
|
||||
|
||||
(cph/clone-object shape nil objects update-new-shape update-original-shape)))
|
||||
|
||||
(defn generate-add-component
|
||||
"If there is exactly one id, and it's a group, use it as root. Otherwise,
|
||||
create a group that contains all ids. Then, make a component with it,
|
||||
and link all shapes to their corresponding one in the component."
|
||||
[it shapes objects page-id file-id]
|
||||
[it shapes objects page-id file-id components-v2]
|
||||
(if (and (= (count shapes) 1)
|
||||
(:component-id (first shapes)))
|
||||
[(first shapes) (pcb/empty-changes it)]
|
||||
|
@ -114,73 +77,54 @@
|
|||
(dwg/prepare-create-group it objects page-id shapes name true))
|
||||
|
||||
[new-shape new-shapes updated-shapes]
|
||||
(make-component-shape group objects file-id)
|
||||
(ctn/make-component-shape group objects file-id components-v2)
|
||||
|
||||
changes (-> changes
|
||||
(pcb/add-component (:id new-shape)
|
||||
path
|
||||
name
|
||||
new-shapes
|
||||
updated-shapes))]
|
||||
updated-shapes
|
||||
(:id group)
|
||||
page-id))]
|
||||
[group new-shape changes])))
|
||||
|
||||
(defn duplicate-component
|
||||
"Clone the root shape of the component and all children. Generate new
|
||||
ids from all of them."
|
||||
[component]
|
||||
(let [component-root (cph/get-component-root component)]
|
||||
(cph/clone-object component-root
|
||||
nil
|
||||
(get component :objects)
|
||||
identity)))
|
||||
[component main-instance-page main-instance-shape]
|
||||
(let [position (gpt/add (gpt/point (:x main-instance-shape) (:y main-instance-shape))
|
||||
(gpt/point (+ (:width main-instance-shape) 50) 0))
|
||||
|
||||
component-root (ctk/get-component-root component)
|
||||
|
||||
[new-component-shape new-component-shapes _]
|
||||
(ctst/clone-object component-root
|
||||
nil
|
||||
(get component :objects)
|
||||
identity)
|
||||
|
||||
|
||||
[new-instance-shape new-instance-shapes]
|
||||
(when (and (some? main-instance-page) (some? main-instance-shape))
|
||||
(ctn/make-component-instance main-instance-page
|
||||
{:id (:id new-component-shape)
|
||||
:name (:name new-component-shape)
|
||||
:objects (d/index-by :id new-component-shapes)}
|
||||
(:component-file main-instance-shape)
|
||||
position
|
||||
false))]
|
||||
|
||||
[new-component-shape new-component-shapes
|
||||
new-instance-shape new-instance-shapes]))
|
||||
|
||||
(defn generate-instantiate-component
|
||||
"Generate changes to create a new instance from a component."
|
||||
[it file-id component-id position page libraries]
|
||||
(let [component (cph/get-component libraries file-id component-id)
|
||||
component-shape (cph/get-shape component component-id)
|
||||
|
||||
orig-pos (gpt/point (:x component-shape) (:y component-shape))
|
||||
delta (gpt/subtract position orig-pos)
|
||||
|
||||
objects (:objects page)
|
||||
unames (volatile! (un/retrieve-used-names objects))
|
||||
|
||||
frame-id (cph/frame-id-by-position objects (gpt/add orig-pos delta))
|
||||
|
||||
update-new-shape
|
||||
(fn [new-shape original-shape]
|
||||
(let [new-name (un/generate-unique-name @unames (:name new-shape))]
|
||||
|
||||
(when (nil? (:parent-id original-shape))
|
||||
(vswap! unames conj new-name))
|
||||
|
||||
(cond-> new-shape
|
||||
true
|
||||
(as-> $
|
||||
(gsh/move $ delta)
|
||||
(assoc $ :frame-id frame-id)
|
||||
(assoc $ :parent-id
|
||||
(or (:parent-id $) (:frame-id $)))
|
||||
(dissoc $ :touched))
|
||||
|
||||
(nil? (:shape-ref original-shape))
|
||||
(assoc :shape-ref (:id original-shape))
|
||||
|
||||
(nil? (:parent-id original-shape))
|
||||
(assoc :component-id (:id original-shape)
|
||||
:component-file file-id
|
||||
:component-root? true
|
||||
:name new-name)
|
||||
|
||||
(some? (:parent-id original-shape))
|
||||
(dissoc :component-root?))))
|
||||
|
||||
[new-shape new-shapes _]
|
||||
(cph/clone-object component-shape
|
||||
nil
|
||||
(get component :objects)
|
||||
update-new-shape)
|
||||
[new-shape new-shapes]
|
||||
(ctn/make-component-instance page component file-id position false)
|
||||
|
||||
changes (reduce #(pcb/add-object %1 %2 {:ignore-touched true})
|
||||
(pcb/empty-changes it (:id page))
|
||||
|
@ -212,14 +156,19 @@
|
|||
|
||||
(defn generate-sync-file
|
||||
"Generate changes to synchronize all shapes in all pages of the given file,
|
||||
that use assets of the given type in the given library."
|
||||
[it file-id asset-type library-id state]
|
||||
that use assets of the given type in the given library.
|
||||
|
||||
If an asset id is given, only shapes linked to this particular asset will
|
||||
be syncrhonized."
|
||||
[it file-id asset-type asset-id library-id state]
|
||||
(s/assert #{:colors :components :typographies} asset-type)
|
||||
(s/assert (s/nilable ::us/uuid) asset-id)
|
||||
(s/assert ::us/uuid file-id)
|
||||
(s/assert ::us/uuid library-id)
|
||||
|
||||
(log/info :msg "Sync file with library"
|
||||
:asset-type asset-type
|
||||
:asset-id asset-id
|
||||
:file (pretty-file file-id state)
|
||||
:library (pretty-file library-id state))
|
||||
|
||||
|
@ -232,6 +181,7 @@
|
|||
changes
|
||||
(generate-sync-container it
|
||||
asset-type
|
||||
asset-id
|
||||
library-id
|
||||
state
|
||||
(cph/make-container page :page))))
|
||||
|
@ -240,11 +190,19 @@
|
|||
(defn generate-sync-library
|
||||
"Generate changes to synchronize all shapes in all components of the
|
||||
local library of the given file, that use assets of the given type in
|
||||
the given library."
|
||||
[it file-id asset-type library-id state]
|
||||
the given library.
|
||||
|
||||
If an asset id is given, only shapes linked to this particular asset will
|
||||
be syncrhonized."
|
||||
[it file-id asset-type asset-id library-id state]
|
||||
(s/assert #{:colors :components :typographies} asset-type)
|
||||
(s/assert (s/nilable ::us/uuid) asset-id)
|
||||
(s/assert ::us/uuid file-id)
|
||||
(s/assert ::us/uuid library-id)
|
||||
|
||||
(log/info :msg "Sync local components with library"
|
||||
:asset-type asset-type
|
||||
:asset-id asset-id
|
||||
:file (pretty-file file-id state)
|
||||
:library (pretty-file library-id state))
|
||||
|
||||
|
@ -257,6 +215,7 @@
|
|||
changes
|
||||
(generate-sync-container it
|
||||
asset-type
|
||||
asset-id
|
||||
library-id
|
||||
state
|
||||
(cph/make-container local-component :component))))
|
||||
|
@ -265,14 +224,14 @@
|
|||
(defn- generate-sync-container
|
||||
"Generate changes to synchronize all shapes in a particular container (a page
|
||||
or a component) that use assets of the given type in the given library."
|
||||
[it asset-type library-id state container]
|
||||
[it asset-type asset-id library-id state container]
|
||||
|
||||
(if (cph/page? container)
|
||||
(log/debug :msg "Sync page in local file" :page-id (:id container))
|
||||
(log/debug :msg "Sync component in local library" :component-id (:id container)))
|
||||
|
||||
(let [linked-shapes (->> (vals (:objects container))
|
||||
(filter #(uses-assets? asset-type % library-id (cph/page? container))))]
|
||||
(let [linked-shapes (->> (vals (:objects container))
|
||||
(filter #(uses-assets? asset-type asset-id % library-id (cph/page? container))))]
|
||||
(loop [shapes (seq linked-shapes)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-container container)
|
||||
|
@ -289,27 +248,26 @@
|
|||
|
||||
(defmulti uses-assets?
|
||||
"Checks if a shape uses some asset of the given type in the given library."
|
||||
(fn [asset-type _ _ _] asset-type))
|
||||
(fn [asset-type _ _ _ _] asset-type))
|
||||
|
||||
(defmethod uses-assets? :components
|
||||
[_ shape library-id page?]
|
||||
(and (some? (:component-id shape))
|
||||
(= (:component-file shape) library-id)
|
||||
[_ component-id shape library-id page?]
|
||||
(and (if (nil? component-id)
|
||||
(ctk/uses-library-components? shape library-id)
|
||||
(ctk/instance-of? shape library-id component-id))
|
||||
(or (:component-root? shape) (not page?)))) ; avoid nested components inside pages
|
||||
|
||||
(defmethod uses-assets? :colors
|
||||
[_ shape library-id _]
|
||||
(ctc/uses-library-colors? shape library-id))
|
||||
[_ color-id shape library-id _]
|
||||
(if (nil? color-id)
|
||||
(ctc/uses-library-colors? shape library-id)
|
||||
(ctc/uses-library-color? shape library-id color-id)))
|
||||
|
||||
(defmethod uses-assets? :typographies
|
||||
[_ shape library-id _]
|
||||
(and (= (:type shape) :text)
|
||||
(->> shape
|
||||
:content
|
||||
;; Check if any node in the content has a reference for the library
|
||||
(txt/node-seq
|
||||
#(and (some? (:typography-ref-id %))
|
||||
(= (:typography-ref-file %) library-id))))))
|
||||
[_ typography-id shape library-id _]
|
||||
(if (nil? typography-id)
|
||||
(cty/uses-library-typographies? shape library-id)
|
||||
(cty/uses-library-typography? shape library-id typography-id)))
|
||||
|
||||
(defmulti generate-sync-shape
|
||||
"Generate changes to synchronize one shape from all assets of the given type
|
||||
|
@ -482,18 +440,18 @@
|
|||
instance, and all its children, from the given component."
|
||||
[changes libraries container shape-id reset?]
|
||||
(log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?)
|
||||
(let [shape-inst (cph/get-shape container shape-id)
|
||||
(let [shape-inst (ctn/get-shape container shape-id)
|
||||
component (cph/get-component libraries
|
||||
(:component-file shape-inst)
|
||||
(:component-id shape-inst))
|
||||
shape-main (when component
|
||||
(cph/get-shape component (:shape-ref shape-inst)))
|
||||
(ctn/get-shape component (:shape-ref shape-inst)))
|
||||
|
||||
initial-root? (:component-root? shape-inst)
|
||||
|
||||
root-inst shape-inst
|
||||
root-main (when component
|
||||
(cph/get-component-root component))]
|
||||
(ctk/get-component-root component))]
|
||||
|
||||
(if component
|
||||
(generate-sync-shape-direct-recursive changes
|
||||
|
@ -543,9 +501,9 @@
|
|||
set-remote-synced?
|
||||
(change-remote-synced shape-inst container true))
|
||||
|
||||
children-inst (mapv #(cph/get-shape container %)
|
||||
children-inst (mapv #(ctn/get-shape container %)
|
||||
(:shapes shape-inst))
|
||||
children-main (mapv #(cph/get-shape component %)
|
||||
children-main (mapv #(ctn/get-shape component %)
|
||||
(:shapes shape-main))
|
||||
|
||||
only-inst (fn [changes child-inst]
|
||||
|
@ -608,16 +566,16 @@
|
|||
the values in the shape and all its children."
|
||||
[changes libraries container shape-id]
|
||||
(log/debug :msg "Sync shape inverse" :shape (str shape-id))
|
||||
(let [shape-inst (cph/get-shape container shape-id)
|
||||
(let [shape-inst (ctn/get-shape container shape-id)
|
||||
component (cph/get-component libraries
|
||||
(:component-file shape-inst)
|
||||
(:component-id shape-inst))
|
||||
shape-main (cph/get-shape component (:shape-ref shape-inst))
|
||||
shape-main (ctn/get-shape component (:shape-ref shape-inst))
|
||||
|
||||
initial-root? (:component-root? shape-inst)
|
||||
|
||||
root-inst shape-inst
|
||||
root-main (cph/get-component-root component)]
|
||||
root-main (ctk/get-component-root component)]
|
||||
|
||||
(if component
|
||||
(generate-sync-shape-inverse-recursive changes
|
||||
|
@ -668,9 +626,9 @@
|
|||
set-remote-synced?
|
||||
(change-remote-synced shape-inst container true))
|
||||
|
||||
children-inst (mapv #(cph/get-shape container %)
|
||||
children-inst (mapv #(ctn/get-shape container %)
|
||||
(:shapes shape-inst))
|
||||
children-main (mapv #(cph/get-shape component %)
|
||||
children-main (mapv #(ctn/get-shape component %)
|
||||
(:shapes shape-main))
|
||||
|
||||
only-inst (fn [changes child-inst]
|
||||
|
@ -751,13 +709,13 @@
|
|||
(reduce only-inst-cb changes children-inst)
|
||||
|
||||
:else
|
||||
(if (cph/is-main-of? child-main child-inst)
|
||||
(if (ctk/is-main-of? child-main child-inst)
|
||||
(recur (next children-inst)
|
||||
(next children-main)
|
||||
(both-cb changes child-inst child-main))
|
||||
|
||||
(let [child-inst' (d/seek #(cph/is-main-of? child-main %) children-inst)
|
||||
child-main' (d/seek #(cph/is-main-of? % child-inst) children-main)]
|
||||
(let [child-inst' (d/seek #(ctk/is-main-of? child-main %) children-inst)
|
||||
child-main' (d/seek #(ctk/is-main-of? % child-inst) children-main)]
|
||||
(cond
|
||||
(nil? child-inst')
|
||||
(recur children-inst
|
||||
|
@ -785,8 +743,8 @@
|
|||
(defn- add-shape-to-instance
|
||||
[changes component-shape index component container root-instance root-main omit-touched? set-remote-synced?]
|
||||
(log/info :msg (str "ADD [P] " (:name component-shape)))
|
||||
(let [component-parent-shape (cph/get-shape component (:parent-id component-shape))
|
||||
parent-shape (d/seek #(cph/is-main-of? component-parent-shape %)
|
||||
(let [component-parent-shape (ctn/get-shape component (:parent-id component-shape))
|
||||
parent-shape (d/seek #(ctk/is-main-of? component-parent-shape %)
|
||||
(cph/get-children-with-self (:objects container)
|
||||
(:id root-instance)))
|
||||
all-parents (into [(:id parent-shape)]
|
||||
|
@ -811,7 +769,7 @@
|
|||
original-shape)
|
||||
|
||||
[_ new-shapes _]
|
||||
(cph/clone-object component-shape
|
||||
(ctst/clone-object component-shape
|
||||
(:id parent-shape)
|
||||
(get component :objects)
|
||||
update-new-shape
|
||||
|
@ -853,8 +811,8 @@
|
|||
(defn- add-shape-to-main
|
||||
[changes shape index component page root-instance root-main]
|
||||
(log/info :msg (str "ADD [C] " (:name shape)))
|
||||
(let [parent-shape (cph/get-shape page (:parent-id shape))
|
||||
component-parent-shape (d/seek #(cph/is-main-of? % parent-shape)
|
||||
(let [parent-shape (ctn/get-shape page (:parent-id shape))
|
||||
component-parent-shape (d/seek #(ctk/is-main-of? % parent-shape)
|
||||
(cph/get-children-with-self (:objects component)
|
||||
(:id root-main)))
|
||||
all-parents (into [(:id component-parent-shape)]
|
||||
|
@ -873,7 +831,7 @@
|
|||
original-shape))
|
||||
|
||||
[_new-shape new-shapes updated-shapes]
|
||||
(cph/clone-object shape
|
||||
(ctst/clone-object shape
|
||||
(:id component-parent-shape)
|
||||
(get page :objects)
|
||||
update-new-shape
|
||||
|
@ -980,7 +938,7 @@
|
|||
index-before
|
||||
" -> "
|
||||
index-after))
|
||||
(let [parent (cph/get-shape container (:parent-id shape))
|
||||
(let [parent (ctn/get-shape container (:parent-id shape))
|
||||
|
||||
changes' (-> changes
|
||||
(update :redo-changes conj (make-change
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
(:require
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.path :as upg]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.path.commands :as upc]
|
||||
[app.common.path.shapes-to-path :as upsp]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.drawing.common :as dwdc]
|
||||
[app.main.data.workspace.edition :as dwe]
|
||||
|
@ -258,7 +258,7 @@
|
|||
(let [objects (wsh/lookup-page-objects state)
|
||||
content (get-in state [:workspace-drawing :object :content] [])
|
||||
position (get-in content [0 :params] nil)
|
||||
frame-id (cph/frame-id-by-position objects position)]
|
||||
frame-id (ctt/frame-id-by-position objects position)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :frame-id] frame-id))))))
|
||||
|
||||
|
|
|
@ -16,12 +16,15 @@
|
|||
[app.config :as cf]
|
||||
[app.main.data.dashboard :as dd]
|
||||
[app.main.data.fonts :as df]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.thumbnails :as dwt]
|
||||
[app.main.features :as features]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.util.http :as http]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.router :as rt]
|
||||
[app.util.time :as dt]
|
||||
[beicon.core :as rx]
|
||||
|
@ -124,8 +127,7 @@
|
|||
(rx/map persist-synchronous-changes)
|
||||
(rx/take-until (rx/delay 100 stoper))
|
||||
(rx/finalize (fn []
|
||||
(log/debug :hint "finalize persistence: synchronous save loop"))))
|
||||
)))))
|
||||
(log/debug :hint "finalize persistence: synchronous save loop")))))))))
|
||||
|
||||
(defn persist-changes
|
||||
[file-id changes]
|
||||
|
@ -134,12 +136,14 @@
|
|||
(ptk/reify ::persist-changes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [sid (:session-id state)
|
||||
file (get state :workspace-file)
|
||||
params {:id (:id file)
|
||||
:revn (:revn file)
|
||||
:session-id sid
|
||||
:changes-with-metadata (into [] changes)}]
|
||||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
sid (:session-id state)
|
||||
file (get state :workspace-file)
|
||||
params {:id (:id file)
|
||||
:revn (:revn file)
|
||||
:session-id sid
|
||||
:changes-with-metadata (into [] changes)
|
||||
:components-v2 components-v2}]
|
||||
|
||||
(when (= file-id (:id params))
|
||||
(->> (rp/mutation :update-file params)
|
||||
|
@ -175,13 +179,15 @@
|
|||
(ptk/reify ::persist-synchronous-changes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [sid (:session-id state)
|
||||
(let [components-v2 (features/active-feature? state :components-v2)
|
||||
sid (:session-id state)
|
||||
file (get-in state [:workspace-libraries file-id])
|
||||
|
||||
params {:id (:id file)
|
||||
:revn (:revn file)
|
||||
:session-id sid
|
||||
:changes changes}]
|
||||
:changes changes
|
||||
:components-v2 components-v2}]
|
||||
|
||||
(when (:id params)
|
||||
(->> (rp/mutation :update-file params)
|
||||
|
@ -261,8 +267,9 @@
|
|||
(ptk/reify ::fetch-bundle
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rx/zip (rp/query :file-raw {:id file-id})
|
||||
(let [share-id (-> state :viewer-local :share-id)
|
||||
components-v2 (features/active-feature? state :components-v2)]
|
||||
(->> (rx/zip (rp/query :file-raw {:id file-id :components-v2 components-v2})
|
||||
(rp/query :team-users {:file-id file-id})
|
||||
(rp/query :project {:id project-id})
|
||||
(rp/query :file-libraries {:file-id file-id})
|
||||
|
@ -276,8 +283,16 @@
|
|||
:file-comments-users file-comments-users}))
|
||||
(rx/mapcat (fn [{:keys [project] :as bundle}]
|
||||
(rx/of (ptk/data-event ::bundle-fetched bundle)
|
||||
(df/load-team-fonts (:team-id project))))))))))
|
||||
|
||||
(df/load-team-fonts (:team-id project)))))
|
||||
(rx/catch (fn [err]
|
||||
(if (and (= (:type err) :restriction)
|
||||
(= (:code err) :feature-disabled))
|
||||
(let [team-id (:current-team-id state)]
|
||||
(rx/of (modal/show
|
||||
{:type :alert
|
||||
:message (tr "errors.components-v2")
|
||||
:on-accept #(st/emit! (rt/nav :dashboard-projects {:team-id team-id}))})))
|
||||
(rx/throw err)))))))))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.modal :as md]
|
||||
|
@ -26,7 +27,6 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.worker :as uw]
|
||||
[app.util.names :as un]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[clojure.set :as set]
|
||||
|
@ -284,7 +284,7 @@
|
|||
move to the desired position, and recalculate parents and frames as needed."
|
||||
[all-objects page ids delta it]
|
||||
(let [shapes (map (d/getf all-objects) ids)
|
||||
unames (volatile! (un/retrieve-used-names (:objects page)))
|
||||
unames (volatile! (ctt/retrieve-used-names (:objects page)))
|
||||
update-unames! (fn [new-name] (vswap! unames conj new-name))
|
||||
all-ids (reduce #(into %1 (cons %2 (cph/get-children-ids all-objects %2))) (d/ordered-set) ids)
|
||||
ids-map (into {} (map #(vector % (uuid/next))) all-ids)
|
||||
|
@ -319,7 +319,7 @@
|
|||
(defn- prepare-duplicate-frame-change
|
||||
[changes objects page unames update-unames! ids-map obj delta]
|
||||
(let [new-id (ids-map (:id obj))
|
||||
frame-name (un/generate-unique-name @unames (:name obj))
|
||||
frame-name (ctt/generate-unique-name @unames (:name obj))
|
||||
_ (update-unames! frame-name)
|
||||
|
||||
new-frame (-> obj
|
||||
|
@ -354,7 +354,7 @@
|
|||
(if (some? obj)
|
||||
(let [new-id (ids-map (:id obj))
|
||||
parent-id (or parent-id frame-id)
|
||||
name (un/generate-unique-name @unames (:name obj))
|
||||
name (ctt/generate-unique-name @unames (:name obj))
|
||||
_ (update-unames! name)
|
||||
|
||||
new-obj (-> obj
|
||||
|
@ -395,7 +395,7 @@
|
|||
(let [update-flows (fn [flows]
|
||||
(reduce
|
||||
(fn [flows frame]
|
||||
(let [name (un/generate-unique-name @unames "Flow-1")
|
||||
(let [name (ctt/generate-unique-name @unames "Flow-1")
|
||||
_ (vswap! unames conj name)
|
||||
new-flow {:id (uuid/next)
|
||||
:name name
|
||||
|
|
|
@ -9,33 +9,33 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.proportions :as gpr]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.page :as csp]
|
||||
[app.common.types.shape :as spec.shape]
|
||||
[app.common.types.shape.interactions :as csi]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.edition :as dwe]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.features :as features]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.names :as un]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
(s/def ::shape-attrs ::spec.shape/shape-attrs)
|
||||
(s/def ::shape-attrs ::cts/shape-attrs)
|
||||
|
||||
(defn get-shape-layer-position
|
||||
[objects selected attrs]
|
||||
|
||||
;; Calculate the frame over which we're drawing
|
||||
(let [position @ms/mouse-position
|
||||
frame-id (:frame-id attrs (cph/frame-id-by-position objects position))
|
||||
frame-id (:frame-id attrs (ctst/frame-id-by-position objects position))
|
||||
shape (when-not (empty? selected)
|
||||
(cph/get-base-shape objects selected))]
|
||||
|
||||
|
@ -52,8 +52,8 @@
|
|||
(defn make-new-shape
|
||||
[attrs objects selected]
|
||||
(let [default-attrs (if (= :frame (:type attrs))
|
||||
cp/default-frame-attrs
|
||||
cp/default-shape-attrs)
|
||||
cts/default-frame-attrs
|
||||
cts/default-shape-attrs)
|
||||
|
||||
selected-non-frames
|
||||
(into #{} (comp (map (d/getf objects))
|
||||
|
@ -84,8 +84,8 @@
|
|||
|
||||
id (or (:id attrs) (uuid/next))
|
||||
name (-> objects
|
||||
(un/retrieve-used-names)
|
||||
(un/generate-unique-name (:name attrs)))
|
||||
(ctst/retrieve-used-names)
|
||||
(ctst/generate-unique-name (:name attrs)))
|
||||
|
||||
shape (make-new-shape
|
||||
(assoc attrs :id id :name name)
|
||||
|
@ -117,7 +117,7 @@
|
|||
to-move-shapes
|
||||
(into []
|
||||
(map (d/getf objects))
|
||||
(reverse (cph/sort-z-index objects shapes)))
|
||||
(reverse (ctst/sort-z-index objects shapes)))
|
||||
|
||||
changes
|
||||
(when (d/not-empty? to-move-shapes)
|
||||
|
@ -138,13 +138,17 @@
|
|||
(ptk/reify ::delete-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
page (wsh/lookup-page state page-id)
|
||||
(let [file-id (:current-file-id state)
|
||||
page-id (:current-page-id state)
|
||||
file (wsh/get-file state file-id)
|
||||
page (wsh/lookup-page state page-id)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
|
||||
ids (cph/clean-loops objects ids)
|
||||
lookup (d/getf objects)
|
||||
|
||||
components-v2 (features/active-feature? state :components-v2)
|
||||
|
||||
groups-to-unmask
|
||||
(reduce (fn [group-ids id]
|
||||
;; When the shape to delete is the mask of a masked group,
|
||||
|
@ -164,7 +168,7 @@
|
|||
;; If any of the deleted shapes is the destination of
|
||||
;; some interaction, this must be deleted, too.
|
||||
(let [interactions (:interactions shape)]
|
||||
(some #(and (csi/has-destination %)
|
||||
(some #(and (ctsi/has-destination %)
|
||||
(contains? ids (:destination %)))
|
||||
interactions)))
|
||||
(vals objects))
|
||||
|
@ -215,9 +219,22 @@
|
|||
;; Any parent whose children are all deleted, must be deleted too.
|
||||
(into (d/ordered-set) (find-all-empty-parents #{}))
|
||||
|
||||
components-to-delete
|
||||
(if components-v2
|
||||
(reduce (fn [components id]
|
||||
(let [shape (get objects id)]
|
||||
(if (and (= (:component-file shape) file-id) ;; Main instances should exist only in local file
|
||||
(:main-instance? shape)) ;; but check anyway
|
||||
(conj components (:component-id shape))
|
||||
components)))
|
||||
[]
|
||||
(into ids all-children))
|
||||
[])
|
||||
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-page page)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/with-library-data file)
|
||||
(pcb/set-page-option :guides guides)
|
||||
(pcb/remove-objects all-children)
|
||||
(pcb/remove-objects ids)
|
||||
|
@ -231,13 +248,18 @@
|
|||
(d/update-when shape :interactions
|
||||
(fn [interactions]
|
||||
(into []
|
||||
(remove #(and (csi/has-destination %)
|
||||
(remove #(and (ctsi/has-destination %)
|
||||
(contains? ids (:destination %))))
|
||||
interactions)))))
|
||||
(cond-> (seq starting-flows)
|
||||
(pcb/update-page-option :flows (fn [flows]
|
||||
(->> (map :id starting-flows)
|
||||
(reduce csp/remove-flow flows))))))]
|
||||
(reduce ctp/remove-flow flows))))))
|
||||
|
||||
changes (reduce (fn [changes component-id]
|
||||
(pcb/delete-component changes component-id))
|
||||
changes
|
||||
components-to-delete)]
|
||||
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dwsl/update-layout-positions all-parents))))))
|
||||
|
@ -260,10 +282,10 @@
|
|||
y (:y data (- vbc-y (/ height 2)))
|
||||
page-id (:current-page-id state)
|
||||
frame-id (-> (wsh/lookup-page-objects state page-id)
|
||||
(cph/frame-id-by-position {:x frame-x :y frame-y}))
|
||||
shape (-> (cp/make-minimal-shape type)
|
||||
(ctst/frame-id-by-position {:x frame-x :y frame-y}))
|
||||
shape (-> (cts/make-minimal-shape type)
|
||||
(merge data)
|
||||
(merge {:x x :y y})
|
||||
(assoc :frame-id frame-id)
|
||||
(cp/setup-rect-selrect))]
|
||||
(cts/setup-rect-selrect))]
|
||||
(rx/of (add-shape shape))))))
|
||||
|
|
|
@ -11,17 +11,16 @@
|
|||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :refer [max-safe-int min-safe-int]]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.util.color :as uc]
|
||||
[app.util.names :as un]
|
||||
[app.util.path.parser :as upp]
|
||||
[app.util.svg :as usvg]
|
||||
[beicon.core :as rx]
|
||||
|
@ -183,7 +182,7 @@
|
|||
(assoc :svg-attrs attrs)
|
||||
(assoc :svg-viewbox (-> (select-keys svg-data [:width :height])
|
||||
(assoc :x offset-x :y offset-y)))
|
||||
(cp/setup-rect-selrect))))
|
||||
(cts/setup-rect-selrect))))
|
||||
|
||||
(defn create-svg-root [frame-id svg-data]
|
||||
(let [{:keys [name x y width height offset-x offset-y]} svg-data]
|
||||
|
@ -195,7 +194,7 @@
|
|||
:height height
|
||||
:x (+ x offset-x)
|
||||
:y (+ y offset-y)}
|
||||
(cp/setup-rect-selrect)
|
||||
(cts/setup-rect-selrect)
|
||||
(assoc :svg-attrs (-> (:attrs svg-data)
|
||||
(dissoc :viewBox :xmlns)
|
||||
(d/without-keys usvg/inheritable-props))))))
|
||||
|
@ -215,7 +214,7 @@
|
|||
(assoc :svg-attrs (d/without-keys attrs usvg/inheritable-props))
|
||||
(assoc :svg-viewbox (-> (select-keys svg-data [:width :height])
|
||||
(assoc :x offset-x :y offset-y)))
|
||||
(cp/setup-rect-selrect))))
|
||||
(cts/setup-rect-selrect))))
|
||||
|
||||
(defn create-path-shape [name frame-id svg-data {:keys [attrs] :as data}]
|
||||
(when (and (contains? attrs :d) (seq (:d attrs)))
|
||||
|
@ -360,7 +359,7 @@
|
|||
(let [{:keys [tag attrs hidden]} element-data
|
||||
attrs (usvg/format-styles attrs)
|
||||
element-data (cond-> element-data (map? element-data) (assoc :attrs attrs))
|
||||
name (un/generate-unique-name unames (or (:id attrs) (tag->name tag)))
|
||||
name (ctt/generate-unique-name unames (or (:id attrs) (tag->name tag)))
|
||||
att-refs (usvg/find-attr-references attrs)
|
||||
references (usvg/find-def-references (:defs svg-data) att-refs)
|
||||
|
||||
|
@ -437,17 +436,17 @@
|
|||
(try
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
frame-id (cph/frame-id-by-position objects position)
|
||||
frame-id (ctt/frame-id-by-position objects position)
|
||||
selected (wsh/lookup-selected state)
|
||||
|
||||
[vb-x vb-y vb-width vb-height] (svg-dimensions svg-data)
|
||||
x (- x vb-x (/ vb-width 2))
|
||||
y (- y vb-y (/ vb-height 2))
|
||||
|
||||
unames (un/retrieve-used-names objects)
|
||||
unames (ctt/retrieve-used-names objects)
|
||||
|
||||
svg-name (->> (str/replace (:name svg-data) ".svg" "")
|
||||
(un/generate-unique-name unames))
|
||||
(ctt/generate-unique-name unames))
|
||||
|
||||
svg-data (-> svg-data
|
||||
(assoc :x x
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[app.common.pages.common :as cpc]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.collapse :as dwc]
|
||||
[app.main.data.workspace.guides :as dwg]
|
||||
|
@ -752,7 +753,7 @@
|
|||
(let [position @ms/mouse-position
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
frame-id (cph/frame-id-by-position objects position)
|
||||
frame-id (ctt/frame-id-by-position objects position)
|
||||
|
||||
moving-shapes
|
||||
(->> ids
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
;;
|
||||
;; Copyright (c) UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.features
|
||||
(ns app.main.features
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.logging :as log]
|
||||
[app.config :as cfg]
|
||||
[app.main.store :as st]
|
||||
[okulary.core :as l]
|
||||
[potok.core :as ptk]
|
||||
|
@ -15,9 +16,9 @@
|
|||
|
||||
(log/set-level! :debug)
|
||||
|
||||
(def features-list #{:auto-layout})
|
||||
(def features-list #{:auto-layout :components-v2})
|
||||
|
||||
(defn toggle-feature
|
||||
(defn- toggle-feature
|
||||
[feature]
|
||||
(ptk/reify ::toggle-feature
|
||||
ptk/UpdateEvent
|
||||
|
@ -27,7 +28,6 @@
|
|||
:result (if (not (contains? (:features state) feature))
|
||||
"enabled"
|
||||
"disabled"))
|
||||
|
||||
(-> state
|
||||
(update :features
|
||||
(fn [features]
|
||||
|
@ -41,6 +41,13 @@
|
|||
(assert (contains? features-list feature) "Not supported feature")
|
||||
(st/emit! (toggle-feature feature)))
|
||||
|
||||
(defn active-feature?
|
||||
([feature]
|
||||
(active-feature? @st/state feature))
|
||||
([state feature]
|
||||
(assert (contains? features-list feature) "Not supported feature")
|
||||
(contains? (get state :features) feature)))
|
||||
|
||||
(def features
|
||||
(l/derived :features st/state))
|
||||
|
||||
|
@ -55,8 +62,14 @@
|
|||
active-feature? (mf/deref active-feature-ref)]
|
||||
active-feature?))
|
||||
|
||||
;; By default the features are active in local environments
|
||||
(when *assert*
|
||||
;; Activate all features in local environment
|
||||
(doseq [f features-list]
|
||||
(toggle-feature! f)))
|
||||
;; Read initial enabled features from config, if set
|
||||
(if-let [enabled-features @cfg/features]
|
||||
(doseq [f enabled-features]
|
||||
(toggle-feature! f))
|
||||
(when *assert*
|
||||
;; By default, all features disabled, except in development
|
||||
;; environment, that are enabled except components-v2
|
||||
(doseq [f features-list]
|
||||
(when (not= f :components-v2)
|
||||
(toggle-feature! f)))))
|
||||
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.store :as st]
|
||||
[okulary.core :as l]))
|
||||
|
@ -284,7 +285,7 @@
|
|||
(l/derived :options workspace-page))
|
||||
|
||||
(def workspace-frames
|
||||
(l/derived cph/get-frames workspace-page-objects =))
|
||||
(l/derived ctt/get-frames workspace-page-objects =))
|
||||
|
||||
(def workspace-editor
|
||||
(l/derived :workspace-editor st/state))
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
[app.common.geom.shapes.bounds :as gsb]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.config :as cfg]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.main.ui.context :as muc]
|
||||
|
@ -61,7 +62,7 @@
|
|||
(defn- calculate-dimensions
|
||||
[objects]
|
||||
(let [bounds
|
||||
(->> (cph/get-root-objects objects)
|
||||
(->> (ctst/get-root-objects objects)
|
||||
(map (partial gsb/get-object-bounds objects))
|
||||
(gsh/join-rects))]
|
||||
(-> bounds
|
||||
|
|
78
frontend/src/app/main/ui/alert.cljs
Normal file
78
frontend/src/app/main/ui/alert.cljs
Normal file
|
@ -0,0 +1,78 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.alert
|
||||
(:require
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr t]]
|
||||
[app.util.keyboard :as k]
|
||||
[goog.events :as events]
|
||||
[rumext.alpha :as mf])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
(mf/defc alert-dialog
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :alert}
|
||||
[{:keys [message
|
||||
scd-message
|
||||
title
|
||||
on-accept
|
||||
hint
|
||||
accept-label
|
||||
accept-style] :as props}]
|
||||
(let [locale (mf/deref i18n/locale)
|
||||
|
||||
on-accept (or on-accept identity)
|
||||
message (or message (t locale "ds.alert-title"))
|
||||
accept-label (or accept-label (tr "ds.alert-ok"))
|
||||
accept-style (or accept-style :danger)
|
||||
title (or title (t locale "ds.alert-title"))
|
||||
|
||||
accept-fn
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (modal/hide))
|
||||
(on-accept props)))]
|
||||
|
||||
(mf/with-effect
|
||||
(letfn [(on-keydown [event]
|
||||
(when (k/enter? event)
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (modal/hide))
|
||||
(on-accept props)))]
|
||||
(->> (events/listen js/document EventType.KEYDOWN on-keydown)
|
||||
(partial events/unlistenByKey))))
|
||||
|
||||
[:div.modal-overlay
|
||||
[:div.modal-container.alert-dialog
|
||||
[:div.modal-header
|
||||
[:div.modal-header-title
|
||||
[:h2 title]]
|
||||
[:div.modal-close-button
|
||||
{:on-click accept-fn} i/close]]
|
||||
|
||||
[:div.modal-content
|
||||
(when (and (string? message) (not= message ""))
|
||||
[:h3 message])
|
||||
(when (and (string? scd-message) (not= scd-message ""))
|
||||
[:h3 scd-message])
|
||||
(when (string? hint)
|
||||
[:p hint])]
|
||||
|
||||
[:div.modal-footer
|
||||
[:div.action-buttons
|
||||
[:input.accept-button
|
||||
{:class (dom/classnames
|
||||
:danger (= accept-style :danger)
|
||||
:primary (= accept-style :primary))
|
||||
:type "button"
|
||||
:value accept-label
|
||||
:on-click accept-fn}]]]]]))
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
|
||||
(mf/defc element-icon
|
||||
[{:keys [shape] :as props}]
|
||||
[{:keys [shape main-instance?] :as props}]
|
||||
(case (:type shape)
|
||||
:frame i/artboard
|
||||
:image i/image
|
||||
|
@ -21,7 +21,9 @@
|
|||
:rect i/box
|
||||
:text i/text
|
||||
:group (if (some? (:component-id shape))
|
||||
i/component
|
||||
(if main-instance?
|
||||
i/component
|
||||
i/component-copy)
|
||||
(if (:masked-group? shape)
|
||||
i/mask
|
||||
i/folder))
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
(def current-project-id (mf/create-context nil))
|
||||
(def current-page-id (mf/create-context nil))
|
||||
(def current-file-id (mf/create-context nil))
|
||||
(def libraries (mf/create-context nil))
|
||||
(def scroll-ctx (mf/create-context nil))
|
||||
(def active-frames-ctx (mf/create-context nil))
|
||||
(def render-thumbnails (mf/create-context nil))
|
||||
(def render-thumbnails (mf/create-context nil))
|
||||
(def components-v2 (mf/create-context nil))
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.features :as features]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.worker :as uw]
|
||||
|
@ -56,6 +57,8 @@
|
|||
:files (->> files (mapv #(assoc % :loading? true)))})
|
||||
selected-option (mf/use-state :all)
|
||||
|
||||
components-v2 (features/use-feature :components-v2)
|
||||
|
||||
start-export
|
||||
(fn []
|
||||
(swap! state assoc :status :exporting)
|
||||
|
@ -64,7 +67,7 @@
|
|||
:team-id team-id
|
||||
:export-type @selected-option
|
||||
:files files
|
||||
})
|
||||
:components-v2 components-v2})
|
||||
(rx/delay-emit 1000)
|
||||
(rx/subs
|
||||
(fn [msg]
|
||||
|
|
|
@ -92,19 +92,26 @@
|
|||
on-delete
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(if multi?
|
||||
(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:title (tr "modals.delete-file-multi-confirm.title" file-count)
|
||||
:message (tr "modals.delete-file-multi-confirm.message" file-count)
|
||||
:accept-label (tr "modals.delete-file-multi-confirm.accept" file-count)
|
||||
:on-accept delete-fn}))
|
||||
(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:title (tr "modals.delete-file-confirm.title")
|
||||
:message (tr "modals.delete-file-confirm.message")
|
||||
:accept-label (tr "modals.delete-file-confirm.accept")
|
||||
:on-accept delete-fn}))))
|
||||
(if (:is-shared file)
|
||||
(do (st/emit! (dd/fetch-library-using-files file))
|
||||
(st/emit! (modal/show
|
||||
{:type :delete-shared
|
||||
:origin :delete
|
||||
:on-accept delete-fn})))
|
||||
|
||||
(if multi?
|
||||
(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:title (tr "modals.delete-file-multi-confirm.title" file-count)
|
||||
:message (tr "modals.delete-file-multi-confirm.message" file-count)
|
||||
:accept-label (tr "modals.delete-file-multi-confirm.accept" file-count)
|
||||
:on-accept delete-fn}))
|
||||
(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:title (tr "modals.delete-file-confirm.title")
|
||||
:message (tr "modals.delete-file-confirm.message")
|
||||
:accept-label (tr "modals.delete-file-confirm.accept")
|
||||
:on-accept delete-fn})))))
|
||||
|
||||
on-move-success
|
||||
(fn [team-id project-id]
|
||||
|
@ -148,13 +155,10 @@
|
|||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dd/fetch-library-using-files file))
|
||||
(st/emit! (modal/show
|
||||
{:type :confirm
|
||||
:message ""
|
||||
:title (tr "modals.remove-shared-confirm.message" (:name file))
|
||||
:hint (tr "modals.remove-shared-confirm.hint")
|
||||
:cancel-label :omit
|
||||
:accept-label (tr "modals.remove-shared-confirm.accept")
|
||||
{:type :delete-shared
|
||||
:origin :unpublish
|
||||
:on-accept del-shared})))
|
||||
|
||||
on-export-files
|
||||
|
@ -233,7 +237,7 @@
|
|||
(when (or (seq current-projects) (seq other-teams))
|
||||
[(tr "dashboard.move-to") nil sub-options "file-move-to"])
|
||||
(if (:is-shared file)
|
||||
[(tr "dashboard.remove-shared") on-del-shared nil "file-del-shared"]
|
||||
[(tr "dashboard.unpublish-shared") on-del-shared nil "file-del-shared"]
|
||||
[(tr "dashboard.add-shared") on-add-shared nil "file-add-shared"])
|
||||
[:separator]
|
||||
[(tr "dashboard.download-binary-file") on-export-binary-files nil "download-binary-file"]
|
||||
|
|
|
@ -127,5 +127,6 @@
|
|||
[:section.dashboard-container
|
||||
[:& grid {:project project
|
||||
:files files
|
||||
:on-create-clicked on-create-clicked}]]]))
|
||||
:on-create-clicked on-create-clicked
|
||||
:origin :files}]]]))
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.math :as mth]
|
||||
[app.main.data.dashboard :as dd]
|
||||
[app.main.data.messages :as dm]
|
||||
[app.main.features :as features]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -36,9 +37,11 @@
|
|||
(defn ask-for-thumbnail
|
||||
"Creates some hooks to handle the files thumbnails cache"
|
||||
[file]
|
||||
(wrk/ask! {:cmd :thumbnails/generate
|
||||
:revn (:revn file)
|
||||
:file-id (:id file)}))
|
||||
(let [components-v2 (features/active-feature? :components-v2)]
|
||||
(wrk/ask! {:cmd :thumbnails/generate
|
||||
:revn (:revn file)
|
||||
:file-id (:id file)
|
||||
:components-v2 components-v2})))
|
||||
|
||||
(mf/defc grid-item-thumbnail
|
||||
{::mf/wrap [mf/memo]}
|
||||
|
@ -72,12 +75,13 @@
|
|||
|
||||
(mf/defc grid-item
|
||||
{:wrap [mf/memo]}
|
||||
[{:keys [file navigate?] :as props}]
|
||||
[{:keys [file navigate? origin] :as props}]
|
||||
(let [file-id (:id file)
|
||||
local (mf/use-state {:menu-open false
|
||||
:menu-pos nil
|
||||
:edition false})
|
||||
selected-files (mf/deref refs/dashboard-selected-files)
|
||||
dashboard-local (mf/deref refs/dashboard-local)
|
||||
item-ref (mf/use-ref)
|
||||
menu-ref (mf/use-ref)
|
||||
selected? (contains? selected-files file-id)
|
||||
|
@ -202,10 +206,12 @@
|
|||
:top (:y (:menu-pos @local))
|
||||
:navigate? navigate?
|
||||
:on-edit on-edit
|
||||
:on-menu-close on-menu-close}])]]]))
|
||||
:on-menu-close on-menu-close
|
||||
:origin origin
|
||||
:dashboard-local dashboard-local}])]]]))
|
||||
|
||||
(mf/defc grid
|
||||
[{:keys [files project on-create-clicked] :as props}]
|
||||
[{:keys [files project on-create-clicked origin] :as props}]
|
||||
(let [dragging? (mf/use-state false)
|
||||
project-id (:id project)
|
||||
|
||||
|
@ -265,7 +271,8 @@
|
|||
[:& grid-item
|
||||
{:file item
|
||||
:key (:id item)
|
||||
:navigate? true}])]
|
||||
:navigate? true
|
||||
:origin origin}])]
|
||||
|
||||
:else
|
||||
[:& empty-placeholder {:default? (:is-default project)
|
||||
|
@ -273,7 +280,7 @@
|
|||
:project project}])]))
|
||||
|
||||
(mf/defc line-grid-row
|
||||
[{:keys [files selected-files on-load-more dragging?] :as props}]
|
||||
[{:keys [files selected-files on-load-more dragging? origin] :as props}]
|
||||
(let [rowref (mf/use-ref)
|
||||
|
||||
width (mf/use-state nil)
|
||||
|
@ -319,7 +326,8 @@
|
|||
:file item
|
||||
:selected-files selected-files
|
||||
:key (:id item)
|
||||
:navigate? false}])
|
||||
:navigate? false
|
||||
:origin origin}])
|
||||
(when (and (> limit 0)
|
||||
(> (count files) limit))
|
||||
[:div.grid-item.placeholder {:on-click on-load-more}
|
||||
|
@ -328,7 +336,7 @@
|
|||
(tr "dashboard.show-all-files")]])]))
|
||||
|
||||
(mf/defc line-grid
|
||||
[{:keys [project team files on-load-more on-create-clicked] :as props}]
|
||||
[{:keys [project team files on-load-more on-create-clicked origin] :as props}]
|
||||
(let [dragging? (mf/use-state false)
|
||||
project-id (:id project)
|
||||
team-id (:id team)
|
||||
|
@ -412,7 +420,8 @@
|
|||
:team-id team-id
|
||||
:selected-files selected-files
|
||||
:on-load-more on-load-more
|
||||
:dragging? @dragging?}]
|
||||
:dragging? @dragging?
|
||||
:origin origin}]
|
||||
|
||||
:else
|
||||
[:& empty-placeholder {:dragging? @dragging?
|
||||
|
|
|
@ -42,5 +42,6 @@
|
|||
[:h1 (tr "dashboard.libraries-title")]]]
|
||||
[:section.dashboard-container
|
||||
[:& grid {:files files
|
||||
:project default-project}]]]))
|
||||
:project default-project
|
||||
:origin :libraries}]]]))
|
||||
|
||||
|
|
|
@ -153,7 +153,8 @@
|
|||
:team team
|
||||
:on-load-more on-nav
|
||||
:files files
|
||||
:on-create-clicked (partial create-file "dashboard:empty-folder-placeholder")}]]))
|
||||
:on-create-clicked (partial create-file "dashboard:empty-folder-placeholder")
|
||||
:origin :project}]]))
|
||||
|
||||
(def recent-files-ref
|
||||
(l/derived :dashboard-recent-files st/state))
|
||||
|
|
117
frontend/src/app/main/ui/delete_shared.cljs
Normal file
117
frontend/src/app/main/ui/delete_shared.cljs
Normal file
|
@ -0,0 +1,117 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.main.ui.delete-shared
|
||||
(:require
|
||||
[app.main.data.dashboard :as dd]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.keyboard :as k]
|
||||
[goog.events :as events]
|
||||
[rumext.alpha :as mf])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
(mf/defc delete-shared-dialog
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :delete-shared}
|
||||
[{:keys [on-accept
|
||||
on-cancel
|
||||
accept-style
|
||||
origin] :as props}]
|
||||
(let [on-accept (or on-accept identity)
|
||||
on-cancel (or on-cancel identity)
|
||||
cancel-label (tr "labels.cancel")
|
||||
accept-style (or accept-style :danger)
|
||||
is-delete? (= origin :delete)
|
||||
dashboard-local (mf/deref refs/dashboard-local)
|
||||
files->shared (:files-with-shared dashboard-local)
|
||||
count-files (count (keys files->shared))
|
||||
title (if is-delete?
|
||||
(tr "modals.delete-shared-confirm.title")
|
||||
(tr "modals.unpublish-shared-confirm.title"))
|
||||
message (if is-delete?
|
||||
(tr "modals.delete-shared-confirm.message")
|
||||
(tr "modals.unpublish-shared-confirm.message"))
|
||||
|
||||
accept-label (if is-delete?
|
||||
(tr "modals.delete-shared-confirm.accept")
|
||||
(tr "modals.unpublish-shared-confirm.accept"))
|
||||
scd-message (if is-delete?
|
||||
(tr "modals.delete-shared-confirm.scd-message" (i18n/c count-files))
|
||||
(tr "modals.unpublish-shared-confirm.scd-message" (i18n/c count-files)))
|
||||
hint (if is-delete?
|
||||
""
|
||||
(tr "modals.unpublish-shared-confirm.hint" (i18n/c count-files)))
|
||||
|
||||
accept-fn
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (modal/hide))
|
||||
(on-accept props)))
|
||||
|
||||
cancel-fn
|
||||
(mf/use-callback
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (modal/hide))
|
||||
(on-cancel props)))]
|
||||
|
||||
(mf/with-effect
|
||||
(letfn [(on-keydown [event]
|
||||
(when (k/enter? event)
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (modal/hide))
|
||||
(on-accept props)))]
|
||||
(->> (events/listen js/document EventType.KEYDOWN on-keydown)
|
||||
(partial events/unlistenByKey)))
|
||||
#(st/emit! (dd/clean-temp-shared)))
|
||||
|
||||
[:div.modal-overlay
|
||||
[:div.modal-container.confirm-dialog
|
||||
[:div.modal-header
|
||||
[:div.modal-header-title
|
||||
[:h2 title]]
|
||||
[:div.modal-close-button
|
||||
{:on-click cancel-fn} i/close]]
|
||||
|
||||
[:div.modal-content.delete-shared
|
||||
(when (and (string? message) (not= message ""))
|
||||
[:h3 message])
|
||||
|
||||
(when (> (count files->shared) 0)
|
||||
[:*
|
||||
[:div
|
||||
(when (and (string? scd-message) (not= scd-message ""))
|
||||
[:h3 scd-message])
|
||||
[:ul.file-list
|
||||
(for [[id file] files->shared]
|
||||
[:li.modal-item-element
|
||||
{:key id}
|
||||
[:span "- " (:name file)]])]]
|
||||
(when (and (string? hint) (not= hint ""))
|
||||
[:h3 hint])])]
|
||||
|
||||
[:div.modal-footer
|
||||
[:div.action-buttons
|
||||
(when-not (= cancel-label :omit)
|
||||
[:input.cancel-button
|
||||
{:type "button"
|
||||
:value cancel-label
|
||||
:on-click cancel-fn}])
|
||||
|
||||
[:input.accept-button
|
||||
{:class (dom/classnames
|
||||
:danger (= accept-style :danger)
|
||||
:primary (= accept-style :primary))
|
||||
:type "button"
|
||||
:value accept-label
|
||||
:on-click accept-fn}]]]]]))
|
|
@ -53,6 +53,7 @@
|
|||
(def close (icon-xref :close))
|
||||
(def code (icon-xref :code))
|
||||
(def component (icon-xref :component))
|
||||
(def component-copy (icon-xref :component-copy))
|
||||
(def copy (icon-xref :copy))
|
||||
(def curve (icon-xref :curve))
|
||||
(def cross (icon-xref :cross))
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.main.data.messages :as msg]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.persistence :as dwp]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.context :as ctx]
|
||||
|
@ -119,6 +120,8 @@
|
|||
layout (mf/deref refs/workspace-layout)
|
||||
wglobal (mf/deref refs/workspace-global)
|
||||
|
||||
components-v2 (features/use-feature :components-v2)
|
||||
|
||||
background-color (:background-color wglobal)]
|
||||
|
||||
;; Setting the layout preset by its name
|
||||
|
@ -145,23 +148,22 @@
|
|||
[:& (mf/provider ctx/current-team-id) {:value (:team-id project)}
|
||||
[:& (mf/provider ctx/current-project-id) {:value (:id project)}
|
||||
[:& (mf/provider ctx/current-page-id) {:value page-id}
|
||||
[:section#workspace {:style {:background-color background-color}}
|
||||
(when (not (:hide-ui layout))
|
||||
[:& header {:file file
|
||||
:page-id page-id
|
||||
:project project
|
||||
:layout layout}])
|
||||
|
||||
[:& context-menu]
|
||||
|
||||
(if (and (and file project)
|
||||
(:initialized file))
|
||||
[:& workspace-page {:key (dm/str "page-" page-id)
|
||||
:page-id page-id
|
||||
:file file
|
||||
:wglobal wglobal
|
||||
:layout layout}]
|
||||
[:& workspace-loader])]]]]]))
|
||||
[:& (mf/provider ctx/components-v2) {:value components-v2}
|
||||
[:section#workspace {:style {:background-color background-color}}
|
||||
(when (not (:hide-ui layout))
|
||||
[:& header {:file file
|
||||
:page-id page-id
|
||||
:project project
|
||||
:layout layout}])
|
||||
|
||||
[:& context-menu]
|
||||
|
||||
(if (and (and file project)
|
||||
(:initialized file))
|
||||
[:& workspace-page {:key (dm/str "page-" page-id)
|
||||
:page-id page-id
|
||||
:file file
|
||||
:wglobal wglobal
|
||||
:layout layout}]
|
||||
[:& workspace-loader])]]]]]]))
|
||||
|
||||
|
|
|
@ -188,7 +188,6 @@
|
|||
(add-group % group-name)))))
|
||||
(st/emit! (dwu/commit-undo-transaction)))
|
||||
|
||||
|
||||
(defn- on-drop-asset
|
||||
[event asset dragging? selected-assets selected-assets-full selected-assets-paths rename]
|
||||
(let [create-typed-assets-group (partial create-assets-group rename)]
|
||||
|
@ -568,7 +567,7 @@
|
|||
(on-assets-delete)
|
||||
(st/emit! (dwu/start-undo-transaction)
|
||||
(dwl/delete-component {:id (:component-id @state)})
|
||||
(dwl/sync-file file-id file-id)
|
||||
(dwl/sync-file file-id file-id :components (:component-id @state))
|
||||
(dwu/commit-undo-transaction)))))
|
||||
|
||||
on-rename
|
||||
|
@ -1120,7 +1119,7 @@
|
|||
(on-assets-delete)
|
||||
(st/emit! (dwu/start-undo-transaction)
|
||||
(dwl/delete-color color)
|
||||
(dwl/sync-file file-id file-id)
|
||||
(dwl/sync-file file-id file-id :color (:id color))
|
||||
(dwu/commit-undo-transaction)))))
|
||||
|
||||
rename-color-clicked
|
||||
|
@ -1762,7 +1761,7 @@
|
|||
(on-assets-delete)
|
||||
(st/emit! (dwu/start-undo-transaction)
|
||||
(dwl/delete-typography (:id @state))
|
||||
(dwl/sync-file file-id file-id)
|
||||
(dwl/sync-file file-id file-id :typographies (:id @state))
|
||||
(dwu/commit-undo-transaction)))))
|
||||
|
||||
editing-id (or (:rename-typography local-data)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.shape-icon :as si]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -101,6 +102,11 @@
|
|||
container? (or (cph/frame-shape? item)
|
||||
(cph/group-shape? item))
|
||||
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
main-instance? (if components-v2
|
||||
(:main-instance? item)
|
||||
true)
|
||||
|
||||
toggle-collapse
|
||||
(mf/use-fn
|
||||
(mf/deps expanded?)
|
||||
|
@ -244,7 +250,8 @@
|
|||
[:div {:on-double-click #(do (dom/stop-propagation %)
|
||||
(dom/prevent-default %)
|
||||
(st/emit! dw/zoom-to-selected-shape))}
|
||||
[:& si/element-icon {:shape item}]]
|
||||
[:& si/element-icon {:shape item
|
||||
:main-instance? main-instance?}]]
|
||||
[:& layer-name {:shape item
|
||||
:name-ref ref
|
||||
:on-start-edit #(reset! disable-drag true)
|
||||
|
@ -444,7 +451,6 @@
|
|||
(take (:num-items @filter-state))
|
||||
filtered-objects-total))))
|
||||
|
||||
|
||||
handle-show-more
|
||||
(fn []
|
||||
(when (<= (:num-items @filter-state) (count filtered-objects-total))
|
||||
|
@ -542,7 +548,6 @@
|
|||
(when last-hidden-frame
|
||||
(dom/add-class! last-hidden-frame "sticky"))))]
|
||||
|
||||
|
||||
[:div#layers.tool-window
|
||||
(if (d/not-empty? focus)
|
||||
[:div.tool-window-bar
|
||||
|
|
|
@ -6,22 +6,23 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.component
|
||||
(:require
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[rumext.alpha :as mf]))
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[rumext.alpha :as mf]))
|
||||
|
||||
(def component-attrs [:component-id :component-file :shape-ref])
|
||||
(def component-attrs [:component-id :component-file :shape-ref :main-instance?])
|
||||
|
||||
(mf/defc component-menu
|
||||
[{:keys [ids values shape-name] :as props}]
|
||||
(let [current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
|
||||
id (first ids)
|
||||
local (mf/use-state {:menu-open false})
|
||||
|
@ -29,6 +30,9 @@
|
|||
component-id (:component-id values)
|
||||
library-id (:component-file values)
|
||||
show? (some? component-id)
|
||||
main-instance? (if components-v2
|
||||
(:main-instance? values)
|
||||
true)
|
||||
|
||||
on-menu-click
|
||||
(mf/use-callback
|
||||
|
@ -69,7 +73,9 @@
|
|||
[:span (tr "workspace.options.component")]]
|
||||
[:div.element-set-content
|
||||
[:div.row-flex.component-row
|
||||
i/component
|
||||
(if main-instance?
|
||||
i/component
|
||||
i/component-copy)
|
||||
shape-name
|
||||
[:div.row-actions
|
||||
{:on-click on-menu-click}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace :as dw]
|
||||
|
@ -182,7 +183,7 @@
|
|||
(let [objects (deref refs/workspace-page-objects)
|
||||
destination (get objects (:destination interaction))
|
||||
|
||||
frames (mf/with-memo [objects] (cph/get-viewer-frames objects {:all-frames? (not= :navigate (:action-type interaction))}))
|
||||
frames (mf/with-memo [objects] (ctt/get-viewer-frames objects {:all-frames? (not= :navigate (:action-type interaction))}))
|
||||
|
||||
overlay-pos-type (:overlay-pos-type interaction)
|
||||
close-click-outside? (:close-click-outside interaction false)
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.frame
|
||||
(:require
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.features :as features]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs-shape fill-menu]]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.refs :as refs]
|
||||
[app.util.geom.grid :as gg]
|
||||
|
@ -134,7 +134,7 @@
|
|||
[:g.grid-display {:style {:pointer-events "none"}}
|
||||
(for [frame frames]
|
||||
(when (and (not (is-transform? frame))
|
||||
(not (cph/rotated-frame? frame))
|
||||
(not (ctst/rotated-frame? frame))
|
||||
(or (empty? focus) (contains? focus (:id frame))))
|
||||
[:& grid-display-frame {:key (str "grid-" (:id frame))
|
||||
:zoom zoom
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -292,7 +293,7 @@
|
|||
|
||||
(when (or (nil? frame)
|
||||
(and (cph/root-frame? frame)
|
||||
(not (cph/rotated-frame? frame))))
|
||||
(not (ctst/rotated-frame? frame))))
|
||||
[:g.guide-area {:opacity (when frame-guide-outside? 0)}
|
||||
(when-not disabled-guides?
|
||||
(let [{:keys [x y width height]} (guide-area-axis pos vbox zoom frame axis)]
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.main.data.shortcuts :as dsc]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.path.shortcuts :as psc]
|
||||
|
@ -183,7 +184,7 @@
|
|||
|
||||
ids (into
|
||||
(d/ordered-set)
|
||||
(cph/sort-z-index objects ids {:bottom-frames? mod?}))
|
||||
(ctt/sort-z-index objects ids {:bottom-frames? mod?}))
|
||||
|
||||
grouped? (fn [id] (contains? #{:group :bool} (get-in objects [id :type])))
|
||||
|
||||
|
@ -218,7 +219,7 @@
|
|||
(let [root-frame-ids
|
||||
(mf/use-memo
|
||||
(mf/deps objects)
|
||||
#(cph/get-root-shapes-ids objects))
|
||||
#(ctt/get-root-shapes-ids objects))
|
||||
modifiers (select-keys modifiers root-frame-ids)]
|
||||
(sfd/use-dynamic-modifiers objects globals/document modifiers)))
|
||||
|
||||
|
@ -229,7 +230,7 @@
|
|||
(defn setup-active-frames
|
||||
[objects hover-ids selected active-frames zoom transform vbox]
|
||||
|
||||
(let [all-frames (mf/use-memo (mf/deps objects) #(cph/get-root-frames-ids objects))
|
||||
(let [all-frames (mf/use-memo (mf/deps objects) #(ctt/get-root-frames-ids objects))
|
||||
selected-frames (mf/use-memo (mf/deps selected) #(->> all-frames (filter selected)))
|
||||
|
||||
xf-selected-frame (comp (remove cph/root-frame?)
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -343,7 +343,7 @@
|
|||
#(->> shapes
|
||||
(map gsh/transform-shape)
|
||||
(gsh/selection-rect)
|
||||
(cp/setup-shape)))
|
||||
(cts/setup-shape)))
|
||||
on-resize
|
||||
(fn [current-position _initial-position event]
|
||||
(when (dom/left-mouse? event)
|
||||
|
@ -371,7 +371,7 @@
|
|||
#(->> shapes
|
||||
(map gsh/transform-shape)
|
||||
(gsh/selection-rect)
|
||||
(cp/setup-shape)))]
|
||||
(cts/setup-shape)))]
|
||||
|
||||
[:& controls-selection
|
||||
{:shape shape
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.interactions :as dwi]
|
||||
|
@ -178,7 +178,7 @@
|
|||
on-frame-enter (unchecked-get props "on-frame-enter")
|
||||
on-frame-leave (unchecked-get props "on-frame-leave")
|
||||
on-frame-select (unchecked-get props "on-frame-select")
|
||||
frames (cph/get-frames objects)]
|
||||
frames (ctt/get-frames objects)]
|
||||
|
||||
[:g.frame-titles
|
||||
(for [frame frames]
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.common.uri :as u]
|
||||
[app.config :as cf]
|
||||
[app.main.data.fonts :as df]
|
||||
[app.main.features :as features]
|
||||
[app.main.render :as render]
|
||||
[app.main.repo :as repo]
|
||||
[app.main.store :as st]
|
||||
|
@ -99,22 +100,24 @@
|
|||
|
||||
(mf/defc object-svg
|
||||
[{:keys [page-id file-id object-id render-embed?]}]
|
||||
(let [fetch-state (mf/use-fn
|
||||
(mf/deps file-id page-id object-id)
|
||||
(fn []
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/query! :page {:file-id file-id
|
||||
:page-id page-id
|
||||
:object-id object-id}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second))
|
||||
(rx/map (fn [objects]
|
||||
(let [objects (render/adapt-objects-for-shape objects object-id)]
|
||||
{:objects objects
|
||||
:object (get objects object-id)}))))))
|
||||
(let [components-v2 (features/use-feature :components-v2)
|
||||
fetch-state (mf/use-fn
|
||||
(mf/deps file-id page-id object-id)
|
||||
(fn []
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/query! :page {:file-id file-id
|
||||
:page-id page-id
|
||||
:object-id object-id
|
||||
:components-v2 components-v2}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second))
|
||||
(rx/map (fn [objects]
|
||||
(let [objects (render/adapt-objects-for-shape objects object-id)]
|
||||
{:objects objects
|
||||
:object (get objects object-id)}))))))
|
||||
|
||||
{:keys [objects object]} (use-resource fetch-state)]
|
||||
|
||||
|
@ -124,8 +127,8 @@
|
|||
(when object
|
||||
(dom/set-page-style!
|
||||
{:size (str/concat
|
||||
(mth/ceil (:width object)) "px "
|
||||
(mth/ceil (:height object)) "px")})))
|
||||
(mth/ceil (:width object)) "px "
|
||||
(mth/ceil (:height object)) "px")})))
|
||||
|
||||
(when objects
|
||||
[:& render/object-svg
|
||||
|
@ -135,17 +138,19 @@
|
|||
|
||||
(mf/defc objects-svg
|
||||
[{:keys [page-id file-id object-ids render-embed?]}]
|
||||
(let [fetch-state (mf/use-fn
|
||||
(mf/deps file-id page-id)
|
||||
(fn []
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/query! :page {:file-id file-id
|
||||
:page-id page-id}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second)))))
|
||||
(let [components-v2 (features/use-feature :components-v2)
|
||||
fetch-state (mf/use-fn
|
||||
(mf/deps file-id page-id)
|
||||
(fn []
|
||||
(->> (rx/zip
|
||||
(repo/query! :font-variants {:file-id file-id})
|
||||
(repo/query! :page {:file-id file-id
|
||||
:page-id page-id
|
||||
:components-v2 components-v2}))
|
||||
(rx/tap (fn [[fonts]]
|
||||
(when (seq fonts)
|
||||
(st/emit! (df/fonts-fetched fonts)))))
|
||||
(rx/map (comp :objects second)))))
|
||||
|
||||
objects (use-resource fetch-state)]
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
(:require
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages.helpers :as cph]))
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctst]))
|
||||
|
||||
(defn selrect-snap-points [{:keys [x y width height] :as selrect}]
|
||||
#{(gpt/point x y)
|
||||
|
@ -38,7 +39,7 @@
|
|||
|
||||
(cond
|
||||
(and (some? frame)
|
||||
(not (cph/rotated-frame? frame))
|
||||
(not (ctst/rotated-frame? frame))
|
||||
(not (cph/root-frame? frame)))
|
||||
#{}
|
||||
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; 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) UXBOX Labs SL
|
||||
|
||||
(ns app.util.names
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.spec :as us]
|
||||
[cljs.spec.alpha :as s]))
|
||||
|
||||
(s/def ::set-of-string (s/every string? :kind set?))
|
||||
|
||||
(defn- extract-numeric-suffix
|
||||
[basename]
|
||||
(if-let [[_ p1 p2] (re-find #"(.*)-([0-9]+)$" basename)]
|
||||
[p1 (+ 1 (d/parse-integer p2))]
|
||||
[basename 1]))
|
||||
|
||||
(defn retrieve-used-names
|
||||
[objects]
|
||||
(into #{} (comp (map :name) (remove nil?)) (vals objects)))
|
||||
|
||||
(defn generate-unique-name
|
||||
"A unique name generator"
|
||||
[used basename]
|
||||
(s/assert ::set-of-string used)
|
||||
(s/assert ::us/string basename)
|
||||
(if-not (contains? used basename)
|
||||
basename
|
||||
(let [[prefix initial] (extract-numeric-suffix basename)]
|
||||
(loop [counter initial]
|
||||
(let [candidate (str prefix "-" counter)]
|
||||
(if (contains? used candidate)
|
||||
(recur (inc counter))
|
||||
candidate))))))
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.pages.diff :as diff]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.util.geom.grid :as gg]
|
||||
[app.util.geom.snap-points :as snap]
|
||||
|
@ -55,7 +56,7 @@
|
|||
|
||||
(defn get-grids-snap-points
|
||||
[frame coord]
|
||||
(if (not (cph/rotated-frame? frame))
|
||||
(if (not (ctst/rotated-frame? frame))
|
||||
[]
|
||||
(let [grid->snap (fn [[grid-type position]]
|
||||
{:type :layout
|
||||
|
@ -196,7 +197,7 @@
|
|||
(defn add-page
|
||||
"Adds page information"
|
||||
[snap-data {:keys [objects options] :as page}]
|
||||
(let [frames (cph/get-frames objects)
|
||||
(let [frames (ctst/get-frames objects)
|
||||
shapes (->> (vals (:objects page))
|
||||
(remove cph/frame-shape?))
|
||||
guides (vals (:guides options))
|
||||
|
|
|
@ -149,8 +149,8 @@
|
|||
(->> (r/render-components (:data file))
|
||||
(rx/map #(vector (str (:id file) "/components.svg") %))))
|
||||
|
||||
(defn fetch-file-with-libraries [file-id]
|
||||
(->> (rx/zip (rp/query :file {:id file-id})
|
||||
(defn fetch-file-with-libraries [file-id components-v2]
|
||||
(->> (rx/zip (rp/query :file {:id file-id :components-v2 components-v2})
|
||||
(rp/query :file-libraries {:file-id file-id}))
|
||||
(rx/map
|
||||
(fn [[file file-libraries]]
|
||||
|
@ -351,7 +351,7 @@
|
|||
(update file-id dissoc :libraries))))
|
||||
|
||||
(defn collect-files
|
||||
[file-id export-type]
|
||||
[file-id export-type components-v2]
|
||||
|
||||
(letfn [(fetch-dependencies [[files pending]]
|
||||
(if (empty? pending)
|
||||
|
@ -365,7 +365,7 @@
|
|||
;; The file is already in the result
|
||||
(rx/of [files pending])
|
||||
|
||||
(->> (fetch-file-with-libraries next)
|
||||
(->> (fetch-file-with-libraries next components-v2)
|
||||
(rx/map
|
||||
(fn [file]
|
||||
[(-> files
|
||||
|
@ -381,9 +381,9 @@
|
|||
(rx/map #(process-export file-id export-type %))))))
|
||||
|
||||
(defn export-file
|
||||
[team-id file-id export-type]
|
||||
[team-id file-id export-type components-v2]
|
||||
|
||||
(let [files-stream (->> (collect-files file-id export-type)
|
||||
(let [files-stream (->> (collect-files file-id export-type components-v2)
|
||||
(rx/share))
|
||||
|
||||
manifest-stream
|
||||
|
@ -471,12 +471,12 @@
|
|||
:file-id (:id file)}))))))))
|
||||
|
||||
(defmethod impl/handler :export-standard-file
|
||||
[{:keys [team-id files export-type] :as message}]
|
||||
[{:keys [team-id files export-type components-v2] :as message}]
|
||||
|
||||
(->> (rx/from files)
|
||||
(rx/mapcat
|
||||
(fn [file]
|
||||
(->> (export-file team-id (:id file) export-type)
|
||||
(->> (export-file team-id (:id file) export-type components-v2)
|
||||
(rx/map
|
||||
(fn [value]
|
||||
(if (contains? value :type)
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
[app.common.geom.shapes.path :as gpa]
|
||||
[app.common.logging :as log]
|
||||
[app.common.media :as cm]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.text :as ct]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.http :as http]
|
||||
|
@ -133,7 +133,7 @@
|
|||
:name (:name context)
|
||||
:is-shared (:shared context)
|
||||
:project-id (:project-id context)
|
||||
:data (-> cp/empty-file-data (assoc :id file-id))})))
|
||||
:data (-> ctf/empty-file-data (assoc :id file-id))})))
|
||||
|
||||
(defn link-file-libraries
|
||||
"Create a new file on the back-end"
|
||||
|
|
|
@ -48,11 +48,12 @@
|
|||
(= :request-body-too-large code)))
|
||||
|
||||
(defn- request-data-for-thumbnail
|
||||
[file-id revn]
|
||||
[file-id revn components-v2]
|
||||
(let [path "api/rpc/query/file-data-for-thumbnail"
|
||||
params {:file-id file-id
|
||||
:revn revn
|
||||
:strip-frames-with-thumbnails true}
|
||||
:strip-frames-with-thumbnails true
|
||||
:components-v2 components-v2}
|
||||
request {:method :get
|
||||
:uri (u/join (cfg/get-public-uri) path)
|
||||
:credentials "include"
|
||||
|
@ -107,18 +108,18 @@
|
|||
(rx/map (constantly params)))))
|
||||
|
||||
(defmethod impl/handler :thumbnails/generate
|
||||
[{:keys [file-id revn] :as message}]
|
||||
[{:keys [file-id revn components-v2] :as message}]
|
||||
(letfn [(on-result [{:keys [data props]}]
|
||||
{:data data
|
||||
:fonts (:fonts props)})
|
||||
|
||||
(on-cache-miss [_]
|
||||
(->> (request-data-for-thumbnail file-id revn)
|
||||
(->> (request-data-for-thumbnail file-id revn components-v2)
|
||||
(rx/map render-thumbnail)
|
||||
(rx/mapcat persist-thumbnail)))]
|
||||
|
||||
(if (debug? :disable-thumbnail-cache)
|
||||
(->> (request-data-for-thumbnail file-id revn)
|
||||
(->> (request-data-for-thumbnail file-id revn components-v2)
|
||||
(rx/map render-thumbnail))
|
||||
(->> (request-thumbnail file-id revn)
|
||||
(rx/catch not-found? on-cache-miss)
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.logging :as l]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.transit :as t]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.dashboard.shortcuts]
|
||||
[app.main.data.viewer.shortcuts]
|
||||
|
@ -211,73 +211,9 @@
|
|||
([state show-ids] (dump-tree' state show-ids false))
|
||||
([state show-ids show-touched]
|
||||
(let [page-id (get state :current-page-id)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
components (get-in state [:workspace-data :components])
|
||||
libraries (get state :workspace-libraries)
|
||||
root (d/seek #(nil? (:parent-id %)) (vals objects))]
|
||||
|
||||
(letfn [(show-shape [shape-id level objects]
|
||||
(let [shape (get objects shape-id)]
|
||||
(println (str/pad (str (str/repeat " " level)
|
||||
(:name shape)
|
||||
(when (seq (:touched shape)) "*")
|
||||
(when show-ids (str/format " <%s>" (:id shape))))
|
||||
{:length 20
|
||||
:type :right})
|
||||
(show-component shape objects))
|
||||
(when show-touched
|
||||
(when (seq (:touched shape))
|
||||
(println (str (str/repeat " " level)
|
||||
" "
|
||||
(str (:touched shape)))))
|
||||
(when (:remote-synced? shape)
|
||||
(println (str (str/repeat " " level)
|
||||
" (remote-synced)"))))
|
||||
(when (:shapes shape)
|
||||
(dorun (for [shape-id (:shapes shape)]
|
||||
(show-shape shape-id (inc level) objects))))))
|
||||
|
||||
(show-component [shape objects]
|
||||
(if (nil? (:shape-ref shape))
|
||||
""
|
||||
(let [root-shape (cph/get-component-shape objects shape)
|
||||
component-id (when root-shape (:component-id root-shape))
|
||||
component-file-id (when root-shape (:component-file root-shape))
|
||||
component-file (when component-file-id (get libraries component-file-id nil))
|
||||
component (when component-id
|
||||
(if component-file
|
||||
(get-in component-file [:data :components component-id])
|
||||
(get components component-id)))
|
||||
component-shape (when (and component (:shape-ref shape))
|
||||
(get-in component [:objects (:shape-ref shape)]))]
|
||||
(str/format " %s--> %s%s%s"
|
||||
(cond (:component-root? shape) "#"
|
||||
(:component-id shape) "@"
|
||||
:else "-")
|
||||
(when component-file (str/format "<%s> " (:name component-file)))
|
||||
(or (:name component-shape) "?")
|
||||
(if (or (:component-root? shape)
|
||||
(nil? (:component-id shape))
|
||||
true)
|
||||
""
|
||||
(let [component-id (:component-id shape)
|
||||
component-file-id (:component-file shape)
|
||||
component-file (when component-file-id (get libraries component-file-id nil))
|
||||
component (if component-file
|
||||
(get-in component-file [:data :components component-id])
|
||||
(get components component-id))]
|
||||
(str/format " (%s%s)"
|
||||
(when component-file (str/format "<%s> " (:name component-file)))
|
||||
(:name component))))))))]
|
||||
|
||||
(println "[Page]")
|
||||
(show-shape (:id root) 0 objects)
|
||||
|
||||
(dorun (for [component (vals components)]
|
||||
(do
|
||||
(println)
|
||||
(println (str/format "[%s]" (:name component)))
|
||||
(show-shape (:id component) 0 (:objects component)))))))))
|
||||
file-data (get state :workspace-data)
|
||||
libraries (get state :workspace-libraries)]
|
||||
(ctf/dump-tree file-data page-id libraries show-ids show-touched))))
|
||||
|
||||
(defn ^:export dump-tree
|
||||
([] (dump-tree' @st/state))
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
;; This namespace is only to export the functions for toggle features
|
||||
(ns features
|
||||
(:require
|
||||
[app.main.ui.features :as features]))
|
||||
[app.main.features :as features]))
|
||||
|
||||
(defn ^:export autolayout []
|
||||
(features/toggle-feature! :auto-layout))
|
||||
|
||||
(defn ^:export components-v2 []
|
||||
(features/toggle-feature! :components-v2))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue