Add to plugins clone and remove

This commit is contained in:
alonso.torres 2024-04-30 11:34:50 +02:00
parent e30c21a71f
commit 9243ba937d
4 changed files with 112 additions and 71 deletions

View file

@ -723,23 +723,21 @@
(gpt/subtract new-pos pt-obj))))) (gpt/subtract new-pos pt-obj)))))
(defn duplicate-selected (defn duplicate-shapes
([move-delta?] [ids & {:keys [move-delta? alt-duplication? change-selection? return-ref]
(duplicate-selected move-delta? false)) :or {move-delta? false alt-duplication? false change-selection? true return-ref nil}}]
([move-delta? alt-duplication?] (ptk/reify ::duplicate-shapes
(ptk/reify ::duplicate-selected
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(when (or (not move-delta?) (nil? (get-in state [:workspace-local :transform])))
(let [page (wsh/lookup-page state) (let [page (wsh/lookup-page state)
objects (:objects page) objects (:objects page)
selected (->> (wsh/lookup-selected state) ids (into #{}
(map (d/getf objects)) (comp (map (d/getf objects))
(filter #(ctk/allow-duplicate? objects %)) (filter #(ctk/allow-duplicate? objects %))
(map :id) (map :id))
set)] ids)]
(when (seq selected) (when (seq ids)
(let [obj (get objects (first selected)) (let [obj (get objects (first ids))
delta (if move-delta? delta (if move-delta?
(calc-duplicate-delta obj state objects) (calc-duplicate-delta obj state objects)
(gpt/point 0 0)) (gpt/point 0 0))
@ -748,37 +746,53 @@
libraries (wsh/get-libraries state) libraries (wsh/get-libraries state)
library-data (wsh/get-file state file-id) library-data (wsh/get-file state file-id)
changes (->> (prepare-duplicate-changes objects page selected delta it libraries library-data file-id) changes (->> (prepare-duplicate-changes objects page ids delta it libraries library-data file-id)
(duplicate-changes-update-indices objects selected)) (duplicate-changes-update-indices objects ids))
tags (or (:tags changes) #{}) tags (or (:tags changes) #{})
changes (cond-> changes alt-duplication? (assoc :tags (conj tags :alt-duplication))) changes (cond-> changes alt-duplication? (assoc :tags (conj tags :alt-duplication)))
id-original (first selected) id-original (first ids)
new-selected (->> changes new-ids (->> changes
:redo-changes :redo-changes
(filter #(= (:type %) :add-obj)) (filter #(= (:type %) :add-obj))
(filter #(selected (:old-id %))) (filter #(ids (:old-id %)))
(map #(get-in % [:obj :id])) (map #(get-in % [:obj :id]))
(into (d/ordered-set))) (into (d/ordered-set)))
id-duplicated (first new-selected) id-duplicated (first new-ids)
frames (into #{} frames (into #{}
(map #(get-in objects [% :frame-id])) (map #(get-in objects [% :frame-id]))
selected) ids)
undo-id (js/Symbol)] undo-id (js/Symbol)]
;; Warning: This order is important for the focus mode. ;; Warning: This order is important for the focus mode.
(rx/of (->> (rx/of
(dwu/start-undo-transaction undo-id) (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes) (dch/commit-changes changes)
(select-shapes new-selected) (when change-selection?
(select-shapes new-ids))
(ptk/data-event :layout/update {:ids frames}) (ptk/data-event :layout/update {:ids frames})
(memorize-duplicated id-original id-duplicated) (memorize-duplicated id-original id-duplicated)
(dwu/commit-undo-transaction undo-id)))))))))) (dwu/commit-undo-transaction undo-id))
(rx/tap #(when (some? return-ref)
(reset! return-ref id-duplicated))))))))))
(defn duplicate-selected
([move-delta?]
(duplicate-selected move-delta? false))
([move-delta? alt-duplication?]
(ptk/reify ::duplicate-selected
ptk/WatchEvent
(watch [_ state _]
(when (or (not move-delta?) (nil? (get-in state [:workspace-local :transform])))
(let [selected (wsh/lookup-selected state)]
(rx/of (duplicate-shapes selected
:move-delta? move-delta?
:alt-duplication? alt-duplication?))))))))
(defn change-hover-state (defn change-hover-state
[id value] [id value]

View file

@ -15,6 +15,8 @@
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.data.workspace :as udw] [app.main.data.workspace :as udw]
[app.main.data.workspace.changes :as dwc] [app.main.data.workspace.changes :as dwc]
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.shapes :as dwsh]
[app.main.store :as st] [app.main.store :as st]
[app.plugins.utils :as utils :refer [get-data get-data-fn]] [app.plugins.utils :as utils :refer [get-data get-data-fn]]
[app.util.object :as obj])) [app.util.object :as obj]))
@ -61,8 +63,18 @@
(st/emit! (udw/update-dimensions [id] :width width) (st/emit! (udw/update-dimensions [id] :width width)
(udw/update-dimensions [id] :height height)))) (udw/update-dimensions [id] :height height))))
(clone [_] (.log js/console (clj->js _data))) (clone [self]
(delete [_] (.log js/console (clj->js _data))) (let [id (get-data self :id)
page-id (:current-page-id @st/state)
ret-v (atom nil)]
(st/emit! (dws/duplicate-shapes #{id} :change-selection? false :return-ref ret-v))
(let [new-id (deref ret-v)
shape (dm/get-in @st/state [:workspace-data :pages-index page-id :objects new-id])]
(data->shape-proxy shape))))
(remove [self]
(let [id (get-data self :id)]
(st/emit! (dwsh/delete-shapes #{id}))))
(appendChild [self child] (appendChild [self child]
(let [parent-id (get-data self :id) (let [parent-id (get-data self :id)

View file

@ -8,12 +8,11 @@
"RPC for plugins runtime." "RPC for plugins runtime."
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.spec :as us]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.util.object :as obj] [app.util.object :as obj]
[cuerdas.core :as str])) [cuerdas.core :as str]
[promesa.core :as p]))
(def uuid-regex
#"\w{8}-\w{4}-\w{4}-\w{4}-\w{12}")
(defn get-data (defn get-data
([self attr] ([self attr]
@ -42,7 +41,7 @@
(let [v (cond (map? v) (let [v (cond (map? v)
(from-js v) (from-js v)
(and (string? v) (re-matches uuid-regex v)) (and (string? v) (re-matches us/uuid-rx v))
(uuid/uuid v) (uuid/uuid v)
:else v)] :else v)]
@ -50,7 +49,6 @@
{} {}
ret))) ret)))
(defn to-js (defn to-js
"Converts to javascript an camelize the keys" "Converts to javascript an camelize the keys"
[obj] [obj]
@ -65,5 +63,19 @@
obj)] obj)]
(clj->js result))) (clj->js result)))
(defn result-p
"Creates a pair of atom+promise. The promise will be resolved when the atom gets a value.
We use this to return the promise to the library clients and resolve its value when a value is passed
to the atom"
[]
(let [ret-v (atom nil)
ret-p
(p/create
(fn [resolve _]
(add-watch
ret-v
::watcher
(fn [_ _ _ value]
(remove-watch ret-v ::watcher)
(resolve value)))))]
[ret-v ret-p]))

View file

@ -9,6 +9,7 @@
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.record :as crc] [app.common.record :as crc]
[app.common.spec :as us]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.data.workspace.viewport :as dwv] [app.main.data.workspace.viewport :as dwv]
[app.main.data.workspace.zoom :as dwz] [app.main.data.workspace.zoom :as dwz]
@ -46,8 +47,9 @@
:set :set
(fn [_ value] (fn [_ value]
(let [new-x (obj/get value "x") (let [new-x (obj/get value "x")
new-y (obj/get value "y") new-y (obj/get value "y")]
vb (dm/get-in @st/state [:workspace-local :vbox]) (when (and (us/safe-number? new-x) (us/safe-number? new-y))
(let [vb (dm/get-in @st/state [:workspace-local :vbox])
old-x (+ (:x vb) (/ (:width vb) 2)) old-x (+ (:x vb) (/ (:width vb) 2))
old-y (+ (:y vb) (/ (:height vb) 2)) old-y (+ (:y vb) (/ (:height vb) 2))
delta-x (- new-x old-x) delta-x (- new-x old-x)
@ -55,7 +57,7 @@
to-position to-position
{:x #(+ % delta-x) {:x #(+ % delta-x)
:y #(+ % delta-y)}] :y #(+ % delta-y)}]
(st/emit! (dwv/update-viewport-position to-position))))} (st/emit! (dwv/update-viewport-position to-position))))))}
{:name "zoom" {:name "zoom"
:get :get
@ -63,8 +65,9 @@
(dm/get-in @st/state [:workspace-local :zoom])) (dm/get-in @st/state [:workspace-local :zoom]))
:set :set
(fn [_ value] (fn [_ value]
(when (us/safe-number? value)
(let [z (dm/get-in @st/state [:workspace-local :zoom])] (let [z (dm/get-in @st/state [:workspace-local :zoom])]
(st/emit! (dwz/set-zoom (/ value z)))))} (st/emit! (dwz/set-zoom (/ value z))))))}
{:name "bounds" {:name "bounds"
:get :get