Migrate proxies to new format

This commit is contained in:
alonso.torres 2024-11-22 11:05:10 +01:00 committed by Andrey Antukh
parent e16ec9c719
commit eccc4226c7
18 changed files with 4355 additions and 4212 deletions

View file

@ -12,7 +12,6 @@
[app.common.files.changes-builder :as cb] [app.common.files.changes-builder :as cb]
[app.common.files.helpers :as cfh] [app.common.files.helpers :as cfh]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.record :as cr]
[app.common.schema :as sm] [app.common.schema :as sm]
[app.common.text :as txt] [app.common.text :as txt]
[app.common.types.color :as ctc] [app.common.types.color :as ctc]
@ -59,39 +58,96 @@
(st/emit! (ch/commit-changes changes)) (st/emit! (ch/commit-changes changes))
(shape/shape-proxy plugin-id (:id shape)))) (shape/shape-proxy plugin-id (:id shape))))
(deftype PenpotContext [$plugin] (defn create-context
Object [plugin-id]
(addListener (obj/reify {:name "PenpotContext"}
[_ type callback props] ;; Private properties
(events/add-listener type $plugin callback props)) :$plugin {:enumerable false :get (fn [] plugin-id)}
(removeListener ;; Public properties
[_ listener-id] :root
{:this true
:get #(.getRoot ^js %)}
:currentFile
{:this true
:get #(.getFile ^js %)}
:currentPage
{:this true
:get #(.getPage ^js %)}
:theme
{:this true
:get #(.getTheme ^js %)}
:selection
{:this true
:get #(.getSelectedShapes ^js %)
:set
(fn [_ shapes]
(cond
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
(u/display-not-valid :selection shapes)
:else
(let [ids (into (d/ordered-set) (map #(obj/get % "$id")) shapes)]
(st/emit! (dws/select-shapes ids)))))}
:viewport
{:this true
:get #(.getViewport ^js %)}
:currentUser
{:this true
:get #(.getCurrentUser ^js %)}
:activeUsers
{:this true
:get #(.getActiveUsers ^js %)}
:fonts
{:get (fn [] (fonts/fonts-subcontext plugin-id))}
:library
{:get (fn [] (library/library-subcontext plugin-id))}
:history
{:get (fn [] (history/history-subcontext plugin-id))}
;; Methods
:addListener
(fn [type callback props]
(events/add-listener type plugin-id callback props))
:removeListener
(fn [listener-id]
(events/remove-listener listener-id)) (events/remove-listener listener-id))
(getViewport :getViewport
[_] (fn []
(viewport/viewport-proxy $plugin)) (viewport/viewport-proxy plugin-id))
(getFile :getFile
[_] (fn []
(when (some? (:current-file-id @st/state)) (when (some? (:current-file-id @st/state))
(file/file-proxy $plugin (:current-file-id @st/state)))) (file/file-proxy plugin-id (:current-file-id @st/state))))
(getPage :getPage
[_] (fn []
(let [file-id (:current-file-id @st/state) (let [file-id (:current-file-id @st/state)
page-id (:current-page-id @st/state)] page-id (:current-page-id @st/state)]
(when (and (some? file-id) (some? page-id)) (when (and (some? file-id) (some? page-id))
(page/page-proxy $plugin file-id page-id)))) (page/page-proxy plugin-id file-id page-id))))
(getSelectedShapes :getSelectedShapes
[_] (fn []
(let [selection (get-in @st/state [:workspace-local :selected])] (let [selection (get-in @st/state [:workspace-local :selected])]
(apply array (sequence (map (partial shape/shape-proxy $plugin)) selection)))) (apply array (sequence (map (partial shape/shape-proxy plugin-id)) selection))))
(shapesColors :shapesColors
[_ shapes] (fn [shapes]
(cond (cond
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes))) (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
(u/display-not-valid :shapesColors-shapes shapes) (u/display-not-valid :shapesColors-shapes shapes)
@ -108,9 +164,8 @@
(group-by :attrs) (group-by :attrs)
(format/format-array format/format-color-result))))) (format/format-array format/format-color-result)))))
(replaceColor :replaceColor
[_ shapes old-color new-color] (fn [shapes old-color new-color]
(let [old-color (parser/parse-color old-color) (let [old-color (parser/parse-color old-color)
new-color (parser/parse-color new-color)] new-color (parser/parse-color new-color)]
(cond (cond
@ -137,33 +192,33 @@
(group-by :attrs))] (group-by :attrs))]
(st/emit! (dwc/change-color-in-selected new-color (get shapes-by-color old-color) old-color)))))) (st/emit! (dwc/change-color-in-selected new-color (get shapes-by-color old-color) old-color))))))
(getRoot :getRoot
[_] (fn []
(when (and (some? (:current-file-id @st/state)) (when (and (some? (:current-file-id @st/state))
(some? (:current-page-id @st/state))) (some? (:current-page-id @st/state)))
(shape/shape-proxy $plugin uuid/zero))) (shape/shape-proxy plugin-id uuid/zero)))
(getTheme :getTheme
[_] (fn []
(let [theme (get-in @st/state [:profile :theme])] (let [theme (get-in @st/state [:profile :theme])]
(if (or (not theme) (= theme "default")) (if (or (not theme) (= theme "default"))
"dark" "dark"
(get-in @st/state [:profile :theme])))) (get-in @st/state [:profile :theme]))))
(getCurrentUser :getCurrentUser
[_] (fn []
(user/current-user-proxy $plugin (:session-id @st/state))) (user/current-user-proxy plugin-id (:session-id @st/state)))
(getActiveUsers :getActiveUsers
[_] (fn []
(apply array (apply array
(->> (:workspace-presence @st/state) (->> (:workspace-presence @st/state)
(vals) (vals)
(remove #(= (:id %) (:session-id @st/state))) (remove #(= (:id %) (:session-id @st/state)))
(map #(user/active-user-proxy $plugin (:id %)))))) (map #(user/active-user-proxy plugin-id (:id %))))))
(uploadMediaUrl :uploadMediaUrl
[_ name url] (fn [name url]
(cond (cond
(not (string? name)) (not (string? name))
(u/display-not-valid :uploadMedia-name name) (u/display-not-valid :uploadMedia-name name)
@ -180,8 +235,8 @@
(rx/map format/format-image) (rx/map format/format-image)
(rx/subs! resolve reject))))))) (rx/subs! resolve reject)))))))
(uploadMediaData :uploadMediaData
[_ name data mime-type] (fn [name data mime-type]
(let [file-id (:current-file-id @st/state)] (let [file-id (:current-file-id @st/state)]
(js/Promise. (js/Promise.
(fn [resolve reject] (fn [resolve reject]
@ -196,8 +251,8 @@
(rx/map format/format-image) (rx/map format/format-image)
(rx/subs! resolve reject)))))) (rx/subs! resolve reject))))))
(group :group
[_ shapes] (fn [shapes]
(cond (cond
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes))) (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
(u/display-not-valid :group-shapes shapes) (u/display-not-valid :group-shapes shapes)
@ -208,11 +263,10 @@
id (uuid/next) id (uuid/next)
ids (into #{} (map #(obj/get % "$id")) shapes)] ids (into #{} (map #(obj/get % "$id")) shapes)]
(st/emit! (dwg/group-shapes id ids)) (st/emit! (dwg/group-shapes id ids))
(shape/shape-proxy $plugin file-id page-id id)))) (shape/shape-proxy plugin-id file-id page-id id))))
(ungroup
[_ group & rest]
:ungroup
(fn [group & rest]
(cond (cond
(not (shape/shape-proxy? group)) (not (shape/shape-proxy? group))
(u/display-not-valid :ungroup group) (u/display-not-valid :ungroup group)
@ -225,20 +279,20 @@
ids (into #{} (map #(obj/get % "$id")) shapes)] ids (into #{} (map #(obj/get % "$id")) shapes)]
(st/emit! (dwg/ungroup-shapes ids))))) (st/emit! (dwg/ungroup-shapes ids)))))
(createBoard :createBoard
[_] (fn []
(create-shape $plugin :frame)) (create-shape plugin-id :frame))
(createRectangle :createRectangle
[_] (fn []
(create-shape $plugin :rect)) (create-shape plugin-id :rect))
(createEllipse :createEllipse
[_] (fn []
(create-shape $plugin :circle)) (create-shape plugin-id :circle))
(createPath :createPath
[_] (fn []
(let [page-id (:current-page-id @st/state) (let [page-id (:current-page-id @st/state)
page (dm/get-in @st/state [:workspace-data :pages-index page-id]) page (dm/get-in @st/state [:workspace-data :pages-index page-id])
shape (cts/setup-shape shape (cts/setup-shape
@ -251,10 +305,10 @@
(cb/with-objects (:objects page)) (cb/with-objects (:objects page))
(cb/add-object shape))] (cb/add-object shape))]
(st/emit! (ch/commit-changes changes)) (st/emit! (ch/commit-changes changes))
(shape/shape-proxy $plugin (:id shape)))) (shape/shape-proxy plugin-id (:id shape))))
(createText :createText
[_ text] (fn [text]
(cond (cond
(or (not (string? text)) (empty? text)) (or (not (string? text)) (empty? text))
(u/display-not-valid :createText text) (u/display-not-valid :createText text)
@ -272,10 +326,10 @@
(cb/with-objects (:objects page)) (cb/with-objects (:objects page))
(cb/add-object shape))] (cb/add-object shape))]
(st/emit! (ch/commit-changes changes)) (st/emit! (ch/commit-changes changes))
(shape/shape-proxy $plugin file-id page-id (:id shape))))) (shape/shape-proxy plugin-id file-id page-id (:id shape)))))
(createShapeFromSvg :createShapeFromSvg
[_ svg-string] (fn [svg-string]
(cond (cond
(or (not (string? svg-string)) (empty? svg-string)) (or (not (string? svg-string)) (empty? svg-string))
(u/display-not-valid :createShapeFromSvg svg-string) (u/display-not-valid :createShapeFromSvg svg-string)
@ -285,9 +339,10 @@
file-id (:current-file-id @st/state) file-id (:current-file-id @st/state)
page-id (:current-page-id @st/state)] page-id (:current-page-id @st/state)]
(st/emit! (dwm/create-svg-shape id "svg" svg-string (gpt/point 0 0))) (st/emit! (dwm/create-svg-shape id "svg" svg-string (gpt/point 0 0)))
(shape/shape-proxy $plugin file-id page-id id)))) (shape/shape-proxy plugin-id file-id page-id id))))
(createBoolean [_ bool-type shapes] :createBoolean
(fn [bool-type shapes]
(let [bool-type (keyword bool-type)] (let [bool-type (keyword bool-type)]
(cond (cond
(not (contains? cts/bool-types bool-type)) (not (contains? cts/bool-types bool-type))
@ -300,10 +355,10 @@
(let [ids (into #{} (map #(obj/get % "$id")) shapes) (let [ids (into #{} (map #(obj/get % "$id")) shapes)
id-ret (atom nil)] id-ret (atom nil)]
(st/emit! (dwb/create-bool bool-type ids {:id-ret id-ret})) (st/emit! (dwb/create-bool bool-type ids {:id-ret id-ret}))
(shape/shape-proxy $plugin @id-ret))))) (shape/shape-proxy plugin-id @id-ret)))))
(generateMarkup :generateMarkup
[_ shapes options] (fn [shapes options]
(let [type (d/nilv (obj/get options "type") "html")] (let [type (d/nilv (obj/get options "type") "html")]
(cond (cond
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes))) (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
@ -317,8 +372,8 @@
shapes (into [] (map u/proxy->shape) shapes)] shapes (into [] (map u/proxy->shape) shapes)]
(cg/generate-markup-code objects type shapes))))) (cg/generate-markup-code objects type shapes)))))
(generateStyle :generateStyle
[_ shapes options] (fn [shapes options]
(let [type (d/nilv (obj/get options "type") "css") (let [type (d/nilv (obj/get options "type") "css")
prelude? (d/nilv (obj/get options "withPrelude") false) prelude? (d/nilv (obj/get options "withPrelude") false)
children? (d/nilv (obj/get options "includeChildren") true)] children? (d/nilv (obj/get options "includeChildren") true)]
@ -349,27 +404,26 @@
(cg/generate-style-code (cg/generate-style-code
objects type shapes shapes-with-children {:with-prelude? prelude?}))))) objects type shapes shapes-with-children {:with-prelude? prelude?})))))
(openViewer :openViewer
[_] (fn []
(let [params {:page-id (:current-page-id @st/state) (let [params {:page-id (:current-page-id @st/state)
:file-id (:current-file-id @st/state) :file-id (:current-file-id @st/state)
:section "interactions"}] :section "interactions"}]
(st/emit! (dw/go-to-viewer params)))) (st/emit! (dw/go-to-viewer params))))
(createPage :createPage
[_] (fn []
(let [file-id (:current-file-id @st/state) (let [file-id (:current-file-id @st/state)
id (uuid/next)] id (uuid/next)]
(st/emit! (dw/create-page {:page-id id :file-id file-id})) (st/emit! (dw/create-page {:page-id id :file-id file-id}))
(page/page-proxy $plugin file-id id))) (page/page-proxy plugin-id file-id id)))
:openPage
(openPage (fn [page]
[_ page]
(let [id (obj/get page "$id")] (let [id (obj/get page "$id")]
(st/emit! (dw/go-to-page id)))) (st/emit! (dw/go-to-page id))))
(alignHorizontal :alignHorizontal
[_ shapes direction] (fn [shapes direction]
(let [dir (case direction (let [dir (case direction
"left" :hleft "left" :hleft
"center" :hcenter "center" :hcenter
@ -386,8 +440,8 @@
(let [ids (into #{} (map #(obj/get % "$id")) shapes)] (let [ids (into #{} (map #(obj/get % "$id")) shapes)]
(st/emit! (dw/align-objects dir ids)))))) (st/emit! (dw/align-objects dir ids))))))
(alignVertical :alignVertical
[_ shapes direction] (fn [shapes direction]
(let [dir (case direction (let [dir (case direction
"top" :vtop "top" :vtop
"center" :vcenter "center" :vcenter
@ -404,8 +458,8 @@
(let [ids (into #{} (map #(obj/get % "$id")) shapes)] (let [ids (into #{} (map #(obj/get % "$id")) shapes)]
(st/emit! (dw/align-objects dir ids)))))) (st/emit! (dw/align-objects dir ids))))))
(distributeHorizontal :distributeHorizontal
[_ shapes] (fn [shapes]
(cond (cond
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes))) (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
(u/display-not-valid :distributeHorizontal-shapes "Not valid shapes") (u/display-not-valid :distributeHorizontal-shapes "Not valid shapes")
@ -414,8 +468,8 @@
(let [ids (into #{} (map #(obj/get % "$id")) shapes)] (let [ids (into #{} (map #(obj/get % "$id")) shapes)]
(st/emit! (dw/distribute-objects :horizontal ids))))) (st/emit! (dw/distribute-objects :horizontal ids)))))
(distributeVertical :distributeVertical
[_ shapes] (fn [shapes]
(cond (cond
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes))) (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
(u/display-not-valid :distributeVertical-shapes "Not valid shapes") (u/display-not-valid :distributeVertical-shapes "Not valid shapes")
@ -424,41 +478,12 @@
(let [ids (into #{} (map #(obj/get % "$id")) shapes)] (let [ids (into #{} (map #(obj/get % "$id")) shapes)]
(st/emit! (dw/distribute-objects :vertical ids))))) (st/emit! (dw/distribute-objects :vertical ids)))))
(flatten :flatten
[_ shapes] (fn [shapes]
(cond (cond
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes))) (or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
(u/display-not-valid :flatten-shapes "Not valid shapes") (u/display-not-valid :flatten-shapes "Not valid shapes")
:else :else
(let [ids (into #{} (map #(obj/get % "$id")) shapes)] (let [ids (into #{} (map #(obj/get % "$id")) shapes)]
(st/emit! (dw/convert-selected-to-path ids)))))) (st/emit! (dw/convert-selected-to-path ids)))))))
(defn create-context
[plugin-id]
(cr/add-properties!
(PenpotContext. plugin-id)
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "root" :get #(.getRoot ^js %)}
{:name "currentFile" :get #(.getFile ^js %)}
{:name "currentPage" :get #(.getPage ^js %)}
{:name "theme" :get #(.getTheme ^js %)}
{:name "selection"
:get #(.getSelectedShapes ^js %)
:set
(fn [_ shapes]
(cond
(or (not (array? shapes)) (not (every? shape/shape-proxy? shapes)))
(u/display-not-valid :selection shapes)
:else
(let [ids (into (d/ordered-set) (map #(obj/get % "$id")) shapes)]
(st/emit! (dws/select-shapes ids)))))}
{:name "viewport" :get #(.getViewport ^js %)}
{:name "currentUser" :get #(.getCurrentUser ^js %)}
{:name "activeUsers" :get #(.getActiveUsers ^js %)}
{:name "fonts" :get (fn [_] (fonts/fonts-subcontext plugin-id))}
{:name "library" :get (fn [_] (library/library-subcontext plugin-id))}
{:name "history" :get (fn [_] (history/history-subcontext plugin-id))}))

View file

@ -7,7 +7,6 @@
(ns app.plugins.comments (ns app.plugins.comments
(:require (:require
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.record :as crc]
[app.common.spec :as us] [app.common.spec :as us]
[app.main.data.comments :as dc] [app.main.data.comments :as dc]
[app.main.data.workspace.comments :as dwc] [app.main.data.workspace.comments :as dwc]
@ -19,45 +18,38 @@
[app.plugins.shape :as shape] [app.plugins.shape :as shape]
[app.plugins.user :as user] [app.plugins.user :as user]
[app.plugins.utils :as u] [app.plugins.utils :as u]
[app.util.object :as obj]
[beicon.v2.core :as rx])) [beicon.v2.core :as rx]))
(deftype CommentProxy [$plugin $file $page $thread $id]
Object
(remove [_]
(js/Promise.
(fn [resolve reject]
(cond
(not (r/check-permission $plugin "comment:write"))
(do
(u/display-not-valid :remove "Plugin doesn't have 'comment:write' permission")
(reject "Plugin doesn't have 'comment:write' permission"))
:else
(->> (rp/cmd! :delete-comment {:id $id})
(rx/tap #(st/emit! (dc/retrieve-comment-threads $file)))
(rx/subs! #(resolve) reject)))))))
(defn comment-proxy? [p] (defn comment-proxy? [p]
(instance? CommentProxy p)) (obj/type-of? p "CommentProxy"))
(defn comment-proxy (defn comment-proxy
[plugin-id file-id page-id thread-id users data] [plugin-id file-id page-id thread-id users data]
(let [data* (atom data)] (let [data* (atom data)]
(crc/add-properties! (obj/reify {:name "CommentProxy"}
(CommentProxy. plugin-id file-id page-id thread-id (:id data)) ;; Private properties
{:name "$plugin" :enumerable false :get (constantly plugin-id)} :$plugin {:enumerable false :get (fn [] plugin-id)}
{:name "$file" :enumerable false :get (constantly file-id)} :$file {:enumerable false :get (fn [] file-id)}
{:name "$page" :enumerable false :get (constantly page-id)} :$page {:enumerable false :get (fn [] page-id)}
{:name "$thread" :enumerable false :get (constantly thread-id)} :$thread {:enumerable false :get (fn [] thread-id)}
{:name "$id" :enumerable false :get (constantly (:id data))} :$id {:enumerable false :get (fn [] (:id data))}
{:name "user" :get (fn [_] (user/user-proxy plugin-id (get users (:owner-id data))))} ;; Public properties
{:name "date" :get (fn [_] (:created-at data))} :user
{:get
(fn [] (user/user-proxy plugin-id (get users (:owner-id data))))}
:date
{:get
(fn [] (:created-at data))}
:content
{:get
(fn [] (:content @data*))
{:name "content"
:get (fn [_] (:content @data*))
:set :set
(fn [_ content] (fn [content]
(let [profile (:profile @st/state)] (let [profile (:profile @st/state)]
(cond (cond
(or (not (string? content)) (empty? content)) (or (not (string? content)) (empty? content))
@ -72,82 +64,49 @@
:else :else
(->> (rp/cmd! :update-comment {:id (:id data) :content content}) (->> (rp/cmd! :update-comment {:id (:id data) :content content})
(rx/tap #(st/emit! (dc/retrieve-comment-threads file-id))) (rx/tap #(st/emit! (dc/retrieve-comment-threads file-id)))
(rx/subs! #(swap! data* assoc :content content))))))}))) (rx/subs! #(swap! data* assoc :content content))))))}
(deftype CommentThreadProxy [$plugin $file $page $users $id owner] ;; Public methods
Object :remove
(findComments (fn []
[_]
(js/Promise. (js/Promise.
(fn [resolve reject] (fn [resolve reject]
(cond (cond
(not (r/check-permission $plugin "comment:read")) (not (r/check-permission plugin-id "comment:write"))
(do (do
(u/display-not-valid :findComments "Plugin doesn't have 'comment:read' permission")
(reject "Plugin doesn't have 'comment:read' permission"))
:else
(->> (rp/cmd! :get-comments {:thread-id $id})
(rx/subs!
(fn [comments]
(resolve
(format/format-array
#(comment-proxy $plugin $file $page $id $users %) comments)))
reject))))))
(reply
[_ content]
(cond
(not (r/check-permission $plugin "comment:write"))
(u/display-not-valid :reply "Plugin doesn't have 'comment:write' permission")
(or (not (string? content)) (empty? content))
(u/display-not-valid :reply "Not valid")
:else
(js/Promise.
(fn [resolve reject]
(->> (rp/cmd! :create-comment {:thread-id $id :content content})
(rx/subs! #(resolve (comment-proxy $plugin $file $page $id $users %)) reject))))))
(remove [_]
(let [profile (:profile @st/state)]
(cond
(not (r/check-permission $plugin "comment:write"))
(u/display-not-valid :remove "Plugin doesn't have 'comment:write' permission") (u/display-not-valid :remove "Plugin doesn't have 'comment:write' permission")
(reject "Plugin doesn't have 'comment:write' permission"))
(not= (:id profile) owner)
(u/display-not-valid :remove "Cannot change content from another user's comments")
:else :else
(js/Promise. (->> (rp/cmd! :delete-comment {:id (:id data)})
(fn [resolve] (rx/tap #(st/emit! (dc/retrieve-comment-threads file-id)))
(js/Promise. (rx/subs! #(resolve) reject)))))))))
(st/emit! (dc/delete-comment-thread-on-workspace {:id $id} #(resolve))))))))))
(defn comment-thread-proxy? [p] (defn comment-thread-proxy? [p]
(instance? CommentThreadProxy p)) (obj/type-of? p "CommentThreadProxy"))
(defn comment-thread-proxy (defn comment-thread-proxy
[plugin-id file-id page-id users data] [plugin-id file-id page-id users data]
(let [data* (atom data)] (let [data* (atom data)]
(crc/add-properties! (obj/reify {:name "CommentThreadProxy"}
(CommentThreadProxy. plugin-id file-id page-id users (:id data) (:owner-id data)) :$plugin {:enumerable false :get (fn [] plugin-id)}
{:name "$plugin" :enumerable false :get (constantly plugin-id)} :$file {:enumerable false :get (fn [] file-id)}
{:name "$file" :enumerable false :get (constantly file-id)} :$page {:enumerable false :get (fn [] page-id)}
{:name "$page" :enumerable false :get (constantly page-id)} :$id {:enumerable false :get (fn [] (:id data))}
{:name "$id" :enumerable false :get (constantly (:id data))} :$users {:enumerable false :get (fn [] users)}
{:name "$users" :enumerable false :get (constantly users)}
{:name "page" :enumerable false :get (fn [_] (u/locate-page file-id page-id))}
{:name "seqNumber" :get (fn [_] (:seqn data))} :page {:enumerable false :get #(u/locate-page file-id page-id)}
{:name "owner" :get (fn [_] (user/user-proxy plugin-id (get users (:owner-id data))))} :seqNumber {:get #(:seqn data)}
{:name "board" :get (fn [_] (shape/shape-proxy plugin-id file-id page-id (:frame-id data)))} :owner {:get #(user/user-proxy plugin-id (get users (:owner-id data)))}
:board {:get #(shape/shape-proxy plugin-id file-id page-id (:frame-id data))}
:position
{:get
(fn []
(format/format-point (:position @data*)))
{:name "position"
:get (fn [_] (format/format-point (:position @data*)))
:set :set
(fn [_ position] (fn [position]
(let [position (parser/parse-point position)] (let [position (parser/parse-point position)]
(cond (cond
(or (not (us/safe-number? (:x position))) (not (us/safe-number? (:y position)))) (or (not (us/safe-number? (:x position))) (not (us/safe-number? (:y position))))
@ -160,10 +119,12 @@
(do (st/emit! (dwc/update-comment-thread-position @data* [(:x position) (:y position)])) (do (st/emit! (dwc/update-comment-thread-position @data* [(:x position) (:y position)]))
(swap! data* assoc :position (gpt/point position))))))} (swap! data* assoc :position (gpt/point position))))))}
{:name "resolved" :resolved
:get (fn [_] (:is-resolved @data*)) {:get
(fn [] (:is-resolved @data*))
:set :set
(fn [_ is-resolved] (fn [is-resolved]
(cond (cond
(not (boolean? is-resolved)) (not (boolean? is-resolved))
(u/display-not-valid :resolved "Not a boolean type") (u/display-not-valid :resolved "Not a boolean type")
@ -173,5 +134,54 @@
:else :else
(do (st/emit! (dc/update-comment-thread (assoc @data* :is-resolved is-resolved))) (do (st/emit! (dc/update-comment-thread (assoc @data* :is-resolved is-resolved)))
(swap! data* assoc :is-resolved is-resolved))))}))) (swap! data* assoc :is-resolved is-resolved))))}
:findComments
(fn []
(js/Promise.
(fn [resolve reject]
(cond
(not (r/check-permission plugin-id "comment:read"))
(do
(u/display-not-valid :findComments "Plugin doesn't have 'comment:read' permission")
(reject "Plugin doesn't have 'comment:read' permission"))
:else
(->> (rp/cmd! :get-comments {:thread-id (:id data)})
(rx/subs!
(fn [comments]
(resolve
(format/format-array
#(comment-proxy plugin-id file-id page-id (:id data) users %) comments)))
reject))))))
:reply
(fn [content]
(cond
(not (r/check-permission plugin-id "comment:write"))
(u/display-not-valid :reply "Plugin doesn't have 'comment:write' permission")
(or (not (string? content)) (empty? content))
(u/display-not-valid :reply "Not valid")
:else
(js/Promise.
(fn [resolve reject]
(->> (rp/cmd! :create-comment {:thread-id (:id data) :content content})
(rx/subs! #(resolve (comment-proxy plugin-id file-id page-id (:id data) users %)) reject))))))
:remove
(fn []
(let [profile (:profile @st/state)
owner (get users (:owner-id data))]
(cond
(not (r/check-permission plugin-id "comment:write"))
(u/display-not-valid :remove "Plugin doesn't have 'comment:write' permission")
(not= (:id profile) owner)
(u/display-not-valid :remove "Cannot change content from another user's comments")
:else
(js/Promise.
(fn [resolve]
(st/emit! (dc/delete-comment-thread-on-workspace {:id (:id data)} #(resolve)))))))))))

View file

@ -62,15 +62,16 @@
(defmethod handle-state-change "shapechange" (defmethod handle-state-change "shapechange"
[_ plugin-id old-val new-val props] [_ plugin-id old-val new-val props]
(let [shape-id (-> (obj/get props "shapeId") parser/parse-id) (if-let [shape-id (-> (obj/get props "shapeId") parser/parse-id)]
old-shape (wsh/lookup-shape old-val shape-id) (let [old-shape (wsh/lookup-shape old-val shape-id)
new-shape (wsh/lookup-shape new-val shape-id) new-shape (wsh/lookup-shape new-val shape-id)
file-id (:current-file-id new-val) file-id (:current-file-id new-val)
page-id (:current-page-id new-val)] page-id (:current-page-id new-val)]
(if (and (identical? old-shape new-shape) (some? plugin-id) (some? file-id) (some? page-id) (some? shape-id)) (if (and (identical? old-shape new-shape) (some? plugin-id) (some? file-id) (some? page-id) (some? shape-id))
::not-changed ::not-changed
(shape/shape-proxy plugin-id file-id page-id shape-id)))) (shape/shape-proxy plugin-id file-id page-id shape-id)))
::not-changed))
(defmethod handle-state-change "contentsave" (defmethod handle-state-change "contentsave"
[_ _ old-val new-val _] [_ _ old-val new-val _]

View file

@ -8,7 +8,6 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.record :as crc]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.config :as cf] [app.config :as cf]
[app.main.data.exports.files :as exports.files] [app.main.data.exports.files :as exports.files]
@ -18,6 +17,7 @@
[app.main.repo :as rp] [app.main.repo :as rp]
[app.main.store :as st] [app.main.store :as st]
[app.main.worker :as uw] [app.main.worker :as uw]
[app.plugins.format :as format]
[app.plugins.page :as page] [app.plugins.page :as page]
[app.plugins.parser :as parser] [app.plugins.parser :as parser]
[app.plugins.register :as r] [app.plugins.register :as r]
@ -28,14 +28,16 @@
[app.util.time :as dt] [app.util.time :as dt]
[beicon.v2.core :as rx])) [beicon.v2.core :as rx]))
(defn file-version-proxy?
[proxy]
(obj/type-of? proxy "FileVersionProxy"))
(defn file-version-proxy (defn file-version-proxy
[plugin-id file-id users data] [plugin-id file-id users data]
(let [data (atom data)] (let [data (atom data)]
(obj/reify {:name "FileVersionProxy"} (obj/reify {:name "FileVersionProxy"}
:$plugin {:get (fn [] plugin-id) :enumerable false} :$plugin {:enumerable false :get (fn [] plugin-id)}
:$file {:get (fn [] file-id) :enumerable false} :$file {:enumerable false :get (fn [] file-id)}
:$version {:get (fn [] (:id @data)) :enumerable false}
:$data {:get (fn [] @data) :enumerable false}
:label :label
{:get #(:label @data) {:get #(:label @data)
@ -111,45 +113,64 @@
(resolve (file-version-proxy plugin-id file-id users @data)))) (resolve (file-version-proxy plugin-id file-id users @data))))
reject)))))))))) reject))))))))))
(deftype FileProxy [$plugin $id] (defn file-proxy? [p]
Object (obj/type-of? p "FileProxy"))
(getPages [_]
(let [file (u/locate-file $id)] (defn file-proxy
(apply array (sequence (map #(page/page-proxy $plugin $id %)) (dm/get-in file [:data :pages]))))) [plugin-id id]
(obj/reify {:name "FileProxy"}
:$plugin {:enumerable false :get (fn [] plugin-id)}
:$id {:enumerable false :get (fn [] id)}
:id
{:get #(format/format-id id)}
:name
{:get #(-> (u/locate-file id) :name)}
:pages
{:this true
:get #(.getPages ^js %)}
:getPages
(fn []
(let [file (u/locate-file id)]
(apply array (sequence (map #(page/page-proxy plugin-id id %)) (dm/get-in file [:data :pages])))))
;; Plugin data ;; Plugin data
(getPluginData :getPluginData
[self key] (fn [key]
(cond (cond
(not (string? key)) (not (string? key))
(u/display-not-valid :getPluginData-key key) (u/display-not-valid :getPluginData-key key)
:else :else
(let [file (u/proxy->file self)] (let [file (u/locate-file id)]
(dm/get-in file [:data :plugin-data (keyword "plugin" (str $plugin)) key])))) (dm/get-in file [:data :plugin-data (keyword "plugin" (str plugin-id)) key]))))
(setPluginData :setPluginData
[_ key value] (fn [key value]
(cond (cond
(or (not (string? key)) (empty? key)) (or (not (string? key)) (empty? key))
(u/display-not-valid :setPluginData-key key) (u/display-not-valid :setPluginData-key key)
(and (some? value) (not (string? value))) (not (string? value))
(u/display-not-valid :setPluginData-value value) (u/display-not-valid :setPluginData-value value)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :setPluginData "Plugin doesn't have 'content:write' permission") (u/display-not-valid :setPluginData "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dw/set-plugin-data $id :file (keyword "plugin" (str $plugin)) key value)))) (st/emit! (dw/set-plugin-data id :file (keyword "plugin" (str plugin-id)) key value))))
(getPluginDataKeys :getPluginDataKeys
[self] (fn []
(let [file (u/proxy->file self)] (let [file (u/locate-file id)]
(apply array (keys (dm/get-in file [:data :plugin-data (keyword "plugin" (str $plugin))]))))) (apply array (keys (dm/get-in file [:data :plugin-data (keyword "plugin" (dm/str plugin-id))])))))
(getSharedPluginData :getSharedPluginData
[self namespace key] (fn [namespace key]
(cond (cond
(not (string? namespace)) (not (string? namespace))
(u/display-not-valid :getSharedPluginData-namespace namespace) (u/display-not-valid :getSharedPluginData-namespace namespace)
@ -158,12 +179,11 @@
(u/display-not-valid :getSharedPluginData-key key) (u/display-not-valid :getSharedPluginData-key key)
:else :else
(let [file (u/proxy->file self)] (let [file (u/locate-file id)]
(dm/get-in file [:data :plugin-data (keyword "shared" namespace) key])))) (dm/get-in file [:data :plugin-data (keyword "shared" namespace) key]))))
(setSharedPluginData :setSharedPluginData
[_ namespace key value] (fn [namespace key value]
(cond (cond
(or (not (string? namespace)) (empty? namespace)) (or (not (string? namespace)) (empty? namespace))
(u/display-not-valid :setSharedPluginData-namespace namespace) (u/display-not-valid :setSharedPluginData-namespace namespace)
@ -171,57 +191,58 @@
(or (not (string? key)) (empty? key)) (or (not (string? key)) (empty? key))
(u/display-not-valid :setSharedPluginData-key key) (u/display-not-valid :setSharedPluginData-key key)
(and (some? value) (not (string? value))) (not (string? value))
(u/display-not-valid :setSharedPluginData-value value) (u/display-not-valid :setSharedPluginData-value value)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :setSharedPluginData "Plugin doesn't have 'content:write' permission") (u/display-not-valid :setSharedPluginData "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dw/set-plugin-data $id :file (keyword "shared" namespace) key value)))) (st/emit! (dw/set-plugin-data id :file (keyword "shared" namespace) key value))))
(getSharedPluginDataKeys :getSharedPluginDataKeys
[self namespace] (fn [namespace]
(cond (cond
(not (string? namespace)) (not (string? namespace))
(u/display-not-valid :getSharedPluginDataKeys namespace) (u/display-not-valid :getSharedPluginDataKeys namespace)
:else :else
(let [file (u/proxy->file self)] (let [file (u/locate-file id)]
(apply array (keys (dm/get-in file [:data :plugin-data (keyword "shared" namespace)])))))) (apply array (keys (dm/get-in file [:data :plugin-data (keyword "shared" namespace)]))))))
(createPage :createPage
[_] (fn []
(cond (cond
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :createPage "Plugin doesn't have 'content:write' permission") (u/display-not-valid :createPage "Plugin doesn't have 'content:write' permission")
:else :else
(let [page-id (uuid/next)] (let [page-id (uuid/next)]
(st/emit! (dw/create-page {:page-id page-id :file-id $id})) (st/emit! (dw/create-page {:page-id page-id :file-id id}))
(page/page-proxy $plugin $id page-id)))) (page/page-proxy plugin-id id page-id))))
(export :export
[self format type] (fn [format type]
(js/Promise.
(fn [resolve reject]
(let [type (or (parser/parse-keyword type) :all)] (let [type (or (parser/parse-keyword type) :all)]
(cond (cond
(not (contains? #{"penpot" "zip"} format)) (and (some? format) (not (contains? #{"penpot" "zip"} format)))
(u/display-not-valid :format type) (u/reject-not-valid reject :format (dm/str "Invalid format: " format))
(not (contains? (set exports.files/valid-types) type)) (not (contains? (set exports.files/valid-types) type))
(u/display-not-valid :type type) (u/reject-not-valid reject :format (dm/str "Invalid type: " type))
:else :else
(let [file (u/proxy->file self) (let [file (u/locate-file id)
features (features/get-team-enabled-features @st/state) features (features/get-team-enabled-features @st/state)
team-id (:current-team-id @st/state) team-id (:current-team-id @st/state)
format (case format format (case format
"penpot" (if (contains? cf/flags :export-file-v3) "zip" :legacy-zip
(if (contains? cf/flags :export-file-v3)
:binfile-v3 :binfile-v3
:binfile-v1) :binfile-v1))]
"zip" :legacy-zip)]
(js/Promise.
(fn [resolve reject]
(->> (uw/ask-many! (->> (uw/ask-many!
{:cmd :export-files {:cmd :export-files
:format format :format format
@ -231,6 +252,7 @@
:files [file]}) :files [file]})
(rx/mapcat (rx/mapcat
(fn [msg] (fn [msg]
(.log js/console msg)
(case (:type msg) (case (:type msg)
:error :error
(rx/throw (ex-info "cannot export file" {:type :export-file})) (rx/throw (ex-info "cannot export file" {:type :export-file}))
@ -244,80 +266,56 @@
:mode :no-cors :mode :no-cors
:response-type :buffer})))) :response-type :buffer}))))
(rx/take 1) (rx/take 1)
(rx/map (fn [data] (js/Uint8Array. data))) (rx/map #(js/Uint8Array. (:body %)))
(rx/subs! resolve reject)))))))) (rx/subs! resolve reject))))))))
:findVersions
(fn [criteria]
(findVersions
[_ criteria]
(let [user (obj/get criteria "createdBy" nil)] (let [user (obj/get criteria "createdBy" nil)]
(js/Promise. (js/Promise.
(fn [resolve reject] (fn [resolve reject]
(cond (cond
(not (r/check-permission $plugin "content:read")) (not (r/check-permission plugin-id "content:read"))
(u/reject-not-valid reject :findVersions "Plugin doesn't have 'content:read' permission") (u/reject-not-valid reject :findVersions "Plugin doesn't have 'content:read' permission")
(and (not user) (not (user/user-proxy? user))) (and (some? user) (not (user/user-proxy? user)))
(u/reject-not-valid reject :findVersions-user "Created by user is not a valid user object") (u/reject-not-valid reject :findVersions-user "Created by user is not a valid user object")
:else :else
(->> (rx/zip (rp/cmd! :get-team-users {:file-id $id}) (->> (rx/zip (rp/cmd! :get-team-users {:file-id id})
(rp/cmd! :get-file-snapshots {:file-id $id})) (rp/cmd! :get-file-snapshots {:file-id id}))
(rx/take 1) (rx/take 1)
(rx/subs! (rx/subs!
(fn [[users snapshots]] (fn [[users snapshots]]
(let [users (d/index-by :id users)] (let [users (d/index-by :id users)]
(->> snapshots (->> snapshots
(filter #(= (dm/str (:profile-id %)) (obj/get user "id"))) (filter #(or (not (obj/get user "id"))
(map #(file-version-proxy $plugin $id users %)) (= (dm/str (:profile-id %))
(obj/get user "id"))))
(map #(file-version-proxy plugin-id id users %))
(sequence) (sequence)
(apply array) (apply array)
(resolve)))) (resolve))))
reject))))))) reject)))))))
(saveVersion :saveVersion
[_ label] (fn [label]
(let [users-promise (let [users-promise
(js/Promise. (js/Promise.
(fn [resolve reject] (fn [resolve reject]
(->> (rp/cmd! :get-team-users {:file-id $id}) (->> (rp/cmd! :get-team-users {:file-id id})
(rx/subs! resolve reject)))) (rx/subs! resolve reject))))
create-version-promise create-version-promise
(js/Promise. (js/Promise.
(fn [resolve reject] (fn [resolve reject]
(cond (cond
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/reject-not-valid reject :findVersions "Plugin doesn't have 'content:write' permission") (u/reject-not-valid reject :findVersions "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwv/create-version-from-plugins $id label resolve reject)))))] (st/emit! (dwv/create-version-from-plugins id label resolve reject)))))]
(-> (js/Promise.all #js [users-promise create-version-promise]) (-> (js/Promise.all #js [users-promise create-version-promise])
(.then (.then
(fn [[users data]] (fn [[users data]]
(let [users (d/index-by :id users)] (let [users (d/index-by :id users)]
(file-version-proxy $plugin $id users data)))))))) (file-version-proxy plugin-id id users data)))))))))
(crc/define-properties!
FileProxy
{:name js/Symbol.toStringTag
:get (fn [] (str "FileProxy"))})
(defn file-proxy? [p]
(instance? FileProxy p))
(defn file-proxy
[plugin-id id]
(crc/add-properties!
(FileProxy. plugin-id id)
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$id" :enumerable false :get (constantly id)}
{:name "id"
:get #(dm/str (obj/get % "$id"))}
{:name "name"
:get #(-> % u/proxy->file :name)}
{:name "pages"
:get #(.getPages ^js %)}))

View file

@ -7,7 +7,6 @@
(ns app.plugins.flex (ns app.plugins.flex
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.record :as crc]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.types.shape.layout :as ctl] [app.common.types.shape.layout :as ctl]
[app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.shape-layout :as dwsl]
@ -21,39 +20,22 @@
;; Define in `app.plugins.shape` we do this way to prevent circular dependency ;; Define in `app.plugins.shape` we do this way to prevent circular dependency
(def shape-proxy? nil) (def shape-proxy? nil)
(deftype FlexLayout [$plugin $file $page $id]
Object
(remove
[_]
(st/emit! (dwsl/remove-layout #{$id})))
(appendChild
[_ child]
(cond
(not (shape-proxy? child))
(u/display-not-valid :appendChild child)
:else
(let [child-id (obj/get child "$id")]
(st/emit! (dwt/move-shapes-to-frame #{child-id} $id nil nil)
(ptk/data-event :layout/update {:ids [$id]}))))))
(defn flex-layout-proxy? [p] (defn flex-layout-proxy? [p]
(instance? FlexLayout p)) (obj/type-of? p "FlexLayoutProxy"))
(defn flex-layout-proxy (defn flex-layout-proxy
[plugin-id file-id page-id id] [plugin-id file-id page-id id]
(-> (FlexLayout. plugin-id file-id page-id id) (obj/reify {:name "FlexLayoutProxy"}
(crc/add-properties! :$plugin {:enumerable false :get (fn [] plugin-id)}
{:name "$plugin" :enumerable false :get (constantly plugin-id)} :$id {:enumerable false :get (fn [] id)}
{:name "$id" :enumerable false :get (constantly id)} :$file {:enumerable false :get (fn [] file-id)}
{:name "$file" :enumerable false :get (constantly file-id)} :$page {:enumerable false :get (fn [] page-id)}
{:name "$page" :enumerable false :get (constantly page-id)}
{:name "dir" :dir
{:this true
:get #(-> % u/proxy->shape :layout-flex-dir d/name) :get #(-> % u/proxy->shape :layout-flex-dir d/name)
:set :set
(fn [self value] (fn [_ value]
(let [value (keyword value)] (let [value (keyword value)]
(cond (cond
(not (contains? ctl/flex-direction-types value)) (not (contains? ctl/flex-direction-types value))
@ -63,13 +45,13 @@
(u/display-not-valid :dir "Plugin doesn't have 'content:write' permission") (u/display-not-valid :dir "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-flex-dir value})))))}
(st/emit! (dwsl/update-layout #{id} {:layout-flex-dir value}))))))}
{:name "wrap" :wrap
{:this true
:get #(-> % u/proxy->shape :layout-wrap-type d/name) :get #(-> % u/proxy->shape :layout-wrap-type d/name)
:set :set
(fn [self value] (fn [_ value]
(let [value (keyword value)] (let [value (keyword value)]
(cond (cond
(not (contains? ctl/wrap-types value)) (not (contains? ctl/wrap-types value))
@ -79,13 +61,13 @@
(u/display-not-valid :wrap "Plugin doesn't have 'content:write' permission") (u/display-not-valid :wrap "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-wrap-type value})))))}
(st/emit! (dwsl/update-layout #{id} {:layout-wrap-type value}))))))}
{:name "alignItems" :alignItems
{:this true
:get #(-> % u/proxy->shape :layout-align-items d/name) :get #(-> % u/proxy->shape :layout-align-items d/name)
:set :set
(fn [self value] (fn [_ value]
(let [value (keyword value)] (let [value (keyword value)]
(cond (cond
(not (contains? ctl/align-items-types value)) (not (contains? ctl/align-items-types value))
@ -95,13 +77,13 @@
(u/display-not-valid :alignItems "Plugin doesn't have 'content:write' permission") (u/display-not-valid :alignItems "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-align-items value})))))}
(st/emit! (dwsl/update-layout #{id} {:layout-align-items value}))))))}
{:name "alignContent" :alignContent
{:this true
:get #(-> % u/proxy->shape :layout-align-content d/name) :get #(-> % u/proxy->shape :layout-align-content d/name)
:set :set
(fn [self value] (fn [_ value]
(let [value (keyword value)] (let [value (keyword value)]
(cond (cond
(not (contains? ctl/align-content-types value)) (not (contains? ctl/align-content-types value))
@ -111,13 +93,13 @@
(u/display-not-valid :alignContent "Plugin doesn't have 'content:write' permission") (u/display-not-valid :alignContent "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-align-content value})))))}
(st/emit! (dwsl/update-layout #{id} {:layout-align-content value}))))))}
{:name "justifyItems" :justifyItems
{:this true
:get #(-> % u/proxy->shape :layout-justify-items d/name) :get #(-> % u/proxy->shape :layout-justify-items d/name)
:set :set
(fn [self value] (fn [_ value]
(let [value (keyword value)] (let [value (keyword value)]
(cond (cond
(not (contains? ctl/justify-items-types value)) (not (contains? ctl/justify-items-types value))
@ -127,13 +109,13 @@
(u/display-not-valid :justifyItems "Plugin doesn't have 'content:write' permission") (u/display-not-valid :justifyItems "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-justify-items value})))))}
(st/emit! (dwsl/update-layout #{id} {:layout-justify-items value}))))))}
{:name "justifyContent" :justifyContent
{:this true
:get #(-> % u/proxy->shape :layout-justify-content d/name) :get #(-> % u/proxy->shape :layout-justify-content d/name)
:set :set
(fn [self value] (fn [_ value]
(let [value (keyword value)] (let [value (keyword value)]
(cond (cond
(not (contains? ctl/justify-content-types value)) (not (contains? ctl/justify-content-types value))
@ -143,13 +125,13 @@
(u/display-not-valid :justifyContent "Plugin doesn't have 'content:write' permission") (u/display-not-valid :justifyContent "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-justify-content value})))))}
(st/emit! (dwsl/update-layout #{id} {:layout-justify-content value}))))))}
{:name "rowGap" :rowGap
{:this true
:get #(-> % u/proxy->shape :layout-gap :row-gap (d/nilv 0)) :get #(-> % u/proxy->shape :layout-gap :row-gap (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-int? value)) (not (us/safe-int? value))
(u/display-not-valid :rowGap value) (u/display-not-valid :rowGap value)
@ -158,13 +140,13 @@
(u/display-not-valid :rowGap "Plugin doesn't have 'content:write' permission") (u/display-not-valid :rowGap "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-gap {:row-gap value}}))))}
(st/emit! (dwsl/update-layout #{id} {:layout-gap {:row-gap value}})))))}
{:name "columnGap" :columnGap
{:this true
:get #(-> % u/proxy->shape :layout-gap :column-gap (d/nilv 0)) :get #(-> % u/proxy->shape :layout-gap :column-gap (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-int? value)) (not (us/safe-int? value))
(u/display-not-valid :columnGap value) (u/display-not-valid :columnGap value)
@ -173,13 +155,13 @@
(u/display-not-valid :columnGap "Plugin doesn't have 'content:write' permission") (u/display-not-valid :columnGap "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-gap {:column-gap value}}))))}
(st/emit! (dwsl/update-layout #{id} {:layout-gap {:column-gap value}})))))}
{:name "verticalPadding" :verticalPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p1 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-padding :p1 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-int? value)) (not (us/safe-int? value))
(u/display-not-valid :verticalPadding value) (u/display-not-valid :verticalPadding value)
@ -188,13 +170,13 @@
(u/display-not-valid :verticalPadding "Plugin doesn't have 'content:write' permission") (u/display-not-valid :verticalPadding "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value :p3 value}}))))}
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value :p3 value}})))))}
{:name "horizontalPadding" :horizontalPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p2 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-padding :p2 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-int? value)) (not (us/safe-int? value))
(u/display-not-valid :horizontalPadding value) (u/display-not-valid :horizontalPadding value)
@ -203,14 +185,14 @@
(u/display-not-valid :horizontalPadding "Plugin doesn't have 'content:write' permission") (u/display-not-valid :horizontalPadding "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}}))))}
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}})))))}
{:name "topPadding" :topPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p1 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-padding :p1 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-int? value)) (not (us/safe-int? value))
(u/display-not-valid :topPadding value) (u/display-not-valid :topPadding value)
@ -219,13 +201,13 @@
(u/display-not-valid :topPadding "Plugin doesn't have 'content:write' permission") (u/display-not-valid :topPadding "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value}}))))}
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value}})))))}
{:name "rightPadding" :rightPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p2 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-padding :p2 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-int? value)) (not (us/safe-int? value))
(u/display-not-valid :rightPadding value) (u/display-not-valid :rightPadding value)
@ -234,13 +216,13 @@
(u/display-not-valid :rightPadding "Plugin doesn't have 'content:write' permission") (u/display-not-valid :rightPadding "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value}}))))}
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value}})))))}
{:name "bottomPadding" :bottomPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p3 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-padding :p3 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-int? value)) (not (us/safe-int? value))
(u/display-not-valid :bottomPadding value) (u/display-not-valid :bottomPadding value)
@ -249,13 +231,13 @@
(u/display-not-valid :bottomPadding "Plugin doesn't have 'content:write' permission") (u/display-not-valid :bottomPadding "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p3 value}}))))}
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p3 value}})))))}
{:name "leftPadding" :leftPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p4 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-padding :p4 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-int? value)) (not (us/safe-int? value))
(u/display-not-valid :leftPadding value) (u/display-not-valid :leftPadding value)
@ -264,28 +246,40 @@
(u/display-not-valid :leftPadding "Plugin doesn't have 'content:write' permission") (u/display-not-valid :leftPadding "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}}))))}
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}})))))})))
:remove
(fn []
(st/emit! (dwsl/remove-layout #{id})))
:appendChild
(fn [child]
(cond
(not (shape-proxy? child))
(u/display-not-valid :appendChild child)
:else
(let [child-id (obj/get child "$id")]
(st/emit! (dwt/move-shapes-to-frame #{child-id} id nil nil)
(ptk/data-event :layout/update {:ids [id]})))))))
(deftype LayoutChildProxy [$plugin $file $page $id])
(defn layout-child-proxy? [p] (defn layout-child-proxy? [p]
(instance? LayoutChildProxy p)) (obj/type-of? p "LayoutChildProxy"))
(defn layout-child-proxy (defn layout-child-proxy
[plugin-id file-id page-id id] [plugin-id file-id page-id id]
(-> (LayoutChildProxy. plugin-id file-id page-id id) (obj/reify {:name "LayoutChildProxy"}
(crc/add-properties! :$plugin {:enumerable false :get (fn [] plugin-id)}
{:name "$plugin" :enumerable false :get (constantly plugin-id)} :$id {:enumerable false :get (fn [] id)}
{:name "$id" :enumerable false :get (constantly id)} :$file {:enumerable false :get (fn [] file-id)}
{:name "$file" :enumerable false :get (constantly file-id)} :$page {:enumerable false :get (fn [] page-id)}
{:name "$page" :enumerable false :get (constantly page-id)}
{:name "absolute" :absolute
{:this true
:get #(-> % u/proxy->shape :layout-item-absolute boolean) :get #(-> % u/proxy->shape :layout-item-absolute boolean)
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (boolean? value)) (not (boolean? value))
(u/display-not-valid :absolute value) (u/display-not-valid :absolute value)
@ -294,13 +288,13 @@
(u/display-not-valid :absolute "Plugin doesn't have 'content:write' permission") (u/display-not-valid :absolute "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout #{id} {:layout-item-absolute value}))))}
(st/emit! (dwsl/update-layout #{id} {:layout-item-absolute value})))))}
{:name "zIndex" :zIndex
{:this true
:get #(-> % u/proxy->shape :layout-item-z-index (d/nilv 0)) :get #(-> % u/proxy->shape :layout-item-z-index (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(us/safe-int? value) (us/safe-int? value)
(u/display-not-valid :zIndex value) (u/display-not-valid :zIndex value)
@ -309,13 +303,13 @@
(u/display-not-valid :zIndex "Plugin doesn't have 'content:write' permission") (u/display-not-valid :zIndex "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-z-index value}))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-z-index value})))))}
{:name "horizontalSizing" :horizontalSizing
{:this true
:get #(-> % u/proxy->shape :layout-item-h-sizing (d/nilv :fix) d/name) :get #(-> % u/proxy->shape :layout-item-h-sizing (d/nilv :fix) d/name)
:set :set
(fn [self value] (fn [_ value]
(let [value (keyword value)] (let [value (keyword value)]
(cond (cond
(not (contains? ctl/item-h-sizing-types value)) (not (contains? ctl/item-h-sizing-types value))
@ -325,13 +319,13 @@
(u/display-not-valid :horizontalPadding "Plugin doesn't have 'content:write' permission") (u/display-not-valid :horizontalPadding "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-h-sizing value})))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-h-sizing value}))))))}
{:name "verticalSizing" :verticalSizing
{:this true
:get #(-> % u/proxy->shape :layout-item-v-sizing (d/nilv :fix) d/name) :get #(-> % u/proxy->shape :layout-item-v-sizing (d/nilv :fix) d/name)
:set :set
(fn [self value] (fn [_ value]
(let [value (keyword value)] (let [value (keyword value)]
(cond (cond
(not (contains? ctl/item-v-sizing-types value)) (not (contains? ctl/item-v-sizing-types value))
@ -341,13 +335,13 @@
(u/display-not-valid :verticalSizing "Plugin doesn't have 'content:write' permission") (u/display-not-valid :verticalSizing "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-v-sizing value})))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-v-sizing value}))))))}
{:name "alignSelf" :alignSelf
{:this true
:get #(-> % u/proxy->shape :layout-item-align-self (d/nilv :auto) d/name) :get #(-> % u/proxy->shape :layout-item-align-self (d/nilv :auto) d/name)
:set :set
(fn [self value] (fn [_ value]
(let [value (keyword value)] (let [value (keyword value)]
(cond (cond
(not (contains? ctl/item-align-self-types value)) (not (contains? ctl/item-align-self-types value))
@ -357,13 +351,13 @@
(u/display-not-valid :alignSelf "Plugin doesn't have 'content:write' permission") (u/display-not-valid :alignSelf "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-align-self value})))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-align-self value}))))))}
{:name "verticalMargin" :verticalMargin
{:this true
:get #(-> % u/proxy->shape :layout-item-margin :m1 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-item-margin :m1 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :verticalMargin value) (u/display-not-valid :verticalMargin value)
@ -372,13 +366,13 @@
(u/display-not-valid :verticalMargin "Plugin doesn't have 'content:write' permission") (u/display-not-valid :verticalMargin "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m1 value :m3 value}}))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m1 value :m3 value}})))))}
{:name "horizontalMargin" :horizontalMargin
{:this true
:get #(-> % u/proxy->shape :layout-item-margin :m2 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-item-margin :m2 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :horizontalMargin value) (u/display-not-valid :horizontalMargin value)
@ -387,13 +381,13 @@
(u/display-not-valid :horizontalMargin "Plugin doesn't have 'content:write' permission") (u/display-not-valid :horizontalMargin "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m2 value :m4 value}}))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m2 value :m4 value}})))))}
{:name "topMargin" :topMargin
{:this true
:get #(-> % u/proxy->shape :layout-item-margin :m1 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-item-margin :m1 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :topMargin value) (u/display-not-valid :topMargin value)
@ -402,13 +396,13 @@
(u/display-not-valid :topMargin "Plugin doesn't have 'content:write' permission") (u/display-not-valid :topMargin "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m1 value}}))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m1 value}})))))}
{:name "rightMargin" :rightMargin
{:this true
:get #(-> % u/proxy->shape :layout-item-margin :m2 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-item-margin :m2 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :rightMargin value) (u/display-not-valid :rightMargin value)
@ -417,13 +411,13 @@
(u/display-not-valid :rightMargin "Plugin doesn't have 'content:write' permission") (u/display-not-valid :rightMargin "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m2 value}}))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m2 value}})))))}
{:name "bottomMargin" :bottomMargin
{:this true
:get #(-> % u/proxy->shape :layout-item-margin :m3 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-item-margin :m3 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :bottomMargin value) (u/display-not-valid :bottomMargin value)
@ -432,13 +426,13 @@
(u/display-not-valid :bottomMargin "Plugin doesn't have 'content:write' permission") (u/display-not-valid :bottomMargin "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m3 value}}))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m3 value}})))))}
{:name "leftMargin" :leftMargin
{:this true
:get #(-> % u/proxy->shape :layout-item-margin :m4 (d/nilv 0)) :get #(-> % u/proxy->shape :layout-item-margin :m4 (d/nilv 0))
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :leftMargin value) (u/display-not-valid :leftMargin value)
@ -447,13 +441,13 @@
(u/display-not-valid :leftMargin "Plugin doesn't have 'content:write' permission") (u/display-not-valid :leftMargin "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m4 value}}))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-margin {:m4 value}})))))}
{:name "maxWidth" :maxWidth
{:this true
:get #(-> % u/proxy->shape :layout-item-max-w) :get #(-> % u/proxy->shape :layout-item-max-w)
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :maxWidth value) (u/display-not-valid :maxWidth value)
@ -462,13 +456,13 @@
(u/display-not-valid :maxWidth "Plugin doesn't have 'content:write' permission") (u/display-not-valid :maxWidth "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-max-w value}))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-max-w value})))))}
{:name "minWidth" :minWidth
{:this true
:get #(-> % u/proxy->shape :layout-item-min-w) :get #(-> % u/proxy->shape :layout-item-min-w)
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :minWidth value) (u/display-not-valid :minWidth value)
@ -477,13 +471,13 @@
(u/display-not-valid :minWidth "Plugin doesn't have 'content:write' permission") (u/display-not-valid :minWidth "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-min-w value}))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-min-w value})))))}
{:name "maxHeight" :maxHeight
{:this true
:get #(-> % u/proxy->shape :layout-item-max-h) :get #(-> % u/proxy->shape :layout-item-max-h)
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :maxHeight value) (u/display-not-valid :maxHeight value)
@ -492,13 +486,13 @@
(u/display-not-valid :maxHeight "Plugin doesn't have 'content:write' permission") (u/display-not-valid :maxHeight "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-max-h value}))))}
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-max-h value})))))}
{:name "minHeight" :minHeight
{:this true
:get #(-> % u/proxy->shape :layout-item-min-h) :get #(-> % u/proxy->shape :layout-item-min-h)
:set :set
(fn [self value] (fn [_ value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :minHeight value) (u/display-not-valid :minHeight value)
@ -507,5 +501,4 @@
(u/display-not-valid :minHeight "Plugin doesn't have 'content:write' permission") (u/display-not-valid :minHeight "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (obj/get self "$id")] (st/emit! (dwsl/update-layout-child #{id} {:layout-item-min-h value}))))}))
(st/emit! (dwsl/update-layout-child #{id} {:layout-item-min-h value})))))})))

View file

@ -7,10 +7,10 @@
(ns app.plugins.fonts (ns app.plugins.fonts
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.record :as cr]
[app.main.data.workspace.texts :as dwt] [app.main.data.workspace.texts :as dwt]
[app.main.fonts :as fonts] [app.main.fonts :as fonts]
[app.main.store :as st] [app.main.store :as st]
[app.plugins.format :as format]
[app.plugins.register :as r] [app.plugins.register :as r]
[app.plugins.shape :as shape] [app.plugins.shape :as shape]
[app.plugins.text :as text] [app.plugins.text :as text]
@ -18,15 +18,41 @@
[app.util.object :as obj] [app.util.object :as obj]
[cuerdas.core :as str])) [cuerdas.core :as str]))
(deftype PenpotFontVariant [name fontVariantId fontWeight fontStyle]) (defn font-variant-proxy? [p]
(obj/type-of? p "FontVariantProxy"))
(defn variant-proxy? [p] (defn font-variant-proxy [name id weight style]
(instance? PenpotFontVariant p)) (obj/reify {:name "FontVariantProxy"}
:name {:get (fn [] name)}
:fontVariantId {:get (fn [] id)}
:fontWeight {:get (fn [] weight)}
:fontStyle {:get (fn [] style)}))
(deftype PenpotFont [name fontId fontFamily fontStyle fontVariantId fontWeight variants] (defn font-proxy? [p]
Object (obj/type-of? p "FontProxy"))
(applyToText [_ text variant] (defn font-proxy
[{:keys [id family name variants] :as font}]
(when (some? font)
(let [default-variant (fonts/get-default-variant font)]
(obj/reify {:name "FontProxy"}
:name {:get (fn [] name)}
:fontId {:get (fn [] id)}
:fontFamily {:get (fn [] family)}
:fontStyle {:get (fn [] (:style default-variant))}
:fontVariantId {:get (fn [] (:id default-variant))}
:fontWeight {:get (fn [] (:weight default-variant))}
:variants
{:get
(fn []
(format/format-array
(fn [{:keys [id name style weight]}]
(font-variant-proxy name id weight style))
variants))}
:applyToText
(fn [text variant]
(cond (cond
(not (shape/shape-proxy? text)) (not (shape/shape-proxy? text))
(u/display-not-valid :applyToText text) (u/display-not-valid :applyToText text)
@ -36,16 +62,17 @@
:else :else
(let [id (obj/get text "$id") (let [id (obj/get text "$id")
values {:font-id fontId values {:font-id id
:font-family fontFamily :font-family family
:font-style (d/nilv (obj/get variant "fontStyle") fontStyle) :font-style (d/nilv (obj/get variant "fontStyle") (:style default-variant))
:font-variant-id (d/nilv (obj/get variant "fontVariantId") fontVariantId) :font-variant-id (d/nilv (obj/get variant "fontVariantId") (:id default-variant))
:font-weight (d/nilv (obj/get variant "fontWeight") fontWeight)}] :font-weight (d/nilv (obj/get variant "fontWeight") (:wegith default-variant))}]
(st/emit! (dwt/update-attrs id values))))) (st/emit! (dwt/update-attrs id values)))))
(applyToRange [_ range variant] :applyToRange
(fn [range variant]
(cond (cond
(not (text/text-range? range)) (not (text/text-range-proxy? range))
(u/display-not-valid :applyToRange range) (u/display-not-valid :applyToRange range)
(not (r/check-permission (obj/get range "$plugin") "content:write")) (not (r/check-permission (obj/get range "$plugin") "content:write"))
@ -55,80 +82,69 @@
(let [id (obj/get range "$id") (let [id (obj/get range "$id")
start (obj/get range "start") start (obj/get range "start")
end (obj/get range "end") end (obj/get range "end")
values {:font-id fontId values {:font-id id
:font-family fontFamily :font-family family
:font-style (d/nilv (obj/get variant "fontStyle") fontStyle) :font-style (d/nilv (obj/get variant "fontStyle") (:style default-variant))
:font-variant-id (d/nilv (obj/get variant "fontVariantId") fontVariantId) :font-variant-id (d/nilv (obj/get variant "fontVariantId") (:id default-variant))
:font-weight (d/nilv (obj/get variant "fontWeight") fontWeight)}] :font-weight (d/nilv (obj/get variant "fontWeight") (:weight default-variant))}]
(st/emit! (dwt/update-text-range id start end values)))))) (st/emit! (dwt/update-text-range id start end values)))))))))
(defn font-proxy? [p] (defn fonts-subcontext
(instance? PenpotFont p)) [plugin-id]
(obj/reify {:name "PenpotFontsSubcontext"}
:$plugin {:name "" :enumerable false :get (constantly plugin-id)}
(defn font-proxy :all
[{:keys [id family name variants] :as font}] {:get
(when (some? font) (fn []
(let [default-variant (fonts/get-default-variant font)] (format/format-array
(PenpotFont. font-proxy
name (vals @fonts/fontsdb)))}
id
family
(:style default-variant)
(:id default-variant)
(:weight default-variant)
(apply
array
(->> variants
(map (fn [{:keys [id name style weight]}]
(PenpotFontVariant. name id weight style)))))))))
(deftype PenpotFontsSubcontext [$plugin] :findById
Object (fn [id]
(findById
[_ id]
(cond (cond
(not (string? id)) (not (string? id))
(u/display-not-valid :findbyId id) (u/display-not-valid :findbyId id)
:else :else
(font-proxy (d/seek #(str/includes? (str/lower (:id %)) (str/lower id)) (vals @fonts/fontsdb))))) (->> (vals @fonts/fontsdb)
(d/seek #(str/includes? (str/lower (:id %)) (str/lower id)))
(font-proxy))))
(findByName :findByName
[_ name] (fn [name]
(cond (cond
(not (string? name)) (not (string? name))
(u/display-not-valid :findByName name) (u/display-not-valid :findByName name)
:else :else
(font-proxy (d/seek #(str/includes? (str/lower (:name %)) (str/lower name)) (vals @fonts/fontsdb))))) (->> (vals @fonts/fontsdb)
(d/seek #(str/includes? (str/lower (:name %)) (str/lower name)))
(font-proxy))))
(findAllById :findAllById
[_ id] (fn [id]
(cond (cond
(not (string? id)) (not (string? id))
(u/display-not-valid :findAllById name) (u/display-not-valid :findAllById name)
:else :else
(apply array (->> (vals @fonts/fontsdb) (format/format-array
(filter #(str/includes? (str/lower (:id %)) (str/lower id))) (fn [font]
(map font-proxy))))) (when (str/includes? (str/lower (:id font)) (str/lower id))
(font-proxy font)))
(vals @fonts/fontsdb))))
(findAllByName :findAllByName
[_ name] (fn [name]
(cond (cond
(not (string? name)) (not (string? name))
(u/display-not-valid :findAllByName name) (u/display-not-valid :findAllByName name)
:else :else
(apply array (->> (vals @fonts/fontsdb) (format/format-array
(filter #(str/includes? (str/lower (:name %)) (str/lower name))) (fn [font]
(map font-proxy)))))) (when (str/includes? (str/lower (:name font)) (str/lower name))
(font-proxy font)))
(defn fonts-subcontext (vals @fonts/fontsdb))))))
[plugin-id]
(cr/add-properties!
(PenpotFontsSubcontext. plugin-id)
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "all" :get
(fn [_]
(apply array (->> @fonts/fontsdb vals (map font-proxy))))}))

View file

@ -7,7 +7,6 @@
(ns app.plugins.grid (ns app.plugins.grid
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.record :as crc]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.types.shape.layout :as ctl] [app.common.types.shape.layout :as ctl]
[app.main.data.workspace.shape-layout :as dwsl] [app.main.data.workspace.shape-layout :as dwsl]
@ -22,11 +21,227 @@
;; Define in `app.plugins.shape` we do this way to prevent circular dependency ;; Define in `app.plugins.shape` we do this way to prevent circular dependency
(def shape-proxy? nil) (def shape-proxy? nil)
(deftype GridLayout [$plugin $file $page $id] (defn grid-layout-proxy? [p]
Object (obj/type-of? p "GridLayoutProxy"))
(addRow (defn grid-layout-proxy
[_ type value] [plugin-id file-id page-id id]
(obj/reify {:name "GridLayoutProxy"}
:$plugin {:enumerable false :get (constantly plugin-id)}
:$id {:enumerable false :get (constantly id)}
:$file {:enumerable false :get (constantly file-id)}
:$page {:enumerable false :get (constantly page-id)}
:dir
{:this true
:get #(-> % u/proxy->shape :layout-grid-dir d/name)
:set
(fn [_ value]
(let [value (keyword value)]
(cond
(not (contains? ctl/grid-direction-types value))
(u/display-not-valid :dir value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :dir "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-grid-dir value})))))}
:rows
{:this true
:get #(-> % u/proxy->shape :layout-grid-rows format/format-tracks)}
:columns
{:this true
:get #(-> % u/proxy->shape :layout-grid-columns format/format-tracks)}
:alignItems
{:this true
:get #(-> % u/proxy->shape :layout-align-items d/name)
:set
(fn [_ value]
(let [value (keyword value)]
(cond
(not (contains? ctl/align-items-types value))
(u/display-not-valid :alignItems value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :alignItems "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-align-items value})))))}
:alignContent
{:this true
:get #(-> % u/proxy->shape :layout-align-content d/name)
:set
(fn [_ value]
(let [value (keyword value)]
(cond
(not (contains? ctl/align-content-types value))
(u/display-not-valid :alignContent value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :alignContent "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-align-content value})))))}
:justifyItems
{:this true
:get #(-> % u/proxy->shape :layout-justify-items d/name)
:set
(fn [_ value]
(let [value (keyword value)]
(cond
(not (contains? ctl/justify-items-types value))
(u/display-not-valid :justifyItems value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :justifyItems "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-justify-items value})))))}
:justifyContent
{:this true
:get #(-> % u/proxy->shape :layout-justify-content d/name)
:set
(fn [_ value]
(let [value (keyword value)]
(cond
(not (contains? ctl/justify-content-types value))
(u/display-not-valid :justifyContent value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :justifyContent "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-justify-content value})))))}
:rowGap
{:this true
:get #(-> % u/proxy->shape :layout-gap :row-gap (d/nilv 0))
:set
(fn [_ value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :rowGap value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :rowGap "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-gap {:row-gap value}}))))}
:columnGap
{:this true
:get #(-> % u/proxy->shape :layout-gap :column-gap (d/nilv 0))
:set
(fn [_ value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :columnGap value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :columnGap "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-gap {:column-gap value}}))))}
:verticalPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p1 (d/nilv 0))
:set
(fn [_ value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :verticalPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :verticalPadding "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value :p3 value}}))))}
:horizontalPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p2 (d/nilv 0))
:set
(fn [_ value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :horizontalPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :horizontalPadding "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}}))))}
:topPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p1 (d/nilv 0))
:set
(fn [_ value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :topPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :topPadding "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value}}))))}
:rightPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p2 (d/nilv 0))
:set
(fn [_ value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :rightPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :righPadding "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value}}))))}
:bottomPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p3 (d/nilv 0))
:set
(fn [_ value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :bottomPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :bottomPadding "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p3 value}}))))}
:leftPadding
{:this true
:get #(-> % u/proxy->shape :layout-padding :p4 (d/nilv 0))
:set
(fn [_ value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :leftPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :leftPadding "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}}))))}
:addRow
(fn [type value]
(let [type (keyword type)] (let [type (keyword type)]
(cond (cond
(not (contains? ctl/grid-track-types type)) (not (contains? ctl/grid-track-types type))
@ -36,14 +251,14 @@
(not (us/safe-number? value))) (not (us/safe-number? value)))
(u/display-not-valid :addRow-value value) (u/display-not-valid :addRow-value value)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :addRow "Plugin doesn't have 'content:write' permission") (u/display-not-valid :addRow "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwsl/add-layout-track #{$id} :row {:type type :value value}))))) (st/emit! (dwsl/add-layout-track #{id} :row {:type type :value value})))))
(addRowAtIndex :addRowAtIndex
[_ index type value] (fn [index type value]
(let [type (keyword type)] (let [type (keyword type)]
(cond (cond
(not (us/safe-int? index)) (not (us/safe-int? index))
@ -56,14 +271,14 @@
(not (us/safe-number? value))) (not (us/safe-number? value)))
(u/display-not-valid :addRowAtIndex-value value) (u/display-not-valid :addRowAtIndex-value value)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :addRowAtIndex "Plugin doesn't have 'content:write' permission") (u/display-not-valid :addRowAtIndex "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwsl/add-layout-track #{$id} :row {:type type :value value} index))))) (st/emit! (dwsl/add-layout-track #{id} :row {:type type :value value} index)))))
(addColumn :addColumn
[_ type value] (fn [type value]
(let [type (keyword type)] (let [type (keyword type)]
(cond (cond
(not (contains? ctl/grid-track-types type)) (not (contains? ctl/grid-track-types type))
@ -73,14 +288,14 @@
(not (us/safe-number? value))) (not (us/safe-number? value)))
(u/display-not-valid :addColumn-value value) (u/display-not-valid :addColumn-value value)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :addColumn "Plugin doesn't have 'content:write' permission") (u/display-not-valid :addColumn "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwsl/add-layout-track #{$id} :column {:type type :value value}))))) (st/emit! (dwsl/add-layout-track #{id} :column {:type type :value value})))))
(addColumnAtIndex :addColumnAtIndex
[_ index type value] (fn [index type value]
(cond (cond
(not (us/safe-int? index)) (not (us/safe-int? index))
(u/display-not-valid :addColumnAtIndex-index index) (u/display-not-valid :addColumnAtIndex-index index)
@ -92,39 +307,39 @@
(not (us/safe-number? value))) (not (us/safe-number? value)))
(u/display-not-valid :addColumnAtIndex-value value) (u/display-not-valid :addColumnAtIndex-value value)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :addColumnAtIndex "Plugin doesn't have 'content:write' permission") (u/display-not-valid :addColumnAtIndex "Plugin doesn't have 'content:write' permission")
:else :else
(let [type (keyword type)] (let [type (keyword type)]
(st/emit! (dwsl/add-layout-track #{$id} :column {:type type :value value} index))))) (st/emit! (dwsl/add-layout-track #{id} :column {:type type :value value} index)))))
(removeRow :removeRow
[_ index] (fn [index]
(cond (cond
(not (us/safe-int? index)) (not (us/safe-int? index))
(u/display-not-valid :removeRow index) (u/display-not-valid :removeRow index)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :removeRow "Plugin doesn't have 'content:write' permission") (u/display-not-valid :removeRow "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwsl/remove-layout-track #{$id} :row index)))) (st/emit! (dwsl/remove-layout-track #{id} :row index))))
(removeColumn :removeColumn
[_ index] (fn [index]
(cond (cond
(not (us/safe-int? index)) (not (us/safe-int? index))
(u/display-not-valid :removeColumn index) (u/display-not-valid :removeColumn index)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :removeColumn "Plugin doesn't have 'content:write' permission") (u/display-not-valid :removeColumn "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwsl/remove-layout-track #{$id} :column index)))) (st/emit! (dwsl/remove-layout-track #{id} :column index))))
(setColumn :setColumn
[_ index type value] (fn [index type value]
(let [type (keyword type)] (let [type (keyword type)]
(cond (cond
(not (us/safe-int? index)) (not (us/safe-int? index))
@ -137,14 +352,14 @@
(not (us/safe-number? value))) (not (us/safe-number? value)))
(u/display-not-valid :setColumn-value value) (u/display-not-valid :setColumn-value value)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :setColumn "Plugin doesn't have 'content:write' permission") (u/display-not-valid :setColumn "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwsl/change-layout-track #{$id} :column index (d/without-nils {:type type :value value})))))) (st/emit! (dwsl/change-layout-track #{id} :column index (d/without-nils {:type type :value value}))))))
(setRow :setRow
[_ index type value] (fn [index type value]
(let [type (keyword type)] (let [type (keyword type)]
(cond (cond
(not (us/safe-int? index)) (not (us/safe-int? index))
@ -157,23 +372,23 @@
(not (us/safe-number? value))) (not (us/safe-number? value)))
(u/display-not-valid :setRow-value value) (u/display-not-valid :setRow-value value)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :setRow "Plugin doesn't have 'content:write' permission") (u/display-not-valid :setRow "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwsl/change-layout-track #{$id} :row index (d/without-nils {:type type :value value})))))) (st/emit! (dwsl/change-layout-track #{id} :row index (d/without-nils {:type type :value value}))))))
(remove :remove
[_] (fn []
(cond (cond
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :remove "Plugin doesn't have 'content:write' permission") (u/display-not-valid :remove "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwsl/remove-layout #{$id})))) (st/emit! (dwsl/remove-layout #{id}))))
(appendChild :appendChild
[_ child row column] (fn [child row column]
(cond (cond
(not (shape-proxy? child)) (not (shape-proxy? child))
(u/display-not-valid :appendChild-child child) (u/display-not-valid :appendChild-child child)
@ -184,236 +399,16 @@
(or (< column 0) (not (us/safe-int? column))) (or (< column 0) (not (us/safe-int? column)))
(u/display-not-valid :appendChild-column column) (u/display-not-valid :appendChild-column column)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :appendChild "Plugin doesn't have 'content:write' permission") (u/display-not-valid :appendChild "Plugin doesn't have 'content:write' permission")
:else :else
(let [child-id (obj/get child "$id")] (let [child-id (obj/get child "$id")]
(st/emit! (dwt/move-shapes-to-frame #{child-id} $id nil [row column]) (st/emit! (dwt/move-shapes-to-frame #{child-id} id nil [row column])
(ptk/data-event :layout/update {:ids [$id]})))))) (ptk/data-event :layout/update {:ids [id]})))))))
(defn grid-layout-proxy? [p]
(instance? GridLayout p))
(defn grid-layout-proxy
[plugin-id file-id page-id id]
(-> (GridLayout. plugin-id file-id page-id id)
(crc/add-properties!
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)}
{:name "$page" :enumerable false :get (constantly page-id)}
{:name "dir"
:get #(-> % u/proxy->shape :layout-grid-dir d/name)
:set
(fn [self value]
(let [value (keyword value)]
(cond
(not (contains? ctl/grid-direction-types value))
(u/display-not-valid :dir value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :dir "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-grid-dir value}))))))}
{:name "rows"
:get #(-> % u/proxy->shape :layout-grid-rows format/format-tracks)}
{:name "columns"
:get #(-> % u/proxy->shape :layout-grid-columns format/format-tracks)}
{:name "alignItems"
:get #(-> % u/proxy->shape :layout-align-items d/name)
:set
(fn [self value]
(let [value (keyword value)]
(cond
(not (contains? ctl/align-items-types value))
(u/display-not-valid :alignItems value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :alignItems "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-align-items value}))))))}
{:name "alignContent"
:get #(-> % u/proxy->shape :layout-align-content d/name)
:set
(fn [self value]
(let [value (keyword value)]
(cond
(not (contains? ctl/align-content-types value))
(u/display-not-valid :alignContent value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :alignContent "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-align-content value}))))))}
{:name "justifyItems"
:get #(-> % u/proxy->shape :layout-justify-items d/name)
:set
(fn [self value]
(let [value (keyword value)]
(cond
(not (contains? ctl/justify-items-types value))
(u/display-not-valid :justifyItems value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :justifyItems "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-justify-items value}))))))}
{:name "justifyContent"
:get #(-> % u/proxy->shape :layout-justify-content d/name)
:set
(fn [self value]
(let [value (keyword value)]
(cond
(not (contains? ctl/justify-content-types value))
(u/display-not-valid :justifyContent value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :justifyContent "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-justify-content value}))))))}
{:name "rowGap"
:get #(-> % u/proxy->shape :layout-gap :row-gap (d/nilv 0))
:set
(fn [self value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :rowGap value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :rowGap "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-gap {:row-gap value}})))))}
{:name "columnGap"
:get #(-> % u/proxy->shape :layout-gap :column-gap (d/nilv 0))
:set
(fn [self value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :columnGap value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :columnGap "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-gap {:column-gap value}})))))}
{:name "verticalPadding"
:get #(-> % u/proxy->shape :layout-padding :p1 (d/nilv 0))
:set
(fn [self value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :verticalPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :verticalPadding "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value :p3 value}})))))}
{:name "horizontalPadding"
:get #(-> % u/proxy->shape :layout-padding :p2 (d/nilv 0))
:set
(fn [self value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :horizontalPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :horizontalPadding "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value :p4 value}})))))}
{:name "topPadding"
:get #(-> % u/proxy->shape :layout-padding :p1 (d/nilv 0))
:set
(fn [self value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :topPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :topPadding "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p1 value}})))))}
{:name "rightPadding"
:get #(-> % u/proxy->shape :layout-padding :p2 (d/nilv 0))
:set
(fn [self value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :rightPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :righPadding "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p2 value}})))))}
{:name "bottomPadding"
:get #(-> % u/proxy->shape :layout-padding :p3 (d/nilv 0))
:set
(fn [self value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :bottomPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :bottomPadding "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p3 value}})))))}
{:name "leftPadding"
:get #(-> % u/proxy->shape :layout-padding :p4 (d/nilv 0))
:set
(fn [self value]
(cond
(not (us/safe-int? value))
(u/display-not-valid :leftPadding value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :leftPadding "Plugin doesn't have 'content:write' permission")
:else
(let [id (obj/get self "$id")]
(st/emit! (dwsl/update-layout #{id} {:layout-padding {:p4 value}})))))})))
(deftype GridCellProxy [$plugin $file $page $id])
(defn layout-cell-proxy? [p] (defn layout-cell-proxy? [p]
(instance? GridCellProxy p)) (obj/type-of? p "GridCellProxy"))
(defn layout-cell-proxy (defn layout-cell-proxy
[plugin-id file-id page-id id] [plugin-id file-id page-id id]
@ -422,14 +417,14 @@
parent (u/locate-shape file-id page-id (:parent-id shape))] parent (u/locate-shape file-id page-id (:parent-id shape))]
(ctl/get-cell-by-shape-id parent id)))] (ctl/get-cell-by-shape-id parent id)))]
(-> (GridCellProxy. plugin-id file-id page-id id) (obj/reify {:name "GridCellProxy"}
(crc/add-properties! :$plugin {:enumerable false :get (constantly plugin-id)}
{:name "$plugin" :enumerable false :get (constantly plugin-id)} :$id {:enumerable false :get (constantly id)}
{:name "$id" :enumerable false :get (constantly id)} :$file {:enumerable false :get (constantly file-id)}
{:name "$file" :enumerable false :get (constantly file-id)} :$page {:enumerable false :get (constantly page-id)}
{:name "$page" :enumerable false :get (constantly page-id)}
{:name "row" :row
{:this true
:get #(-> % locate-cell :row) :get #(-> % locate-cell :row)
:set :set
(fn [self value] (fn [self value]
@ -448,7 +443,8 @@
:else :else
(st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:row value})))))} (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:row value})))))}
{:name "rowSpan" :rowSpan
{:this true
:get #(-> % locate-cell :row-span) :get #(-> % locate-cell :row-span)
:set :set
(fn [self value] (fn [self value]
@ -467,7 +463,8 @@
:else :else
(st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:row-span value})))))} (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:row-span value})))))}
{:name "column" :column
{:this true
:get #(-> % locate-cell :column) :get #(-> % locate-cell :column)
:set :set
(fn [self value] (fn [self value]
@ -486,7 +483,8 @@
:else :else
(st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:column value})))))} (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:column value})))))}
{:name "columnSpan" :columnSpan
{:this true
:get #(-> % locate-cell :column-span) :get #(-> % locate-cell :column-span)
:set :set
(fn [self value] (fn [self value]
@ -505,7 +503,8 @@
:else :else
(st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:column-span value})))))} (st/emit! (dwsl/update-grid-cell-position (:parent-id shape) (:id cell) {:column-span value})))))}
{:name "areaName" :areaName
{:this true
:get #(-> % locate-cell :area-name) :get #(-> % locate-cell :area-name)
:set :set
(fn [self value] (fn [self value]
@ -524,7 +523,8 @@
:else :else
(st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:area-name value})))))} (st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:area-name value})))))}
{:name "position" :position
{:this true
:get #(-> % locate-cell :position d/name) :get #(-> % locate-cell :position d/name)
:set :set
(fn [self value] (fn [self value]
@ -544,7 +544,8 @@
:else :else
(st/emit! (dwsl/change-cells-mode (:parent-id shape) #{(:id cell)} value)))))} (st/emit! (dwsl/change-cells-mode (:parent-id shape) #{(:id cell)} value)))))}
{:name "alignSelf" :alignSelf
{:this true
:get #(-> % locate-cell :align-self d/name) :get #(-> % locate-cell :align-self d/name)
:set :set
(fn [self value] (fn [self value]
@ -564,7 +565,8 @@
:else :else
(st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:align-self value})))))} (st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:align-self value})))))}
{:name "justifySelf" :justifySelf
{:this true
:get #(-> % locate-cell :justify-self d/name) :get #(-> % locate-cell :justify-self d/name)
:set :set
(fn [self value] (fn [self value]
@ -582,4 +584,4 @@
(u/display-not-valid :justifySelf "Plugin doesn't have 'content:write' permission") (u/display-not-valid :justifySelf "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:justify-self value})))))})))) (st/emit! (dwsl/update-grid-cells (:parent-id shape) #{(:id cell)} {:justify-self value})))))})))

View file

@ -6,18 +6,24 @@
(ns app.plugins.history (ns app.plugins.history
(:require (:require
[app.common.record :as crc]
[app.main.data.workspace.undo :as dwu] [app.main.data.workspace.undo :as dwu]
[app.main.store :as st] [app.main.store :as st]
[app.plugins.register :as r] [app.plugins.register :as r]
[app.plugins.utils :as u])) [app.plugins.utils :as u]
[app.util.object :as obj]))
(deftype HistorySubcontext [$plugin] (defn history-subcontext? [p]
Object (obj/type-of? p "HistorySubcontext"))
(undoBlockBegin
[_] (defn history-subcontext
[plugin-id]
(obj/reify {:name "HistorySubcontext"}
:$plugin {:enumerable false :get (fn [] plugin-id)}
:undoBlockBegin
(fn []
(cond (cond
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :resize "Plugin doesn't have 'content:write' permission") (u/display-not-valid :resize "Plugin doesn't have 'content:write' permission")
:else :else
@ -25,28 +31,16 @@
(st/emit! (dwu/start-undo-transaction id)) (st/emit! (dwu/start-undo-transaction id))
id))) id)))
(undoBlockFinish :undoBlockFinish
[_ block-id] (fn [block-id]
(cond (cond
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :resize "Plugin doesn't have 'content:write' permission") (u/display-not-valid :resize "Plugin doesn't have 'content:write' permission")
(not block-id) (not block-id)
(u/display-not-valid :undoBlockFinish block-id) (u/display-not-valid :undoBlockFinish block-id)
:else :else
(st/emit! (dwu/commit-undo-transaction block-id))))) (st/emit! (dwu/commit-undo-transaction block-id))))))
(crc/define-properties!
HistorySubcontext
{:name js/Symbol.toStringTag
:get (fn [] (str "HistorySubcontext"))})
(defn history-subcontext? [p]
(instance? HistorySubcontext p))
(defn history-subcontext
[plugin-id]
(HistorySubcontext. plugin-id))

File diff suppressed because it is too large Load diff

View file

@ -11,7 +11,6 @@
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.files.helpers :as cfh] [app.common.files.helpers :as cfh]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.record :as crc]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.data.comments :as dc] [app.main.data.comments :as dc]
@ -31,25 +30,27 @@
[beicon.v2.core :as rx] [beicon.v2.core :as rx]
[cuerdas.core :as str])) [cuerdas.core :as str]))
(deftype FlowProxy [$plugin $file $page $id] (declare page-proxy)
Object
(remove [_]
(st/emit! (dwi/remove-flow $page $id))))
(defn flow-proxy? [p] (defn flow-proxy? [p]
(instance? FlowProxy p)) (obj/type-of? p "FlowProxy"))
(defn flow-proxy (defn flow-proxy
[plugin-id file-id page-id id] [plugin-id file-id page-id id]
(crc/add-properties! (obj/reify {:name "FlowProxy"}
(FlowProxy. plugin-id file-id page-id id) :$plugin {:enumerable false :get (fn [] plugin-id)}
{:name "$plugin" :enumerable false :get (constantly plugin-id)} :$file {:enumerable false :get (fn [] file-id)}
{:name "$file" :enumerable false :get (constantly file-id)} :$page {:enumerable false :get (fn [] page-id)}
{:name "$page" :enumerable false :get (constantly page-id)} :$id {:enumerable false :get (fn [] id)}
{:name "$id" :enumerable false :get (constantly id)}
{:name "page" :enumerable false :get (fn [_] (u/locate-page file-id page-id))}
{:name "name" :page
{:enumerable false
:get
(fn []
(page-proxy plugin-id file-id page-id))}
:name
{:this true
:get #(-> % u/proxy->flow :name) :get #(-> % u/proxy->flow :name)
:set :set
(fn [_ value] (fn [_ value]
@ -60,11 +61,12 @@
:else :else
(st/emit! (dwi/update-flow page-id id #(assoc % :name value)))))} (st/emit! (dwi/update-flow page-id id #(assoc % :name value)))))}
{:name "startingBoard" :startingBoard
{:this true
:get :get
(fn [self] (fn [self]
(let [frame (-> self u/proxy->flow :starting-frame)] (when-let [frame (-> self u/proxy->flow :starting-frame)]
(u/locate-shape file-id page-id frame))) (shape/shape-proxy file-id page-id frame)))
:set :set
(fn [_ value] (fn [_ value]
(cond (cond
@ -72,28 +74,97 @@
(u/display-not-valid :startingBoard value) (u/display-not-valid :startingBoard value)
:else :else
(st/emit! (dwi/update-flow page-id id #(assoc % :starting-frame (obj/get value "$id"))))))})) (st/emit! (dwi/update-flow page-id id #(assoc % :starting-frame (obj/get value "$id"))))))}
(deftype PageProxy [$plugin $file $id] :remove
Object (fn []
(getShapeById (st/emit! (dwi/remove-flow page-id id)))))
[_ shape-id]
(defn page-proxy? [proxy]
(obj/type-of? proxy "PageProxy"))
(defn page-proxy
[plugin-id file-id id]
(obj/reify {:name "PageProxy"}
:$plugin {:enumerable false :get (fn [] plugin-id)}
:$file {:enumerable false :get (fn [] file-id)}
:$id {:enumerable false :get (fn [] id)}
:id
{:get #(dm/str id)}
:name
{:this true
:get #(-> % u/proxy->page :name)
:set
(fn [_ value]
(cond
(not (string? value))
(u/display-not-valid :name value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :name "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dw/rename-page id value))))}
:getRoot
(fn []
(shape/shape-proxy plugin-id file-id id uuid/zero))
:root
{:this true
:enumerable false
:get #(.getRoot ^js %)}
:background
{:this true
:get #(or (-> % u/proxy->page :background) cc/canvas)
:set
(fn [_ value]
(cond
(or (not (string? value)) (not (cc/valid-hex-color? value)))
(u/display-not-valid :background value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :background "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dw/change-canvas-color id {:color value}))))}
:flows
{:this true
:get
(fn [self]
(let [flows (d/nilv (-> (u/proxy->page self) :flows) [])]
(->> (vals flows)
(format/format-array #(flow-proxy plugin-id file-id id (:id %))))))}
:rulerGuides
{:this true
:get
(fn [self]
(let [guides (-> (u/proxy->page self) :guides)]
(->> guides
(vals)
(filter #(nil? (:frame-id %)))
(format/format-array #(rg/ruler-guide-proxy plugin-id file-id id (:id %))))))}
:getShapeById
(fn [shape-id]
(cond (cond
(not (string? shape-id)) (not (string? shape-id))
(u/display-not-valid :getShapeById shape-id) (u/display-not-valid :getShapeById shape-id)
:else :else
(let [shape-id (uuid/uuid shape-id) (let [shape-id (uuid/uuid shape-id)
shape (u/locate-shape $file $id shape-id)] shape (u/locate-shape file-id id shape-id)]
(when (some? shape) (when (some? shape)
(shape/shape-proxy $plugin $file $id shape-id))))) (shape/shape-proxy plugin-id file-id id shape-id)))))
(getRoot :findShapes
[_] (fn [criteria]
(shape/shape-proxy $plugin $file $id uuid/zero))
(findShapes
[_ criteria]
;; Returns a lazy (iterable) of all available shapes ;; Returns a lazy (iterable) of all available shapes
(let [criteria (parser/parse-criteria criteria) (let [criteria (parser/parse-criteria criteria)
match-criteria? match-criteria?
@ -109,26 +180,26 @@
(or (not (:type criteria)) (or (not (:type criteria))
(= (:type criteria) (:type shape))))) (= (:type criteria) (:type shape)))))
identity)] identity)]
(when (and (some? $file) (some? $id)) (when (and (some? file-id) (some? id))
(let [page (u/locate-page $file $id) (let [page (u/locate-page file-id id)
xf (comp xf (comp
(filter match-criteria?) (filter match-criteria?)
(map #(shape/shape-proxy $plugin $file $id (first %))))] (map #(shape/shape-proxy plugin-id file-id id (first %))))]
(apply array (sequence xf (:objects page))))))) (apply array (sequence xf (:objects page)))))))
;; Plugin data ;; Plugin data
(getPluginData :getPluginData
[self key] (fn [key]
(cond (cond
(not (string? key)) (not (string? key))
(u/display-not-valid :page-plugin-data-key key) (u/display-not-valid :page-plugin-data-key key)
:else :else
(let [page (u/proxy->page self)] (let [page (u/locate-page file-id id)]
(dm/get-in page [:plugin-data (keyword "plugin" (str $plugin)) key])))) (dm/get-in page [:plugin-data (keyword "plugin" (str plugin-id)) key]))))
(setPluginData :setPluginData
[_ key value] (fn [key value]
(cond (cond
(not (string? key)) (not (string? key))
(u/display-not-valid :setPluginData-key key) (u/display-not-valid :setPluginData-key key)
@ -136,19 +207,19 @@
(and (some? value) (not (string? value))) (and (some? value) (not (string? value)))
(u/display-not-valid :setPluginData-value value) (u/display-not-valid :setPluginData-value value)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :setPluginData "Plugin doesn't have 'content:write' permission") (u/display-not-valid :setPluginData "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dw/set-plugin-data $file :page $id (keyword "plugin" (str $plugin)) key value)))) (st/emit! (dw/set-plugin-data file-id :page id (keyword "plugin" (str plugin-id)) key value))))
(getPluginDataKeys :getPluginDataKeys
[self] (fn []
(let [page (u/proxy->page self)] (let [page (u/locate-page file-id id)]
(apply array (keys (dm/get-in page [:plugin-data (keyword "plugin" (str $plugin))]))))) (apply array (keys (dm/get-in page [:plugin-data (keyword "plugin" (str plugin-id))])))))
(getSharedPluginData :getSharedPluginData
[self namespace key] (fn [namespace key]
(cond (cond
(not (string? namespace)) (not (string? namespace))
(u/display-not-valid :page-plugin-data-namespace namespace) (u/display-not-valid :page-plugin-data-namespace namespace)
@ -157,12 +228,11 @@
(u/display-not-valid :page-plugin-data-key key) (u/display-not-valid :page-plugin-data-key key)
:else :else
(let [page (u/proxy->page self)] (let [page (u/locate-page file-id id)]
(dm/get-in page [:plugin-data (keyword "shared" namespace) key])))) (dm/get-in page [:plugin-data (keyword "shared" namespace) key]))))
(setSharedPluginData :setSharedPluginData
[_ namespace key value] (fn [namespace key value]
(cond (cond
(not (string? namespace)) (not (string? namespace))
(u/display-not-valid :setSharedPluginData-namespace namespace) (u/display-not-valid :setSharedPluginData-namespace namespace)
@ -173,14 +243,14 @@
(and (some? value) (not (string? value))) (and (some? value) (not (string? value)))
(u/display-not-valid :setSharedPluginData-value value) (u/display-not-valid :setSharedPluginData-value value)
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :setSharedPluginData "Plugin doesn't have 'content:write' permission") (u/display-not-valid :setSharedPluginData "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dw/set-plugin-data $file :page $id (keyword "shared" namespace) key value)))) (st/emit! (dw/set-plugin-data file-id :page id (keyword "shared" namespace) key value))))
(getSharedPluginDataKeys :getSharedPluginDataKeys
[self namespace] (fn [self namespace]
(cond (cond
(not (string? namespace)) (not (string? namespace))
(u/display-not-valid :page-plugin-data-namespace namespace) (u/display-not-valid :page-plugin-data-namespace namespace)
@ -189,17 +259,17 @@
(let [page (u/proxy->page self)] (let [page (u/proxy->page self)]
(apply array (keys (dm/get-in page [:plugin-data (keyword "shared" namespace)])))))) (apply array (keys (dm/get-in page [:plugin-data (keyword "shared" namespace)]))))))
(openPage :openPage
[_] (fn []
(cond (cond
(not (r/check-permission $plugin "content:read")) (not (r/check-permission plugin-id "content:read"))
(u/display-not-valid :openPage "Plugin doesn't have 'content:read' permission") (u/display-not-valid :openPage "Plugin doesn't have 'content:read' permission")
:else :else
(st/emit! (dw/go-to-page $id)))) (st/emit! (dw/go-to-page id))))
(createFlow :createFlow
[_ name frame] (fn [name frame]
(cond (cond
(or (not (string? name)) (empty? name)) (or (not (string? name)) (empty? name))
(u/display-not-valid :createFlow-name name) (u/display-not-valid :createFlow-name name)
@ -209,20 +279,20 @@
:else :else
(let [flow-id (uuid/next)] (let [flow-id (uuid/next)]
(st/emit! (dwi/add-flow flow-id $id name (obj/get frame "$id"))) (st/emit! (dwi/add-flow flow-id id name (obj/get frame "$id")))
(flow-proxy $plugin $file $id flow-id)))) (flow-proxy plugin-id file-id id flow-id))))
(removeFlow :removeFlow
[_ flow] (fn [flow]
(cond (cond
(not (flow-proxy? flow)) (not (flow-proxy? flow))
(u/display-not-valid :removeFlow-flow flow) (u/display-not-valid :removeFlow-flow flow)
:else :else
(st/emit! (dwi/remove-flow $id (obj/get flow "$id"))))) (st/emit! (dwi/remove-flow id (obj/get flow "$id")))))
(addRulerGuide :addRulerGuide
[_ orientation value board] (fn [orientation value board]
(let [shape (u/proxy->shape board)] (let [shape (u/proxy->shape board)]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
@ -236,35 +306,35 @@
(not (cfh/frame-shape? shape)))) (not (cfh/frame-shape? shape))))
(u/display-not-valid :addRulerGuide "The shape is not a board") (u/display-not-valid :addRulerGuide "The shape is not a board")
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :addRulerGuide "Plugin doesn't have 'content:write' permission") (u/display-not-valid :addRulerGuide "Plugin doesn't have 'content:write' permission")
:else :else
(let [id (uuid/next)] (let [ruler-id (uuid/next)]
(st/emit! (st/emit!
(dwgu/update-guides (dwgu/update-guides
(d/without-nils (d/without-nils
{:id id {:id ruler-id
:axis (parser/orientation->axis orientation) :axis (parser/orientation->axis orientation)
:position value :position value
:frame-id (when board (obj/get board "$id"))}))) :frame-id (when board (obj/get board "$id"))})))
(rg/ruler-guide-proxy $plugin $file $id id))))) (rg/ruler-guide-proxy plugin-id file-id id ruler-id)))))
(removeRulerGuide :removeRulerGuide
[_ value] (fn [value]
(cond (cond
(not (rg/ruler-guide-proxy? value)) (not (rg/ruler-guide-proxy? value))
(u/display-not-valid :removeRulerGuide "Guide not provided") (u/display-not-valid :removeRulerGuide "Guide not provided")
(not (r/check-permission $plugin "content:write")) (not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :removeRulerGuide "Plugin doesn't have 'comment:write' permission") (u/display-not-valid :removeRulerGuide "Plugin doesn't have 'comment:write' permission")
:else :else
(let [guide (u/proxy->ruler-guide value)] (let [guide (u/proxy->ruler-guide value)]
(st/emit! (dwgu/remove-guide guide))))) (st/emit! (dwgu/remove-guide guide)))))
(addCommentThread :addCommentThread
[_ content position board] (fn [content position board]
(let [shape (when board (u/proxy->shape board)) (let [shape (when board (u/proxy->shape board))
position (parser/parse-point position)] position (parser/parse-point position)]
(cond (cond
@ -278,7 +348,7 @@
(and (some? board) (or (not (shape/shape-proxy? board)) (not (cfh/frame-shape? shape)))) (and (some? board) (or (not (shape/shape-proxy? board)) (not (cfh/frame-shape? shape))))
(u/display-not-valid :addCommentThread "Board not valid") (u/display-not-valid :addCommentThread "Board not valid")
(not (r/check-permission $plugin "comment:write")) (not (r/check-permission plugin-id "comment:write"))
(u/display-not-valid :addCommentThread "Plugin doesn't have 'comment:write' permission") (u/display-not-valid :addCommentThread "Plugin doesn't have 'comment:write' permission")
:else :else
@ -291,26 +361,26 @@
(fn [resolve] (fn [resolve]
(st/emit! (st/emit!
(dc/create-thread-on-workspace (dc/create-thread-on-workspace
{:file-id $file {:file-id file-id
:page-id $id :page-id id
:position (gpt/point position) :position (gpt/point position)
:content content} :content content}
(fn [data] (fn [data]
(->> (rp/cmd! :get-team-users {:file-id $file}) (->> (rp/cmd! :get-team-users {:file-id file-id})
(rx/subs! (rx/subs!
(fn [users] (fn [users]
(let [users (d/index-by :id users)] (let [users (d/index-by :id users)]
(resolve (pc/comment-thread-proxy $plugin $file $id users data))))))) (resolve (pc/comment-thread-proxy plugin-id file-id id users data)))))))
false)))))))) false))))))))
(removeCommentThread :removeCommentThread
[_ thread] (fn [thread]
(cond (cond
(not (pc/comment-thread-proxy? thread)) (not (pc/comment-thread-proxy? thread))
(u/display-not-valid :removeCommentThread "Comment thread not valid") (u/display-not-valid :removeCommentThread "Comment thread not valid")
(not (r/check-permission $plugin "comment:write")) (not (r/check-permission plugin-id "comment:write"))
(u/display-not-valid :removeCommentThread "Plugin doesn't have 'content:write' permission") (u/display-not-valid :removeCommentThread "Plugin doesn't have 'content:write' permission")
:else :else
@ -320,22 +390,22 @@
(js/Promise. (js/Promise.
(st/emit! (dc/delete-comment-thread-on-workspace {:id thread-id} #(resolve))))))))) (st/emit! (dc/delete-comment-thread-on-workspace {:id thread-id} #(resolve)))))))))
(findCommentThreads :findCommentThreads
[_ criteria] (fn [criteria]
(let [only-yours (boolean (obj/get criteria "onlyYours" false)) (let [only-yours (boolean (obj/get criteria "onlyYours" false))
show-resolved (boolean (obj/get criteria "showResolved" true)) show-resolved (boolean (obj/get criteria "showResolved" true))
user-id (-> @st/state :profile :id)] user-id (-> @st/state :profile :id)]
(js/Promise. (js/Promise.
(fn [resolve reject] (fn [resolve reject]
(cond (cond
(not (r/check-permission $plugin "comment:read")) (not (r/check-permission plugin-id "comment:read"))
(do (do
(u/display-not-valid :findCommentThreads "Plugin doesn't have 'comment:read' permission") (u/display-not-valid :findCommentThreads "Plugin doesn't have 'comment:read' permission")
(reject "Plugin doesn't have 'comment:read' permission")) (reject "Plugin doesn't have 'comment:read' permission"))
:else :else
(->> (rx/zip (rp/cmd! :get-team-users {:file-id $file}) (->> (rx/zip (rp/cmd! :get-team-users {:file-id file-id})
(rp/cmd! :get-comment-threads {:file-id $file})) (rp/cmd! :get-comment-threads {:file-id file-id}))
(rx/take 1) (rx/take 1)
(rx/subs! (rx/subs!
(fn [[users comments]] (fn [[users comments]]
@ -349,72 +419,5 @@
(filter #(contains? (:participants %) user-id)))] (filter #(contains? (:participants %) user-id)))]
(resolve (resolve
(format/format-array (format/format-array
#(pc/comment-thread-proxy $plugin $file $id users %) comments)))) #(pc/comment-thread-proxy plugin-id file-id id users %) comments))))
reject)))))))) reject)))))))))
(crc/define-properties!
PageProxy
{:name js/Symbol.toStringTag
:get (fn [] (str "PageProxy"))})
(defn page-proxy? [p]
(instance? PageProxy p))
(defn page-proxy
[plugin-id file-id id]
(crc/add-properties!
(PageProxy. plugin-id file-id id)
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)}
{:name "id"
:get #(dm/str (obj/get % "$id"))}
{:name "name"
:get #(-> % u/proxy->page :name)
:set
(fn [_ value]
(cond
(not (string? value))
(u/display-not-valid :name value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :name "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dw/rename-page id value))))}
{:name "root"
:enumerable false
:get #(.getRoot ^js %)}
{:name "background"
:enumerable false
:get #(or (-> % u/proxy->page :background) cc/canvas)
:set
(fn [_ value]
(cond
(or (not (string? value)) (not (cc/valid-hex-color? value)))
(u/display-not-valid :background value)
(not (r/check-permission plugin-id "content:write"))
(u/display-not-valid :background "Plugin doesn't have 'content:write' permission")
:else
(st/emit! (dw/change-canvas-color id {:color value}))))}
{:name "flows"
:get
(fn [self]
(let [flows (d/nilv (-> (u/proxy->page self) :flows) [])]
(format/format-array #(flow-proxy plugin-id file-id id (:id %)) flows)))}
{:name "rulerGuides"
:get
(fn [self]
(let [guides (-> (u/proxy->page self) :guides)]
(->> guides
(vals)
(filter #(nil? (:frame-id %)))
(format/format-array #(rg/ruler-guide-proxy plugin-id file-id id (:id %))))))}))

View file

@ -45,7 +45,7 @@
(conj "content:read") (conj "content:read")
(contains? permissions "library:write") (contains? permissions "library:write")
(conj "content:write") (conj "library:read")
(contains? permissions "comment:write") (contains? permissions "comment:write")
(conj "comment:read")) (conj "comment:read"))

View file

@ -8,7 +8,6 @@
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.files.helpers :as cfh] [app.common.files.helpers :as cfh]
[app.common.record :as crc]
[app.common.spec :as us] [app.common.spec :as us]
[app.main.data.workspace.guides :as dwgu] [app.main.data.workspace.guides :as dwgu]
[app.main.store :as st] [app.main.store :as st]
@ -20,25 +19,20 @@
(def shape-proxy identity) (def shape-proxy identity)
(def shape-proxy? identity) (def shape-proxy? identity)
(deftype RulerGuideProxy [$plugin $file $page $id]
Object
(remove [self]
(let [guide (u/proxy->ruler-guide self)]
(st/emit! (dwgu/remove-guide guide)))))
(defn ruler-guide-proxy? [p] (defn ruler-guide-proxy? [p]
(instance? RulerGuideProxy p)) (obj/type-of? p "RulerGuideProxy"))
(defn ruler-guide-proxy (defn ruler-guide-proxy
[plugin-id file-id page-id id] [plugin-id file-id page-id id]
(crc/add-properties! (obj/reify {:name "RuleGuideProxy"}
(RulerGuideProxy. plugin-id file-id page-id id) :$plugin {:enumerable false :get (constantly plugin-id)}
{:name "$plugin" :enumerable false :get (constantly plugin-id)} :$file {:enumerable false :get (constantly file-id)}
{:name "$file" :enumerable false :get (constantly file-id)} :$page {:enumerable false :get (constantly page-id)}
{:name "$page" :enumerable false :get (constantly page-id)} :$id {:enumerable false :get (constantly id)}
{:name "$id" :enumerable false :get (constantly id)}
{:name "board" :enumerable false :board
{:this true
:enumerable false
:get :get
(fn [self] (fn [self]
(let [board-id (-> self u/proxy->ruler-guide :frame-id)] (let [board-id (-> self u/proxy->ruler-guide :frame-id)]
@ -63,10 +57,12 @@
guide (-> self u/proxy->ruler-guide)] guide (-> self u/proxy->ruler-guide)]
(st/emit! (dwgu/update-guides (assoc guide :frame-id board-id)))))))} (st/emit! (dwgu/update-guides (assoc guide :frame-id board-id)))))))}
{:name "orientation" :orientation
{:this true
:get #(-> % u/proxy->ruler-guide :axis format/axis->orientation)} :get #(-> % u/proxy->ruler-guide :axis format/axis->orientation)}
{:name "position" :position
{:this true
:get :get
(fn [self] (fn [self]
(let [guide (u/proxy->ruler-guide self)] (let [guide (u/proxy->ruler-guide self)]
@ -96,4 +92,9 @@
(+ board-pos value)) (+ board-pos value))
value)] value)]
(st/emit! (dwgu/update-guides (assoc guide :position position))))))})) (st/emit! (dwgu/update-guides (assoc guide :position position))))))}
:remove
(fn []
(let [guide (u/locate-ruler-guide file-id page-id id)]
(st/emit! (dwgu/remove-guide guide))))))

File diff suppressed because it is too large Load diff

View file

@ -27,21 +27,16 @@
;; This regex seems duplicated but probably in the future when we support diferent units ;; This regex seems duplicated but probably in the future when we support diferent units
;; this will need to reflect changes for each property ;; this will need to reflect changes for each property
(def font-size-re #"^\d*\.?\d*$") (def ^:private font-size-re #"^\d*\.?\d*$")
(def line-height-re #"^\d*\.?\d*$") (def ^:private line-height-re #"^\d*\.?\d*$")
(def letter-spacing-re #"^\d*\.?\d*$") (def ^:private letter-spacing-re #"^\d*\.?\d*$")
(def text-transform-re #"uppercase|capitalize|lowercase|none") (def ^:private text-transform-re #"uppercase|capitalize|lowercase|none")
(def text-decoration-re #"underline|line-through|none") (def ^:private text-decoration-re #"underline|line-through|none")
(def text-direction-re #"ltr|rtl") (def ^:private text-direction-re #"ltr|rtl")
(def text-align-re #"left|center|right|justify") (def ^:private text-align-re #"left|center|right|justify")
(def vertical-align-re #"top|center|bottom") (def ^:private vertical-align-re #"top|center|bottom")
(defn mixed-value (defn- font-data
[values]
(let [s (set values)]
(if (= (count s) 1) (first s) "mixed")))
(defn font-data
[font variant] [font variant]
(d/without-nils (d/without-nils
{:font-id (:id font) {:font-id (:id font)
@ -50,55 +45,51 @@
:font-style (:style variant) :font-style (:style variant)
:font-weight (:weight variant)})) :font-weight (:weight variant)}))
(defn variant-data (defn- variant-data
[variant] [variant]
(d/without-nils (d/without-nils
{:font-variant-id (:id variant) {:font-variant-id (:id variant)
:font-style (:style variant) :font-style (:style variant)
:font-weight (:weight variant)})) :font-weight (:weight variant)}))
(deftype TextRange [$plugin $file $page $id start end] (defn- text-props
Object
(applyTypography [_ typography]
(let [typography (u/proxy->library-typography typography)
attrs (-> typography
(assoc :typography-ref-file $file)
(assoc :typography-ref-id (:id typography))
(dissoc :id :name))]
(st/emit! (dwt/update-text-range $id start end attrs)))))
(defn text-range?
[range]
(instance? TextRange range))
(defn text-props
[shape] [shape]
(d/merge (d/merge
(dwt/current-root-values {:shape shape :attrs txt/root-attrs}) (dwt/current-root-values {:shape shape :attrs txt/root-attrs})
(dwt/current-paragraph-values {:shape shape :attrs txt/paragraph-attrs}) (dwt/current-paragraph-values {:shape shape :attrs txt/paragraph-attrs})
(dwt/current-text-values {:shape shape :attrs txt/text-node-attrs}))) (dwt/current-text-values {:shape shape :attrs txt/text-node-attrs})))
(defn text-range (defn text-range-proxy?
[plugin-id file-id page-id id start end] [range]
(-> (TextRange. plugin-id file-id page-id id start end) (obj/type-of? range "TextRange"))
(crc/add-properties!
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$id" :enumerable false :get (constantly id)}
{:name "$file" :enumerable false :get (constantly file-id)}
{:name "$page" :enumerable false :get (constantly page-id)}
{:name "shape" (defn text-range-proxy
[plugin-id file-id page-id id start end]
(obj/reify {:name "TextRange"}
:$plugin {:enumerable false :get (constantly plugin-id)}
:$id {:enumerable false :get (constantly id)}
:$file {:enumerable false :get (constantly file-id)}
:$page {:enumerable false :get (constantly page-id)}
:shape
{:this true
:get #(-> % u/proxy->shape)} :get #(-> % u/proxy->shape)}
{:name "characters" :characters
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :text) (str/join "")))} (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :text) (str/join ""))))}
{:name "fontId" :fontId
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :font-id) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :font-id) u/mixed-value)))
:set :set
(fn [_ value] (fn [_ value]
@ -114,10 +105,13 @@
:else :else
(st/emit! (dwt/update-text-range id start end (font-data font variant))))))} (st/emit! (dwt/update-text-range id start end (font-data font variant))))))}
{:name "fontFamily" :fontFamily
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :font-family) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :font-family) u/mixed-value)))
:set :set
(fn [_ value] (fn [_ value]
@ -133,10 +127,13 @@
:else :else
(st/emit! (dwt/update-text-range id start end (font-data font variant))))))} (st/emit! (dwt/update-text-range id start end (font-data font variant))))))}
{:name "fontVariantId" :fontVariantId
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :font-variant-id) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :font-variant-id) u/mixed-value)))
:set :set
(fn [self value] (fn [self value]
(let [font (fonts/get-font-data (obj/get self "fontId")) (let [font (fonts/get-font-data (obj/get self "fontId"))
@ -151,10 +148,13 @@
:else :else
(st/emit! (dwt/update-text-range id start end (variant-data variant))))))} (st/emit! (dwt/update-text-range id start end (variant-data variant))))))}
{:name "fontSize" :fontSize
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :font-size) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :font-size) u/mixed-value)))
:set :set
(fn [_ value] (fn [_ value]
(let [value (str/trim (dm/str value))] (let [value (str/trim (dm/str value))]
@ -168,10 +168,14 @@
:else :else
(st/emit! (dwt/update-text-range id start end {:font-size value})))))} (st/emit! (dwt/update-text-range id start end {:font-size value})))))}
{:name "fontWeight" :fontWeight
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :font-weight) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :font-weight) u/mixed-value)))
:set :set
(fn [self value] (fn [self value]
(let [font (fonts/get-font-data (obj/get self "fontId")) (let [font (fonts/get-font-data (obj/get self "fontId"))
@ -191,10 +195,13 @@
:else :else
(st/emit! (dwt/update-text-range id start end (variant-data variant))))))} (st/emit! (dwt/update-text-range id start end (variant-data variant))))))}
{:name "fontStyle" :fontStyle
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :font-style) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :font-style) u/mixed-value)))
:set :set
(fn [self value] (fn [self value]
(let [font (fonts/get-font-data (obj/get self "fontId")) (let [font (fonts/get-font-data (obj/get self "fontId"))
@ -214,10 +221,13 @@
:else :else
(st/emit! (dwt/update-text-range id start end (variant-data variant))))))} (st/emit! (dwt/update-text-range id start end (variant-data variant))))))}
{:name "lineHeight" :lineHeight
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :line-height) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :line-height) u/mixed-value)))
:set :set
(fn [_ value] (fn [_ value]
(let [value (str/trim (dm/str value))] (let [value (str/trim (dm/str value))]
@ -231,10 +241,13 @@
:else :else
(st/emit! (dwt/update-text-range id start end {:line-height value})))))} (st/emit! (dwt/update-text-range id start end {:line-height value})))))}
{:name "letterSpacing" :letterSpacing
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :letter-spacing) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :letter-spacing) u/mixed-value)))
:set :set
(fn [_ value] (fn [_ value]
(let [value (str/trim (dm/str value))] (let [value (str/trim (dm/str value))]
@ -248,14 +261,17 @@
:else :else
(st/emit! (dwt/update-text-range id start end {:letter-spacing value})))))} (st/emit! (dwt/update-text-range id start end {:letter-spacing value})))))}
{:name "textTransform" :textTransform
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :text-transform) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :text-transform) u/mixed-value)))
:set :set
(fn [_ value] (fn [_ value]
(cond (cond
(and (string? value) (re-matches text-transform-re value)) (and (string? value) (not (re-matches text-transform-re value)))
(u/display-not-valid :textTransform value) (u/display-not-valid :textTransform value)
(not (r/check-permission plugin-id "content:write")) (not (r/check-permission plugin-id "content:write"))
@ -264,10 +280,13 @@
:else :else
(st/emit! (dwt/update-text-range id start end {:text-transform value}))))} (st/emit! (dwt/update-text-range id start end {:text-transform value}))))}
{:name "textDecoration" :textDecoration
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :text-decoration) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :text-decoration) u/mixed-value)))
:set :set
(fn [_ value] (fn [_ value]
(cond (cond
@ -280,10 +299,13 @@
:else :else
(st/emit! (dwt/update-text-range id start end {:text-decoration value}))))} (st/emit! (dwt/update-text-range id start end {:text-decoration value}))))}
{:name "direction" :direction
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :direction) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :direction) u/mixed-value)))
:set :set
(fn [_ value] (fn [_ value]
(cond (cond
@ -296,10 +318,13 @@
:else :else
(st/emit! (dwt/update-text-range id start end {:direction value}))))} (st/emit! (dwt/update-text-range id start end {:direction value}))))}
{:name "align" :align
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :text-align) mixed-value)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :text-align) u/mixed-value)))
:set :set
(fn [_ value] (fn [_ value]
(cond (cond
@ -312,10 +337,13 @@
:else :else
(st/emit! (dwt/update-text-range id start end {:text-align value}))))} (st/emit! (dwt/update-text-range id start end {:text-align value}))))}
{:name "fills" :fills
:get #(let [range-data {:this true
(-> % u/proxy->shape :content (txt/content-range->text+styles start end))] :get
(->> range-data (map :fills) mixed-value format/format-fills)) (fn [self]
(let [range-data
(-> self u/proxy->shape :content (txt/content-range->text+styles start end))]
(->> range-data (map :fills) u/mixed-value format/format-fills)))
:set :set
(fn [_ value] (fn [_ value]
(let [value (parser/parse-fills value)] (let [value (parser/parse-fills value)]
@ -327,7 +355,16 @@
(u/display-not-valid :fills "Plugin doesn't have 'content:write' permission") (u/display-not-valid :fills "Plugin doesn't have 'content:write' permission")
:else :else
(st/emit! (dwt/update-text-range id start end {:fills value})))))}))) (st/emit! (dwt/update-text-range id start end {:fills value})))))}
:applyTypography
(fn [typography]
(let [typography (u/proxy->library-typography typography)
attrs (-> typography
(assoc :typography-ref-file file-id)
(assoc :typography-ref-id (:id typography))
(dissoc :id :name))]
(st/emit! (dwt/update-text-range id start end attrs))))))
(defn add-text-props (defn add-text-props
[shape-proxy plugin-id] [shape-proxy plugin-id]

View file

@ -41,23 +41,28 @@
(defn current-user-proxy? [p] (defn current-user-proxy? [p]
(instance? CurrentUserProxy p)) (obj/type-of? p "CurrentUserProxy"))
(defn current-user-proxy (defn current-user-proxy
[plugin-id session-id] [plugin-id session-id]
(-> (CurrentUserProxy. plugin-id) (-> (obj/reify {:name "CurrentUserProxy"}
:$plugin {:enumerable false :get (fn [] plugin-id)})
(add-session-properties session-id))) (add-session-properties session-id)))
(defn active-user-proxy? [p] (defn active-user-proxy? [p]
(instance? ActiveUserProxy p)) (obj/type-of? p "ActiveUserProxy"))
(defn active-user-proxy (defn active-user-proxy
[plugin-id session-id] [plugin-id session-id]
(-> (ActiveUserProxy. plugin-id) (-> (obj/reify {:name "ActiveUserProxy"}
(add-session-properties session-id) :$plugin {:enumerable false :get (fn [] plugin-id)}
(crc/add-properties!
{:name "position" :get (fn [_] (-> (u/locate-presence session-id) :point format/format-point))} :position
{:name "zoom" :get (fn [_] (-> (u/locate-presence session-id) :zoom))}))) {:get (fn [] (-> (u/locate-presence session-id) :point format/format-point))}
:zoom
{:get (fn [] (-> (u/locate-presence session-id) :zoom))})
(add-session-properties session-id)))
(defn- add-user-properties (defn- add-user-properties
[user-proxy data] [user-proxy data]
@ -75,13 +80,14 @@
{:name "avatarUrl" {:name "avatarUrl"
:get (fn [_] (cfg/resolve-profile-photo-url data))}))) :get (fn [_] (cfg/resolve-profile-photo-url data))})))
(defn user-proxy?
[p]
(or (instance? UserProxy p)
(current-user-proxy? p)
(active-user-proxy? p)))
(defn user-proxy (defn user-proxy
[plugin-id data] [plugin-id data]
(-> (UserProxy. plugin-id) (-> (obj/reify {:name "UserProxy"}
:$plugin {:enumerable false :get (fn [] plugin-id)})
(add-user-properties data))) (add-user-properties data)))
(defn user-proxy?
[p]
(or (obj/type-of? p "UserProxy")
(current-user-proxy? p)
(active-user-proxy? p)))

View file

@ -119,26 +119,33 @@
flow-id (obj/get proxy "$id") flow-id (obj/get proxy "$id")
page (locate-page file-id page-id)] page (locate-page file-id page-id)]
(when (some? page) (when (some? page)
(d/seek #(= (:id %) flow-id) (:flows page))))) (get (:flows page) flow-id))))
(defn locate-ruler-guide
[file-id page-id ruler-id]
(let [page (locate-page file-id page-id)]
(when (some? page)
(d/seek #(= (:id %) ruler-id) (-> page :guides vals)))))
(defn proxy->ruler-guide (defn proxy->ruler-guide
[proxy] [proxy]
(let [file-id (obj/get proxy "$file") (let [file-id (obj/get proxy "$file")
page-id (obj/get proxy "$page") page-id (obj/get proxy "$page")
ruler-id (obj/get proxy "$id") ruler-id (obj/get proxy "$id")]
page (locate-page file-id page-id)] (locate-ruler-guide file-id page-id ruler-id)))
(when (some? page)
(d/seek #(= (:id %) ruler-id) (-> page :guides vals))))) (defn locate-interaction
[file-id page-id shape-id index]
(when-let [shape (locate-shape file-id page-id shape-id)]
(get-in shape [:interactions index])))
(defn proxy->interaction (defn proxy->interaction
[proxy] [proxy]
(let [file-id (obj/get proxy "$file") (let [file-id (obj/get proxy "$file")
page-id (obj/get proxy "$page") page-id (obj/get proxy "$page")
shape-id (obj/get proxy "$shape") shape-id (obj/get proxy "$shape")
index (obj/get proxy "$index") index (obj/get proxy "$index")]
shape (locate-shape file-id page-id shape-id)] (locate-interaction file-id page-id shape-id index)))
(when (some? shape)
(get-in shape [:interactions index]))))
(defn get-data (defn get-data
([self attr] ([self attr]
@ -193,3 +200,8 @@
(let [msg (dm/str "[PENPOT PLUGIN] Value not valid: " value ". Code: " code)] (let [msg (dm/str "[PENPOT PLUGIN] Value not valid: " value ". Code: " code)]
(.error js/console msg) (.error js/console msg)
(reject msg))) (reject msg)))
(defn mixed-value
[values]
(let [s (set values)]
(if (= (count s) 1) (first s) "mixed")))

View file

@ -7,7 +7,6 @@
(ns app.plugins.viewport (ns app.plugins.viewport
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.record :as crc]
[app.common.spec :as us] [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]
@ -17,45 +16,24 @@
[app.plugins.utils :as u] [app.plugins.utils :as u]
[app.util.object :as obj])) [app.util.object :as obj]))
(deftype ViewportProxy [$plugin]
Object
(zoomReset [_]
(st/emit! dwz/reset-zoom))
(zoomToFitAll [_]
(st/emit! dwz/zoom-to-fit-all))
(zoomIntoView [_ shapes]
(let [ids
(->> shapes
(map (fn [v]
(if (string? v)
(uuid/uuid v)
(uuid/uuid (obj/get v "x"))))))]
(st/emit! (dwz/fit-to-shapes ids)))))
(crc/define-properties!
ViewportProxy
{:name js/Symbol.toStringTag
:get (fn [] (str "ViewportProxy"))})
(defn viewport-proxy? [p] (defn viewport-proxy? [p]
(instance? ViewportProxy p)) (obj/type-of? p "ViewportProxy"))
(defn viewport-proxy (defn viewport-proxy
[plugin-id] [plugin-id]
(crc/add-properties! (obj/reify {:name "ViewportProxy"}
(ViewportProxy. plugin-id) :$plugin {:enumerable false :get (fn [] plugin-id)}
{:name "center"
:get :center
(fn [_] {:get
(fn []
(let [vp (dm/get-in @st/state [:workspace-local :vbox]) (let [vp (dm/get-in @st/state [:workspace-local :vbox])
x (+ (:x vp) (/ (:width vp) 2)) x (+ (:x vp) (/ (:width vp) 2))
y (+ (:y vp) (/ (:height vp) 2))] y (+ (:y vp) (/ (:height vp) 2))]
(.freeze js/Object #js {:x x :y y}))) (.freeze js/Object #js {:x x :y y})))
: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")]
(cond (cond
@ -76,12 +54,13 @@
:y #(+ % delta-y)}] :y #(+ % delta-y)}]
(st/emit! (dwv/update-viewport-position to-position))))))} (st/emit! (dwv/update-viewport-position to-position))))))}
{:name "zoom" :zoom
:get {:get
(fn [_] (fn []
(dm/get-in @st/state [:workspace-local :zoom])) (dm/get-in @st/state [:workspace-local :zoom]))
:set :set
(fn [_ value] (fn [value]
(cond (cond
(not (us/safe-number? value)) (not (us/safe-number? value))
(u/display-not-valid :zoom value) (u/display-not-valid :zoom value)
@ -90,10 +69,28 @@
(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" :bounds
:get {:get
(fn [_] (fn []
(let [vbox (dm/get-in @st/state [:workspace-local :vbox])] (let [vbox (dm/get-in @st/state [:workspace-local :vbox])]
(.freeze js/Object (format/format-bounds vbox))))})) (.freeze js/Object (format/format-bounds vbox))))}
:zoomReset
(fn []
(st/emit! dwz/reset-zoom))
:zoomToFitAll
(fn []
(st/emit! dwz/zoom-to-fit-all))
:zoomIntoView
(fn [shapes]
(let [ids
(->> shapes
(map (fn [v]
(if (string? v)
(uuid/uuid v)
(uuid/uuid (obj/get v "x"))))))]
(st/emit! (dwz/fit-to-shapes ids))))))

View file

@ -173,7 +173,7 @@
(let [definition (first params)] (let [definition (first params)]
(if (some? definition) (if (some? definition)
(let [definition (if (map? definition) (let [definition (if (map? definition)
(assoc definition :name (name ckey) :this false) (c/merge {:this false} (assoc definition :name (name ckey)))
(-> {:enumerable false} (-> {:enumerable false}
(c/merge (meta definition)) (c/merge (meta definition))
(assoc :name (name ckey)) (assoc :name (name ckey))
@ -210,6 +210,16 @@
:else :else
(throw (ex-info "invalid params" {})))))) (throw (ex-info "invalid params" {}))))))
#?(:cljs
(def type-symbol
(js/Symbol.for "penpot.reify:type")))
#?(:cljs
(defn type-of?
[o t]
(let [o (get o type-symbol)]
(= o t))))
(defmacro reify (defmacro reify
"A domain specific variation of reify that creates anonymous objects "A domain specific variation of reify that creates anonymous objects
on demand with the ability to assign protocol implementations and on demand with the ability to assign protocol implementations and
@ -221,6 +231,10 @@
(add-properties! ~obj-sym (add-properties! ~obj-sym
~@(when-let [tname (:name tmeta)] ~@(when-let [tname (:name tmeta)]
[`{:name ~'js/Symbol.toStringTag [`{:name ~'js/Symbol.toStringTag
:this false
:enumerable false
:get (fn [] ~tname)}
`{:name type-symbol
:this false :this false
:enumerable false :enumerable false
:get (fn [] ~tname)}]) :get (fn [] ~tname)}])
@ -230,6 +244,4 @@
~@(mapcat (fn [[k v]] (cons k v)) definitions)) ~@(mapcat (fn [[k v]] (cons k v)) definitions))
obj-sym)] obj-sym)]
(cljs.core/specify! ~obj-sym (cljs.core/specify! ~obj-sym)))))
cljs.core/IMeta
(~'-meta [_#] ~tmeta))))))