mirror of
https://github.com/penpot/penpot.git
synced 2025-05-26 06:16:11 +02:00
♻️ Refactor state locality
The main purpose of this refactor is reduce a custom state from different pages and unify them under common access patterns
This commit is contained in:
parent
f62aecb383
commit
85746e7cb2
110 changed files with 2254 additions and 2125 deletions
|
@ -47,31 +47,28 @@
|
|||
(str/join "")))
|
||||
|
||||
(defn- format-comment-url
|
||||
[thread {:keys [team-id file-id page-id]}]
|
||||
[thread file]
|
||||
(str/ffmt "%/#/workspace?%"
|
||||
(cf/get :public-uri)
|
||||
(uri/map->query-string
|
||||
{:file-id file-id
|
||||
:page-id page-id
|
||||
:team-id team-id
|
||||
{:file-id (:id file)
|
||||
:page-id (:page-id file)
|
||||
:team-id (:team-id file)
|
||||
:comment-id (:id thread)})))
|
||||
|
||||
(defn- format-comment-ref
|
||||
[{:keys [seqn]} {:keys [file-name page-name]}]
|
||||
(str/ffmt "#%, %, %" seqn file-name page-name))
|
||||
[thread file]
|
||||
(str/ffmt "#%, %, %"
|
||||
(:seqn thread)
|
||||
(:name file)
|
||||
(:page-name file)))
|
||||
|
||||
(defn get-team-users
|
||||
(defn- get-team-users
|
||||
[conn team-id]
|
||||
(->> (teams/get-users+props conn team-id)
|
||||
(map profile/decode-row)
|
||||
(d/index-by :id)))
|
||||
|
||||
(defn- resolve-profile-name
|
||||
[conn profile-id]
|
||||
(-> (db/get conn :profile {:id profile-id}
|
||||
{::sql/columns [:fullname]})
|
||||
(get :fullname)))
|
||||
|
||||
(defn- notification-email?
|
||||
[profile-id owner-id props]
|
||||
(if (= profile-id owner-id)
|
||||
|
@ -83,24 +80,22 @@
|
|||
(not= :none (-> props :notifications :email-comments)))
|
||||
|
||||
(defn send-comment-emails!
|
||||
[conn {:keys [profile-id team-id] :as params} comment thread]
|
||||
|
||||
(let [team-users (get-team-users conn team-id)
|
||||
source-user (resolve-profile-name conn profile-id)
|
||||
|
||||
comment-reference (format-comment-ref thread params)
|
||||
[conn profile comment thread file]
|
||||
(let [team-users (get-team-users conn (:team-id file))
|
||||
comment-reference (format-comment-ref thread file)
|
||||
comment-content (format-comment comment)
|
||||
comment-url (format-comment-url thread params)
|
||||
comment-url (format-comment-url thread file)
|
||||
profile-id (get profile :id)
|
||||
|
||||
;; Users mentioned in this comment
|
||||
comment-mentions
|
||||
(-> (:mentions comment)
|
||||
(set/difference #{profile-id}))
|
||||
(disj profile-id))
|
||||
|
||||
;; Users mentioned in this thread
|
||||
thread-mentions
|
||||
(-> (:mentions thread)
|
||||
;; Remove the mentions in the thread because we're already sending a
|
||||
;; Remove the mentions in the comment because we're already sending a
|
||||
;; notification
|
||||
(set/difference comment-mentions)
|
||||
(disj profile-id))
|
||||
|
@ -118,9 +113,10 @@
|
|||
(eml/send!
|
||||
{::eml/conn conn
|
||||
::eml/factory eml/comment-mention
|
||||
:public-uri (cf/get :public-uri)
|
||||
:to email
|
||||
:name fullname
|
||||
:source-user source-user
|
||||
:source-user (:fullname profile)
|
||||
:comment-reference comment-reference
|
||||
:comment-content comment-content
|
||||
:comment-url comment-url}))))
|
||||
|
@ -132,9 +128,10 @@
|
|||
(eml/send!
|
||||
{::eml/conn conn
|
||||
::eml/factory eml/comment-thread
|
||||
:public-uri (cf/get :public-uri)
|
||||
:to email
|
||||
:name fullname
|
||||
:source-user source-user
|
||||
:source-user (:fullname profile)
|
||||
:comment-reference comment-reference
|
||||
:comment-content comment-content
|
||||
:comment-url comment-url}))))
|
||||
|
@ -146,9 +143,10 @@
|
|||
(eml/send!
|
||||
{::eml/conn conn
|
||||
::eml/factory eml/comment-notification
|
||||
:public-uri (cf/get :public-uri)
|
||||
:to email
|
||||
:name fullname
|
||||
:source-user source-user
|
||||
:source-user (:fullname profile)
|
||||
:comment-reference comment-reference
|
||||
:comment-content comment-content
|
||||
:comment-url comment-url}))))))
|
||||
|
@ -165,12 +163,13 @@
|
|||
|
||||
(def ^:private
|
||||
sql:get-file
|
||||
"select f.id, f.modified_at, f.revn, f.features, f.name,
|
||||
f.project_id, p.team_id, f.data
|
||||
from file as f
|
||||
join project as p on (p.id = f.project_id)
|
||||
where f.id = ?
|
||||
and f.deleted_at is null")
|
||||
"SELECT f.id, f.modified_at, f.revn, f.features, f.name,
|
||||
f.project_id, p.team_id, f.data,
|
||||
f.data_ref_id, f.data_backend
|
||||
FROM file as f
|
||||
INNER JOIN project as p on (p.id = f.project_id)
|
||||
WHERE f.id = ?
|
||||
AND (f.deleted_at IS NULL OR f.deleted_at > now())")
|
||||
|
||||
(defn- get-file
|
||||
"A specialized version of get-file for comments module."
|
||||
|
@ -182,12 +181,16 @@
|
|||
:hint "file not found"))
|
||||
|
||||
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer cfg file-id)]
|
||||
(let [{:keys [data] :as file} (files/decode-row file)]
|
||||
(let [file (->> file
|
||||
(files/decode-row)
|
||||
(feat.fdata/resolve-file-data cfg))
|
||||
data (get file :data)]
|
||||
(-> file
|
||||
(assoc :page-name (dm/get-in data [:pages-index page-id :name]))
|
||||
(assoc :page-id page-id)
|
||||
(dissoc :data))))))
|
||||
|
||||
;; FIXME: rename
|
||||
(defn- get-comment-thread
|
||||
[conn thread-id & {:as opts}]
|
||||
(-> (db/get-by-id conn :comment-thread thread-id opts)
|
||||
|
@ -249,6 +252,9 @@
|
|||
(def ^:private sql:comment-threads
|
||||
"SELECT DISTINCT ON (ct.id)
|
||||
ct.*,
|
||||
pf.fullname AS owner_fullname,
|
||||
pf.email AS owner_email,
|
||||
pf.photo_id AS owner_photo_id,
|
||||
p.team_id AS team_id,
|
||||
f.name AS file_name,
|
||||
f.project_id AS project_id,
|
||||
|
@ -265,6 +271,7 @@
|
|||
INNER JOIN file AS f ON (f.id = ct.file_id)
|
||||
INNER JOIN project AS p ON (p.id = f.project_id)
|
||||
LEFT JOIN comment_thread_status AS cts ON (cts.thread_id = ct.id AND cts.profile_id = ?)
|
||||
LEFT JOIN profile AS pf ON (ct.owner_id = pf.id)
|
||||
WINDOW w AS (PARTITION BY c.thread_id ORDER BY c.created_at ASC)")
|
||||
|
||||
(def ^:private sql:comment-threads-by-file-id
|
||||
|
@ -360,15 +367,25 @@
|
|||
::sm/params schema:get-comments}
|
||||
[cfg {:keys [::rpc/profile-id thread-id share-id]}]
|
||||
(db/run! cfg (fn [{:keys [::db/conn]}]
|
||||
(let [{:keys [file-id] :as thread} (get-comment-thread conn thread-id)]
|
||||
(let [{:keys [file-id]} (get-comment-thread conn thread-id)]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(get-comments conn thread-id)))))
|
||||
|
||||
(def sql:get-comments
|
||||
"SELECT c.*,
|
||||
ct.file_id AS file_id,
|
||||
pf.fullname AS owner_fullname,
|
||||
pf.email AS owner_email,
|
||||
pf.photo_id AS owner_photo_id
|
||||
FROM comment AS c
|
||||
INNER JOIN comment_thread AS ct ON (ct.id = c.thread_id)
|
||||
LEFT JOIN profile AS pf ON (c.owner_id = pf.id)
|
||||
WHERE c.thread_id = ?
|
||||
ORDER BY c.created_at ASC")
|
||||
|
||||
(defn- get-comments
|
||||
[conn thread-id]
|
||||
(->> (db/query conn :comment
|
||||
{:thread-id thread-id}
|
||||
{:order-by [[:created-at :asc]]})
|
||||
(->> (db/exec! conn [sql:get-comments thread-id])
|
||||
(into [] xf-decode-row)))
|
||||
|
||||
;; --- COMMAND: Get file comments users
|
||||
|
@ -429,7 +446,21 @@
|
|||
[:page-id ::sm/uuid]
|
||||
[:frame-id ::sm/uuid]
|
||||
[:share-id {:optional true} [:maybe ::sm/uuid]]
|
||||
[:mentions {:optional true} [:vector ::sm/uuid]]])
|
||||
[:mentions {:optional true} [::sm/set ::sm/uuid]]])
|
||||
|
||||
(defn- update-thread-seqn
|
||||
[conn file-id seqn]
|
||||
(db/update! conn :file
|
||||
{:comment-thread-seqn seqn}
|
||||
{:id file-id}
|
||||
{::db/return-keys false}))
|
||||
|
||||
(defn add-owner
|
||||
[thread-or-comment profile]
|
||||
(-> thread-or-comment
|
||||
(assoc :owner-fullname (:fullname profile))
|
||||
(assoc :owner-email (:email profile))
|
||||
(assoc :owner-photo-id (:photo-id profile))))
|
||||
|
||||
(sv/defmethod ::create-comment-thread
|
||||
{::doc/added "1.15"
|
||||
|
@ -437,10 +468,10 @@
|
|||
::rtry/enabled true
|
||||
::rtry/when rtry/conflict-exception?
|
||||
::sm/params schema:create-comment-thread}
|
||||
[cfg {:keys [::rpc/profile-id ::rpc/request-at file-id page-id share-id mentions position content frame-id]}]
|
||||
[cfg {:keys [::rpc/profile-id file-id page-id share-id] :as params}]
|
||||
(files/check-comment-permissions! cfg profile-id file-id share-id)
|
||||
|
||||
(let [{:keys [team-id project-id page-name name]} (get-file cfg file-id page-id)]
|
||||
(let [{:keys [team-id project-id] :as file} (get-file cfg file-id page-id)]
|
||||
(-> cfg
|
||||
(assoc ::quotes/profile-id profile-id)
|
||||
(assoc ::quotes/team-id team-id)
|
||||
|
@ -449,26 +480,14 @@
|
|||
(quotes/check! {::quotes/id ::quotes/comment-threads-per-file}
|
||||
{::quotes/id ::quotes/comments-per-file}))
|
||||
|
||||
(let [params {:created-at request-at
|
||||
:profile-id profile-id
|
||||
:file-id file-id
|
||||
:file-name name
|
||||
:page-id page-id
|
||||
:page-name page-name
|
||||
:position position
|
||||
:content content
|
||||
:frame-id frame-id
|
||||
:team-id team-id
|
||||
:project-id project-id
|
||||
:mentions mentions}
|
||||
thread (-> (db/tx-run! cfg create-comment-thread params)
|
||||
(decode-row))]
|
||||
(let [params (assoc params ::file file)
|
||||
thread (db/tx-run! cfg create-comment-thread params)]
|
||||
|
||||
(vary-meta thread assoc ::audit/props thread))))
|
||||
|
||||
(defn- create-comment-thread
|
||||
[{:keys [::db/conn] :as cfg}
|
||||
{:keys [profile-id file-id page-id page-name created-at position content mentions frame-id] :as params}]
|
||||
{:keys [::rpc/profile-id ::rpc/request-at ::file position content mentions frame-id] :as params}]
|
||||
|
||||
(let [;; NOTE: we take the next seq number from a separate query
|
||||
;; because we need to lock the file for avoid race conditions
|
||||
|
@ -479,46 +498,47 @@
|
|||
;; different storage (example: redis) for alivate the update
|
||||
;; pression on the file table
|
||||
|
||||
seqn (get-next-seqn conn file-id)
|
||||
profile (profile/get-profile conn profile-id)
|
||||
seqn (get-next-seqn conn (:id file))
|
||||
|
||||
file-id (get file :id)
|
||||
thread-id (uuid/next)
|
||||
|
||||
thread (-> (db/insert! conn :comment-thread
|
||||
{:id thread-id
|
||||
:file-id file-id
|
||||
:page-name (:page-name file)
|
||||
:page-id (:page-id file)
|
||||
:owner-id profile-id
|
||||
:participants (db/tjson #{profile-id})
|
||||
:page-name page-name
|
||||
:page-id page-id
|
||||
:created-at created-at
|
||||
:modified-at created-at
|
||||
:created-at request-at
|
||||
:modified-at request-at
|
||||
:seqn seqn
|
||||
:position (db/pgpoint position)
|
||||
:frame-id frame-id
|
||||
:position (db/pgpoint position)
|
||||
:mentions (db/encode-pgarray mentions conn "uuid")})
|
||||
(decode-row))
|
||||
comment (-> (db/insert! conn :comment
|
||||
{:id (uuid/next)
|
||||
:thread-id thread-id
|
||||
:owner-id profile-id
|
||||
:created-at created-at
|
||||
:modified-at created-at
|
||||
:created-at request-at
|
||||
:modified-at request-at
|
||||
:mentions (db/encode-pgarray mentions conn "uuid")
|
||||
:content content})
|
||||
(decode-row))]
|
||||
|
||||
;; Make the current thread as read.
|
||||
(upsert-comment-thread-status! conn profile-id thread-id created-at)
|
||||
(upsert-comment-thread-status! conn profile-id thread-id request-at)
|
||||
|
||||
;; Optimistic update of current seq number on file.
|
||||
(db/update! conn :file
|
||||
{:comment-thread-seqn seqn}
|
||||
{:id file-id}
|
||||
{::db/return-keys false})
|
||||
(update-thread-seqn conn file-id seqn)
|
||||
|
||||
;; Send mentions emails
|
||||
(send-comment-emails! conn params comment thread)
|
||||
(send-comment-emails! conn profile comment thread file)
|
||||
|
||||
(-> thread
|
||||
(select-keys [:id :file-id :page-id :mentions])
|
||||
(add-owner profile)
|
||||
(assoc :comment-id (:id comment)))))
|
||||
|
||||
;; --- COMMAND: Update Comment Thread Status
|
||||
|
@ -534,7 +554,7 @@
|
|||
::sm/params schema:update-comment-thread-status
|
||||
::db/transaction true}
|
||||
[{:keys [::db/conn]} {:keys [::rpc/profile-id id share-id]}]
|
||||
(let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)]
|
||||
(let [{:keys [file-id]} (get-comment-thread conn id ::sql/for-update true)]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(upsert-comment-thread-status! conn profile-id id)))
|
||||
|
||||
|
@ -552,7 +572,7 @@
|
|||
::sm/params schema:update-comment-thread
|
||||
::db/transaction true}
|
||||
[{:keys [::db/conn]} {:keys [::rpc/profile-id id is-resolved share-id]}]
|
||||
(let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)]
|
||||
(let [{:keys [file-id]} (get-comment-thread conn id ::sql/for-update true)]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(db/update! conn :comment-thread
|
||||
{:is-resolved is-resolved}
|
||||
|
@ -561,15 +581,13 @@
|
|||
|
||||
;; --- COMMAND: Add Comment
|
||||
|
||||
(declare ^:private get-comment-thread)
|
||||
|
||||
(def ^:private
|
||||
schema:create-comment
|
||||
[:map {:title "create-comment"}
|
||||
[:thread-id ::sm/uuid]
|
||||
[:content [:string {:max 250}]]
|
||||
[:share-id {:optional true} [:maybe ::sm/uuid]]
|
||||
[:mentions {:optional true} [:vector ::sm/uuid]]])
|
||||
[:mentions {:optional true} [::sm/set ::sm/uuid]]])
|
||||
|
||||
(sv/defmethod ::create-comment
|
||||
{::doc/added "1.15"
|
||||
|
@ -577,65 +595,58 @@
|
|||
::sm/params schema:create-comment
|
||||
::db/transaction true}
|
||||
[{:keys [::db/conn] :as cfg} {:keys [::rpc/profile-id ::rpc/request-at thread-id share-id content mentions]}]
|
||||
(let [{:keys [file-id page-id] :as thread} (get-comment-thread conn thread-id ::sql/for-update true)
|
||||
{file-name :name :keys [team-id project-id page-name] :as file} (get-file cfg file-id page-id)]
|
||||
(let [{:keys [file-id page-id] :as thread}
|
||||
(get-comment-thread conn thread-id ::sql/for-update true)
|
||||
|
||||
{:keys [team-id project-id] :as file}
|
||||
(get-file cfg file-id page-id)]
|
||||
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
|
||||
(quotes/check! cfg {::quotes/id ::quotes/comments-per-file
|
||||
::quotes/profile-id profile-id
|
||||
::quotes/team-id team-id
|
||||
::quotes/project-id project-id
|
||||
::quotes/file-id file-id})
|
||||
|
||||
;; Update the page-name cached attribute on comment thread table.
|
||||
(when (not= page-name (:page-name thread))
|
||||
(db/update! conn :comment-thread
|
||||
{:page-name page-name}
|
||||
{:id thread-id}))
|
||||
|
||||
(let [comment (-> (db/insert!
|
||||
conn :comment
|
||||
{:id (uuid/next)
|
||||
(let [profile (profile/get-profile conn profile-id)
|
||||
mentions (into #{} mentions)
|
||||
params {:id (uuid/next)
|
||||
:created-at request-at
|
||||
:modified-at request-at
|
||||
:thread-id thread-id
|
||||
:owner-id profile-id
|
||||
:content content
|
||||
:mentions
|
||||
(-> mentions
|
||||
(set)
|
||||
(db/encode-pgarray conn "uuid"))})
|
||||
(decode-row))
|
||||
props {:file-id file-id
|
||||
:share-id nil}]
|
||||
:mentions (db/encode-pgarray mentions conn "uuid")}
|
||||
|
||||
comment (-> (db/insert! conn :comment params)
|
||||
(decode-row)
|
||||
(add-owner profile))]
|
||||
|
||||
;; Update thread modified-at attribute and assoc the current
|
||||
;; profile to the participant set.
|
||||
(db/update! conn :comment-thread
|
||||
{:modified-at request-at
|
||||
:participants (-> (:participants thread #{})
|
||||
(conj profile-id)
|
||||
(db/tjson))
|
||||
:mentions (-> (:mentions thread)
|
||||
(set)
|
||||
(into mentions)
|
||||
(db/encode-pgarray conn "uuid"))}
|
||||
{:id thread-id})
|
||||
(let [mentions (into (:mentions thread) mentions)
|
||||
participants (-> (:participants thread #{})
|
||||
(conj profile-id))
|
||||
params {:modified-at request-at
|
||||
:participants (db/tjson participants)
|
||||
:mentions (db/encode-pgarray mentions conn "uuid")}
|
||||
|
||||
;; Update the current profile status in relation to the
|
||||
;; current thread.
|
||||
;; Update the page-name cached attribute on comment thread table.
|
||||
params (cond-> params
|
||||
(not= (:page-name file) (:page-name thread))
|
||||
(assoc :page-name (:page-name file)))]
|
||||
|
||||
(db/update! conn :comment-thread params
|
||||
{:id thread-id}
|
||||
{::db/return-keys false}))
|
||||
|
||||
;; Update the current profile status in relation to the current thread
|
||||
(upsert-comment-thread-status! conn profile-id thread-id)
|
||||
|
||||
(let [params {:project-id project-id
|
||||
:profile-id profile-id
|
||||
:team-id team-id
|
||||
:file-id (:file-id thread)
|
||||
:page-id (:page-id thread)
|
||||
:file-name file-name
|
||||
:page-name page-name}]
|
||||
(send-comment-emails! conn params comment thread))
|
||||
(send-comment-emails! conn profile comment thread file)
|
||||
|
||||
(vary-meta comment assoc ::audit/props props))))
|
||||
(vary-meta comment assoc ::audit/props comment))))
|
||||
|
||||
;; --- COMMAND: Update Comment
|
||||
|
||||
|
@ -645,16 +656,20 @@
|
|||
[:id ::sm/uuid]
|
||||
[:content [:string {:max 250}]]
|
||||
[:share-id {:optional true} [:maybe ::sm/uuid]]
|
||||
[:mentions {:optional true} [:vector ::sm/uuid]]])
|
||||
[:mentions {:optional true} [::sm/set ::sm/uuid]]])
|
||||
|
||||
;; TODO: Check if there are new mentions, if there are send the new emails.
|
||||
|
||||
;; TODO Check if there are new mentions, if there are send the new emails.
|
||||
(sv/defmethod ::update-comment
|
||||
{::doc/added "1.15"
|
||||
::sm/params schema:update-comment
|
||||
::db/transaction true}
|
||||
[{:keys [::db/conn] :as cfg} {:keys [::rpc/profile-id ::rpc/request-at id share-id content mentions]}]
|
||||
(let [{:keys [thread-id owner-id] :as comment} (get-comment conn id ::sql/for-update true)
|
||||
{:keys [file-id page-id] :as thread} (get-comment-thread conn thread-id ::sql/for-update true)]
|
||||
(let [{:keys [thread-id owner-id] :as comment}
|
||||
(get-comment conn id ::sql/for-update true)
|
||||
|
||||
{:keys [file-id page-id] :as thread}
|
||||
(get-comment-thread conn thread-id ::sql/for-update true)]
|
||||
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
|
||||
|
@ -675,10 +690,10 @@
|
|||
:page-name page-name
|
||||
:mentions
|
||||
(-> (:mentions thread)
|
||||
(set)
|
||||
(into mentions)
|
||||
(db/encode-pgarray conn "uuid"))}
|
||||
{:id thread-id})
|
||||
{:id thread-id}
|
||||
{::db/return-keys false})
|
||||
nil)))
|
||||
|
||||
;; --- COMMAND: Delete Comment Thread
|
||||
|
@ -700,7 +715,8 @@
|
|||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
|
||||
(db/delete! conn :comment-thread {:id id})
|
||||
(db/delete! conn :comment-thread {:id id}
|
||||
{::db/return-keys false})
|
||||
nil))
|
||||
|
||||
;; --- COMMAND: Delete comment
|
||||
|
@ -716,13 +732,19 @@
|
|||
::sm/params schema:delete-comment
|
||||
::db/transaction true}
|
||||
[{:keys [::db/conn]} {:keys [::rpc/profile-id id share-id]}]
|
||||
(let [{:keys [owner-id thread-id] :as comment} (get-comment conn id ::sql/for-update true)
|
||||
{:keys [file-id] :as thread} (get-comment-thread conn thread-id)]
|
||||
(let [{:keys [owner-id thread-id] :as comment}
|
||||
(get-comment conn id ::sql/for-update true)
|
||||
|
||||
{:keys [file-id]}
|
||||
(get-comment-thread conn thread-id)]
|
||||
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(when-not (= owner-id profile-id)
|
||||
(ex/raise :type :validation
|
||||
:code :not-allowed))
|
||||
(db/delete! conn :comment {:id id})
|
||||
|
||||
(db/delete! conn :comment {:id id}
|
||||
{::db/return-keys false})
|
||||
nil))
|
||||
|
||||
;; --- COMMAND: Update comment thread position
|
||||
|
@ -740,13 +762,14 @@
|
|||
::sm/params schema:update-comment-thread-position
|
||||
::db/transaction true}
|
||||
[{:keys [::db/conn]} {:keys [::rpc/profile-id ::rpc/request-at id position frame-id share-id]}]
|
||||
(let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)]
|
||||
(let [{:keys [file-id]} (get-comment-thread conn id ::sql/for-update true)]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(db/update! conn :comment-thread
|
||||
{:modified-at request-at
|
||||
:position (db/pgpoint position)
|
||||
:frame-id frame-id}
|
||||
{:id (:id thread)})
|
||||
{:id id}
|
||||
{::db/return-keys false})
|
||||
nil))
|
||||
|
||||
;; --- COMMAND: Update comment frame
|
||||
|
@ -763,10 +786,11 @@
|
|||
::sm/params schema:update-comment-thread-frame
|
||||
::db/transaction true}
|
||||
[{:keys [::db/conn]} {:keys [::rpc/profile-id ::rpc/request-at id frame-id share-id]}]
|
||||
(let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)]
|
||||
(let [{:keys [file-id]} (get-comment-thread conn id ::sql/for-update true)]
|
||||
(files/check-comment-permissions! conn profile-id file-id share-id)
|
||||
(db/update! conn :comment-thread
|
||||
{:modified-at request-at
|
||||
:frame-id frame-id}
|
||||
{:id id})
|
||||
{:id id}
|
||||
{::db/return-keys false})
|
||||
nil))
|
||||
|
|
|
@ -614,7 +614,8 @@
|
|||
l.name,
|
||||
l.revn,
|
||||
l.vern,
|
||||
l.synced_at
|
||||
l.synced_at,
|
||||
l.is_shared
|
||||
FROM libs AS l
|
||||
WHERE l.deleted_at IS NULL OR l.deleted_at > now();")
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
:deleted-at nil})]
|
||||
|
||||
{:users members
|
||||
:profiles members
|
||||
:fonts fonts
|
||||
:project project
|
||||
:share-links links
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
[app.common.types.color :as ctc]
|
||||
[app.common.types.colors-list :as ctcl]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.pages-list :as ctpl]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
|
@ -43,8 +42,7 @@
|
|||
frame-id (if (cfh/frame-shape? parent)
|
||||
(:id parent)
|
||||
(:frame-id parent))]
|
||||
(ctf/update-file-data
|
||||
file
|
||||
(update file :data
|
||||
(fn [file-data]
|
||||
(ctpl/update-page file-data
|
||||
(:id page)
|
||||
|
@ -60,8 +58,9 @@
|
|||
[file label & {:keys [page-label]}]
|
||||
(let [page (if page-label
|
||||
(thf/get-page file page-label)
|
||||
(thf/current-page file))]
|
||||
(ctst/get-shape page (thi/id label))))
|
||||
(thf/current-page file))
|
||||
shape-id (thi/id label)]
|
||||
(ctst/get-shape page shape-id)))
|
||||
|
||||
(defn get-shape-by-id
|
||||
[file id & {:keys [page-label]}]
|
||||
|
@ -76,8 +75,7 @@
|
|||
(thf/get-page file page-label)
|
||||
(thf/current-page file))
|
||||
shape (ctst/get-shape page (thi/id shape-label))]
|
||||
(ctf/update-file-data
|
||||
file
|
||||
(update file :data
|
||||
(fn [file-data]
|
||||
(ctpl/update-page file-data
|
||||
(:id page)
|
||||
|
@ -104,7 +102,7 @@
|
|||
(defn add-sample-library-color
|
||||
[file label & {:keys [] :as params}]
|
||||
(let [color (sample-color label params)]
|
||||
(ctf/update-file-data file #(ctcl/add-color % color))))
|
||||
(update file :data ctcl/add-color color)))
|
||||
|
||||
(defn sample-typography
|
||||
[label & {:keys [] :as params}]
|
||||
|
@ -113,7 +111,7 @@
|
|||
(defn add-sample-typography
|
||||
[file label & {:keys [] :as params}]
|
||||
(let [typography (sample-typography label params)]
|
||||
(ctf/update-file-data file #(cttl/add-typography % typography))))
|
||||
(update file :data cttl/add-typography typography)))
|
||||
|
||||
(defn add-interaction
|
||||
[file origin-label dest-label]
|
||||
|
@ -124,8 +122,7 @@
|
|||
(ctsi/set-destination (:id dest))
|
||||
(assoc :position-relative-to (:id origin)))
|
||||
interactions (ctsi/add-interaction (:interactions origin) interaction)]
|
||||
(ctf/update-file-data
|
||||
file
|
||||
(update file :data
|
||||
(fn [file-data]
|
||||
(ctpl/update-page file-data
|
||||
(:id page)
|
||||
|
|
|
@ -143,6 +143,7 @@
|
|||
|
||||
;; --- fill
|
||||
|
||||
;; FIXME: revisit, this generates invalid colors
|
||||
(defn fill->shape-color
|
||||
[fill]
|
||||
(d/without-nils
|
||||
|
@ -153,6 +154,16 @@
|
|||
:ref-id (:fill-color-ref-id fill)
|
||||
:ref-file (:fill-color-ref-file fill)}))
|
||||
|
||||
(defn fill->color
|
||||
[fill]
|
||||
(d/without-nils
|
||||
{:color (:fill-color fill)
|
||||
:opacity (:fill-opacity fill)
|
||||
:gradient (:fill-color-gradient fill)
|
||||
:image (:fill-image fill)
|
||||
:id (:fill-color-ref-id fill)
|
||||
:file-id (:fill-color-ref-file fill)}))
|
||||
|
||||
(defn set-fill-color
|
||||
[shape position color opacity gradient image]
|
||||
(update-in shape [:fills position]
|
||||
|
|
|
@ -103,4 +103,3 @@
|
|||
(txt/transform-nodes #(not= (:typography-ref-file %) file-id)
|
||||
remove-ref-file
|
||||
content)))))
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.common.logging :as log]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.features :as features]
|
||||
[app.main.worker :as uw]
|
||||
[app.util.time :as dt]
|
||||
|
@ -76,12 +77,8 @@
|
|||
(ptk/reify ::apply-changes-localy
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [current-file-id (get state :current-file-id)
|
||||
path (if (= file-id current-file-id)
|
||||
[:workspace-data]
|
||||
[:libraries file-id :data])
|
||||
|
||||
undo-changes (if pending
|
||||
(let [undo-changes
|
||||
(if pending
|
||||
(->> pending
|
||||
(map :undo-changes)
|
||||
(reverse)
|
||||
|
@ -89,19 +86,21 @@
|
|||
(vec))
|
||||
nil)
|
||||
|
||||
redo-changes (if pending
|
||||
redo-changes
|
||||
(if pending
|
||||
(into redo-changes
|
||||
(mapcat :redo-changes)
|
||||
pending)
|
||||
redo-changes)]
|
||||
redo-changes)
|
||||
|
||||
(d/update-in-when state path
|
||||
(fn [file]
|
||||
(let [file (cpc/process-changes file undo-changes false)
|
||||
file (cpc/process-changes file redo-changes false)
|
||||
apply-changes
|
||||
(fn [fdata]
|
||||
(let [fdata (cpc/process-changes fdata undo-changes false)
|
||||
fdata (cpc/process-changes fdata redo-changes false)
|
||||
pids (into #{} xf:map-page-id redo-changes)]
|
||||
(reduce #(ctst/update-object-indices %1 %2) file pids))))))))
|
||||
(reduce #(ctst/update-object-indices %1 %2) fdata pids)))]
|
||||
|
||||
(update-in state [:files file-id :data] apply-changes)))))
|
||||
|
||||
(defn commit
|
||||
"Create a commit event instance"
|
||||
|
@ -156,17 +155,11 @@
|
|||
|
||||
(defn- resolve-file-revn
|
||||
[state file-id]
|
||||
(let [file (:workspace-file state)]
|
||||
(if (= (:id file) file-id)
|
||||
(:revn file)
|
||||
(dm/get-in state [:libraries file-id :revn]))))
|
||||
(:revn (dsh/lookup-file state file-id)))
|
||||
|
||||
(defn- resolve-file-vern
|
||||
[state file-id]
|
||||
(let [file (:workspace-file state)]
|
||||
(if (= (:id file) file-id)
|
||||
(:vern file)
|
||||
(dm/get-in state [:libraries file-id :vern]))))
|
||||
(:vern (dsh/lookup-file state file-id)))
|
||||
|
||||
(defn commit-changes
|
||||
"Schedules a list of changes to execute now, and add the corresponding undo changes to
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.team :as dtm]
|
||||
[app.main.repo :as rp]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -25,8 +26,10 @@
|
|||
[:file-id ::sm/uuid]
|
||||
[:project-id ::sm/uuid]
|
||||
[:owner-id ::sm/uuid]
|
||||
[:page-name {:optional true} :string]
|
||||
[:file-name :string]
|
||||
[:owner-fullname {:optional true} ::sm/text]
|
||||
[:owner-email {:optional true} ::sm/email]
|
||||
[:page-name {:optional true} ::sm/text]
|
||||
[:file-name ::sm/text]
|
||||
[:seqn :int]
|
||||
[:content :string]
|
||||
[:participants ::sm/set-of-uuid]
|
||||
|
@ -40,7 +43,10 @@
|
|||
[:map {:title "Comment"}
|
||||
[:id ::sm/uuid]
|
||||
[:thread-id ::sm/uuid]
|
||||
[:file-id ::sm/uuid]
|
||||
[:owner-id ::sm/uuid]
|
||||
[:owner-fullname {:optional true} ::sm/text]
|
||||
[:owner-email {:optional true} ::sm/email]
|
||||
[:created-at ::sm/inst]
|
||||
[:modified-at ::sm/inst]
|
||||
[:content :string]])
|
||||
|
@ -75,10 +81,11 @@
|
|||
(ptk/reify ::created-thread-on-workspace
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [position (select-keys thread [:position :frame-id])]
|
||||
(let [position (select-keys thread [:position :frame-id])
|
||||
page-id (or page-id (:current-page-id state))]
|
||||
(-> state
|
||||
(update :comment-threads assoc id (dissoc thread :comment))
|
||||
(update-in [:workspace-data :pages-index page-id :comment-thread-positions] assoc id position)
|
||||
(dsh/update-page page-id #(update % :comment-thread-positions assoc id position))
|
||||
(cond-> open?
|
||||
(update :comments-local assoc :open id))
|
||||
(update :comments-local assoc :options nil)
|
||||
|
@ -94,8 +101,6 @@
|
|||
:id id
|
||||
:content-size (count (:content comment))}))))))
|
||||
|
||||
|
||||
|
||||
(def ^:private
|
||||
schema:create-thread-on-workspace
|
||||
[:map {:title "created-thread-on-workspace"}
|
||||
|
@ -114,7 +119,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
frame-id (ctst/get-frame-id-by-position objects (:position params))
|
||||
params (-> params
|
||||
(update-mentions)
|
||||
|
@ -263,7 +268,7 @@
|
|||
(rx/of (refresh-comment-thread thread)))))))
|
||||
|
||||
(defn update-comment
|
||||
[{:keys [id content thread-id] :as comment}]
|
||||
[{:keys [id content thread-id file-id] :as comment}]
|
||||
(dm/assert!
|
||||
"expected valid comment"
|
||||
(check-comment! comment))
|
||||
|
@ -277,15 +282,13 @@
|
|||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(d/update-in-when [:comments thread-id id] assoc :content content)))
|
||||
(d/update-in-when state [:comments thread-id id] assoc :content content))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
share-id (-> state :viewer-local :share-id)
|
||||
params (-> {:id id :content content :share-id share-id}
|
||||
(update-mentions))]
|
||||
(let [share-id (-> state :viewer-local :share-id)
|
||||
params {:id id :content content :share-id share-id}
|
||||
params (update-mentions params)]
|
||||
(->> (rp/cmd! :update-comment params)
|
||||
(rx/catch #(rx/throw {:type :comment-error}))
|
||||
(rx/map #(retrieve-comment-threads file-id)))))))
|
||||
|
@ -299,11 +302,10 @@
|
|||
(ptk/reify ::delete-comment-thread-on-workspace
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)]
|
||||
(-> state
|
||||
(update-in [:workspace-data :pages-index page-id :comment-thread-positions] dissoc id)
|
||||
(dsh/update-page #(update % :comment-thread-positions dissoc id))
|
||||
(update :comments dissoc id)
|
||||
(update :comment-threads dissoc id))))
|
||||
(update :comment-threads dissoc id)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
|
@ -380,35 +382,37 @@
|
|||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error}))))))))
|
||||
|
||||
|
||||
(defn- comment-threads-fetched
|
||||
[threads]
|
||||
(ptk/reify ::comment-threads-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(reduce (fn [state {:keys [id file-id page-id] :as thread}]
|
||||
(-> state
|
||||
(update :comment-threads assoc id thread)
|
||||
(dsh/update-page file-id page-id
|
||||
(fn [page]
|
||||
(update-in page [:comment-thread-positions id]
|
||||
(fn [state]
|
||||
(-> state
|
||||
(assoc :position (:position thread))
|
||||
(assoc :frame-id (:frame-id thread)))))))))
|
||||
state
|
||||
threads))))
|
||||
|
||||
(defn retrieve-comment-threads
|
||||
[file-id]
|
||||
(dm/assert! (uuid? file-id))
|
||||
(letfn [(set-comment-threds [state comment-thread]
|
||||
(let [path [:workspace-data :pages-index (:page-id comment-thread) :comment-thread-positions (:id comment-thread)]
|
||||
thread-position (get-in state path)]
|
||||
(cond-> state
|
||||
(nil? thread-position)
|
||||
(->
|
||||
(assoc-in (conj path :position) (:position comment-thread))
|
||||
(assoc-in (conj path :frame-id) (:frame-id comment-thread))))))
|
||||
(fetched [[users comments] state]
|
||||
(let [pages (-> (get-in state [:workspace-data :pages])
|
||||
set)
|
||||
comments (filter #(contains? pages (:page-id %)) comments)
|
||||
state (-> state
|
||||
(assoc :comment-threads (d/index-by :id comments))
|
||||
(update :current-file-comments-users merge (d/index-by :id users)))]
|
||||
(reduce set-comment-threds state comments)))]
|
||||
|
||||
(ptk/reify ::retrieve-comment-threads
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rx/zip (rp/cmd! :get-team-users {:file-id file-id})
|
||||
(rp/cmd! :get-comment-threads {:file-id file-id :share-id share-id}))
|
||||
(rx/take 1)
|
||||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error}))))))))
|
||||
(rx/merge
|
||||
(->> (rp/cmd! :get-comment-threads {:file-id file-id :share-id share-id})
|
||||
(rx/map comment-threads-fetched))
|
||||
|
||||
;; Refresh team members
|
||||
(rx/of (dtm/fetch-members)))))))
|
||||
|
||||
(defn retrieve-comments
|
||||
[thread-id]
|
||||
|
@ -423,6 +427,8 @@
|
|||
(rx/map #(partial fetched %))
|
||||
(rx/catch #(rx/throw {:type :comment-error}))))))))
|
||||
|
||||
|
||||
;; FIXME: revisit
|
||||
(defn retrieve-unread-comment-threads
|
||||
"A event used mainly in dashboard for retrieve all unread threads of a team."
|
||||
[team-id]
|
||||
|
@ -544,6 +550,13 @@
|
|||
;; Helpers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn get-owner
|
||||
[thread-or-comment]
|
||||
{:id (:owner-id thread-or-comment)
|
||||
:fullname (:owner-fullname thread-or-comment)
|
||||
:email (:owner-email thread-or-comment)
|
||||
:photo-id (:owner-photo-id thread-or-comment)})
|
||||
|
||||
(defn group-threads-by-page
|
||||
[threads]
|
||||
(letfn [(group-by-page [result thread]
|
||||
|
@ -621,7 +634,7 @@
|
|||
(ptk/reify ::detach-comment-thread
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
is-frame? (fn [id] (= :frame (get-in objects [id :type])))
|
||||
frame-ids? (into #{} (filter is-frame?) ids)]
|
||||
|
||||
|
@ -635,7 +648,7 @@
|
|||
(defn fetch-profiles
|
||||
"Fetch or refresh all profile data for comments of the current file"
|
||||
[]
|
||||
(ptk/reify ::fetch-comments-profiles
|
||||
(ptk/reify ::fetch-profiles
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.common.schema :as sm]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.team :as ctt]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.persistence :as-alias dps]
|
||||
|
@ -111,8 +112,9 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [features (features/get-team-enabled-features state)
|
||||
data (:workspace-data state)
|
||||
file (:workspace-file state)]
|
||||
file (dsh/lookup-file state)
|
||||
data (get file :data)]
|
||||
|
||||
(->> (if (and data file)
|
||||
(rx/of {:name (:name file)
|
||||
:components-count (count (ctkl/components-seq data))
|
||||
|
@ -368,7 +370,9 @@
|
|||
(let [team-id (or team-id (:current-team-id state))
|
||||
file-id (or file-id (:current-file-id state))
|
||||
page-id (or page-id (:current-page-id state)
|
||||
(dm/get-in state [:workspace-data :pages 0]))
|
||||
(-> (dsh/lookup-file-data state file-id)
|
||||
(get :pages)
|
||||
(first)))
|
||||
|
||||
params (-> (rt/get-params state)
|
||||
(assoc :team-id team-id)
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
(:require
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.persistence :as dwp]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
|
@ -56,11 +56,11 @@
|
|||
(watch [_ state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
page-id (:current-page-id state)
|
||||
selected (or selected (wsh/lookup-selected state page-id {}))
|
||||
selected (or selected (dsh/lookup-selected state page-id {}))
|
||||
|
||||
shapes (if (seq selected)
|
||||
(wsh/lookup-shapes state selected)
|
||||
(reverse (wsh/filter-shapes state #(pos? (count (:exports %))))))
|
||||
(dsh/lookup-shapes state selected)
|
||||
(reverse (dsh/filter-shapes state #(pos? (count (:exports %))))))
|
||||
|
||||
exports (for [shape shapes
|
||||
export (:exports shape)]
|
||||
|
|
|
@ -327,27 +327,23 @@
|
|||
;; Workspace related events
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- update-recent-font
|
||||
"Moves the font/font to the top of the list of recents and then truncates up to 4"
|
||||
[state file-id font]
|
||||
(let [xform (comp
|
||||
(remove #(= font %))
|
||||
(take 3))]
|
||||
(update state file-id #(into [font] xform %))))
|
||||
|
||||
(defn add-recent-font
|
||||
[font]
|
||||
(ptk/reify ::add-recent-font
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [recent-fonts (get-in state [:workspace-data :recent-fonts])
|
||||
most-recent-fonts (into [font] (comp (remove #(= font %)) (take 3)) recent-fonts)]
|
||||
(assoc-in state [:workspace-data :recent-fonts] most-recent-fonts)))
|
||||
(let [file-id (:current-file-id state)]
|
||||
(update state :recent-fonts update-recent-font file-id font)))
|
||||
|
||||
ptk/EffectEvent
|
||||
(effect [_ state _]
|
||||
(let [most-recent-fonts (get-in state [:workspace-data :recent-fonts])]
|
||||
;; FIXME: this should be prefixed by team
|
||||
(swap! storage/user assoc ::recent-fonts most-recent-fonts)))))
|
||||
|
||||
(defn load-recent-fonts
|
||||
[fonts]
|
||||
(ptk/reify ::load-recent-fonts
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [fonts-map (d/index-by :id fonts)
|
||||
saved-recent-fonts (->> (::recent-fonts storage/user)
|
||||
(keep #(get fonts-map (:id %)))
|
||||
(into #{}))]
|
||||
(assoc-in state [:workspace-data :recent-fonts] saved-recent-fonts)))))
|
||||
(let [recent-fonts (:recent-fonts state)]
|
||||
(swap! storage/user assoc :recent-fonts recent-fonts)))))
|
||||
|
|
170
frontend/src/app/main/data/helpers.cljs
Normal file
170
frontend/src/app/main/data/helpers.cljs
Normal file
|
@ -0,0 +1,170 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.data.helpers
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.svg.path.command :as upc]))
|
||||
|
||||
(defn lookup-profile
|
||||
([state]
|
||||
(:profile state))
|
||||
([state profile-id]
|
||||
(dm/get-in state [:profiles profile-id])))
|
||||
|
||||
(defn lookup-libraries
|
||||
"Retrieve all libraries, including the local file."
|
||||
[state]
|
||||
(:files state))
|
||||
|
||||
(defn lookup-file
|
||||
([state]
|
||||
(lookup-file state (:current-file-id state)))
|
||||
([state file-id]
|
||||
(dm/get-in state [:files file-id])))
|
||||
|
||||
(defn lookup-file-data
|
||||
([state]
|
||||
(lookup-file-data state (:current-file-id state)))
|
||||
([state file-id]
|
||||
(dm/get-in state [:files file-id :data])))
|
||||
|
||||
(defn get-page
|
||||
[fdata page-id]
|
||||
(dm/get-in fdata [:pages-index page-id]))
|
||||
|
||||
(defn lookup-page
|
||||
([state]
|
||||
(let [file-id (:current-file-id state)
|
||||
page-id (:current-page-id state)]
|
||||
(lookup-page state file-id page-id)))
|
||||
([state page-id]
|
||||
(let [file-id (:current-file-id state)]
|
||||
(lookup-page state file-id page-id)))
|
||||
([state file-id page-id]
|
||||
(dm/get-in state [:files file-id :data :pages-index page-id])))
|
||||
|
||||
(defn lookup-page-objects
|
||||
([state]
|
||||
(lookup-page-objects state
|
||||
(:current-file-id state)
|
||||
(:current-page-id state)))
|
||||
([state page-id]
|
||||
(lookup-page-objects state
|
||||
(:current-file-id state)
|
||||
page-id))
|
||||
([state file-id page-id]
|
||||
(-> (lookup-page state file-id page-id)
|
||||
(get :objects))))
|
||||
|
||||
(defn process-selected-shapes
|
||||
([objects selected]
|
||||
(process-selected-shapes objects selected nil))
|
||||
|
||||
([objects selected {:keys [omit-blocked?] :or {omit-blocked? false}}]
|
||||
(letfn [(selectable? [id]
|
||||
(and (contains? objects id)
|
||||
(or (not omit-blocked?)
|
||||
(not (get-in objects [id :blocked] false)))))]
|
||||
(let [selected (->> selected (cfh/clean-loops objects))]
|
||||
(into (d/ordered-set)
|
||||
(filter selectable?)
|
||||
selected)))))
|
||||
|
||||
;; DEPRECATED
|
||||
(defn lookup-selected-raw
|
||||
[state]
|
||||
(dm/get-in state [:workspace-local :selected]))
|
||||
|
||||
(defn get-selected-ids
|
||||
[state]
|
||||
(dm/get-in state [:workspace-local :selected]))
|
||||
|
||||
(defn lookup-selected
|
||||
([state]
|
||||
(lookup-selected state (:current-page-id state) nil))
|
||||
([state options]
|
||||
(lookup-selected state (:current-page-id state) options))
|
||||
([state page-id options]
|
||||
(let [objects (lookup-page-objects state page-id)
|
||||
selected (dm/get-in state [:workspace-local :selected])]
|
||||
(process-selected-shapes objects selected options))))
|
||||
|
||||
(defn lookup-shape
|
||||
([state id]
|
||||
(lookup-shape state (:current-page-id state) id))
|
||||
|
||||
([state page-id id]
|
||||
(let [objects (lookup-page-objects state page-id)]
|
||||
(get objects id))))
|
||||
|
||||
(defn lookup-shapes
|
||||
([state ids]
|
||||
(lookup-shapes state (:current-page-id state) ids))
|
||||
([state page-id ids]
|
||||
(let [objects (lookup-page-objects state page-id)]
|
||||
(into [] (keep (d/getf objects)) ids))))
|
||||
|
||||
(defn update-file
|
||||
([state f]
|
||||
(update-file state (:current-file-id state) f))
|
||||
([state file-id f]
|
||||
(d/update-in-when state [:files file-id] f)))
|
||||
|
||||
(defn update-page
|
||||
([state f]
|
||||
(update-page state
|
||||
(:current-file-id state)
|
||||
(:current-page-id state)
|
||||
f))
|
||||
([state page-id f]
|
||||
(update-page state
|
||||
(:current-file-id state)
|
||||
page-id
|
||||
f))
|
||||
([state file-id page-id f]
|
||||
(d/update-in-when state [:files file-id :data :pages-index page-id] f)))
|
||||
|
||||
(defn filter-shapes
|
||||
([state filter-fn]
|
||||
(filter-shapes state (:current-page-id state) filter-fn))
|
||||
([state page-id filter-fn]
|
||||
(let [objects (lookup-page-objects state page-id)]
|
||||
(into [] (filter filter-fn) (vals objects)))))
|
||||
|
||||
(defn select-bool-children
|
||||
[state parent-id]
|
||||
(let [objects (lookup-page-objects state)
|
||||
|
||||
shape-modifiers
|
||||
(:workspace-modifiers state)
|
||||
|
||||
content-modifiers
|
||||
(dm/get-in state [:workspace-local :edit-path])]
|
||||
|
||||
(reduce (fn [result id]
|
||||
(if-let [shape (get objects id)]
|
||||
(let [modifiers (dm/get-in shape-modifiers [id :modifiers])
|
||||
shape (if (some? modifiers)
|
||||
(gsh/transform-shape shape modifiers)
|
||||
shape)
|
||||
modifiers (dm/get-in content-modifiers [id :content-modifiers])
|
||||
shape (if (some? modifiers)
|
||||
(update shape :content upc/apply-content-modifiers modifiers)
|
||||
shape)]
|
||||
(assoc result id shape))
|
||||
result))
|
||||
{}
|
||||
(cfh/get-children-ids objects parent-id))))
|
||||
|
||||
(defn get-viewport-center
|
||||
[state]
|
||||
(when-let [{:keys [x y width height]} (get-in state [:workspace-local :vbox])]
|
||||
(gpt/point (+ x (/ width 2)) (+ y (/ height 2)))))
|
|
@ -11,6 +11,7 @@
|
|||
[app.common.logging :as log]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.repo :as rp]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -49,11 +50,7 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(log/dbg :hint "update-file-revn" :file-id (dm/str file-id) :revn revn)
|
||||
(if-let [current-file-id (:current-file-id state)]
|
||||
(if (= file-id current-file-id)
|
||||
(update-in state [:workspace-file :revn] max revn)
|
||||
(d/update-in-when state [:libraries file-id :revn] max revn))
|
||||
state))
|
||||
(dsh/update-file state file-id #(update % :revn max revn)))
|
||||
|
||||
ptk/EffectEvent
|
||||
(effect [_ _ _]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.main.refs :as refs]
|
||||
[app.util.code-beautify :as cb]
|
||||
|
@ -57,7 +57,7 @@
|
|||
(ptk/reify ::update-preview
|
||||
ptk/EffectEvent
|
||||
(effect [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects shape-id)
|
||||
|
||||
all-children
|
||||
|
@ -94,7 +94,7 @@
|
|||
(ptk/reify ::open-preview-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [shape-id (first (wsh/lookup-selected state))
|
||||
(let [shape-id (first (dsh/lookup-selected state))
|
||||
closed-preview (rx/subject)
|
||||
preview (.open js/window "/#/frame-preview")
|
||||
listener-fn #(rx/push! closed-preview true)]
|
||||
|
|
|
@ -330,19 +330,6 @@
|
|||
(rx/map (constantly (refresh-profile)))
|
||||
(rx/catch on-error))))))
|
||||
|
||||
(defn fetch-users
|
||||
[]
|
||||
(letfn [(fetched [users state]
|
||||
(->> users
|
||||
(d/index-by :id)
|
||||
(assoc state :users)))]
|
||||
(ptk/reify ::fetch-team-users
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [team-id (:current-team-id state)]
|
||||
(->> (rp/cmd! :get-team-users {:team-id team-id})
|
||||
(rx/map #(partial fetched %))))))))
|
||||
|
||||
(defn fetch-file-comments-users
|
||||
[{:keys [team-id]}]
|
||||
(dm/assert! (uuid? team-id))
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
[app.common.types.shape :as cts]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.tokens.token-set :as wtts]
|
||||
[app.main.ui.workspace.tokens.update :as wtu]
|
||||
[beicon.v2.core :as rx]
|
||||
|
@ -42,18 +42,15 @@
|
|||
;; TOKENS Getters
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn get-tokens-lib [state]
|
||||
(get-in state [:workspace-data :tokens-lib]))
|
||||
(defn get-tokens-lib
|
||||
[state]
|
||||
(-> (dsh/lookup-file-data state)
|
||||
(get :tokens-lib)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; TOKENS Actions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn get-token-data-from-token-id
|
||||
[id]
|
||||
(let [workspace-data (deref refs/workspace-data)]
|
||||
(get (:tokens workspace-data) id)))
|
||||
|
||||
(defn set-selected-token-set-path
|
||||
[full-path]
|
||||
(ptk/reify ::set-selected-token-set-path
|
||||
|
@ -112,7 +109,8 @@
|
|||
(ptk/reify ::delete-token-theme
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-token-theme group name))]
|
||||
|
@ -178,7 +176,7 @@
|
|||
(ptk/reify ::import-tokens-lib
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
update-token-set-change (some-> lib
|
||||
(ctob/get-sets)
|
||||
(first)
|
||||
|
@ -196,7 +194,7 @@
|
|||
(ptk/reify ::delete-token-set-path
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-token-set-path prefixed-full-set-path))]
|
||||
|
@ -259,7 +257,7 @@
|
|||
(ptk/reify ::delete-token
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-token set-name token-name))]
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
[app.main.data.common :as dcm]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.fonts :as df]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.plugins :as dp]
|
||||
|
@ -67,7 +68,6 @@
|
|||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.texts :as dwtxt]
|
||||
[app.main.data.workspace.thumbnails :as dwth]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
|
@ -174,16 +174,21 @@
|
|||
(ptk/reify ::libraries-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state :libraries (d/index-by :id libraries)))
|
||||
(let [libraries (d/index-by :id libraries)]
|
||||
(update state :files merge libraries)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [file-id (dm/get-in state [:workspace-file :id])
|
||||
ignore-until (dm/get-in state [:workspace-file :ignore-sync-until])
|
||||
needs-check? (some #(and (> (:modified-at %) (:synced-at %))
|
||||
(let [file (dsh/lookup-file state)
|
||||
file-id (get file :id)
|
||||
ignore-until (get file :ignore-sync-until)
|
||||
|
||||
needs-check?
|
||||
(some #(and (> (:modified-at %) (:synced-at %))
|
||||
(or (not ignore-until)
|
||||
(> (:modified-at %) ignore-until)))
|
||||
libraries)]
|
||||
|
||||
(when needs-check?
|
||||
(rx/concat (rx/timer 1000)
|
||||
(rx/of (dwl/notify-sync-file file-id))))))))
|
||||
|
@ -213,21 +218,17 @@
|
|||
(rx/map dwl/library-thumbnails-fetched))))))))))
|
||||
|
||||
(defn- workspace-initialized
|
||||
[]
|
||||
[file-id]
|
||||
(ptk/reify ::workspace-initialized
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc :workspace-undo {})
|
||||
(assoc :workspace-ready true)))
|
||||
(assoc :workspace-ready file-id)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(rx/of
|
||||
(when (and (not (boolean (-> state :profile :props :v2-info-shown)))
|
||||
(features/active-feature? state "components/v2"))
|
||||
(modal/show :v2-info {}))
|
||||
(dp/check-open-plugin)
|
||||
(watch [_ _ _]
|
||||
(rx/of (dp/check-open-plugin)
|
||||
(fdf/fix-deleted-fonts)
|
||||
(fbs/fix-broken-shapes)))))
|
||||
|
||||
|
@ -242,10 +243,10 @@
|
|||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [file-id (:id file)]
|
||||
(-> state
|
||||
(assoc :thumbnails thumbnails)
|
||||
(assoc :workspace-file (dissoc file :data))
|
||||
(assoc :workspace-data (:data file))))
|
||||
(update :files assoc file-id file))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
|
@ -317,11 +318,13 @@
|
|||
(ptk/reify ::initialize-workspace
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc state
|
||||
:recent-colors (:recent-colors storage/user)
|
||||
:workspace-ready false
|
||||
:current-file-id file-id
|
||||
:workspace-presence {}))
|
||||
(-> state
|
||||
(dissoc :files)
|
||||
(dissoc :workspace-ready)
|
||||
(assoc :recent-colors (:recent-colors storage/user))
|
||||
(assoc :recent-fonts (:recent-fonts storage/user))
|
||||
(assoc :current-file-id file-id)
|
||||
(assoc :workspace-presence {})))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
@ -341,7 +344,7 @@
|
|||
(rx/map deref)
|
||||
(rx/mapcat (fn [{:keys [file]}]
|
||||
(rx/of (dpj/initialize-project (:project-id file))
|
||||
(-> (workspace-initialized)
|
||||
(-> (workspace-initialized file-id)
|
||||
(with-meta {:file-id file-id}))))))
|
||||
|
||||
(when-let [component-id (some-> rparams :component-id parse-uuid)]
|
||||
|
@ -388,12 +391,11 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
;; FIXME: revisit
|
||||
(dissoc
|
||||
:current-file-id
|
||||
:workspace-data
|
||||
:workspace-editor-state
|
||||
:workspace-file
|
||||
:libraries
|
||||
:files
|
||||
:workspace-media-objects
|
||||
:workspace-persistence
|
||||
:workspace-presence
|
||||
|
@ -431,7 +433,7 @@
|
|||
(ptk/reify ::initialize-page
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(if-let [{:keys [id] :as page} (dm/get-in state [:workspace-data :pages-index page-id])]
|
||||
(if-let [{:keys [id] :as page} (dsh/lookup-page state page-id)]
|
||||
;; we maintain a cache of page state for user convenience with the exception of the
|
||||
;; selection; when user abandon the current page, the selection is lost
|
||||
(let [local (dm/get-in state [:workspace-cache id] default-workspace-local)]
|
||||
|
@ -483,7 +485,7 @@
|
|||
(cond
|
||||
(some? metadata) (cf/resolve-file-media metadata)
|
||||
(some? fill-image) (cf/resolve-file-media fill-image)))))
|
||||
uris (into #{} xform (wsh/lookup-page-objects state page-id))]
|
||||
uris (into #{} xform (dsh/lookup-page-objects state page-id))]
|
||||
|
||||
(->> (rx/from uris)
|
||||
(rx/subs! #(http/fetch-data-uri % false)))))))
|
||||
|
@ -503,7 +505,9 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [pages (get-in state [:workspace-data :pages-index])
|
||||
(let [pages (-> (dsh/lookup-file-data state)
|
||||
(get :pages-index))
|
||||
|
||||
unames (cfh/get-used-names pages)
|
||||
name (cfh/generate-unique-name unames "Page 1")
|
||||
|
||||
|
@ -518,14 +522,14 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [id (uuid/next)
|
||||
pages (get-in state [:workspace-data :pages-index])
|
||||
fdata (dsh/lookup-file-data state)
|
||||
pages (get fdata :pages-index)
|
||||
page (get pages page-id)
|
||||
|
||||
unames (cfh/get-used-names pages)
|
||||
page (get-in state [:workspace-data :pages-index page-id])
|
||||
name (cfh/generate-unique-name unames (:name page))
|
||||
fdata (:workspace-data state)
|
||||
components-v2 (dm/get-in fdata [:options :components-v2])
|
||||
objects (->> (:objects page)
|
||||
(d/mapm (fn [_ val] (dissoc val :use-for-thumbnail))))
|
||||
objects (update-vals (:objects page) #(dissoc % :use-for-thumbnail))
|
||||
|
||||
main-instances-ids (set (keep #(when (ctk/main-instance? (val %)) (key %)) objects))
|
||||
ids-to-remove (set (apply concat (map #(cfh/get-children-ids objects %) main-instances-ids)))
|
||||
|
||||
|
@ -537,7 +541,7 @@
|
|||
component
|
||||
fdata
|
||||
(gpt/point (:x shape) (:y shape))
|
||||
components-v2
|
||||
true
|
||||
{:keep-ids? true})
|
||||
children (into {} (map (fn [shape] [(:id shape) shape]) new-shapes))
|
||||
objs (assoc objs id new-shape)]
|
||||
|
@ -576,10 +580,9 @@
|
|||
(ptk/reify ::rename-page
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page (get-in state [:workspace-data :pages-index id])
|
||||
(let [page (dsh/lookup-page state id)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/mod-page page {:name name}))]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
(defn set-plugin-data
|
||||
|
@ -599,20 +602,14 @@
|
|||
(ptk/reify ::set-file-plugin-data
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file-data
|
||||
(if (= file-id (:current-file-id state))
|
||||
(:workspace-data state)
|
||||
(get-in state [:libraries file-id :data]))
|
||||
|
||||
changes
|
||||
(-> (pcb/empty-changes it)
|
||||
(let [file-data (dm/get-in state [:files file-id :data])
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-file-data file-data)
|
||||
(assoc :file-id file-id)
|
||||
(pcb/set-plugin-data type id page-id namespace key value))]
|
||||
(rx/of (dch/commit-changes changes)))))))
|
||||
|
||||
(declare purge-page)
|
||||
(declare go-to-file)
|
||||
|
||||
(defn- delete-page-components
|
||||
[changes page]
|
||||
|
@ -633,30 +630,29 @@
|
|||
(ptk/reify ::delete-page
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [components-v2 (features/active-feature? state "components/v2")
|
||||
file-id (:current-file-id state)
|
||||
file (wsh/get-file state file-id)
|
||||
pages (get-in state [:workspace-data :pages])
|
||||
(let [file-id (:current-file-id state)
|
||||
fdata (dsh/lookup-file-data state file-id)
|
||||
pindex (:pages-index fdata)
|
||||
pages (:pages fdata)
|
||||
|
||||
index (d/index-of pages id)
|
||||
page (get-in state [:workspace-data :pages-index id])
|
||||
page (get pindex id)
|
||||
page (assoc page :index index)
|
||||
|
||||
changes (cond-> (pcb/empty-changes it)
|
||||
components-v2
|
||||
(pcb/with-library-data file)
|
||||
components-v2
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data fdata)
|
||||
(delete-page-components page)
|
||||
:always
|
||||
(pcb/del-page page))]
|
||||
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(when (= id (:current-page-id state))
|
||||
(go-to-file)))))))
|
||||
(dcm/go-to-workspace)))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; WORKSPACE File Actions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; FIXME: move to common
|
||||
(defn rename-file
|
||||
[id name]
|
||||
{:pre [(uuid? id) (string? name)]}
|
||||
|
@ -668,7 +664,8 @@
|
|||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-file :name] name))
|
||||
(let [file-id (:current-file-id state)]
|
||||
(assoc-in state [:files file-id :name] name)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
|
@ -752,7 +749,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when-let [shape-id (d/nilv shape-id (dm/get-in state [:workspace-local :shape-for-rename]))]
|
||||
(let [shape (wsh/lookup-shape state shape-id)
|
||||
(let [shape (dsh/lookup-shape state shape-id)
|
||||
name (str/trim name)
|
||||
clean-name (cfh/clean-path name)
|
||||
valid? (and (not (str/ends-with? name "/"))
|
||||
|
@ -782,7 +779,7 @@
|
|||
(ptk/reify ::update-selected-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(let [selected (dsh/lookup-selected state)]
|
||||
(rx/from (map #(update-shape % attrs) selected))))))
|
||||
|
||||
;; --- Delete Selected
|
||||
|
@ -793,7 +790,7 @@
|
|||
(ptk/reify ::delete-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
hover-guides (get-in state [:workspace-guides :hover])]
|
||||
(cond
|
||||
(d/not-empty? selected)
|
||||
|
@ -812,7 +809,7 @@
|
|||
(ptk/reify ::start-rename-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
id (first selected)]
|
||||
(when (= (count selected) 1)
|
||||
(rx/of (dcm/go-to-workspace :layout :layers)
|
||||
|
@ -832,8 +829,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected-ids (wsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected-ids (dsh/lookup-selected state)
|
||||
selected-shapes (map (d/getf objects) selected-ids)
|
||||
undo-id (js/Symbol)
|
||||
|
||||
|
@ -876,7 +873,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
|
||||
;; Ignore any shape whose parent is also intended to be moved
|
||||
ids (cfh/clean-loops objects ids)
|
||||
|
@ -906,7 +903,7 @@
|
|||
(ptk/reify ::relocate-selected-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(let [selected (dsh/lookup-selected state)]
|
||||
(rx/of (relocate-shapes selected parent-id to-index))))))
|
||||
|
||||
(defn start-editing-selected
|
||||
|
@ -914,8 +911,8 @@
|
|||
(ptk/reify ::start-editing-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
objects (wsh/lookup-page-objects state)]
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state)]
|
||||
|
||||
(if (> (count selected) 1)
|
||||
(let [shapes-to-select
|
||||
|
@ -950,8 +947,8 @@
|
|||
(ptk/reify ::select-parent-layer
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
shapes-to-select
|
||||
(->> selected
|
||||
(reduce
|
||||
|
@ -970,7 +967,8 @@
|
|||
(ptk/reify ::relocate-page
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [prev-index (-> (get-in state [:workspace-data :pages])
|
||||
(let [prev-index (-> (dsh/lookup-file-data state)
|
||||
(get :pages)
|
||||
(d/index-of id))
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/move-page id index prev-index))]
|
||||
|
@ -1009,8 +1007,8 @@
|
|||
(ptk/reify ::align-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (or selected (wsh/lookup-selected state))
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (or selected (dsh/lookup-selected state))
|
||||
moved (if (= 1 (count selected))
|
||||
(align-object-to-parent objects (first selected) axis)
|
||||
(align-objects-list objects selected axis))
|
||||
|
@ -1039,8 +1037,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (or ids (wsh/lookup-selected state))
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected (or ids (dsh/lookup-selected state))
|
||||
moved (-> (map #(get objects %) selected)
|
||||
(gal/distribute-space axis))
|
||||
undo-id (js/Symbol)]
|
||||
|
@ -1070,8 +1068,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (wsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected (dsh/lookup-selected state)
|
||||
selected-obj (-> (map #(get objects %) selected))
|
||||
multi (attrs/get-attrs-multi selected-obj [:proportion-lock])
|
||||
multi? (= :multiple (:proportion-lock multi))]
|
||||
|
@ -1157,9 +1155,12 @@
|
|||
(ptk/reify ::show-component-in-assets
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [component-path (cfh/split-path (get-in state [:workspace-data :components component-id :path]))
|
||||
paths (map (fn [i] (cfh/join-path (take (inc i) component-path))) (range (count component-path)))
|
||||
file-id (:current-file-id state)]
|
||||
(let [file-id (:current-file-id state)
|
||||
fdata (dsh/lookup-file-data state file-id)
|
||||
cpath (dm/get-in fdata [:components component-id :path])
|
||||
cpath (cfh/split-path cpath)
|
||||
paths (map (fn [i] (cfh/join-path (take (inc i) cpath)))
|
||||
(range (count cpath)))]
|
||||
(rx/concat
|
||||
(rx/from (map #(set-assets-group-open file-id :components % true) paths))
|
||||
(rx/of (dcm/go-to-workspace :layout :assets)
|
||||
|
@ -1189,8 +1190,8 @@
|
|||
(ptk/reify ::show-shape-context-menu
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
all-selected (into [] (mapcat #(cfh/get-children-with-self objects %)) selected)
|
||||
head (get objects (first selected))
|
||||
|
||||
|
@ -1236,7 +1237,7 @@
|
|||
(ptk/reify ::show-grid-cell-context-menu
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
grid (get objects grid-id)
|
||||
cells (->> (get-in state [:workspace-grid-edition grid-id :selected])
|
||||
(map #(get-in grid [:layout-grid-cells %])))]
|
||||
|
@ -1260,8 +1261,8 @@
|
|||
(defn copy-selected
|
||||
[]
|
||||
(letfn [(sort-selected [state data]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
|
||||
;; Narrow the objects map so it contains only relevant data for
|
||||
;; selected and its parents
|
||||
|
@ -1325,9 +1326,10 @@
|
|||
;; When copying an instance that is nested inside another one, we need to
|
||||
;; advance the shape refs to one or more levels of remote mains.
|
||||
(advance-copies [state selected data]
|
||||
(let [file (wsh/get-local-file-full state)
|
||||
libraries (wsh/get-libraries state)
|
||||
page (wsh/lookup-page state)
|
||||
(let [file (dsh/lookup-file state)
|
||||
libraries (:files state)
|
||||
;; FIXME
|
||||
page (dsh/lookup-page state)
|
||||
heads (mapcat #(ctn/get-child-heads (:objects data) %) selected)]
|
||||
(update data :objects
|
||||
#(reduce (partial advance-copy file libraries page)
|
||||
|
@ -1364,15 +1366,16 @@
|
|||
(catch :default e
|
||||
(on-copy-error e)))
|
||||
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (->> (dsh/lookup-selected state)
|
||||
(cfh/clean-loops objects))
|
||||
features (-> (features/get-team-enabled-features state)
|
||||
(set/difference cfeat/frontend-only-features))
|
||||
|
||||
file-id (:current-file-id state)
|
||||
frame-id (cfh/common-parent-frame objects selected)
|
||||
version (dm/get-in state [:workspace-file :version])
|
||||
file (dsh/lookup-file state file-id)
|
||||
version (get file :version)
|
||||
|
||||
initial {:type :copied-shapes
|
||||
:features features
|
||||
|
@ -1478,7 +1481,7 @@
|
|||
(ptk/reify ::paste-from-event
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
edit-id (dm/get-in state [:workspace-local :edition])
|
||||
is-editing? (and edit-id (= :text (get-in objects [edit-id :type])))]
|
||||
|
||||
|
@ -1516,8 +1519,8 @@
|
|||
(ptk/reify ::copy-selected-css
|
||||
ptk/EffectEvent
|
||||
(effect [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state) (mapv (d/getf objects)))
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (->> (dsh/lookup-selected state) (mapv (d/getf objects)))
|
||||
css (css/generate-style objects selected selected {:with-prelude? false})]
|
||||
(wapi/write-to-clipboard css)))))
|
||||
|
||||
|
@ -1526,8 +1529,8 @@
|
|||
(ptk/reify ::copy-selected-css-nested
|
||||
ptk/EffectEvent
|
||||
(effect [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (->> (dsh/lookup-selected state)
|
||||
(cfh/selected-with-children objects)
|
||||
(mapv (d/getf objects)))
|
||||
css (css/generate-style objects selected selected {:with-prelude? false})]
|
||||
|
@ -1564,14 +1567,14 @@
|
|||
(js/console.error "clipboard blocked:" error)
|
||||
(rx/empty))]
|
||||
|
||||
(let [selected (->> (wsh/lookup-selected state) first)
|
||||
objects (wsh/lookup-page-objects state)]
|
||||
(let [selected (->> (dsh/lookup-selected state) first)
|
||||
objects (dsh/lookup-page-objects state)]
|
||||
|
||||
(when-let [shape (get objects selected)]
|
||||
(let [props (cts/extract-props shape)
|
||||
features (-> (features/get-team-enabled-features state)
|
||||
(set/difference cfeat/frontend-only-features))
|
||||
version (dm/get-in state [:workspace-file :version])
|
||||
version (-> (dsh/lookup-file state) :version)
|
||||
|
||||
copy-data {:type :copied-props
|
||||
:features features
|
||||
|
@ -1628,8 +1631,8 @@
|
|||
(rx/catch on-error))))))
|
||||
|
||||
(defn selected-frame? [state]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
objects (wsh/lookup-page-objects state)]
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state)]
|
||||
|
||||
(and (= 1 (count selected))
|
||||
(= :frame (get-in objects [(first selected) :type])))))
|
||||
|
@ -1643,7 +1646,7 @@
|
|||
(filter #(contains? parent-ids %)))))
|
||||
|
||||
(defn any-same-frame-from-selected? [state frame-ids]
|
||||
(let [selected (first (wsh/lookup-selected state))]
|
||||
(let [selected (first (dsh/lookup-selected state))]
|
||||
(< 0 (count (filter #(= % selected) frame-ids)))))
|
||||
|
||||
(defn frame-same-size?
|
||||
|
@ -1777,7 +1780,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [features (features/get-team-enabled-features state)
|
||||
selected (wsh/lookup-selected state)]
|
||||
selected (dsh/lookup-selected state)]
|
||||
|
||||
(when (paste-data-valid? pdata)
|
||||
(cfeat/check-paste-features! features (:features pdata))
|
||||
|
@ -1841,10 +1844,10 @@
|
|||
change)))
|
||||
|
||||
(calculate-paste-position [state pobjects selected position]
|
||||
(let [page-objects (wsh/lookup-page-objects state)
|
||||
(let [page-objects (dsh/lookup-page-objects state)
|
||||
selected-objs (map (d/getf pobjects) selected)
|
||||
first-selected-obj (first selected-objs)
|
||||
page-selected (wsh/lookup-selected state)
|
||||
page-selected (dsh/lookup-selected state)
|
||||
wrapper (gsh/shapes->rect selected-objs)
|
||||
orig-pos (gpt/point (:x1 wrapper) (:y1 wrapper))
|
||||
frame-id (first page-selected)
|
||||
|
@ -1954,7 +1957,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
page (wsh/lookup-page state)
|
||||
page (dsh/lookup-page state)
|
||||
|
||||
media-idx (->> (:images pdata)
|
||||
(d/index-by :prev-id))
|
||||
|
@ -1972,10 +1975,12 @@
|
|||
|
||||
page-objects (:objects page)
|
||||
|
||||
libraries (wsh/get-libraries state)
|
||||
ldata (wsh/get-local-file state)
|
||||
libraries (dsh/lookup-libraries state)
|
||||
ldata (dsh/lookup-file-data state file-id)
|
||||
|
||||
full-libs (assoc-in libraries [(:id ldata) :data] ldata)
|
||||
;; full-libs (assoc-in libraries [(:id ldata) :data] ldata)
|
||||
|
||||
full-libs libraries
|
||||
|
||||
[parent-id
|
||||
frame-id] (ctn/find-valid-parent-and-frame-ids candidate-parent-id page-objects (vals objects) true full-libs)
|
||||
|
@ -2053,8 +2058,8 @@
|
|||
(cond
|
||||
;; Pasting inside a frame
|
||||
(selected-frame? state)
|
||||
(let [page-selected (wsh/lookup-selected state)
|
||||
page-objects (wsh/lookup-page-objects state)
|
||||
(let [page-selected (dsh/lookup-selected state)
|
||||
page-objects (dsh/lookup-page-objects state)
|
||||
frame-id (first page-selected)
|
||||
frame-object (get page-objects frame-id)]
|
||||
(gsh/shape->center frame-object))
|
||||
|
@ -2133,7 +2138,7 @@
|
|||
(ptk/reify ::paste-image
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [file-id (dm/get-in state [:workspace-file :id])
|
||||
(let [file-id (:current-file-id state)
|
||||
position (calculate-paste-position state)
|
||||
params {:file-id file-id
|
||||
:blobs [image]
|
||||
|
@ -2177,7 +2182,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (or page-id (:current-page-id state))
|
||||
page (wsh/lookup-page state page-id)
|
||||
page (dsh/lookup-page state page-id)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-page page)
|
||||
(pcb/mod-page {:background (:color color)}))]
|
||||
|
@ -2214,12 +2219,24 @@
|
|||
;; Orphan Shapes
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- find-orphan-shapes
|
||||
([state]
|
||||
(find-orphan-shapes state (:current-page-id state)))
|
||||
([state page-id]
|
||||
(let [objects (dsh/lookup-page-objects state page-id)
|
||||
objects (filter (fn [item]
|
||||
(and
|
||||
(not= (key item) uuid/zero)
|
||||
(not (contains? objects (:parent-id (val item))))))
|
||||
objects)]
|
||||
objects)))
|
||||
|
||||
(defn fix-orphan-shapes
|
||||
[]
|
||||
(ptk/reify ::fix-orphan-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [orphans (set (into [] (keys (wsh/find-orphan-shapes state))))]
|
||||
(let [orphans (set (into [] (keys (find-orphan-shapes state))))]
|
||||
(rx/of (relocate-shapes orphans uuid/zero 0 true))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -2254,7 +2271,9 @@
|
|||
(ptk/reify ::update-component-annotation
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data
|
||||
(dsh/lookup-file-data state)
|
||||
|
||||
update-fn
|
||||
(fn [component]
|
||||
;; NOTE: we need to ensure the component exists,
|
||||
|
@ -2265,7 +2284,8 @@
|
|||
(dissoc component :annotation)
|
||||
(assoc component :annotation annotation))))
|
||||
|
||||
changes (-> (pcb/empty-changes it)
|
||||
changes
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/update-component id update-fn))]
|
||||
|
||||
|
@ -2323,7 +2343,7 @@
|
|||
(ptk/reify ::find-components-norefs
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
copies (->> objects
|
||||
vals
|
||||
(filter #(and (ctk/instance-head? %) (not (ctk/main-instance? %)))))
|
||||
|
|
|
@ -16,17 +16,17 @@
|
|||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
(defn selected-shapes-idx
|
||||
[state]
|
||||
(let [objects (wsh/lookup-page-objects state)]
|
||||
(->> (wsh/lookup-selected state)
|
||||
(let [objects (dsh/lookup-page-objects state)]
|
||||
(->> (dsh/lookup-selected state)
|
||||
(cph/clean-loops objects))))
|
||||
|
||||
(defn create-bool-data
|
||||
|
@ -91,9 +91,9 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
name (-> bool-type d/name str/capital)
|
||||
ids (->> (or ids (wsh/lookup-selected state))
|
||||
ids (->> (or ids (dsh/lookup-selected state))
|
||||
(cph/clean-loops objects))
|
||||
ordered-indexes (cph/order-by-indexed-shapes objects ids)
|
||||
shapes (->> ordered-indexes
|
||||
|
@ -121,7 +121,7 @@
|
|||
(ptk/reify ::group-to-bool
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
change-to-bool
|
||||
(fn [shape] (group->bool shape bool-type objects))]
|
||||
(when-not (ctn/has-any-copy-parent? objects (get objects shape-id))
|
||||
|
@ -132,7 +132,7 @@
|
|||
(ptk/reify ::bool-to-group
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
change-to-group
|
||||
(fn [shape] (bool->group shape objects))]
|
||||
(when-not (ctn/has-any-copy-parent? objects (get objects shape-id))
|
||||
|
@ -144,7 +144,7 @@
|
|||
(ptk/reify ::change-bool-type
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
change-type
|
||||
(fn [shape] (assoc shape :bool-type bool-type))]
|
||||
(when-not (ctn/has-any-copy-parent? objects (get objects shape-id))
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
[app.common.types.shape.shadow :refer [check-shadow!]]
|
||||
[app.main.broadcast :as mbc]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.modal :as md]
|
||||
[app.main.data.workspace.layout :as layout]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.util.storage :as storage]
|
||||
|
@ -84,8 +84,7 @@
|
|||
(defn transform-fill
|
||||
([state ids color transform] (transform-fill state ids color transform nil))
|
||||
([state ids color transform options]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
is-text? #(= :text (:type (get objects %)))
|
||||
text-ids (filter is-text? ids)
|
||||
shape-ids (remove is-text? ids)
|
||||
|
@ -135,7 +134,7 @@
|
|||
(ptk/reify ::reorder-fills
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
|
||||
is-text? #(= :text (:type (get objects %)))
|
||||
text-ids (filter is-text? ids)
|
||||
|
@ -234,7 +233,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
is-text? #(= :text (:type (get objects %)))
|
||||
shape-ids (filter (complement is-text?) ids)
|
||||
attrs {:hide-fill-on-export hide-fill-on-export}]
|
||||
|
@ -436,7 +435,7 @@
|
|||
(ptk/reify ::picker-for-selected-shape
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [ids (wsh/lookup-selected state)
|
||||
(let [ids (dsh/lookup-selected state)
|
||||
stop? (rx/filter (ptk/type? ::stop-picker) stream)
|
||||
|
||||
update-events
|
||||
|
@ -541,8 +540,8 @@
|
|||
(ptk/reify ::apply-color-from-palette
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (->> (dsh/lookup-selected state)
|
||||
(cfh/clean-loops objects))
|
||||
|
||||
ids
|
||||
|
@ -716,7 +715,7 @@
|
|||
(ptk/reify ::update-colorpicker
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [shape-id (-> state wsh/lookup-selected first)]
|
||||
(let [shape-id (-> state dsh/lookup-selected first)]
|
||||
(update state :colorpicker
|
||||
(fn [state]
|
||||
(let [current-color (:current-color state)]
|
||||
|
@ -978,8 +977,8 @@
|
|||
(ptk/reify ::select-color
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
shapes (wsh/lookup-shapes state selected)
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
shapes (dsh/lookup-shapes state selected)
|
||||
shape (first shapes)
|
||||
fills (if (cfh/text-shape? shape)
|
||||
(:fills (dwt/current-text-values
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
[app.main.data.comments :as dcmt]
|
||||
[app.main.data.common :as dcm]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.common :as dwco]
|
||||
[app.main.data.workspace.drawing :as dwd]
|
||||
[app.main.data.workspace.edition :as dwe]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.viewport :as dwv]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.router :as rt]
|
||||
|
@ -35,12 +35,11 @@
|
|||
|
||||
(defn initialize-comments
|
||||
[file-id]
|
||||
(dm/assert! (uuid? file-id))
|
||||
(ptk/reify ::initialize-comments
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ stream]
|
||||
(let [stopper (rx/filter #(= ::finalize %) stream)]
|
||||
(rx/merge
|
||||
(let [stopper-s (rx/filter #(= ::finalize %) stream)]
|
||||
(->> (rx/merge
|
||||
(rx/of (dcmt/retrieve-comment-threads file-id))
|
||||
(->> stream
|
||||
(rx/filter mse/mouse-event?)
|
||||
|
@ -49,12 +48,12 @@
|
|||
(rx/with-latest-from ms/keyboard-space)
|
||||
(rx/filter (fn [[_ space]] (not space)))
|
||||
(rx/map first)
|
||||
(rx/map handle-comment-layer-click)
|
||||
(rx/take-until stopper))
|
||||
(rx/map handle-comment-layer-click))
|
||||
(->> stream
|
||||
(rx/filter dwco/interrupt?)
|
||||
(rx/map handle-interrupt)
|
||||
(rx/take-until stopper)))))))
|
||||
(rx/map handle-interrupt)))
|
||||
|
||||
(rx/take-until stopper-s))))))
|
||||
|
||||
(defn- handle-interrupt
|
||||
[]
|
||||
|
@ -65,9 +64,7 @@
|
|||
(cond
|
||||
(:draft local) (rx/of (dcmt/close-thread))
|
||||
(:open local) (rx/of (dcmt/close-thread))
|
||||
|
||||
:else
|
||||
(rx/of (dwe/clear-edition-mode)
|
||||
:else (rx/of (dwe/clear-edition-mode)
|
||||
(dws/deselect-all true)))))))
|
||||
|
||||
;; Event responsible of the what should be executed when user clicked
|
||||
|
@ -139,9 +136,9 @@
|
|||
(ptk/reify ::update-comment-thread-position
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page (wsh/lookup-page state)
|
||||
(let [page (dsh/lookup-page state)
|
||||
page-id (:id page)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
frame-id (if (nil? frame-id)
|
||||
(ctst/get-frame-id-by-position objects (gpt/point new-x new-y))
|
||||
(:frame-id thread))
|
||||
|
@ -172,7 +169,7 @@
|
|||
(ptk/reify ::move-frame-comment-threads
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page (wsh/lookup-page state)
|
||||
(let [page (dsh/lookup-page state)
|
||||
objects (get page :objects)
|
||||
|
||||
is-frame? (fn [id] (= :frame (get-in objects [id :type])))
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.constants :refer [zoom-half-pixel-precision]]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.drawing.common :as common]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.snap :as snap]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.array :as array]
|
||||
|
@ -87,7 +87,7 @@
|
|||
initial (cond-> @ms/mouse-position snap-pixel? (gpt/round-step snap-prec))
|
||||
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
focus (:workspace-focus-selected state)
|
||||
|
||||
fid (->> (ctst/top-nested-frame objects initial)
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
[app.common.math :as mth]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.worker :as uw]
|
||||
[beicon.v2.core :as rx]
|
||||
|
@ -33,7 +33,7 @@
|
|||
(watch [_ state _]
|
||||
(let [tool (dm/get-in state [:workspace-drawing :tool])
|
||||
shape (dm/get-in state [:workspace-drawing :object])
|
||||
objects (wsh/lookup-page-objects state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
page-id (:current-page-id state)]
|
||||
|
||||
(rx/concat
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.drawing.common :as common]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.mouse :as mse]
|
||||
[app.util.path.simplify-curve :as ups]
|
||||
|
@ -51,7 +51,7 @@
|
|||
(ptk/reify ::setup-frame
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
content (dm/get-in state [:workspace-drawing :object :content] [])
|
||||
start (dm/get-in content [0 :params] nil)
|
||||
position (when start (gpt/point start))
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
(ns app.main.data.workspace.edition
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.path.common :as dwpc]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
|||
(ptk/reify ::start-edition-mode
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)]
|
||||
(let [objects (dsh/lookup-page-objects state)]
|
||||
;; Can only edit objects that exist
|
||||
(if (contains? objects id)
|
||||
(-> state
|
||||
|
@ -38,7 +38,10 @@
|
|||
(rx/take 1)
|
||||
(rx/map clear-edition-mode)))))
|
||||
|
||||
;; If these event change modules review /src/app/main/data/workspace/path/undo.cljs
|
||||
;; IMPORTANT: If this event is moved from this namespace to other,
|
||||
;; update namespace reference in the
|
||||
;; app/main/data/workspace/path/undo.cljs file.
|
||||
|
||||
(defn clear-edition-mode
|
||||
[]
|
||||
(ptk/reify ::clear-edition-mode
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.data.workspace.fix-broken-shapes
|
||||
(:require
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
|
@ -39,12 +40,12 @@
|
|||
(ptk/reify ::fix-broken-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [fdata (dsh/lookup-file-data state)
|
||||
changes (concat
|
||||
(mapcat (partial generate-broken-link-changes :page-id)
|
||||
(vals (:pages-index data)))
|
||||
(vals (:pages-index fdata)))
|
||||
(mapcat (partial generate-broken-link-changes :component-id)
|
||||
(vals (:components data))))]
|
||||
(vals (:components fdata))))]
|
||||
|
||||
(if (seq changes)
|
||||
(rx/of (dch/commit-changes
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[app.common.files.helpers :as cfh]
|
||||
[app.common.text :as txt]
|
||||
[app.main.data.changes :as dwc]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.fonts :as fonts]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -91,7 +91,7 @@
|
|||
objects))
|
||||
|
||||
(defn- generate-deleted-font-components-changes
|
||||
[state]
|
||||
[fdata]
|
||||
(sequence
|
||||
(comp (map val)
|
||||
(filter should-fix-deleted-font-component?)
|
||||
|
@ -99,27 +99,29 @@
|
|||
{:type :mod-component
|
||||
:id (:id component)
|
||||
:objects (-> (fix-deleted-font-component component) :objects)})))
|
||||
(wsh/lookup-local-components state)))
|
||||
(:components fdata)))
|
||||
|
||||
(defn- generate-deleted-font-typography-changes
|
||||
[state]
|
||||
[fdata]
|
||||
(sequence
|
||||
(comp (map val)
|
||||
(filter has-invalid-font-family?)
|
||||
(map (fn [typography]
|
||||
{:type :mod-typography
|
||||
:typography (fix-deleted-font-typography typography)})))
|
||||
(get-in state [:workspace-data :typographies])))
|
||||
(:typographies fdata)))
|
||||
|
||||
(defn fix-deleted-fonts
|
||||
[]
|
||||
(ptk/reify ::fix-deleted-fonts
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
shape-changes (mapcat generate-deleted-font-shape-changes (vals (:pages-index data)))
|
||||
components-changes (generate-deleted-font-components-changes state)
|
||||
typography-changes (generate-deleted-font-typography-changes state)
|
||||
(let [fdata (dsh/lookup-file-data state)
|
||||
pages (:pages-index fdata)
|
||||
|
||||
shape-changes (mapcat generate-deleted-font-shape-changes (vals pages))
|
||||
components-changes (generate-deleted-font-components-changes fdata)
|
||||
typography-changes (generate-deleted-font-typography-changes fdata)
|
||||
changes (concat shape-changes
|
||||
components-changes
|
||||
typography-changes)]
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
[app.common.files.changes-builder :as pcb]
|
||||
[app.common.types.grid :as ctg]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
|
@ -26,8 +26,7 @@
|
|||
(ptk/reify ::add-frame-grid
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
page (dm/get-in state [:workspace-data :pages-index page-id])
|
||||
(let [page (dsh/lookup-page state)
|
||||
params (or (dm/get-in page [:default-grids :square])
|
||||
(:square ctg/default-grid-params))
|
||||
grid {:type :square
|
||||
|
@ -56,7 +55,7 @@
|
|||
(ptk/reify ::set-default-grid
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page (wsh/lookup-page state)]
|
||||
(let [page (dsh/lookup-page state)]
|
||||
(rx/of (dch/commit-changes
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/with-page page)
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.rect :as grc]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
(defn hover-grid-cell
|
||||
|
@ -34,7 +34,7 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(if shift?
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
grid (get objects grid-id)
|
||||
selected (or (dm/get-in state [:workspace-grid-edition grid-id :selected]) #{})
|
||||
selected (into selected [cell-id])
|
||||
|
@ -74,7 +74,7 @@
|
|||
(ptk/reify ::clean-selection
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects grid-id)]
|
||||
(update-in state [:workspace-grid-edition grid-id :selected]
|
||||
(fn [selected]
|
||||
|
@ -94,7 +94,7 @@
|
|||
(ptk/reify ::locate-board
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
srect (get-in objects [grid-id :selrect])]
|
||||
(-> state
|
||||
(update :workspace-local
|
||||
|
@ -111,7 +111,7 @@
|
|||
(ptk/reify ::select-track-cells
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
parent (get objects grid-id)
|
||||
|
||||
cells
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -182,7 +182,7 @@
|
|||
(watch [it state _]
|
||||
(let [id (d/nilv id (uuid/next))
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
|
||||
shapes
|
||||
(->> ids
|
||||
|
@ -203,7 +203,7 @@
|
|||
(ptk/reify ::group-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(let [selected (dsh/lookup-selected state)]
|
||||
(rx/of (group-shapes nil selected :change-selection? true))))))
|
||||
|
||||
(defn ungroup-shapes
|
||||
|
@ -212,7 +212,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
|
||||
prepare
|
||||
(fn [shape-id]
|
||||
|
@ -264,7 +264,7 @@
|
|||
(ptk/reify ::ungroup-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(let [selected (dsh/lookup-selected state)]
|
||||
(rx/of (ungroup-shapes selected :change-selection? true))))))
|
||||
|
||||
(defn mask-group
|
||||
|
@ -275,8 +275,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (->> (or ids (wsh/lookup-selected state))
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected (->> (or ids (dsh/lookup-selected state))
|
||||
(cfh/clean-loops objects)
|
||||
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
|
||||
shapes (shapes-for-grouping objects selected)
|
||||
|
@ -323,9 +323,9 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
|
||||
masked-groups (->> (d/nilv ids (wsh/lookup-selected state))
|
||||
masked-groups (->> (d/nilv ids (dsh/lookup-selected state))
|
||||
(map #(get objects %))
|
||||
(filter #(or (= :bool (:type %)) (= :group (:type %)))))
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[app.common.types.page :as ctp]
|
||||
[app.main.data.changes :as dwc]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page (wsh/lookup-page state)
|
||||
(let [page (dsh/lookup-page state)
|
||||
changes
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/with-page page)
|
||||
|
@ -56,7 +56,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page (wsh/lookup-page state)
|
||||
(let [page (dsh/lookup-page state)
|
||||
changes
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/with-page page)
|
||||
|
@ -73,7 +73,7 @@
|
|||
(ptk/reify ::remove-guides
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [{:keys [guides] :as page} (wsh/lookup-page state)
|
||||
(let [{:keys [guides] :as page} (dsh/lookup-page state)
|
||||
guides (-> (select-keys guides ids) (vals))]
|
||||
(rx/from (mapv remove-guide guides))))))
|
||||
|
||||
|
@ -88,7 +88,7 @@
|
|||
(let [ids (:ids args)
|
||||
object-modifiers (:modifiers args)
|
||||
|
||||
objects (wsh/lookup-page-objects state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
|
||||
is-frame? (fn [id] (= :frame (get-in objects [id :type])))
|
||||
frame-ids? (into #{} (filter is-frame?) ids)
|
||||
|
@ -104,7 +104,7 @@
|
|||
guide (update guide :position + (get moved (:axis guide)))]
|
||||
(update-guides guide)))
|
||||
|
||||
guides (-> state wsh/lookup-page :guides vals)]
|
||||
guides (-> state dsh/lookup-page :guides vals)]
|
||||
|
||||
(->> guides
|
||||
(filter (comp frame-ids? :frame-id))
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.mouse :as mse]
|
||||
|
@ -41,8 +41,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page (if page-id
|
||||
(wsh/lookup-page state page-id)
|
||||
(wsh/lookup-page state))
|
||||
(dsh/lookup-page state page-id)
|
||||
(dsh/lookup-page state))
|
||||
|
||||
flows (get page :flows)
|
||||
unames (cfh/get-used-names (vals flows))
|
||||
|
@ -64,7 +64,7 @@
|
|||
(ptk/reify ::add-flow-selected-frame
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(let [selected (dsh/lookup-selected state)]
|
||||
(rx/of (add-flow (first selected)))))))
|
||||
|
||||
(defn remove-flow
|
||||
|
@ -77,8 +77,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page (if page-id
|
||||
(wsh/lookup-page state page-id)
|
||||
(wsh/lookup-page state))]
|
||||
(dsh/lookup-page state page-id)
|
||||
(dsh/lookup-page state))]
|
||||
(rx/of (dch/commit-changes
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/with-page page)
|
||||
|
@ -94,8 +94,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page (if page-id
|
||||
(wsh/lookup-page state page-id)
|
||||
(wsh/lookup-page state))
|
||||
(dsh/lookup-page state page-id)
|
||||
(dsh/lookup-page state))
|
||||
flow (dm/get-in page [:flows flow-id])
|
||||
flow (some-> flow update-fn)]
|
||||
|
||||
|
@ -114,7 +114,7 @@
|
|||
(ptk/reify ::rename-flow
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page (wsh/lookup-page state)]
|
||||
(let [page (dsh/lookup-page state)]
|
||||
(rx/of (update-flow (:id page) flow-id #(assoc % :name name)))))))
|
||||
|
||||
(defn start-rename-flow
|
||||
|
@ -165,7 +165,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
page (wsh/lookup-page state page-id)
|
||||
page (dsh/lookup-page state page-id)
|
||||
objects (get page :objects)
|
||||
frame (cfh/get-root-frame objects (:id shape))
|
||||
|
||||
|
@ -229,7 +229,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
|
||||
remove-interactions-shape
|
||||
(fn [shape]
|
||||
|
@ -258,7 +258,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [initial-pos @ms/mouse-position
|
||||
selected (wsh/lookup-selected state)
|
||||
selected (dsh/lookup-selected state)
|
||||
stopper (mse/drag-stopper stream)]
|
||||
(when (= 1 (count selected))
|
||||
(rx/concat
|
||||
|
@ -270,9 +270,9 @@
|
|||
(defn- get-target-frame
|
||||
[state position]
|
||||
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
from-id (-> state wsh/lookup-selected first)
|
||||
from-shape (wsh/lookup-shape state from-id)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
from-id (-> state dsh/lookup-selected first)
|
||||
from-shape (dsh/lookup-shape state from-id)
|
||||
|
||||
from-frame-id (if (cfh/frame-shape? from-shape)
|
||||
from-id (:frame-id from-shape))
|
||||
|
@ -309,8 +309,8 @@
|
|||
(watch [_ state _]
|
||||
(let [position @ms/mouse-position
|
||||
target-frame (get-target-frame state position)
|
||||
shape-id (-> state wsh/lookup-selected first)
|
||||
shape (wsh/lookup-shape state shape-id)
|
||||
shape-id (-> state dsh/lookup-selected first)
|
||||
shape (dsh/lookup-shape state shape-id)
|
||||
|
||||
change-interaction
|
||||
(fn [interaction]
|
||||
|
@ -368,13 +368,13 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [initial-pos @ms/mouse-position
|
||||
selected (wsh/lookup-selected state)
|
||||
selected (dsh/lookup-selected state)
|
||||
stopper (mse/drag-stopper stream)]
|
||||
(when (= 1 (count selected))
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
shape (->> state
|
||||
wsh/lookup-selected
|
||||
dsh/lookup-selected
|
||||
first
|
||||
(get objects))
|
||||
overlay-pos (-> shape
|
||||
|
@ -418,9 +418,9 @@
|
|||
(gpt/subtract offset))
|
||||
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
shape (->> state
|
||||
wsh/lookup-selected
|
||||
dsh/lookup-selected
|
||||
first
|
||||
(get objects))
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.math :as mth]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -43,8 +43,8 @@
|
|||
(ptk/reify ::set-opacity
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (wsh/lookup-selected state {:omit-blocked? true})
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (dsh/lookup-selected state {:omit-blocked? true})
|
||||
shapes (map #(get objects %) selected)
|
||||
shapes-ids (->> shapes
|
||||
(map :id))]
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
[app.main.data.comments :as dc]
|
||||
[app.main.data.common :as dcm]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.workspace :as-alias dw]
|
||||
|
@ -37,7 +38,6 @@
|
|||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.specialized-panel :as dwsp]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.thumbnails :as dwt]
|
||||
[app.main.data.workspace.transforms :as dwtr]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
|
@ -63,7 +63,7 @@
|
|||
[file-id state]
|
||||
(if (= file-id (:current-file-id state))
|
||||
"<local>"
|
||||
(str "<" (get-in state [:libraries file-id :name]) ">")))
|
||||
(str "<" (get-in state [:files file-id :name]) ">")))
|
||||
|
||||
(defn- log-changes
|
||||
[changes file]
|
||||
|
@ -164,7 +164,7 @@
|
|||
|
||||
(defn- update-color*
|
||||
[it state color file-id]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
[path name] (cfh/parse-path-name (:name color))
|
||||
color (assoc color :path path :name name)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
|
@ -173,7 +173,7 @@
|
|||
undo-id (js/Symbol)]
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dch/commit-changes changes)
|
||||
(sync-file (:current-file-id state) file-id :colors (:id color))
|
||||
(sync-file (:id data) file-id :colors (:id color))
|
||||
(dwu/commit-undo-transaction undo-id))))
|
||||
|
||||
(defn update-color
|
||||
|
@ -212,6 +212,7 @@
|
|||
(let [color (assoc color :name (dm/str (:path color) "/" (:name color)))]
|
||||
(update-color* it state color file-id))))))
|
||||
|
||||
;; FIXME: revisit why file-id is passed on the event
|
||||
(defn rename-color
|
||||
[file-id id new-name]
|
||||
(dm/assert!
|
||||
|
@ -232,7 +233,7 @@
|
|||
(let [new-name (str/trim new-name)]
|
||||
(if (str/empty? new-name)
|
||||
(rx/empty)
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
color (get-in data [:colors id])
|
||||
color (assoc color :name new-name)
|
||||
color (d/without-nils color)]
|
||||
|
@ -247,7 +248,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-color id))]
|
||||
|
@ -288,7 +289,7 @@
|
|||
(if (str/empty? new-name)
|
||||
(rx/empty)
|
||||
(let [[path name] (cfh/parse-path-name new-name)
|
||||
data (get state :workspace-data)
|
||||
data (dsh/lookup-file-data state)
|
||||
object (get-in data [:media id])
|
||||
new-object (assoc object :path path :name name)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
|
@ -308,7 +309,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-media id))]
|
||||
|
@ -337,7 +338,7 @@
|
|||
|
||||
(defn- do-update-tipography
|
||||
[it state typography file-id]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
typography (extract-path-if-missing typography)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
|
@ -373,7 +374,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(when (and (some? new-name) (not= "" new-name))
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
[path name] (cfh/parse-path-name new-name)
|
||||
object (get-in data [:typographies id])
|
||||
new-object (assoc object :path path :name name)]
|
||||
|
@ -388,7 +389,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-typography id))]
|
||||
|
@ -409,7 +410,7 @@
|
|||
(watch [it state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
shapes (dwg/shapes-for-grouping objects selected)
|
||||
parents (into #{} (map :parent-id) shapes)]
|
||||
(when-not (empty? shapes)
|
||||
|
@ -436,8 +437,8 @@
|
|||
(ptk/reify ::add-component
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> (d/nilv ids (wsh/lookup-selected state))
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (->> (d/nilv ids (dsh/lookup-selected state))
|
||||
(cfh/clean-loops objects))
|
||||
selected-objects (map #(get objects %) selected)
|
||||
components-v2 (features/active-feature? state "components/v2")
|
||||
|
@ -454,8 +455,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [components-v2 (features/active-feature? state "components/v2")
|
||||
objects (wsh/lookup-page-objects state)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
selected (->> (dsh/lookup-selected state)
|
||||
(cfh/clean-loops objects))
|
||||
selected-objects (map #(get objects %) selected)
|
||||
;; We don't want to change the structure of component copies
|
||||
|
@ -488,11 +489,9 @@
|
|||
(let [new-name (str/trim new-name)]
|
||||
(if (str/empty? new-name)
|
||||
(rx/empty)
|
||||
(let [library-data (get state :workspace-data)
|
||||
components-v2 (features/active-feature? state "components/v2")
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(cll/generate-rename-component id new-name library-data components-v2))]
|
||||
|
||||
(cll/generate-rename-component id new-name data true))]
|
||||
(rx/of (dch/commit-changes changes))))))))
|
||||
|
||||
(defn rename-component-and-main-instance
|
||||
|
@ -505,10 +504,13 @@
|
|||
valid? (and (not (str/ends-with? name "/"))
|
||||
(string? clean-name)
|
||||
(not (str/blank? clean-name)))
|
||||
component (dm/get-in state [:workspace-data :components component-id])]
|
||||
data (dsh/lookup-file-data state)
|
||||
component (dm/get-in data [:components component-id])]
|
||||
|
||||
(when (and valid? component)
|
||||
(let [shape-id (:main-instance-id component)
|
||||
page-id (:main-instance-page component)]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (rename-component component-id clean-name))
|
||||
|
||||
|
@ -522,7 +524,7 @@
|
|||
(ptk/reify ::duplicate-component
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [libraries (wsh/get-libraries state)
|
||||
(let [libraries (dsh/lookup-libraries state)
|
||||
library (get libraries library-id)
|
||||
components-v2 (features/active-feature? state "components/v2")
|
||||
changes (-> (pcb/empty-changes it nil)
|
||||
|
@ -540,22 +542,22 @@
|
|||
(ptk/reify ::delete-component
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)]
|
||||
(if (features/active-feature? state "components/v2")
|
||||
(let [component (ctkl/get-component data id)
|
||||
(let [file-id (:current-file-id state)
|
||||
fdata (dsh/lookup-file-data state file-id)
|
||||
component (ctkl/get-component fdata id)
|
||||
page-id (:main-instance-page component)
|
||||
root-id (:main-instance-id component)
|
||||
file-id (:current-file-id state)
|
||||
file (wsh/get-file state file-id)
|
||||
page (wsh/lookup-page state page-id)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
components-v2 (features/active-feature? state "components/v2")
|
||||
|
||||
page (dsh/get-page fdata page-id)
|
||||
objects (:objects page)
|
||||
|
||||
undo-group (uuid/next)
|
||||
undo-id (js/Symbol)
|
||||
|
||||
[all-parents changes]
|
||||
(-> (pcb/empty-changes it page-id)
|
||||
;; Deleting main root triggers component delete
|
||||
(cls/generate-delete-shapes file page objects #{root-id} {:components-v2 components-v2
|
||||
(cls/generate-delete-shapes fdata page objects #{root-id} {:components-v2 true
|
||||
:undo-group undo-group
|
||||
:undo-id undo-id}))]
|
||||
(rx/of
|
||||
|
@ -564,13 +566,7 @@
|
|||
(dc/detach-comment-thread #{root-id})
|
||||
(dch/commit-changes changes)
|
||||
(ptk/data-event :layout/update {:ids all-parents :undo-group undo-group})
|
||||
(dwu/commit-undo-transaction undo-id)))
|
||||
(let [page-id (:current-page-id state)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/delete-component id page-id))]
|
||||
(rx/of (dch/commit-changes changes))))))))
|
||||
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
(defn restore-component
|
||||
"Restore a deleted component, with the given id, in the given file library."
|
||||
|
@ -581,11 +577,13 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
current-page (dm/get-in state [:workspace-data :pages-index page-id])
|
||||
library-data (wsh/get-file state library-id)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
page (dsh/lookup-page state page-id)
|
||||
objects (:objects page)
|
||||
|
||||
ldata (dsh/lookup-file-data state library-id)
|
||||
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(cll/generate-restore-component library-data component-id library-id current-page objects))]
|
||||
(cll/generate-restore-component ldata component-id library-id page objects))]
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
|
||||
|
@ -614,8 +612,8 @@
|
|||
(ptk/reify ::instantiate-component
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page (wsh/lookup-page state)
|
||||
libraries (wsh/get-libraries state)
|
||||
(let [page (dsh/lookup-page state)
|
||||
libraries (dsh/lookup-libraries state)
|
||||
|
||||
objects (:objects page)
|
||||
changes (-> (pcb/empty-changes it (:id page))
|
||||
|
@ -637,8 +635,7 @@
|
|||
(when id-ref
|
||||
(reset! id-ref (:id new-shape)))
|
||||
|
||||
(rx/of (ptk/event
|
||||
::ev/event
|
||||
(rx/of (ptk/event ::ev/event
|
||||
{::ev/name "use-library-component"
|
||||
::ev/origin origin
|
||||
:external-library (not= file-id current-file-id)})
|
||||
|
@ -658,12 +655,14 @@
|
|||
(ptk/reify ::detach-component
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file (wsh/get-local-file state)
|
||||
page-id (get state :current-page-id)
|
||||
libraries (wsh/get-libraries state)
|
||||
(let [page-id (:current-page-id state)
|
||||
file-id (:current-file-id state)
|
||||
|
||||
fdata (dsh/lookup-file-data state file-id)
|
||||
libraries (dsh/lookup-libraries state)
|
||||
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(cll/generate-detach-component id file page-id libraries))]
|
||||
(cll/generate-detach-component id fdata page-id libraries))]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
|
@ -685,20 +684,27 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
file (wsh/get-local-file state)
|
||||
libraries (wsh/get-libraries state)
|
||||
file-id (:current-file-id state)
|
||||
|
||||
;; FIXME: revisit, innefficient access
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
|
||||
libraries (dsh/lookup-libraries state)
|
||||
fdata (dsh/lookup-file-data state file-id)
|
||||
|
||||
selected (->> state
|
||||
(wsh/lookup-selected)
|
||||
(dsh/lookup-selected)
|
||||
(cfh/clean-loops objects))
|
||||
|
||||
selected-objects (map #(get objects %) selected)
|
||||
copies (filter ctk/in-component-copy? selected-objects)
|
||||
can-detach? (and (seq copies)
|
||||
(every? #(not (ctn/has-any-copy-parent? objects %)) selected-objects))
|
||||
|
||||
changes (when can-detach?
|
||||
(reduce
|
||||
(fn [changes id]
|
||||
(cll/generate-detach-component changes id file page-id libraries))
|
||||
(cll/generate-detach-component changes id fdata page-id libraries))
|
||||
(pcb/empty-changes it)
|
||||
selected))]
|
||||
|
||||
|
@ -725,6 +731,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [current-page-id (:current-page-id state)
|
||||
data (dsh/lookup-file-data state)
|
||||
|
||||
select-and-zoom
|
||||
(fn [shape-id]
|
||||
|
@ -741,7 +748,7 @@
|
|||
(rx/observe-on :async)
|
||||
(rx/mapcat (fn [_] (select-and-zoom shape-id))))))]
|
||||
|
||||
(when-let [component (dm/get-in state [:workspace-data :components id])]
|
||||
(when-let [component (dm/get-in data [:components id])]
|
||||
(let [page-id (:main-instance-page component)
|
||||
shape-id (:main-instance-id component)]
|
||||
(when (some? page-id)
|
||||
|
@ -779,9 +786,9 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(update-in [:libraries library-id]
|
||||
(update-in [:files library-id]
|
||||
assoc :modified-at modified-at :revn revn)
|
||||
(d/update-in-when [:libraries library-id :data]
|
||||
(d/update-in-when [:files library-id :data]
|
||||
ch/process-changes changes)))
|
||||
|
||||
ptk/WatchEvent
|
||||
|
@ -805,28 +812,23 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(log/info :msg "RESET-COMPONENT of shape" :id (str id))
|
||||
(let [file (wsh/get-local-file state)
|
||||
file-full (wsh/get-local-file-full state)
|
||||
libraries (wsh/get-libraries state)
|
||||
|
||||
(let [libraries (:files state)
|
||||
page-id (:current-page-id state)
|
||||
container (ctn/get-container file :page page-id)
|
||||
|
||||
components-v2
|
||||
(features/active-feature? state "components/v2")
|
||||
file (dsh/lookup-file state)
|
||||
data (:data file)
|
||||
|
||||
container (ctn/get-container data :page page-id)
|
||||
undo-id (js/Symbol)
|
||||
|
||||
changes
|
||||
(-> (pcb/empty-changes it)
|
||||
(cll/generate-reset-component file-full libraries container id components-v2))]
|
||||
(cll/generate-reset-component file libraries container id true))]
|
||||
|
||||
(log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes
|
||||
(:redo-changes changes)
|
||||
file))
|
||||
|
||||
(rx/of
|
||||
(dwu/start-undo-transaction undo-id)
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dch/commit-changes changes)
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
|
@ -859,24 +861,24 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(log/info :msg "UPDATE-COMPONENT of shape" :id (str id) :undo-group undo-group)
|
||||
(let [page-id (get state :current-page-id)
|
||||
local-file (wsh/get-local-file state)
|
||||
full-file (wsh/get-local-file-full state)
|
||||
container (ctn/get-container local-file :page page-id)
|
||||
shape (ctn/get-shape container id)
|
||||
components-v2 (features/active-feature? state "components/v2")]
|
||||
(let [page-id (:current-page-id state)
|
||||
|
||||
libraries (dsh/lookup-libraries state)
|
||||
file (dsh/lookup-file state)
|
||||
fdata (:data file)
|
||||
|
||||
container (ctn/get-container fdata :page page-id)
|
||||
shape (ctn/get-shape container id)]
|
||||
|
||||
(when (ctk/instance-head? shape)
|
||||
(let [libraries (wsh/get-libraries state)
|
||||
|
||||
changes
|
||||
(let [changes
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/set-undo-group undo-group)
|
||||
(pcb/with-container container)
|
||||
(cll/generate-sync-shape-inverse full-file libraries container id components-v2))
|
||||
(cll/generate-sync-shape-inverse fdata libraries container id true))
|
||||
|
||||
file-id (:component-file shape)
|
||||
file (wsh/get-file state file-id)
|
||||
ldata (->> (:component-file shape)
|
||||
(dsh/lookup-file-data state))
|
||||
|
||||
xf-filter (comp
|
||||
(filter :local-change?)
|
||||
|
@ -897,26 +899,22 @@
|
|||
(log/debug :msg "UPDATE-COMPONENT finished"
|
||||
:js/local-changes (log-changes
|
||||
(:redo-changes local-changes)
|
||||
file)
|
||||
fdata)
|
||||
:js/nonlocal-changes (log-changes
|
||||
(:redo-changes nonlocal-changes)
|
||||
file))
|
||||
fdata))
|
||||
|
||||
(rx/of
|
||||
(when (seq (:redo-changes local-changes))
|
||||
(dch/commit-changes (assoc local-changes
|
||||
:file-id (:id local-file))))
|
||||
:file-id (:id file))))
|
||||
(when (seq (:redo-changes nonlocal-changes))
|
||||
(dch/commit-changes (assoc nonlocal-changes
|
||||
:file-id file-id)))))))))))
|
||||
:file-id (:id ldata))))))))))))
|
||||
|
||||
(defn- update-component-thumbnail-sync
|
||||
[state component-id file-id tag]
|
||||
(let [current-file-id (:current-file-id state)
|
||||
current-file? (= current-file-id file-id)
|
||||
data (if current-file?
|
||||
(get state :workspace-data)
|
||||
(get-in state [:libraries file-id :data]))
|
||||
(let [data (dsh/lookup-file-data state file-id)
|
||||
component (ctkl/get-component data component-id)
|
||||
page-id (:main-instance-page component)
|
||||
root-id (:main-instance-id component)]
|
||||
|
@ -930,7 +928,8 @@
|
|||
(watch [_ state _]
|
||||
(let [current-file-id (:current-file-id state)
|
||||
current-file? (= current-file-id file-id)
|
||||
page (wsh/lookup-page state)
|
||||
|
||||
page (dsh/lookup-page state)
|
||||
shape (ctn/get-shape page shape-id)
|
||||
component-id (:component-id shape)
|
||||
undo-id (js/Symbol)]
|
||||
|
@ -995,12 +994,13 @@
|
|||
(watch [it state _]
|
||||
;; First delete shapes so we have space in the layout otherwise we can have problems
|
||||
;; in the grid creating new rows/columns to make space
|
||||
(let [file (wsh/get-file state file-id)
|
||||
libraries (wsh/get-libraries state)
|
||||
page (wsh/lookup-page state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
(let [libraries (dsh/lookup-libraries state)
|
||||
page (dsh/lookup-page state)
|
||||
objects (:objects page)
|
||||
parent (get objects (:parent-id shape))
|
||||
|
||||
ldata (dsh/lookup-file-data state file-id)
|
||||
|
||||
;; If the target parent is a grid layout we need to pass the target cell
|
||||
target-cell (when (ctl/grid-layout? parent)
|
||||
(ctl/get-cell-by-shape-id parent (:id shape)))
|
||||
|
@ -1016,7 +1016,7 @@
|
|||
[new-shape all-parents changes]
|
||||
(-> (pcb/empty-changes it (:id page))
|
||||
(pcb/set-undo-group undo-group)
|
||||
(cll/generate-component-swap objects shape file page libraries id-new-component index target-cell keep-props-values))]
|
||||
(cll/generate-component-swap objects shape ldata page libraries id-new-component index target-cell keep-props-values))]
|
||||
|
||||
(rx/of
|
||||
(dwu/start-undo-transaction undo-id)
|
||||
|
@ -1086,7 +1086,7 @@
|
|||
(update [_ state]
|
||||
(if (and (not= library-id (:current-file-id state))
|
||||
(nil? asset-id))
|
||||
(d/assoc-in-when state [:libraries library-id :synced-at] (dt/now))
|
||||
(d/assoc-in-when state [:files library-id :synced-at] (dt/now))
|
||||
state))
|
||||
|
||||
ptk/WatchEvent
|
||||
|
@ -1098,8 +1098,8 @@
|
|||
:asset-type asset-type
|
||||
:asset-id asset-id
|
||||
:undo-group undo-group)
|
||||
(let [file (wsh/get-file state file-id)
|
||||
libraries (wsh/get-libraries state)
|
||||
(let [ldata (dsh/lookup-file-data state file-id)
|
||||
libraries (dsh/lookup-libraries state)
|
||||
current-file-id (:current-file-id state)
|
||||
|
||||
changes (cll/generate-sync-file-changes
|
||||
|
@ -1113,7 +1113,7 @@
|
|||
current-file-id)
|
||||
|
||||
find-frames (fn [change]
|
||||
(->> (ch/frames-changed file change)
|
||||
(->> (ch/frames-changed ldata change)
|
||||
(map #(assoc %1 :page-id (:page-id change)))))
|
||||
|
||||
updated-frames (->> changes
|
||||
|
@ -1123,7 +1123,7 @@
|
|||
|
||||
(log/debug :msg "SYNC-FILE finished" :js/rchanges (log-changes
|
||||
(:redo-changes changes)
|
||||
file))
|
||||
ldata))
|
||||
(rx/concat
|
||||
(rx/of (set-updating-library false)
|
||||
(ntf/hide {:tag :sync-dialog}))
|
||||
|
@ -1161,7 +1161,8 @@
|
|||
(ptk/reify ::ignore-sync
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-file :ignore-sync-until] (dt/now)))
|
||||
(let [file-id (:current-file-id state)]
|
||||
(assoc-in state [:files file-id :ignore-sync-until] (dt/now))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
|
@ -1175,11 +1176,13 @@
|
|||
"Get a lazy sequence of all the assets of each type in the library that have
|
||||
been modified after the last sync of the library. The sync date may be
|
||||
overriden by providing a ignore-until parameter."
|
||||
([library file-data] (assets-need-sync library file-data nil))
|
||||
([library file-data]
|
||||
(assets-need-sync library file-data nil))
|
||||
([library file-data ignore-until]
|
||||
(when (not= (:id library) (:id file-data))
|
||||
(let [sync-date (max (:synced-at library) (or ignore-until 0))]
|
||||
(when (> (:modified-at library) sync-date)
|
||||
(ctf/used-assets-changed-since file-data library sync-date)))))
|
||||
(ctf/used-assets-changed-since file-data library sync-date))))))
|
||||
|
||||
(defn notify-sync-file
|
||||
[file-id]
|
||||
|
@ -1187,17 +1190,28 @@
|
|||
(ptk/reify ::notify-sync-file
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [file-data (:workspace-data state)
|
||||
ignore-until (dm/get-in state [:workspace-file :ignore-sync-until])
|
||||
libraries-need-sync (filter #(seq (assets-need-sync % file-data ignore-until))
|
||||
(vals (get state :libraries)))
|
||||
do-more-info #(modal/show! :libraries-dialog {:starting-tab "updates"})
|
||||
do-update #(do (apply st/emit! (map (fn [library]
|
||||
(let [file (dm/get-in state [:files file-id])
|
||||
file-data (get file :data)
|
||||
ignore-until (get file :ignore-sync-until)
|
||||
|
||||
|
||||
;; FIXME: syntax of this can be improved
|
||||
libraries-need-sync
|
||||
(filter #(seq (assets-need-sync % file-data ignore-until))
|
||||
(vals (get state :files)))
|
||||
|
||||
do-more-info
|
||||
#(modal/show! :libraries-dialog {:starting-tab "updates"})
|
||||
|
||||
do-update
|
||||
#(do (apply st/emit! (map (fn [library]
|
||||
(sync-file (:current-file-id state)
|
||||
(:id library)))
|
||||
libraries-need-sync))
|
||||
(st/emit! (ntf/hide)))
|
||||
do-dismiss #(do (st/emit! ignore-sync)
|
||||
|
||||
do-dismiss
|
||||
#(do (st/emit! ignore-sync)
|
||||
(st/emit! (ntf/hide)))]
|
||||
|
||||
(when (seq libraries-need-sync)
|
||||
|
@ -1227,7 +1241,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (dsh/lookup-file-data state)
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/update-component id #(assoc % :modified-at (dt/now))))]
|
||||
|
@ -1351,7 +1365,7 @@
|
|||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-file :is-shared] is-shared))
|
||||
(update-in state [:files id] assoc :is-shared is-shared))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
|
@ -1377,7 +1391,7 @@
|
|||
(let [libraries (:workspace-shared-files state)
|
||||
library (d/seek #(= (:id %) library-id) libraries)]
|
||||
(if library
|
||||
(update state :libraries assoc library-id (dissoc library :library-summary))
|
||||
(update state :files assoc library-id (dissoc library :library-summary))
|
||||
state)))
|
||||
|
||||
ptk/WatchEvent
|
||||
|
@ -1389,9 +1403,10 @@
|
|||
(rx/ignore))
|
||||
(->> (rp/cmd! :get-file {:id library-id :features features})
|
||||
(rx/merge-map fpmap/resolve-file)
|
||||
;; FIXME: this should call the libraries-fetched event instead of ad-hoc assoc event
|
||||
(rx/map (fn [file]
|
||||
(fn [state]
|
||||
(assoc-in state [:libraries library-id] file)))))
|
||||
(assoc-in state [:files library-id] file)))))
|
||||
(->> (rp/cmd! :get-file-object-thumbnails {:file-id library-id :tag "component"})
|
||||
(rx/map (fn [thumbnails]
|
||||
(fn [state]
|
||||
|
@ -1409,7 +1424,7 @@
|
|||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(d/dissoc-in state [:libraries library-id]))
|
||||
(update state :files dissoc library-id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
|
|
|
@ -21,11 +21,11 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.media :as dmm]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.svg-upload :as svg]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
|
@ -266,9 +266,11 @@
|
|||
(on-success image)
|
||||
(dmm/notify-finished-loading))
|
||||
|
||||
file-id (:current-file-id state)
|
||||
|
||||
prepare
|
||||
(fn [content]
|
||||
{:file-id (get-in state [:workspace-file :id])
|
||||
{:file-id file-id
|
||||
:name (if (dmm/file? content) (.-name content) (tr "media.image"))
|
||||
:is-local false
|
||||
:content content})]
|
||||
|
@ -399,22 +401,31 @@
|
|||
(ptk/reify ::process-img-component
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file-data (wsh/get-local-file state)
|
||||
page (wsh/lookup-page state)
|
||||
pos (wsh/viewport-center state)]
|
||||
(let [file-id (:current-file-id state)
|
||||
page-id (:current-page-id state)
|
||||
|
||||
fdata (dsh/lookup-file-data state file-id)
|
||||
page (dsh/get-page fdata page-id)
|
||||
pos (dsh/get-viewport-center state)]
|
||||
|
||||
(->> (create-shapes-img pos media-obj)
|
||||
(rx/map (partial add-shapes-and-component it file-data page (:name media-obj))))))))
|
||||
(rx/map (partial add-shapes-and-component it fdata page (:name media-obj))))))))
|
||||
|
||||
(defn- process-svg-component
|
||||
[svg-data]
|
||||
(ptk/reify ::process-svg-component
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file-data (wsh/get-local-file state)
|
||||
page (wsh/lookup-page state)
|
||||
pos (wsh/viewport-center state)]
|
||||
(->> (create-shapes-svg (:id file-data) (:objects page) pos svg-data)
|
||||
(rx/map (partial add-shapes-and-component it file-data page (:name svg-data))))))))
|
||||
|
||||
(let [file-id (:current-file-id state)
|
||||
page-id (:current-page-id state)
|
||||
|
||||
fdata (dsh/lookup-file-data state file-id)
|
||||
page (dsh/get-page fdata page-id)
|
||||
pos (dsh/get-viewport-center state)]
|
||||
|
||||
(->> (create-shapes-svg file-id (:objects page) pos svg-data)
|
||||
(rx/map (partial add-shapes-and-component it fdata page (:name svg-data))))))))
|
||||
|
||||
(defn upload-media-components
|
||||
[params]
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.constants :refer [zoom-half-pixel-precision]]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.comments :as-alias dwcm]
|
||||
[app.main.data.workspace.guides :as-alias dwg]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -335,7 +335,7 @@
|
|||
|
||||
([state ignore-constraints ignore-snap-pixel modif-tree params]
|
||||
(let [objects
|
||||
(wsh/lookup-page-objects state)
|
||||
(dsh/lookup-page-objects state)
|
||||
|
||||
snap-pixel?
|
||||
(and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))
|
||||
|
@ -355,7 +355,7 @@
|
|||
(defn- calculate-update-modifiers
|
||||
[old-modif-tree state ignore-constraints ignore-snap-pixel modif-tree]
|
||||
(let [objects
|
||||
(wsh/lookup-page-objects state)
|
||||
(dsh/lookup-page-objects state)
|
||||
|
||||
snap-pixel?
|
||||
(and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))
|
||||
|
@ -421,7 +421,7 @@
|
|||
(ptk/reify ::set-rotation-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
ids (sequence xf-rotation-shape shapes)
|
||||
|
||||
get-modifier
|
||||
|
@ -442,7 +442,7 @@
|
|||
(ptk/reify ::set-delta-rotation-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
ids
|
||||
(->> shapes
|
||||
(remove #(get % :blocked false))
|
||||
|
@ -473,7 +473,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [text-modifiers (get state :workspace-text-modifier)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
|
||||
object-modifiers
|
||||
(if (some? modifiers)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.common :as dc]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.plugins :as dpl]
|
||||
[app.main.data.websocket :as dws]
|
||||
|
@ -273,7 +274,7 @@
|
|||
[:file-id ::sm/uuid]
|
||||
[:vern :int]])
|
||||
|
||||
(def ^:private check-file-restore-params!
|
||||
(def ^:private check-file-restore-params
|
||||
(sm/check-fn schema:handle-file-restore))
|
||||
|
||||
(defn handle-file-restore
|
||||
|
@ -281,15 +282,17 @@
|
|||
|
||||
(dm/assert!
|
||||
"expected valid parameters"
|
||||
(check-file-restore-params! msg))
|
||||
(check-file-restore-params msg))
|
||||
|
||||
(ptk/reify ::handle-file-restore
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [curr-file-id (:current-file-id state)
|
||||
curr-vern (dm/get-in state [:workspace-file :vern])
|
||||
reload? (and (= file-id curr-file-id) (not= vern curr-vern))]
|
||||
(when reload?
|
||||
file (dsh/lookup-file state curr-file-id)
|
||||
curr-vern (:vern file)]
|
||||
|
||||
(when (and (= file-id curr-file-id)
|
||||
(not= vern curr-vern))
|
||||
(rx/of (ptk/event ::dw/reload-current-file)))))))
|
||||
|
||||
(def ^:private schema:handle-library-change
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.files.changes-builder :as pcb]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.path.common :refer [check-path-content!]]
|
||||
[app.main.data.workspace.path.helpers :as helpers]
|
||||
[app.main.data.workspace.path.state :as st]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
|
@ -83,7 +83,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
page-id (:current-page-id state)
|
||||
id (get-in state [:workspace-local :edition])
|
||||
old-content (get-in state [:workspace-local :edit-path id :old-content])
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.drawing.common :as dwdc]
|
||||
[app.main.data.workspace.edition :as dwe]
|
||||
[app.main.data.workspace.path.changes :as changes]
|
||||
|
@ -24,7 +25,6 @@
|
|||
[app.main.data.workspace.path.streams :as streams]
|
||||
[app.main.data.workspace.path.undo :as undo]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.util.mouse :as mse]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -252,7 +252,7 @@
|
|||
(ptk/reify ::setup-frame
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
content (get-in state [:workspace-drawing :object :content] [])
|
||||
position (gpt/point (get-in content [0 :params] nil))
|
||||
frame-id (->> (ctst/top-nested-frame objects position)
|
||||
|
@ -321,11 +321,10 @@
|
|||
(ptk/reify ::start-draw-mode
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [id (get-in state [:workspace-local :edition])
|
||||
page-id (:current-page-id state)
|
||||
old-content (get-in state [:workspace-data :pages-index page-id :objects id :content])]
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :edit-path id :old-content] old-content))))
|
||||
(let [id (dm/get-in state [:workspace-local :edition])
|
||||
objects (dsh/lookup-page-objects state)
|
||||
content (dm/get-in objects [id :content])]
|
||||
(update-in state [:workspace-local :edit-path id] assoc :old-content content)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[app.common.svg.path.shapes-to-path :as upsp]
|
||||
[app.common.svg.path.subpath :as ups]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.edition :as dwe]
|
||||
[app.main.data.workspace.path.changes :as changes]
|
||||
[app.main.data.workspace.path.drawing :as drawing]
|
||||
|
@ -24,7 +25,6 @@
|
|||
[app.main.data.workspace.path.streams :as streams]
|
||||
[app.main.data.workspace.path.undo :as undo]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.mouse :as mse]
|
||||
[app.util.path.tools :as upt]
|
||||
|
@ -50,7 +50,7 @@
|
|||
(ptk/reify ::apply-content-modifiers
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
|
||||
id (st/get-path-id state)
|
||||
page-id (:current-page-id state)
|
||||
|
@ -294,7 +294,7 @@
|
|||
(ptk/reify ::start-path-edit
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
edit-path (dm/get-in state [:workspace-local :edit-path id])
|
||||
content (st/get-path state :content)
|
||||
state (cond-> state
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[app.common.svg.path.shapes-to-path :as upsp]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
|
@ -23,8 +23,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
selected (->> (or ids (wsh/lookup-selected state))
|
||||
objects (dsh/lookup-page-objects state)
|
||||
selected (->> (or ids (dsh/lookup-selected state))
|
||||
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
|
||||
|
||||
children-ids
|
||||
|
|
|
@ -51,12 +51,11 @@
|
|||
|
||||
(defn get-path-location
|
||||
[state & ks]
|
||||
(let [edit-id (get-in state [:workspace-local :edition])
|
||||
page-id (:current-page-id state)]
|
||||
(into (if edit-id
|
||||
[:workspace-data :pages-index page-id :objects edit-id]
|
||||
[:workspace-drawing :object])
|
||||
ks)))
|
||||
(if-let [edit-id (dm/get-in state [:workspace-local :edition])]
|
||||
(let [page-id (:current-page-id state)
|
||||
file-id (:current-file-id state)]
|
||||
(into [:files file-id :data :pages-index page-id :objects edit-id] ks))
|
||||
(into [:workspace-drawing :object] ks)))
|
||||
|
||||
(defn get-path
|
||||
"Retrieves the location of the path object and additionally can pass
|
||||
|
@ -66,7 +65,6 @@
|
|||
shape (-> (get-in state path-loc)
|
||||
;; Empty map because we know the current shape will not have children
|
||||
(upsp/convert-to-path {}))]
|
||||
|
||||
(if (empty? ks)
|
||||
shape
|
||||
(get-in shape ks))))
|
||||
|
@ -74,5 +72,4 @@
|
|||
(defn set-content
|
||||
[state content]
|
||||
(let [path-loc (get-path-location state :content)]
|
||||
(-> state
|
||||
(assoc-in path-loc content))))
|
||||
(assoc-in state path-loc content)))
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
[app.common.svg.path.shapes-to-path :as upsp]
|
||||
[app.common.svg.path.subpath :as ups]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.edition :as dwe]
|
||||
[app.main.data.workspace.path.changes :as changes]
|
||||
[app.main.data.workspace.path.state :as st]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.util.path.tools :as upt]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -26,7 +26,7 @@
|
|||
(ptk/reify ::process-path-tool
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
id (st/get-path-id state)
|
||||
page-id (:current-page-id state)
|
||||
shape (st/get-path state)
|
||||
|
|
|
@ -132,8 +132,9 @@
|
|||
dissoc :undo-lock :undo-stack)))))
|
||||
|
||||
(defn- stop-undo? [event]
|
||||
(or (= :app.main.data.workspace.common/clear-edition-mode (ptk/type event))
|
||||
(= :app.main.data.workspace/finalize-page (ptk/type event))))
|
||||
(let [type (ptk/type event)]
|
||||
(or (= :app.main.data.workspace.edition/clear-edition-mode type)
|
||||
(= :app.main.data.workspace/finalize-page type))))
|
||||
|
||||
(def path-content-ref
|
||||
(letfn [(selector [state]
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.modal :as md]
|
||||
[app.main.data.workspace.collapse :as dwc]
|
||||
[app.main.data.workspace.specialized-panel :as-alias dwsp]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.zoom :as dwz]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -140,9 +140,9 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected-id (wsh/lookup-selected state)
|
||||
selected (wsh/lookup-shapes state selected-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected-id (dsh/lookup-selected state)
|
||||
selected (dsh/lookup-shapes state selected-id)
|
||||
frame-ids (map (fn [item] (let [parent (cfh/get-frame objects (:id item))]
|
||||
(:id parent))) selected)
|
||||
params-without-board (-> (rt/get-params state)
|
||||
|
@ -162,11 +162,11 @@
|
|||
(ptk/reify ::select-prev-shape
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
count-selected (count selected)
|
||||
first-selected (first selected)
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
current (get objects first-selected)
|
||||
parent (get objects (:parent-id current))
|
||||
sibling-ids (:shapes parent)
|
||||
|
@ -187,11 +187,11 @@
|
|||
(ptk/reify ::select-next-shape
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
count-selected (count selected)
|
||||
first-selected (first selected)
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
current (get objects first-selected)
|
||||
parent (get objects (:parent-id current))
|
||||
sibling-ids (:shapes parent)
|
||||
|
@ -230,10 +230,10 @@
|
|||
(rx/of ::dwsp/interrupt))
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (or objects (wsh/lookup-page-objects state))
|
||||
(let [objects (or objects (dsh/lookup-page-objects state))
|
||||
append-to-selection (cfh/expand-region-selection objects (into #{} [(get-in state [:workspace-local :last-selected]) id]))
|
||||
selection (-> state
|
||||
wsh/lookup-selected
|
||||
dsh/lookup-selected
|
||||
(conj id))]
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :selected]
|
||||
|
@ -250,7 +250,7 @@
|
|||
(ptk/reify ::select-shapes
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
focus (:workspace-focus-selected state)
|
||||
ids (if (d/not-empty? focus)
|
||||
(cpf/filter-not-focus objects focus ids)
|
||||
|
@ -259,7 +259,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)]
|
||||
(let [objects (dsh/lookup-page-objects state)]
|
||||
(rx/of
|
||||
(dwc/expand-all-parents ids objects)
|
||||
::dwsp/interrupt)))))
|
||||
|
@ -273,11 +273,11 @@
|
|||
;; case delimit the objects to the focused shapes if focus
|
||||
;; mode is active
|
||||
focus (:workspace-focus-selected state)
|
||||
objects (-> (wsh/lookup-page-objects state)
|
||||
objects (-> (dsh/lookup-page-objects state)
|
||||
(cpf/focus-objects focus))
|
||||
|
||||
lookup (d/getf objects)
|
||||
parents (->> (wsh/lookup-selected state)
|
||||
parents (->> (dsh/lookup-selected state)
|
||||
(into #{} (comp (keep lookup) (map :parent-id))))
|
||||
|
||||
;; If we have a only unique parent, then use it as main
|
||||
|
@ -307,6 +307,7 @@
|
|||
(dissoc :board-id))]
|
||||
(rx/of ::dwsp/interrupt)
|
||||
(rx/of (rt/nav :workspace params-without-board {::rt/replace true}))))
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
|
||||
|
@ -329,8 +330,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
selected (wsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
selected (dsh/lookup-selected state)
|
||||
initial-set (if preserve?
|
||||
selected
|
||||
lks/empty-linked-set)
|
||||
|
@ -363,7 +364,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
group (get objects group-id)
|
||||
children (map #(get objects %) (:shapes group))
|
||||
|
||||
|
@ -435,7 +436,7 @@
|
|||
(ptk/reify ::duplicate-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page (wsh/lookup-page state)
|
||||
(let [page (dsh/lookup-page state)
|
||||
objects (:objects page)
|
||||
ids (into #{}
|
||||
(comp (map (d/getf objects))
|
||||
|
@ -449,8 +450,9 @@
|
|||
(gpt/point 0 0))
|
||||
|
||||
file-id (:current-file-id state)
|
||||
libraries (wsh/get-libraries state)
|
||||
library-data (wsh/get-file state file-id)
|
||||
|
||||
libraries (dsh/lookup-libraries state)
|
||||
library-data (dsh/lookup-file-data state file-id)
|
||||
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(cll/generate-duplicate-changes objects page ids delta libraries library-data file-id)
|
||||
|
@ -504,7 +506,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when (or (not move-delta?) (nil? (get-in state [:workspace-local :transform])))
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(let [selected (dsh/lookup-selected state)]
|
||||
(rx/of (duplicate-shapes selected
|
||||
:move-delta? move-delta?
|
||||
:alt-duplication? alt-duplication?))))))))
|
||||
|
@ -523,7 +525,7 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
|
||||
focus (-> (:workspace-focus-selected state)
|
||||
(set/union added)
|
||||
|
@ -541,7 +543,7 @@
|
|||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(let [selected (dsh/lookup-selected state)]
|
||||
(cond-> state
|
||||
(and (empty? (:workspace-focus-selected state))
|
||||
(d/not-empty? selected))
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.colors :as cl]
|
||||
[app.main.data.workspace.grid-layout.editor :as dwge]
|
||||
[app.main.data.workspace.modifiers :as dwm]
|
||||
[app.main.data.workspace.selection :as dwse]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -101,7 +101,7 @@
|
|||
(ptk/reify ::update-layout-positions
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
ids (->> ids (filter #(contains? objects %)))]
|
||||
(if (d/not-empty? ids)
|
||||
(let [modif-tree (dwm/create-modif-tree ids (ctm/reflow-modifiers))]
|
||||
|
@ -144,7 +144,7 @@
|
|||
(ptk/reify ::create-layout-from-id
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
parent (get objects id)
|
||||
undo-id (js/Symbol)
|
||||
layout-initializer (get-layout-initializer type from-frame? calculate-params?)]
|
||||
|
@ -162,8 +162,8 @@
|
|||
(watch [_ state _]
|
||||
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (wsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected (dsh/lookup-selected state)
|
||||
selected-shapes (map (d/getf objects) selected)
|
||||
single? (= (count selected-shapes) 1)
|
||||
has-group? (->> selected-shapes (d/seek cfh/group-shape?))
|
||||
|
@ -229,8 +229,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (wsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected (dsh/lookup-selected state)
|
||||
selected-shapes (map (d/getf objects) selected)
|
||||
single? (= (count selected-shapes) 1)
|
||||
is-frame? (= :frame (:type (first selected-shapes)))
|
||||
|
@ -248,8 +248,8 @@
|
|||
(ptk/reify ::toggle-shape-layout
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (wsh/lookup-selected state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (dsh/lookup-selected state)
|
||||
selected-shapes (map (d/getf objects) selected)
|
||||
single? (= (count selected-shapes) 1)
|
||||
has-layout? (and single?
|
||||
|
@ -300,7 +300,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [undo-id (js/Symbol)]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
|
||||
shapes-to-delete
|
||||
(when with-shapes?
|
||||
|
@ -334,10 +334,10 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
page (wsh/lookup-page state)
|
||||
page (dsh/lookup-page state)
|
||||
objects (:objects page)
|
||||
libraries (wsh/get-libraries state)
|
||||
library-data (wsh/get-file state file-id)
|
||||
libraries (dsh/lookup-libraries state)
|
||||
library-data (dsh/lookup-file state file-id)
|
||||
shape-id (first ids)
|
||||
base-shape (get objects shape-id)
|
||||
|
||||
|
@ -406,7 +406,7 @@
|
|||
(ptk/reify ::hover-layout-track
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects (first ids))
|
||||
|
||||
highlighted
|
||||
|
@ -524,7 +524,7 @@
|
|||
(ptk/reify ::update-layout-child
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
children-ids (->> ids (mapcat #(cfh/get-children-ids objects %)))
|
||||
parent-ids (->> ids (map #(cfh/get-parent-id objects %)))
|
||||
undo-id (js/Symbol)]
|
||||
|
@ -694,7 +694,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
frame-id (uuid/next)
|
||||
|
||||
undo-id (js/Symbol)
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
[app.main.data.changes :as dch]
|
||||
[app.main.data.comments :as dc]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.edition :as dwe]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.features :as features]
|
||||
[beicon.v2.core :as rx]
|
||||
|
@ -60,7 +60,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (or page-id (:current-page-id state))
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
ids (into [] (filter some?) ids)
|
||||
|
||||
update-layout-ids
|
||||
|
@ -107,7 +107,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
|
||||
[shape changes]
|
||||
(-> (pcb/empty-changes it page-id)
|
||||
|
@ -140,7 +140,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
shapes (->> shapes
|
||||
(remove #(dm/get-in objects [% :blocked]))
|
||||
(cfh/order-by-indexed-shapes objects))
|
||||
|
@ -169,13 +169,16 @@
|
|||
(watch [it state _]
|
||||
(let [file-id (:current-file-id state)
|
||||
page-id (or page-id (:current-page-id state))
|
||||
file (wsh/get-file state file-id)
|
||||
page (wsh/lookup-page state page-id)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
|
||||
fdata (dsh/lookup-file-data state file-id)
|
||||
page (dsh/get-page fdata page-id)
|
||||
objects (:objects page)
|
||||
|
||||
components-v2 (features/active-feature? state "components/v2")
|
||||
undo-id (or (:undo-id options) (js/Symbol))
|
||||
[all-parents changes] (-> (pcb/empty-changes it (:id page))
|
||||
(cls/generate-delete-shapes file page objects ids {:components-v2 components-v2
|
||||
(cls/generate-delete-shapes fdata page objects ids
|
||||
{:components-v2 components-v2
|
||||
:ignore-touched (:component-swap options)
|
||||
:undo-group (:undo-group options)
|
||||
:undo-id undo-id}))]
|
||||
|
@ -191,15 +194,15 @@
|
|||
(ptk/reify ::create-and-add-shape
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [vbc (wsh/viewport-center state)
|
||||
(let [vbc (dsh/get-viewport-center state)
|
||||
x (:x attrs (- (:x vbc) (/ width 2)))
|
||||
y (:y attrs (- (:y vbc) (/ height 2)))
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
frame-id (-> (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
frame-id (-> (dsh/lookup-page-objects state page-id)
|
||||
(ctst/top-nested-frame {:x frame-x :y frame-y}))
|
||||
|
||||
selected (wsh/lookup-selected state)
|
||||
selected (dsh/lookup-selected state)
|
||||
base (cfh/get-base-shape objects selected)
|
||||
|
||||
parent-id (if (or (and (= 1 (count selected))
|
||||
|
@ -241,8 +244,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (->> (wsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected (->> (dsh/lookup-selected state)
|
||||
(cfh/clean-loops objects)
|
||||
(remove #(ctn/has-any-copy-parent? objects (get objects %))))
|
||||
|
||||
|
@ -291,7 +294,7 @@
|
|||
(cond-> obj
|
||||
(boolean? blocked) (assoc :blocked blocked)
|
||||
(boolean? hidden) (assoc :hidden hidden)))
|
||||
objects (wsh/lookup-page-objects state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
;; We have change only the hidden behaviour, to hide only the
|
||||
;; selected shape, block behaviour remains the same.
|
||||
ids (if (boolean? blocked)
|
||||
|
@ -304,7 +307,7 @@
|
|||
(ptk/reify ::toggle-visibility-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(let [selected (dsh/lookup-selected state)]
|
||||
(rx/of (update-shapes selected #(update % :hidden not)))))))
|
||||
|
||||
(defn toggle-lock-selected
|
||||
|
@ -312,7 +315,7 @@
|
|||
(ptk/reify ::toggle-lock-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(let [selected (dsh/lookup-selected state)]
|
||||
(rx/of (update-shapes selected #(update % :blocked not)))))))
|
||||
|
||||
|
||||
|
@ -323,8 +326,9 @@
|
|||
(ptk/reify ::toggle-file-thumbnail-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
pages (-> state :workspace-data :pages-index vals)
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
fdata (dsh/lookup-file-data state)
|
||||
pages (-> fdata :pages-index vals)
|
||||
undo-id (js/Symbol)]
|
||||
|
||||
(rx/concat
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
(ns app.main.data.workspace.specialized-panel
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.common :as-alias dwc]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
|
@ -28,8 +28,8 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected-ids (wsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected-ids (dsh/lookup-selected state)
|
||||
selected-shapes (map (d/getf objects) selected-ids)]
|
||||
(assoc state :specialized-panel {:type type :shapes selected-shapes})))
|
||||
ptk/WatchEvent
|
||||
|
|
|
@ -1,168 +0,0 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.data.workspace.state-helpers
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.svg.path.command :as upc]
|
||||
[app.common.uuid :as uuid]))
|
||||
|
||||
(defn lookup-page
|
||||
([state]
|
||||
(lookup-page state (:current-page-id state)))
|
||||
([state page-id]
|
||||
(get-in state [:workspace-data :pages-index page-id])))
|
||||
|
||||
(defn lookup-page-objects
|
||||
([state]
|
||||
(lookup-page-objects state (:current-page-id state)))
|
||||
([state page-id]
|
||||
(-> (lookup-page state page-id)
|
||||
(get :objects))))
|
||||
|
||||
(defn lookup-library-objects
|
||||
[state file-id page-id]
|
||||
(dm/get-in state [:libraries file-id :data :pages-index page-id :objects]))
|
||||
|
||||
(defn lookup-objects
|
||||
[state file-id page-id]
|
||||
(let [current-file? (= file-id (:current-file-id state))]
|
||||
(if ^boolean current-file?
|
||||
(lookup-page-objects state page-id)
|
||||
(lookup-library-objects state file-id page-id))))
|
||||
|
||||
(defn lookup-local-components
|
||||
([state]
|
||||
(dm/get-in state [:workspace-data :components])))
|
||||
|
||||
(defn process-selected-shapes
|
||||
([objects selected]
|
||||
(process-selected-shapes objects selected nil))
|
||||
|
||||
([objects selected {:keys [omit-blocked?] :or {omit-blocked? false}}]
|
||||
(letfn [(selectable? [id]
|
||||
(and (contains? objects id)
|
||||
(or (not omit-blocked?)
|
||||
(not (get-in objects [id :blocked] false)))))]
|
||||
(let [selected (->> selected (cfh/clean-loops objects))]
|
||||
(into (d/ordered-set)
|
||||
(filter selectable?)
|
||||
selected)))))
|
||||
|
||||
(defn lookup-selected-raw
|
||||
[state]
|
||||
(dm/get-in state [:workspace-local :selected]))
|
||||
|
||||
(defn lookup-selected
|
||||
([state]
|
||||
(lookup-selected state nil))
|
||||
([state options]
|
||||
(lookup-selected state (:current-page-id state) options))
|
||||
([state page-id options]
|
||||
(let [objects (lookup-page-objects state page-id)
|
||||
selected (dm/get-in state [:workspace-local :selected])]
|
||||
(process-selected-shapes objects selected options))))
|
||||
|
||||
(defn lookup-shape
|
||||
([state id]
|
||||
(lookup-shape state (:current-page-id state) id))
|
||||
|
||||
([state page-id id]
|
||||
(let [objects (lookup-page-objects state page-id)]
|
||||
(get objects id))))
|
||||
|
||||
(defn lookup-shapes
|
||||
([state ids]
|
||||
(lookup-shapes state (:current-page-id state) ids))
|
||||
([state page-id ids]
|
||||
(let [objects (lookup-page-objects state page-id)]
|
||||
(into [] (keep (d/getf objects)) ids))))
|
||||
|
||||
(defn filter-shapes
|
||||
([state filter-fn]
|
||||
(filter-shapes state (:current-page-id state) filter-fn))
|
||||
([state page-id filter-fn]
|
||||
(let [objects (lookup-page-objects state page-id)]
|
||||
(into [] (filter filter-fn) (vals objects)))))
|
||||
|
||||
(defn get-local-file
|
||||
"Get the data content of the file you are currently working with."
|
||||
[state]
|
||||
(get state :workspace-data))
|
||||
|
||||
(defn get-local-file-full
|
||||
[state]
|
||||
(-> (get state :workspace-file)
|
||||
(assoc :data (get state :workspace-data))))
|
||||
|
||||
(defn get-file
|
||||
"Get the data content of the given file (it may be the current file
|
||||
or one library)."
|
||||
[state file-id]
|
||||
(if (= file-id (:current-file-id state))
|
||||
(get state :workspace-data)
|
||||
(dm/get-in state [:libraries file-id :data])))
|
||||
|
||||
(defn get-file-full
|
||||
"Get the data content of the given file (it may be the current file
|
||||
or one library)."
|
||||
[state file-id]
|
||||
(if (= file-id (:current-file-id state))
|
||||
(-> (get state :workspace-file)
|
||||
(assoc :data (get state :workspace-data)))
|
||||
(dm/get-in state [:libraries file-id :data])))
|
||||
|
||||
(defn get-libraries
|
||||
"Retrieve all libraries, including the local file."
|
||||
[state]
|
||||
(let [{:keys [id] :as local} (:workspace-data state)]
|
||||
(-> (:libraries state)
|
||||
(assoc id {:id id
|
||||
:data local}))))
|
||||
|
||||
(defn- set-content-modifiers [state]
|
||||
(fn [id shape]
|
||||
(let [content-modifiers (dm/get-in state [:workspace-local :edit-path id :content-modifiers])]
|
||||
(if (some? content-modifiers)
|
||||
(update shape :content upc/apply-content-modifiers content-modifiers)
|
||||
shape))))
|
||||
|
||||
(defn select-bool-children
|
||||
[parent-id state]
|
||||
(let [objects (lookup-page-objects state)
|
||||
modifiers (:workspace-modifiers state)
|
||||
children-ids (cfh/get-children-ids objects parent-id)
|
||||
children
|
||||
(-> (select-keys objects children-ids)
|
||||
(update-vals
|
||||
(fn [child]
|
||||
(cond-> child
|
||||
(contains? modifiers (:id child))
|
||||
(gsh/transform-shape (get-in modifiers [(:id child) :modifiers]))))))]
|
||||
|
||||
(as-> children $
|
||||
(d/mapm (set-content-modifiers state) $))))
|
||||
|
||||
(defn viewport-center
|
||||
[state]
|
||||
(let [{:keys [x y width height]} (get-in state [:workspace-local :vbox])]
|
||||
(gpt/point (+ x (/ width 2)) (+ y (/ height 2)))))
|
||||
|
||||
(defn find-orphan-shapes
|
||||
([state]
|
||||
(find-orphan-shapes state (:current-page-id state)))
|
||||
([state page-id]
|
||||
(let [objects (lookup-page-objects state page-id)
|
||||
objects (filter (fn [item]
|
||||
(and
|
||||
(not= (key item) uuid/zero)
|
||||
(not (contains? objects (:parent-id (val item))))))
|
||||
objects)]
|
||||
objects)))
|
|
@ -15,8 +15,8 @@
|
|||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.repo :as rp]
|
||||
[app.util.webapi :as wapi]
|
||||
|
@ -72,8 +72,8 @@
|
|||
(try
|
||||
(let [id (d/nilv id (uuid/next))
|
||||
page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (if ignore-selection? #{} (wsh/lookup-selected state))
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected (if ignore-selection? #{} (dsh/lookup-selected state))
|
||||
base (cfh/get-base-shape objects selected)
|
||||
|
||||
selected-id (first selected)
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.data.workspace.modifiers :as dwm]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.features :as features]
|
||||
[app.main.fonts :as fonts]
|
||||
|
@ -89,7 +89,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when (dwc/initialized? state)
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects id)
|
||||
editor-state (get-in state [:workspace-editor-state id])
|
||||
content (-> editor-state
|
||||
|
@ -321,7 +321,7 @@
|
|||
(ptk/reify ::update-text-range
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects id)
|
||||
|
||||
update-fn
|
||||
|
@ -347,7 +347,7 @@
|
|||
(ptk/reify ::update-root-attrs
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects id)
|
||||
|
||||
update-fn
|
||||
|
@ -372,7 +372,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when-not (some? (get-in state [:workspace-editor-state id]))
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects id)
|
||||
|
||||
merge-fn (fn [node attrs]
|
||||
|
@ -398,7 +398,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when-not (some? (get-in state [:workspace-editor-state id]))
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects id)
|
||||
update-node? (fn [node]
|
||||
(or (txt/is-text-node? node)
|
||||
|
@ -446,9 +446,8 @@
|
|||
(when (or
|
||||
(and (features/active-feature? state "text-editor/v2") (nil? (:workspace-editor state)))
|
||||
(and (not (features/active-feature? state "text-editor/v2")) (nil? (get-in state [:workspace-editor-state id]))))
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects id)
|
||||
|
||||
update-node? (some-fn txt/is-text-node? txt/is-paragraph-node?)
|
||||
|
||||
shape-ids
|
||||
|
@ -485,8 +484,8 @@
|
|||
(ptk/reify ::start-edit-if-selected
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (->> state wsh/lookup-selected (mapv #(get objects %)))]
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (->> state dsh/lookup-selected (mapv #(get objects %)))]
|
||||
(cond-> state
|
||||
(and (= 1 (count selected))
|
||||
(= (-> selected first :type) :text))
|
||||
|
@ -501,7 +500,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [props (::resize-text-debounce-props state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
undo-id (js/Symbol)]
|
||||
|
||||
(letfn [(changed-text? [id]
|
||||
|
@ -765,7 +764,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [editor-state (:workspace-editor-state state)
|
||||
ids (d/nilv ids (wsh/lookup-selected state))
|
||||
ids (d/nilv ids (dsh/lookup-selected state))
|
||||
attrs (-> typography
|
||||
(assoc :typography-ref-file file-id)
|
||||
(assoc :typography-ref-id (:id typography))
|
||||
|
@ -794,8 +793,8 @@
|
|||
(ptk/reify ::add-typography
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [selected (wsh/lookup-selected state)
|
||||
objects (wsh/lookup-page-objects state)
|
||||
(let [selected (dsh/lookup-selected state)
|
||||
objects (dsh/lookup-page-objects state)
|
||||
|
||||
xform (comp (keep (d/getf objects))
|
||||
(filter cfh/text-shape?))
|
||||
|
@ -863,7 +862,7 @@
|
|||
(ptk/reify ::v2-update-text-shape-content
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects id)
|
||||
modifiers (get-in state [:workspace-text-modifier id])
|
||||
new-shape? (nil? (:content shape))]
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
[app.common.thumbnails :as thc]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.persistence :as-alias dps]
|
||||
[app.main.data.workspace.notifications :as-alias wnt]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.rasterizer :as thr]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.render :as render]
|
||||
|
@ -65,7 +65,9 @@
|
|||
[state file-id page-id frame-id tag]
|
||||
(let [object-id (thc/fmt-object-id file-id page-id frame-id tag)
|
||||
tp (tp/tpoint-ms)
|
||||
objects (wsh/lookup-objects state file-id page-id)
|
||||
objects (-> (dsh/lookup-file state file-id)
|
||||
(dsh/get-page page-id)
|
||||
:objects)
|
||||
shape (get objects frame-id)]
|
||||
|
||||
(->> (render/render-frame objects shape object-id)
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.collapse :as dwc]
|
||||
[app.main.data.workspace.modifiers :as dwm]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.snap :as snap]
|
||||
[app.main.streams :as ms]
|
||||
|
@ -262,7 +262,7 @@
|
|||
page-id (:current-page-id state)
|
||||
focus (:workspace-focus-selected state)
|
||||
zoom (dm/get-in state [:workspace-local :zoom] 1)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
shapes (map (d/getf objects) ids)]
|
||||
|
||||
(rx/concat
|
||||
|
@ -313,10 +313,9 @@
|
|||
(ptk/reify ::update-dimensions
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
get-modifier
|
||||
(fn [shape] (ctm/change-dimensions-modifiers shape attr value))
|
||||
|
||||
modif-tree
|
||||
(-> (dwm/build-modif-tree ids objects get-modifier)
|
||||
(gm/set-objects-modifiers objects))]
|
||||
|
@ -341,7 +340,7 @@
|
|||
(ptk/reify ::change-orientation
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
|
||||
get-modifier
|
||||
(fn [shape] (ctm/change-orientation-modifiers shape orientation))
|
||||
|
@ -408,7 +407,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
shapes (->> ids (map #(get objects %)))]
|
||||
(rx/concat
|
||||
(rx/of (dwm/set-delta-rotation-modifiers rotation shapes params))
|
||||
|
@ -438,7 +437,7 @@
|
|||
|
||||
;; We toggle the selection so we don't have to wait for the event
|
||||
selected
|
||||
(cond-> (wsh/lookup-selected state {:omit-blocked? true})
|
||||
(cond-> (dsh/lookup-selected state {:omit-blocked? true})
|
||||
(some? id)
|
||||
(d/toggle-selection id shift?))]
|
||||
|
||||
|
@ -502,8 +501,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (wsh/lookup-selected state {:omit-blocked? true})
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
selected (dsh/lookup-selected state {:omit-blocked? true})
|
||||
ids (if (nil? ids) selected ids)
|
||||
shapes (into []
|
||||
(comp (map (d/getf objects))
|
||||
|
@ -625,8 +624,8 @@
|
|||
(ptk/reify ::reorder-layout-child
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [selected (wsh/lookup-selected state {:omit-blocked? true})
|
||||
objects (wsh/lookup-page-objects state)
|
||||
(let [selected (dsh/lookup-selected state {:omit-blocked? true})
|
||||
objects (dsh/lookup-page-objects state)
|
||||
page-id (:current-page-id state)
|
||||
|
||||
get-move-to-index
|
||||
|
@ -734,7 +733,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(if (= same-event (get state ::current-move-selected))
|
||||
(let [selected (wsh/lookup-selected state {:omit-blocked? true})
|
||||
(let [selected (dsh/lookup-selected state {:omit-blocked? true})
|
||||
nudge (get-in state [:profile :props :nudge] {:big 10 :small 1})
|
||||
move-events (->> stream
|
||||
(rx/filter (ptk/type? ::nudge-selected-shapes))
|
||||
|
@ -776,8 +775,8 @@
|
|||
(ptk/reify ::move-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (wsh/lookup-selected state {:omit-blocked? true})
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (dsh/lookup-selected state {:omit-blocked? true})
|
||||
selected-shapes (->> selected (map (d/getf objects)))]
|
||||
(if (every? #(and (ctl/any-layout-immediate-child? objects %)
|
||||
(not (ctl/position-absolute? %)))
|
||||
|
@ -794,7 +793,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
shape (get objects id)
|
||||
|
||||
;; FIXME: performance rect
|
||||
|
@ -817,7 +816,7 @@
|
|||
(ptk/reify ::position-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shapes (d/index-by :id shapes)
|
||||
|
||||
modif-tree
|
||||
|
@ -864,7 +863,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
ids (cleanup-invalid-moving-shapes ids objects frame-id)
|
||||
changes (cls/generate-relocate (pcb/empty-changes it)
|
||||
objects
|
||||
|
@ -898,8 +897,8 @@
|
|||
(ptk/reify ::flip-horizontal-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (or ids (wsh/lookup-selected state {:omit-blocked? true}))
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (or ids (dsh/lookup-selected state {:omit-blocked? true}))
|
||||
shapes (map #(get objects %) selected)
|
||||
selrect (gsh/shapes->rect shapes)
|
||||
center (grc/rect->center selrect)
|
||||
|
@ -913,8 +912,8 @@
|
|||
(ptk/reify ::flip-vertical-selected
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
selected (or ids (wsh/lookup-selected state {:omit-blocked? true}))
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (or ids (dsh/lookup-selected state {:omit-blocked? true}))
|
||||
shapes (map #(get objects %) selected)
|
||||
selrect (gsh/shapes->rect shapes)
|
||||
center (grc/rect->center selrect)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.changes :as dch]
|
||||
[app.main.data.common :as dcm]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.util.time :as dt]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -186,7 +186,7 @@
|
|||
(ptk/reify ::undo-to-index
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
edition (get-in state [:workspace-local :edition])
|
||||
drawing (get state :workspace-drawing)]
|
||||
(when-not (and (or (some? edition) (some? (:object drawing)))
|
||||
|
@ -219,7 +219,7 @@
|
|||
(ptk/reify ::undo
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
edition (get-in state [:workspace-local :edition])
|
||||
drawing (get state :workspace-drawing)]
|
||||
|
||||
|
@ -257,7 +257,7 @@
|
|||
(ptk/reify ::redo
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
edition (get-in state [:workspace-local :edition])
|
||||
drawing (get state :workspace-drawing)]
|
||||
(when (and (or (nil? edition) (ctl/grid-layout? objects edition))
|
||||
|
@ -291,7 +291,8 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
pages (dm/get-in state [:workspace-data :pages])]
|
||||
pages (-> (dsh/lookup-file-data state)
|
||||
(get :pages))]
|
||||
(if (contains? pages page-id)
|
||||
(rx/empty)
|
||||
(rx/of (dcm/go-to-workspace :page-id (first pages))))))))
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[app.common.geom.rect :as gpr]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.util.mouse :as mse]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
@ -38,7 +38,7 @@
|
|||
|
||||
(initialize [state local]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
shapes (cfh/get-immediate-children objects)
|
||||
srect (gsh/shapes->rect shapes)
|
||||
local (assoc local :vport size :zoom 1 :zoom-inverse 1 :hide-toolbar false)]
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.rect :as grc]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.mouse :as mse]
|
||||
[beicon.v2.core :as rx]
|
||||
|
@ -83,7 +83,7 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
shapes (cfh/get-immediate-children objects)
|
||||
srect (gsh/shapes->rect shapes)]
|
||||
(if (empty? shapes)
|
||||
|
@ -101,11 +101,11 @@
|
|||
(ptk/reify ::zoom-to-selected-shape
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(let [selected (dsh/lookup-selected state)]
|
||||
(if (empty? selected)
|
||||
state
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
srect (->> selected
|
||||
(map #(get objects %))
|
||||
(gsh/shapes->rect))]
|
||||
|
@ -126,7 +126,7 @@
|
|||
(if (empty? ids)
|
||||
state
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
srect (->> ids
|
||||
(map #(get objects %))
|
||||
(gsh/shapes->rect))]
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.config :as cf]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.workspace.tokens.token-set :as wtts]
|
||||
[okulary.core :as l]))
|
||||
|
@ -53,7 +53,7 @@
|
|||
(def exception
|
||||
(l/derived :exception st/state))
|
||||
|
||||
(def threads-ref
|
||||
(def threads
|
||||
(l/derived :comment-threads st/state))
|
||||
|
||||
(def share-links
|
||||
|
@ -71,13 +71,22 @@
|
|||
(def files
|
||||
(l/derived :files st/state))
|
||||
|
||||
(def file
|
||||
(l/derived (fn [state]
|
||||
(let [file-id (:current-file-id state)
|
||||
files (:files state)]
|
||||
(get files file-id)))
|
||||
st/state))
|
||||
|
||||
(def shared-files
|
||||
"A derived state that points to the current list of shared
|
||||
files (without the content, only summary)"
|
||||
(l/derived :shared-files st/state))
|
||||
|
||||
(def libraries
|
||||
(l/derived :libraries st/state))
|
||||
"A derived state that contanins the currently loaded shared libraries
|
||||
with all its content; including the current file"
|
||||
(l/derived :files st/state))
|
||||
|
||||
(defn extract-selected-files
|
||||
[files selected]
|
||||
|
@ -121,7 +130,7 @@
|
|||
(def ^:private selected-shapes-data
|
||||
(l/derived
|
||||
(fn [state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
selected (dm/get-in state [:workspace-local :selected])]
|
||||
{:objects objects :selected selected}))
|
||||
st/state (fn [v1 v2]
|
||||
|
@ -131,7 +140,7 @@
|
|||
(def selected-shapes
|
||||
(l/derived
|
||||
(fn [{:keys [objects selected]}]
|
||||
(wsh/process-selected-shapes objects selected))
|
||||
(dsh/process-selected-shapes objects selected))
|
||||
selected-shapes-data))
|
||||
|
||||
(defn make-selected-ref
|
||||
|
@ -217,20 +226,10 @@
|
|||
(def rulers?
|
||||
(l/derived #(contains? % :rulers) workspace-layout))
|
||||
|
||||
(def workspace-file
|
||||
"A ref to a striped vision of file (without data)."
|
||||
(l/derived (fn [state]
|
||||
(let [file (:workspace-file state)
|
||||
data (:workspace-data state)]
|
||||
(-> file
|
||||
(dissoc :data)
|
||||
;; FIXME: still used in sitemaps but sitemaps
|
||||
;; should declare its own lense for it
|
||||
(assoc :pages (:pages data)))))
|
||||
st/state =))
|
||||
|
||||
;; FIXME: rename to current-file-data
|
||||
(def workspace-data
|
||||
(l/derived :workspace-data st/state))
|
||||
"Currently working file data on workspace"
|
||||
(l/derived dsh/lookup-file-data st/state))
|
||||
|
||||
(def workspace-file-colors
|
||||
(l/derived (fn [{:keys [id] :as data}]
|
||||
|
@ -238,18 +237,19 @@
|
|||
workspace-data
|
||||
=))
|
||||
|
||||
(def workspace-recent-colors
|
||||
(def recent-colors
|
||||
"Recent colors for the currently selected file"
|
||||
(l/derived (fn [state]
|
||||
(when-let [file-id (:current-file-id state)]
|
||||
(dm/get-in state [:recent-colors file-id])))
|
||||
st/state))
|
||||
|
||||
;; FIXME: fonts are not prefixed, so the recent font list is shared
|
||||
;; across all teams. This may not be expected behavior
|
||||
(def workspace-recent-fonts
|
||||
(l/derived (fn [data]
|
||||
(get data :recent-fonts []))
|
||||
workspace-data))
|
||||
(def recent-fonts
|
||||
"Recent fonts for the currently selected file"
|
||||
(l/derived (fn [state]
|
||||
(when-let [file-id (:current-file-id state)]
|
||||
(dm/get-in state [:recent-fonts file-id])))
|
||||
st/state))
|
||||
|
||||
(def workspace-file-typography
|
||||
(l/derived :typographies workspace-data))
|
||||
|
@ -258,23 +258,20 @@
|
|||
(l/derived :workspace-presence st/state))
|
||||
|
||||
(def workspace-page
|
||||
(l/derived (fn [state]
|
||||
(let [page-id (:current-page-id state)
|
||||
data (:workspace-data state)]
|
||||
(dm/get-in data [:pages-index page-id])))
|
||||
st/state))
|
||||
"Ref to currently active page on workspace"
|
||||
(l/derived dsh/lookup-page st/state))
|
||||
|
||||
(def workspace-page-flows
|
||||
(l/derived #(-> % :flows not-empty) workspace-page))
|
||||
|
||||
(defn workspace-page-object-by-id
|
||||
[page-id shape-id]
|
||||
(l/derived #(wsh/lookup-shape % page-id shape-id) st/state =))
|
||||
(l/derived #(dsh/lookup-shape % page-id shape-id) st/state =))
|
||||
|
||||
;; TODO: Looks like using the `=` comparator can be pretty expensive
|
||||
;; on large pages, we are using this for some reason?
|
||||
(def workspace-page-objects
|
||||
(l/derived wsh/lookup-page-objects st/state =))
|
||||
(l/derived dsh/lookup-page-objects st/state =))
|
||||
|
||||
(def workspace-read-only?
|
||||
(l/derived :read-only? workspace-global))
|
||||
|
@ -348,7 +345,7 @@
|
|||
(l/derived
|
||||
(fn [state]
|
||||
{:modifiers (:workspace-modifiers state)
|
||||
:objects (wsh/lookup-page-objects state)})
|
||||
:objects (dsh/lookup-page-objects state)})
|
||||
st/state
|
||||
(fn [a b]
|
||||
(and (= (:modifiers a) (:modifiers b))
|
||||
|
@ -379,11 +376,11 @@
|
|||
(l/derived #(get % frame-id) workspace-frame-modifiers =))
|
||||
|
||||
(defn select-bool-children [id]
|
||||
(l/derived (partial wsh/select-bool-children id) st/state =))
|
||||
(l/derived #(dsh/select-bool-children % id) st/state =))
|
||||
|
||||
(def selected-data
|
||||
(l/derived #(let [selected (wsh/lookup-selected %)
|
||||
objects (wsh/lookup-page-objects %)]
|
||||
(l/derived #(let [selected (dsh/lookup-selected %)
|
||||
objects (dsh/lookup-page-objects %)]
|
||||
(hash-map :selected selected
|
||||
:objects objects))
|
||||
st/state =))
|
||||
|
@ -415,7 +412,7 @@
|
|||
[ids]
|
||||
(l/derived
|
||||
(fn [state]
|
||||
(let [objects (wsh/lookup-page-objects state)]
|
||||
(let [objects (dsh/lookup-page-objects state)]
|
||||
(into []
|
||||
(comp (map (d/getf objects))
|
||||
(filter (partial ctl/flex-layout-immediate-child? objects)))
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
(r/map->Match data))
|
||||
|
||||
(defn resolve
|
||||
([router id] (resolve router id {}))
|
||||
([router id]
|
||||
(resolve router id {}))
|
||||
([router id params]
|
||||
(when router
|
||||
(when-let [match (r/match-by-name router id)]
|
||||
|
|
|
@ -37,14 +37,13 @@
|
|||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def comments-local-options (l/derived :options refs/comments-local))
|
||||
(def ^:private ref:comments-local-options
|
||||
(l/derived :options refs/comments-local))
|
||||
|
||||
(def mentions-context (mf/create-context nil))
|
||||
|
||||
(def r-mentions-split #"@\[[^\]]*\]\([^\)]*\)")
|
||||
(def r-mentions #"@\[([^\]]*)\]\(([^\)]*)\)")
|
||||
|
||||
|
||||
(defn- parse-comment
|
||||
"Parse a comment into its elements (texts and mentions)"
|
||||
[comment]
|
||||
|
@ -58,7 +57,7 @@
|
|||
:content user
|
||||
:data {:id id}})))))
|
||||
|
||||
(defn parse-nodes
|
||||
(defn- parse-nodes
|
||||
"Parse the nodes to format a comment"
|
||||
[node]
|
||||
(->> (dom/get-children node)
|
||||
|
@ -72,8 +71,7 @@
|
|||
(.-textContent node))))
|
||||
(str/join "")))
|
||||
|
||||
|
||||
(defn create-text-node
|
||||
(defn- create-text-node
|
||||
"Creates a text-only node"
|
||||
([]
|
||||
(create-text-node ""))
|
||||
|
@ -82,7 +80,7 @@
|
|||
(dom/set-data! "type" "text")
|
||||
(dom/set-html! (if (empty? text) "​" text)))))
|
||||
|
||||
(defn create-mention-node
|
||||
(defn- create-mention-node
|
||||
"Creates a mention node"
|
||||
[id fullname]
|
||||
(-> (dom/create-element "span")
|
||||
|
@ -91,7 +89,7 @@
|
|||
(dom/set-data! "fullname" fullname)
|
||||
(obj/set! "textContent" fullname)))
|
||||
|
||||
(defn current-text-node
|
||||
(defn- current-text-node
|
||||
"Retrieves the text node and the offset that the cursor is positioned on"
|
||||
[node]
|
||||
|
||||
|
@ -108,7 +106,7 @@
|
|||
(when (= node container)
|
||||
[span-node anchor-offset])))))
|
||||
|
||||
(defn absolute-offset
|
||||
(defn- absolute-offset
|
||||
[node child offset]
|
||||
(loop [nodes (seq (dom/get-children node))
|
||||
acc 0]
|
||||
|
@ -118,7 +116,7 @@
|
|||
(recur (rest nodes) (+ acc (.-length (.-textContent head)))))
|
||||
nil)))
|
||||
|
||||
(defn get-prev-node
|
||||
(defn- get-prev-node
|
||||
[parent node]
|
||||
(->> (d/with-prev (dom/get-children parent))
|
||||
(d/seek (fn [[it _]] (= node it)))
|
||||
|
@ -126,8 +124,7 @@
|
|||
|
||||
;; Component that renders the component content
|
||||
(mf/defc comment-content*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [content]}]
|
||||
(let [comment-elements (mf/use-memo (mf/deps content) #(parse-comment content))]
|
||||
(for [[idx {:keys [type content]}] (d/enumerate comment-elements)]
|
||||
|
@ -141,22 +138,20 @@
|
|||
|
||||
;; Input text for comments with mentions
|
||||
(mf/defc comment-input*
|
||||
{::mf/props :obj
|
||||
::mf/private true
|
||||
::mf/wrap-props false}
|
||||
[{:keys [value placeholder max-length autofocus? on-focus on-blur on-change on-esc on-ctrl-enter]}]
|
||||
{::mf/private true}
|
||||
[{:keys [value placeholder max-length autofocus on-focus on-blur on-change on-esc on-ctrl-enter]}]
|
||||
|
||||
(let [value (d/nilv value "")
|
||||
prev-value (h/use-previous value)
|
||||
|
||||
local-ref (mf/use-ref nil)
|
||||
mentions-str (mf/use-ctx mentions-context)
|
||||
mentions-s (mf/use-ctx mentions-context)
|
||||
cur-mention (mf/use-var nil)
|
||||
|
||||
prev-selection (mf/use-var nil)
|
||||
|
||||
init-input
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn [node]
|
||||
(mf/set-ref-val! local-ref node)
|
||||
(when node
|
||||
|
@ -167,13 +162,13 @@
|
|||
nil)))))
|
||||
|
||||
handle-input
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps on-change)
|
||||
(fn []
|
||||
(let [node (mf/ref-val local-ref)
|
||||
children (dom/get-children node)]
|
||||
|
||||
(doseq [child-node children]
|
||||
(doseq [^js child-node children]
|
||||
;; Remove nodes that are not span. This can happen if the user copy/pastes
|
||||
(when (not= (.-tagName child-node) "SPAN")
|
||||
(.remove child-node))
|
||||
|
@ -198,7 +193,7 @@
|
|||
(on-change new-input))))))
|
||||
|
||||
handle-select
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(let [node (mf/ref-val local-ref)
|
||||
selection (wapi/get-selection)
|
||||
|
@ -240,16 +235,16 @@
|
|||
(if (re-matches #"@\w*" mention-text)
|
||||
(do
|
||||
(reset! cur-mention mention-text)
|
||||
(rx/push! mentions-str {:type :display-mentions})
|
||||
(rx/push! mentions-s {:type :display-mentions})
|
||||
(let [mention (subs mention-text 1)]
|
||||
(when (d/not-empty? mention)
|
||||
(rx/push! mentions-str {:type :filter-mentions :data mention}))))
|
||||
(rx/push! mentions-s {:type :filter-mentions :data mention}))))
|
||||
(do
|
||||
(reset! cur-mention nil)
|
||||
(rx/push! mentions-str {:type :hide-mentions}))))))))
|
||||
(rx/push! mentions-s {:type :hide-mentions}))))))))
|
||||
|
||||
handle-focus
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/set-css-property! (mf/ref-val local-ref) "--placeholder" "")
|
||||
|
@ -257,7 +252,7 @@
|
|||
(on-focus event))))
|
||||
|
||||
handle-blur
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps value)
|
||||
(fn [event]
|
||||
(when (empty? value)
|
||||
|
@ -268,6 +263,8 @@
|
|||
(on-blur event))))
|
||||
|
||||
handle-insert-mention
|
||||
(mf/use-fn
|
||||
(mf/deps on-change)
|
||||
(fn [data]
|
||||
(let [node (mf/ref-val local-ref)
|
||||
[span-node offset] (current-text-node node)]
|
||||
|
@ -298,8 +295,8 @@
|
|||
(wapi/set-cursor-after! after-span)
|
||||
(wapi/collapse-end! sel)
|
||||
|
||||
(when on-change
|
||||
(on-change (parse-nodes node)))))))
|
||||
(when (fn? on-change)
|
||||
(on-change (parse-nodes node))))))))
|
||||
|
||||
handle-key-down
|
||||
(mf/use-fn
|
||||
|
@ -314,22 +311,22 @@
|
|||
(and @cur-mention (kbd/enter? event))
|
||||
(do (dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(rx/push! mentions-str {:type :insert-selected-mention}))
|
||||
(rx/push! mentions-s {:type :insert-selected-mention}))
|
||||
|
||||
(and @cur-mention (kbd/down-arrow? event))
|
||||
(do (dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(rx/push! mentions-str {:type :insert-next-mention}))
|
||||
(rx/push! mentions-s {:type :insert-next-mention}))
|
||||
|
||||
(and @cur-mention (kbd/up-arrow? event))
|
||||
(do (dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(rx/push! mentions-str {:type :insert-prev-mention}))
|
||||
(rx/push! mentions-s {:type :insert-prev-mention}))
|
||||
|
||||
(and @cur-mention (kbd/esc? event))
|
||||
(do (dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(rx/push! mentions-str {:type :hide-mentions}))
|
||||
(rx/push! mentions-s {:type :hide-mentions}))
|
||||
|
||||
(and (kbd/esc? event) (fn? on-esc))
|
||||
(on-esc event)
|
||||
|
@ -362,43 +359,36 @@
|
|||
(.remove prev-node)))))))]
|
||||
|
||||
(mf/use-layout-effect
|
||||
(mf/deps autofocus?)
|
||||
(mf/deps autofocus)
|
||||
(fn []
|
||||
(when autofocus?
|
||||
(when autofocus
|
||||
(dom/focus! (mf/ref-val local-ref)))))
|
||||
|
||||
;; Creates the handlers for selection
|
||||
(mf/use-effect
|
||||
(mf/deps handle-select)
|
||||
(fn []
|
||||
(mf/with-effect [handle-select]
|
||||
(let [handle-select* handle-select]
|
||||
(js/document.addEventListener "selectionchange" handle-select*)
|
||||
#(js/document.removeEventListener "selectionchange" handle-select*))))
|
||||
#(js/document.removeEventListener "selectionchange" handle-select*)))
|
||||
|
||||
;; Effect to communicate with the mentions panel
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
(when mentions-str
|
||||
(->> mentions-str
|
||||
(mf/with-effect []
|
||||
(when mentions-s
|
||||
(->> mentions-s
|
||||
(rx/subs!
|
||||
(fn [{:keys [type data]}]
|
||||
(case type
|
||||
:insert-mention
|
||||
(handle-insert-mention data)
|
||||
|
||||
nil)))))))
|
||||
nil))))))
|
||||
|
||||
;; Auto resize input to display the comment
|
||||
(mf/use-layout-effect
|
||||
nil
|
||||
(fn []
|
||||
(let [node (mf/ref-val local-ref)]
|
||||
(mf/with-layout-effect nil
|
||||
(let [^js node (mf/ref-val local-ref)]
|
||||
(set! (.-height (.-style node)) "0")
|
||||
(set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px")))))
|
||||
(set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px"))))
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps value prev-value)
|
||||
(fn []
|
||||
(mf/with-effect [value prev-value]
|
||||
(let [node (mf/ref-val local-ref)]
|
||||
(cond
|
||||
(and (d/not-empty? prev-value) (empty? value))
|
||||
|
@ -411,7 +401,7 @@
|
|||
(dom/set-css-property! node "--placeholder" (dm/str "\"" placeholder "\""))
|
||||
|
||||
(some? node)
|
||||
(dom/set-css-property! node "--placeholder" "")))))
|
||||
(dom/set-css-property! node "--placeholder" ""))))
|
||||
|
||||
[:div
|
||||
{:role "textbox"
|
||||
|
@ -425,27 +415,26 @@
|
|||
:on-blur handle-blur}]))
|
||||
|
||||
(mf/defc mentions-panel*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [profiles]}]
|
||||
|
||||
(let [mentions-str (mf/use-ctx mentions-context)
|
||||
|
||||
[]
|
||||
(let [mentions-s (mf/use-ctx mentions-context)
|
||||
profile (mf/deref refs/profile)
|
||||
profiles (mf/deref refs/profiles)
|
||||
|
||||
mention-state
|
||||
(mf/use-state {:display? false
|
||||
state*
|
||||
(mf/use-state
|
||||
#(do {:display false
|
||||
:mention-filter ""
|
||||
:selected 0})
|
||||
:selected 0}))
|
||||
|
||||
{:keys [display? mention-filter selected]} @mention-state
|
||||
{:keys [display mention-filter selected]}
|
||||
(deref state*)
|
||||
|
||||
mentions-users
|
||||
(mf/use-memo
|
||||
(mf/deps mention-filter)
|
||||
#(->> (vals profiles)
|
||||
(filter
|
||||
(fn [{:keys [id fullname email]}]
|
||||
(mf/with-memo [mention-filter]
|
||||
|
||||
|
||||
(->> (vals profiles)
|
||||
(filter (fn [{:keys [id fullname email]}]
|
||||
(and
|
||||
(not= id (:id profile))
|
||||
(or (not mention-filter)
|
||||
|
@ -455,54 +444,53 @@
|
|||
(take 4)
|
||||
(into [])))
|
||||
|
||||
selected (mth/clamp selected 0 (dec (count mentions-users)))
|
||||
selected
|
||||
(mth/clamp selected 0 (dec (count mentions-users)))
|
||||
|
||||
handle-click-mention
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(let [id (-> (dom/get-current-target event)
|
||||
(dom/get-data "user-id")
|
||||
(uuid/uuid))]
|
||||
(rx/push! mentions-str {:type :insert-mention
|
||||
(rx/push! mentions-s {:type :insert-mention
|
||||
:data {:user (get profiles id)}}))))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps mentions-users selected)
|
||||
(fn []
|
||||
(mf/with-effect [mentions-users selected]
|
||||
(let [sub
|
||||
(->> mentions-str
|
||||
(->> mentions-s
|
||||
(rx/subs!
|
||||
(fn [{:keys [type data]}]
|
||||
(case type
|
||||
;; Display the mentions dialog
|
||||
:display-mentions
|
||||
(swap! mention-state assoc :display? true)
|
||||
(swap! state* assoc :display true)
|
||||
|
||||
;; Hide mentions
|
||||
:hide-mentions
|
||||
(swap! mention-state assoc :display? false :mention-filter "")
|
||||
(swap! state* assoc :display false :mention-filter "")
|
||||
|
||||
;; Filter the metions by some characters
|
||||
:filter-mentions
|
||||
(swap! mention-state assoc :mention-filter data)
|
||||
(swap! state* assoc :mention-filter data)
|
||||
|
||||
:insert-selected-mention
|
||||
(rx/push! mentions-str {:type :insert-mention
|
||||
(rx/push! mentions-s {:type :insert-mention
|
||||
:data {:user (get mentions-users selected)}})
|
||||
|
||||
:insert-next-mention
|
||||
(swap! mention-state update :selected #(mth/clamp (inc %) 0 (dec (count mentions-users))))
|
||||
(swap! state* update :selected #(mth/clamp (inc %) 0 (dec (count mentions-users))))
|
||||
|
||||
:insert-prev-mention
|
||||
(swap! mention-state update :selected #(mth/clamp (dec %) 0 (dec (count mentions-users))))
|
||||
(swap! state* update :selected #(mth/clamp (dec %) 0 (dec (count mentions-users))))
|
||||
|
||||
;;
|
||||
nil))))]
|
||||
#(rx/dispose! sub))))
|
||||
#(rx/dispose! sub)))
|
||||
|
||||
(when display?
|
||||
(when ^boolean display
|
||||
[:div {:class (stl/css :comments-mentions-choice)}
|
||||
(if (empty? mentions-users)
|
||||
[:div {:class (stl/css :comments-mentions-empty)}
|
||||
|
@ -523,15 +511,15 @@
|
|||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[]
|
||||
(let [mentions-str (mf/use-ctx mentions-context)
|
||||
(let [mentions-s (mf/use-ctx mentions-context)
|
||||
display-mentions* (mf/use-state false)
|
||||
|
||||
handle-mouse-down
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(rx/push! mentions-str {:type :display-mentions})))]
|
||||
(rx/push! mentions-s {:type :display-mentions})))]
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
|
@ -542,7 +530,7 @@
|
|||
:display-mentions (reset! display-mentions* true)
|
||||
:hide-mentions (reset! display-mentions* false)
|
||||
nil))
|
||||
mentions-str)]
|
||||
mentions-s)]
|
||||
#(rx/dispose! sub))))
|
||||
|
||||
[:> icon-button*
|
||||
|
@ -561,8 +549,7 @@
|
|||
[:maybe [:enum "read" "unread" "solved"]]]])
|
||||
|
||||
(mf/defc comment-avatar*
|
||||
{::mf/props :obj
|
||||
::mf/schema schema:comment-avatar}
|
||||
{::mf/schema schema:comment-avatar}
|
||||
[{:keys [image variant class] :rest props}]
|
||||
(let [variant (or variant "read")
|
||||
class (dm/str class " " (stl/css-case :avatar true
|
||||
|
@ -577,8 +564,7 @@
|
|||
:avatar-darken (= variant "solved"))}]]))
|
||||
|
||||
(mf/defc comment-info*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [item profile]}]
|
||||
[:*
|
||||
[:div {:class (stl/css :author)}
|
||||
|
@ -642,11 +628,12 @@
|
|||
(fn []
|
||||
(st/emit! (dcm/add-comment thread @content))
|
||||
(on-cancel)))]
|
||||
|
||||
[:div {:class (stl/css :form)}
|
||||
[:> comment-input*
|
||||
{:value @content
|
||||
:placeholder (tr "labels.reply.thread")
|
||||
:autofocus? true
|
||||
:autofocus true
|
||||
:on-blur on-blur
|
||||
:on-focus on-focus
|
||||
:on-ctrl-enter on-submit
|
||||
|
@ -664,8 +651,7 @@
|
|||
(tr "labels.post")]])]))
|
||||
|
||||
(mf/defc comment-edit-form*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [content on-submit on-cancel]}]
|
||||
(let [content (mf/use-state content)
|
||||
|
||||
|
@ -684,7 +670,7 @@
|
|||
[:div {:class (stl/css :form)}
|
||||
[:> comment-input*
|
||||
{:value @content
|
||||
:autofocus? true
|
||||
:autofocus true
|
||||
:on-ctrl-enter on-submit*
|
||||
:on-change on-change
|
||||
:max-length 750}]
|
||||
|
@ -699,11 +685,10 @@
|
|||
(tr "labels.post")]]]))
|
||||
|
||||
(mf/defc comment-floating-thread-draft*
|
||||
{::mf/props :obj}
|
||||
[{:keys [draft zoom on-cancel on-submit position-modifier profiles]}]
|
||||
[{:keys [draft zoom on-cancel on-submit position-modifier]}]
|
||||
(let [profile (mf/deref refs/profile)
|
||||
|
||||
mentions-str (mf/use-memo #(rx/subject))
|
||||
mentions-s (mf/use-memo #(rx/subject))
|
||||
|
||||
position (cond-> (:position draft)
|
||||
(some? position-modifier)
|
||||
|
@ -736,7 +721,7 @@
|
|||
(mf/deps draft)
|
||||
(partial on-submit draft))]
|
||||
|
||||
[:> (mf/provider mentions-context) {:value mentions-str}
|
||||
[:> (mf/provider mentions-context) {:value mentions-s}
|
||||
[:div
|
||||
{:class (stl/css :floating-preview-wrapper)
|
||||
:data-testid "floating-thread-bubble"
|
||||
|
@ -753,7 +738,7 @@
|
|||
[:> comment-input*
|
||||
{:placeholder (tr "labels.write-new-comment")
|
||||
:value (or content "")
|
||||
:autofocus? true
|
||||
:autofocus true
|
||||
:on-esc on-esc
|
||||
:on-change on-change
|
||||
:on-ctrl-enter on-submit
|
||||
|
@ -769,15 +754,14 @@
|
|||
:disabled disabled?}
|
||||
(tr "labels.post")]]]
|
||||
|
||||
[:> mentions-panel* {:profiles profiles}]]]))
|
||||
[:> mentions-panel*]]]))
|
||||
|
||||
(mf/defc comment-floating-thread-header*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [profiles thread origin]}]
|
||||
(let [owner (get profiles (:owner-id thread))
|
||||
{::mf/private true}
|
||||
[{:keys [thread origin]}]
|
||||
(let [owner (dcm/get-owner thread)
|
||||
profile (mf/deref refs/profile)
|
||||
options (mf/deref comments-local-options)
|
||||
options (mf/deref ref:comments-local-options)
|
||||
|
||||
toggle-resolved
|
||||
(mf/use-fn
|
||||
|
@ -842,12 +826,11 @@
|
|||
(tr "labels.delete-comment-thread")]]]]))
|
||||
|
||||
(mf/defc comment-floating-thread-item*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [comment thread profiles]}]
|
||||
(let [owner (get profiles (:owner-id comment))
|
||||
{::mf/private true}
|
||||
[{:keys [comment thread]}]
|
||||
(let [owner (dcm/get-owner comment)
|
||||
profile (mf/deref refs/profile)
|
||||
options (mf/deref comments-local-options)
|
||||
options (mf/deref ref:comments-local-options)
|
||||
edition? (mf/use-state false)
|
||||
|
||||
on-toggle-options
|
||||
|
@ -945,11 +928,10 @@
|
|||
{:x x :y y :h-dir h-dir :v-dir v-dir}))
|
||||
|
||||
(mf/defc comment-floating-thread*
|
||||
{::mf/props :obj
|
||||
::mf/wrap [mf/memo]}
|
||||
[{:keys [thread zoom profiles origin position-modifier viewport]}]
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [thread zoom origin position-modifier viewport]}]
|
||||
(let [ref (mf/use-ref)
|
||||
mentions-str (mf/use-memo #(rx/subject))
|
||||
mentions-s (mf/use-memo #(rx/subject))
|
||||
thread-id (:id thread)
|
||||
thread-pos (:position thread)
|
||||
|
||||
|
@ -960,7 +942,7 @@
|
|||
max-height (when (some? viewport) (int (* (:height viewport) 0.5)))
|
||||
|
||||
;; We should probably look for a better way of doing this.
|
||||
bubble-margin {:x 24 :y 24}
|
||||
bubble-margin (gpt/point 24 24)
|
||||
pos (offset-position base-pos viewport zoom bubble-margin)
|
||||
|
||||
margin-x (* (:x bubble-margin) (if (= (:h-dir pos) :left) -1 1))
|
||||
|
@ -988,7 +970,7 @@
|
|||
(when-let [node (mf/ref-val ref)]
|
||||
(dom/scroll-into-view-if-needed! node)))
|
||||
|
||||
[:& (mf/provider mentions-context) {:value mentions-str}
|
||||
[:> (mf/provider mentions-context) {:value mentions-s}
|
||||
(when (some? first-comment)
|
||||
[:div {:class (stl/css-case :floating-thread-wrapper true
|
||||
:left (= (:h-dir pos) :left)
|
||||
|
@ -1000,29 +982,25 @@
|
|||
:on-click dom/stop-propagation}
|
||||
|
||||
[:div {:class (stl/css :floating-thread-header)}
|
||||
[:> comment-floating-thread-header* {:profiles profiles
|
||||
:thread thread
|
||||
[:> comment-floating-thread-header* {:thread thread
|
||||
:origin origin}]]
|
||||
|
||||
[:div {:class (stl/css :floating-thread-main)}
|
||||
[:> comment-floating-thread-item* {:comment first-comment
|
||||
:profiles profiles
|
||||
:thread thread}]
|
||||
(for [item (rest comments)]
|
||||
[:* {:key (dm/str (:id item))}
|
||||
[:> comment-floating-thread-item* {:comment item
|
||||
:profiles profiles}]])]
|
||||
[:> comment-floating-thread-item* {:comment item}]])]
|
||||
|
||||
[:> comment-reply-form* {:thread thread}]
|
||||
|
||||
[:> mentions-panel* {:profiles profiles}]])]))
|
||||
[:> mentions-panel*]])]))
|
||||
|
||||
(mf/defc comment-floating-bubble*
|
||||
{::mf/props :obj
|
||||
::mf/wrap [mf/memo]}
|
||||
[{:keys [thread profiles zoom is-open on-click origin position-modifier]}]
|
||||
(let [owner (get profiles (:owner-id thread))
|
||||
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [thread zoom is-open on-click origin position-modifier]}]
|
||||
(let [owner (mf/with-memo [thread]
|
||||
(dcm/get-owner thread))
|
||||
base-pos (cond-> (:position thread)
|
||||
(some? position-modifier)
|
||||
(gpt/transform position-modifier))
|
||||
|
@ -1036,11 +1014,12 @@
|
|||
position (:position thread)
|
||||
frame-id (:frame-id thread)
|
||||
|
||||
state (mf/use-state {:hover? false
|
||||
:grabbing? false
|
||||
state (mf/use-state
|
||||
#(do {:is-hover false
|
||||
:is-grabbing false
|
||||
:new-position-x nil
|
||||
:new-position-y nil
|
||||
:new-frame-id frame-id})
|
||||
:new-frame-id frame-id}))
|
||||
|
||||
pos-x (floor (* (or (:new-position-x @state) (:x base-pos)) zoom))
|
||||
pos-y (floor (* (or (:new-position-y @state) (:y base-pos)) zoom))
|
||||
|
@ -1050,7 +1029,7 @@
|
|||
(mf/deps origin was-open? is-open drag?)
|
||||
(fn [event]
|
||||
(when (not= origin :viewer)
|
||||
(swap! state assoc :grabbing? true)
|
||||
(swap! state assoc :is-grabbing true)
|
||||
(mf/set-ref-val! was-open? is-open)
|
||||
(when is-open (st/emit! (dcm/close-thread)))
|
||||
(mf/set-ref-val! drag? false)
|
||||
|
@ -1064,7 +1043,7 @@
|
|||
(mf/deps origin thread (select-keys @state [:new-position-x :new-position-y :new-frame-id]))
|
||||
(fn [event]
|
||||
(when (not= origin :viewer)
|
||||
(swap! state assoc :grabbing? false)
|
||||
(swap! state assoc :is-grabbing false)
|
||||
(dom/stop-propagation event)
|
||||
(dom/release-pointer event)
|
||||
(mf/set-ref-val! dragging-ref false)
|
||||
|
@ -1100,28 +1079,28 @@
|
|||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when (false? is-open)
|
||||
(swap! state assoc :hover? true))))
|
||||
(swap! state assoc :is-hover true))))
|
||||
|
||||
on-pointer-leave
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state assoc :hover? false)))
|
||||
(swap! state assoc :is-hover false)))
|
||||
|
||||
on-click*
|
||||
(mf/use-fn
|
||||
(mf/deps origin thread on-click was-open? drag? (select-keys @state [:hover?]))
|
||||
(mf/deps origin thread on-click was-open? drag? (select-keys @state [:is-hover]))
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(when (or (and (mf/ref-val was-open?) (mf/ref-val drag?))
|
||||
(and (not (mf/ref-val was-open?)) (not (mf/ref-val drag?))))
|
||||
(swap! state assoc :hover? false)
|
||||
(swap! state assoc :is-hover false)
|
||||
(st/emit! (dcm/open-thread thread)))
|
||||
(when (= origin :viewer)
|
||||
(on-click thread))))]
|
||||
|
||||
[:div {:style {:top (str pos-y "px")
|
||||
:left (str pos-x "px")}
|
||||
[:div {:style {:top (dm/str pos-y "px")
|
||||
:left (dm/str pos-x "px")}
|
||||
:on-pointer-down on-pointer-down
|
||||
:on-pointer-up on-pointer-up
|
||||
:on-pointer-move on-pointer-move
|
||||
|
@ -1129,29 +1108,30 @@
|
|||
:on-pointer-leave on-pointer-leave
|
||||
:on-click on-click*
|
||||
:class (stl/css-case :floating-preview-wrapper true
|
||||
:floating-preview-bubble (false? (:hover? @state))
|
||||
:grabbing (true? (:grabbing? @state)))}
|
||||
:floating-preview-bubble (false? (:is-hover @state))
|
||||
:grabbing (true? (:is-grabbing @state)))}
|
||||
|
||||
(if (:hover? @state)
|
||||
(if (:is-hover @state)
|
||||
[:div {:class (stl/css :floating-thread-wrapper :floating-preview-displacement)}
|
||||
[:div {:class (stl/css :floating-thread-item-wrapper)}
|
||||
[:div {:class (stl/css :floating-thread-item)}
|
||||
[:> comment-info* {:item thread
|
||||
:profile owner}]]]]
|
||||
|
||||
[:> comment-avatar* {:image (cfg/resolve-profile-photo-url owner)
|
||||
[:> comment-avatar*
|
||||
{:image (cfg/resolve-profile-photo-url owner)
|
||||
:class (stl/css :avatar-lg)
|
||||
:data-testid (str "floating-thread-bubble-" (:seqn thread))
|
||||
:variant (cond (:is-resolved thread) "solved"
|
||||
:data-testid (dm/str "floating-thread-bubble-" (:seqn thread))
|
||||
:variant (cond
|
||||
(:is-resolved thread) "solved"
|
||||
(pos? (:count-unread-comments thread)) "unread"
|
||||
:else "read")}])]))
|
||||
|
||||
(mf/defc comment-sidebar-thread-item*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [item profiles on-click]}]
|
||||
(let [owner (get profiles (:owner-id item))
|
||||
|
||||
{::mf/private true}
|
||||
[{:keys [item on-click]}]
|
||||
(let [owner (dcm/get-owner item)
|
||||
;; FIXME
|
||||
frame (mf/deref (refs/workspace-page-object-by-id (:page-id item) (:frame-id item)))
|
||||
|
||||
on-click*
|
||||
|
@ -1176,21 +1156,18 @@
|
|||
:profile owner}]]))
|
||||
|
||||
(mf/defc comment-sidebar-thread-group*
|
||||
{::mf/props :obj}
|
||||
[{:keys [group profiles on-thread-click]}]
|
||||
[{:keys [group on-thread-click]}]
|
||||
[:div
|
||||
(for [item (:items group)]
|
||||
[:> comment-sidebar-thread-item*
|
||||
{:item item
|
||||
:on-click on-thread-click
|
||||
:profiles profiles
|
||||
:key (:id item)}])])
|
||||
|
||||
(mf/defc comment-dashboard-thread-item*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [item profiles on-click]}]
|
||||
(let [owner (get profiles (:owner-id item))
|
||||
{::mf/private true}
|
||||
[{:keys [item on-click]}]
|
||||
(let [owner (dcm/get-owner item)
|
||||
|
||||
on-click*
|
||||
(mf/use-fn
|
||||
|
@ -1215,12 +1192,10 @@
|
|||
:profile owner}]]))
|
||||
|
||||
(mf/defc comment-dashboard-thread-group*
|
||||
{::mf/props :obj}
|
||||
[{:keys [group profiles on-thread-click]}]
|
||||
[{:keys [group on-thread-click]}]
|
||||
[:div
|
||||
(for [item (:items group)]
|
||||
[:> comment-dashboard-thread-item*
|
||||
{:item item
|
||||
:on-click on-thread-click
|
||||
:profiles profiles
|
||||
:key (:id item)}])])
|
||||
|
|
|
@ -50,9 +50,9 @@
|
|||
(mf/defc comments-section
|
||||
[{:keys [profile team show? on-hide-comments]}]
|
||||
(let [threads-map (mf/deref refs/comment-threads)
|
||||
profiles (mf/deref refs/profiles)
|
||||
team-id (:id team)
|
||||
|
||||
;; FIXME: with-memo
|
||||
team-id (:id team)
|
||||
tgroups (->> (vals threads-map)
|
||||
(sort-by :modified-at)
|
||||
(reverse)
|
||||
|
@ -93,14 +93,12 @@
|
|||
[:> cmt/comment-dashboard-thread-group*
|
||||
{:group (first tgroups)
|
||||
:on-thread-click on-navigate
|
||||
:show-file-name true
|
||||
:profiles profiles}]
|
||||
:show-file-name true}]
|
||||
(for [tgroup (rest tgroups)]
|
||||
[:> cmt/comment-dashboard-thread-group*
|
||||
{:group tgroup
|
||||
:on-thread-click on-navigate
|
||||
:show-file-name true
|
||||
:profiles profiles
|
||||
:key (:page-id tgroup)}])]
|
||||
|
||||
[:div {:class (stl/css :thread-groups-placeholder)}
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.modifiers :as dwm]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.css-cursors :as cur]
|
||||
|
@ -135,7 +135,7 @@
|
|||
negate {:column-gap (if flip-x true false)
|
||||
:row-gap (if flip-y true false)}
|
||||
|
||||
objects (wsh/lookup-page-objects @st/state)
|
||||
objects (dsh/lookup-page-objects @st/state)
|
||||
children (->> (cfh/get-immediate-children objects frame-id)
|
||||
(remove ctl/position-absolute?))
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@
|
|||
|
||||
(mf/defc comments-layer
|
||||
{::mf/props :obj}
|
||||
[{:keys [zoom file users frame page]}]
|
||||
[{:keys [zoom file frame page]}]
|
||||
(let [profile (mf/deref refs/profile)
|
||||
local (mf/deref refs/comments-local)
|
||||
|
||||
|
@ -208,7 +208,6 @@
|
|||
(for [item threads]
|
||||
[:> cmt/comment-floating-bubble*
|
||||
{:thread item
|
||||
:profiles users
|
||||
:position-modifier modifier1
|
||||
:zoom zoom
|
||||
:on-click on-bubble-click
|
||||
|
@ -219,7 +218,6 @@
|
|||
(when-let [thread (get threads-map open-thread-id)]
|
||||
[:> cmt/comment-floating-thread*
|
||||
{:thread thread
|
||||
:profiles users
|
||||
:position-modifier modifier1
|
||||
:viewport {:offset-x 0 :offset-y 0 :width (:width vsize) :height (:height vsize)}
|
||||
:zoom zoom}])
|
||||
|
@ -227,7 +225,6 @@
|
|||
(when-let [draft (:draft local)]
|
||||
[:> cmt/comment-floating-thread-draft*
|
||||
{:draft draft
|
||||
:profiles users
|
||||
:position-modifier modifier1
|
||||
:on-cancel on-draft-cancel
|
||||
:on-submit on-draft-submit
|
||||
|
|
|
@ -9,11 +9,13 @@
|
|||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.common :as dcm]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.persistence :as dps]
|
||||
[app.main.data.plugins :as dpl]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.router :as-alias rt]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.ds.product.loader :refer [loader*]]
|
||||
|
@ -21,7 +23,7 @@
|
|||
[app.main.ui.hooks.resize :refer [use-resize-observer]]
|
||||
[app.main.ui.modal :refer [modal-container*]]
|
||||
[app.main.ui.workspace.colorpicker]
|
||||
[app.main.ui.workspace.context-menu :refer [context-menu]]
|
||||
[app.main.ui.workspace.context-menu :refer [context-menu*]]
|
||||
[app.main.ui.workspace.coordinates :as coordinates]
|
||||
[app.main.ui.workspace.libraries]
|
||||
[app.main.ui.workspace.nudge]
|
||||
|
@ -32,7 +34,7 @@
|
|||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
|
||||
[app.main.ui.workspace.tokens.modals]
|
||||
[app.main.ui.workspace.tokens.modals.themes]
|
||||
[app.main.ui.workspace.viewport :refer [viewport]]
|
||||
[app.main.ui.workspace.viewport :refer [viewport*]]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.globals :as globals]
|
||||
|
@ -41,27 +43,19 @@
|
|||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defn- make-file-ready-ref
|
||||
(defn- make-workspace-ready-ref
|
||||
[file-id]
|
||||
(l/derived (fn [state]
|
||||
(let [data (:workspace-data state)]
|
||||
(and (:workspace-ready state)
|
||||
(= file-id (:current-file-id state))
|
||||
(= file-id (:id data)))))
|
||||
(and (= file-id (:workspace-ready state))
|
||||
(some? (dsh/lookup-file-data state file-id))))
|
||||
st/state))
|
||||
|
||||
(defn- make-page-ready-ref
|
||||
[page-id]
|
||||
(l/derived (fn [state]
|
||||
(and (some? page-id)
|
||||
(= page-id (:current-page-id state))))
|
||||
st/state))
|
||||
|
||||
(mf/defc workspace-content
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file layout page-id wglobal]}]
|
||||
(mf/defc workspace-content*
|
||||
{::mf/private true}
|
||||
[{:keys [file layout page wglobal]}]
|
||||
(let [palete-size (mf/use-state nil)
|
||||
selected (mf/deref refs/selected-shapes)
|
||||
page-id (:id page)
|
||||
|
||||
{:keys [vport] :as wlocal} (mf/deref refs/workspace-local)
|
||||
{:keys [options-mode]} wglobal
|
||||
|
@ -102,7 +96,9 @@
|
|||
[:button {:on-click #(st/emit! dw/reinitialize-undo)} "CLEAR"]
|
||||
[:> history-toolbox*]])
|
||||
|
||||
[:& viewport {:file file
|
||||
[:> viewport*
|
||||
{:file file
|
||||
:page page
|
||||
:wlocal wlocal
|
||||
:wglobal wglobal
|
||||
:selected selected
|
||||
|
@ -125,21 +121,17 @@
|
|||
:page-id page-id}]])]))
|
||||
|
||||
(mf/defc workspace-loader*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[]
|
||||
[:> loader* {:title (tr "labels.loading")
|
||||
:class (stl/css :workspace-loader)
|
||||
:overlay true}])
|
||||
|
||||
(mf/defc workspace-page*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
{::mf/private true}
|
||||
[{:keys [page-id file layout wglobal]}]
|
||||
(let [page-id (hooks/use-equal-memo page-id)
|
||||
page-ready* (mf/with-memo [page-id]
|
||||
(make-page-ready-ref page-id))
|
||||
page-ready? (mf/deref page-ready*)]
|
||||
page (mf/deref refs/workspace-page)]
|
||||
|
||||
(mf/with-effect []
|
||||
(let [focus-out #(st/emit! (dw/workspace-focus-lost))
|
||||
|
@ -149,29 +141,39 @@
|
|||
(mf/with-effect [page-id]
|
||||
(if (some? page-id)
|
||||
(st/emit! (dw/initialize-page page-id))
|
||||
(st/emit! (dcm/go-to-workspace)))
|
||||
(st/emit! (dcm/go-to-workspace ::rt/replace true)))
|
||||
|
||||
(fn []
|
||||
(when (some? page-id)
|
||||
(st/emit! (dw/finalize-page page-id)))))
|
||||
|
||||
(if ^boolean page-ready?
|
||||
[:& workspace-content {:page-id page-id
|
||||
:file file
|
||||
(if (some? page)
|
||||
[:> workspace-content* {:file file
|
||||
:page page
|
||||
:wglobal wglobal
|
||||
:layout layout}]
|
||||
[:& workspace-loader*])))
|
||||
|
||||
|
||||
(def ^:private ref:file-without-data
|
||||
(l/derived (fn [file]
|
||||
(dissoc file :data))
|
||||
refs/file
|
||||
=))
|
||||
|
||||
(mf/defc workspace*
|
||||
{::mf/props :obj
|
||||
::mf/wrap [mf/memo]}
|
||||
[{:keys [project-id file-id page-id layout-name]}]
|
||||
|
||||
(let [layout (mf/deref refs/workspace-layout)
|
||||
(let [file-id (hooks/use-equal-memo file-id)
|
||||
page-id (hooks/use-equal-memo page-id)
|
||||
|
||||
layout (mf/deref refs/workspace-layout)
|
||||
wglobal (mf/deref refs/workspace-global)
|
||||
|
||||
team (mf/deref refs/team)
|
||||
file (mf/deref refs/workspace-file)
|
||||
file (mf/deref ref:file-without-data)
|
||||
|
||||
file-name (:name file)
|
||||
permissions (:permissions team)
|
||||
|
@ -179,11 +181,10 @@
|
|||
read-only? (mf/deref refs/workspace-read-only?)
|
||||
read-only? (or read-only? (not (:can-edit permissions)))
|
||||
|
||||
file-ready* (mf/with-memo [file-id]
|
||||
(make-file-ready-ref file-id))
|
||||
file-ready? (mf/deref file-ready*)
|
||||
ready* (mf/with-memo [file-id]
|
||||
(make-workspace-ready-ref file-id))
|
||||
ready? (mf/deref ready*)
|
||||
|
||||
components-v2? (features/use-feature "components/v2")
|
||||
design-tokens? (features/use-feature "design-tokens/v1")
|
||||
|
||||
background-color (:background-color wglobal)]
|
||||
|
@ -206,21 +207,21 @@
|
|||
(st/emit! ::dps/force-persist
|
||||
(dw/finalize-workspace file-id))))
|
||||
|
||||
[:& (mf/provider ctx/current-project-id) {:value project-id}
|
||||
[:& (mf/provider ctx/current-file-id) {:value file-id}
|
||||
[:& (mf/provider ctx/current-page-id) {:value page-id}
|
||||
[:& (mf/provider ctx/components-v2) {:value components-v2?}
|
||||
[:& (mf/provider ctx/design-tokens) {:value design-tokens?}
|
||||
[:& (mf/provider ctx/workspace-read-only?) {:value read-only?}
|
||||
[:> (mf/provider ctx/current-project-id) {:value project-id}
|
||||
[:> (mf/provider ctx/current-file-id) {:value file-id}
|
||||
[:> (mf/provider ctx/current-page-id) {:value page-id}
|
||||
[:> (mf/provider ctx/components-v2) {:value true}
|
||||
[:> (mf/provider ctx/design-tokens) {:value design-tokens?}
|
||||
[:> (mf/provider ctx/workspace-read-only?) {:value read-only?}
|
||||
[:> modal-container*]
|
||||
[:section {:class (stl/css :workspace)
|
||||
:style {:background-color background-color
|
||||
:touch-action "none"}}
|
||||
[:& context-menu]
|
||||
[:> context-menu*]
|
||||
|
||||
(if ^boolean file-ready?
|
||||
(if ^boolean ready?
|
||||
[:> workspace-page* {:page-id page-id
|
||||
:file file
|
||||
:wglobal wglobal
|
||||
:layout layout}]
|
||||
[:> workspace-loader* {}])]]]]]]]))
|
||||
[:> workspace-loader*])]]]]]]]))
|
||||
|
|
|
@ -24,20 +24,22 @@
|
|||
[potok.v2.core :as ptk]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc palette-item
|
||||
(mf/defc palette-item*
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [color size selected]}]
|
||||
(letfn [(select-color [event]
|
||||
(st/emit!
|
||||
(dwl/add-recent-color color)
|
||||
(let [select-color
|
||||
(mf/use-fn
|
||||
(mf/deps color selected)
|
||||
(fn [event]
|
||||
(st/emit! (dwl/add-recent-color color)
|
||||
(mdc/apply-color-from-palette color (kbd/alt? event))
|
||||
(when (not= selected :recent)
|
||||
(ptk/event
|
||||
::ev/event
|
||||
(ptk/data-event ::ev/event
|
||||
{::ev/name "use-library-color"
|
||||
::ev/origin "color-palette"
|
||||
:external-library (not= selected :file)}))))]
|
||||
[:div {:class (stl/css-case :color-cell true
|
||||
:external-library (not= selected :file)})))))]
|
||||
[:div {:class (stl/css-case
|
||||
:color-cell true
|
||||
:is-not-library-color (nil? (:id color))
|
||||
:no-text (<= size 64))
|
||||
:title (uc/get-color-name color)
|
||||
|
@ -45,8 +47,7 @@
|
|||
[:& cb/color-bullet {:color color}]
|
||||
[:& cb/color-name {:color color :size size :origin :palette}]]))
|
||||
|
||||
|
||||
(mf/defc palette
|
||||
(mf/defc palette*
|
||||
[{:keys [current-colors size width selected]}]
|
||||
(let [;; We had to do this due to a bug that leave some bugged colors
|
||||
current-colors (h/use-equal-memo (filter #(or (:gradient %) (:color %) (:image %)) current-colors))
|
||||
|
@ -140,7 +141,7 @@
|
|||
:max-width (str width "px")
|
||||
:right (str (* offset-step offset) "px")}}
|
||||
(for [[idx item] (map-indexed vector current-colors)]
|
||||
[:& palette-item {:color item :key idx :size size :selected selected}])])]
|
||||
[:> palette-item* {:color item :key idx :size size :selected selected}])])]
|
||||
(when show-arrows?
|
||||
[:button {:class (stl/css :right-arrow)
|
||||
:disabled (= offset max-offset)
|
||||
|
@ -155,7 +156,7 @@
|
|||
(mf/defc color-palette
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [size width selected] :as props}]
|
||||
(let [recent-colors (mf/deref refs/workspace-recent-colors)
|
||||
(let [recent-colors (mf/deref refs/recent-colors)
|
||||
file-colors (mf/deref refs/workspace-file-colors)
|
||||
shared-libs (mf/deref refs/libraries)
|
||||
colors (mf/use-state [])]
|
||||
|
@ -176,7 +177,7 @@
|
|||
(reset! colors (into [] (->> (vals file-colors)
|
||||
(sort-by :name))))))
|
||||
|
||||
[:& palette {:current-colors @colors
|
||||
[:> palette* {:current-colors @colors
|
||||
:size size
|
||||
:width width
|
||||
:selected selected}]))
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
(mf/defc color-palette-ctx-menu
|
||||
[{:keys [show-menu? close-menu on-select-palette selected]}]
|
||||
(let [recent-colors (mf/deref refs/workspace-recent-colors)
|
||||
(let [recent-colors (mf/deref refs/recent-colors)
|
||||
file-colors (mf/deref refs/workspace-file-colors)
|
||||
shared-libs (mf/deref refs/libraries)]
|
||||
[:& dropdown {:show show-menu?
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
shared-libs (mf/deref refs/libraries)
|
||||
file-colors (mf/deref refs/workspace-file-colors)
|
||||
recent-colors (mf/deref refs/workspace-recent-colors)
|
||||
recent-colors (mf/deref refs/recent-colors)
|
||||
recent-colors (h/use-equal-memo (filter #(or (:gradient %) (:color %) (:image %)) recent-colors))
|
||||
|
||||
on-library-change
|
||||
|
|
|
@ -73,9 +73,8 @@
|
|||
[:span {:class (stl/css :icon)} i/tick]]]))
|
||||
|
||||
(mf/defc comments-sidebar*
|
||||
{::mf/props :obj}
|
||||
[{:keys [profiles threads page-id from-viewer]}]
|
||||
(let [threads-map (mf/deref refs/threads-ref)
|
||||
(let [threads-map (mf/deref refs/threads)
|
||||
profile (mf/deref refs/profile)
|
||||
profiles' (mf/deref refs/profiles)
|
||||
profiles (or profiles profiles')
|
||||
|
|
|
@ -748,7 +748,7 @@
|
|||
|
||||
;; FIXME: optimize because it is rendered always
|
||||
|
||||
(mf/defc context-menu
|
||||
(mf/defc context-menu*
|
||||
[]
|
||||
(let [mdata (mf/deref menu-ref)
|
||||
top (- (get-in mdata [:position :y]) 20)
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
[app.main.ui.components.link-button :as lb]
|
||||
[app.main.ui.components.search-bar :refer [search-bar]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.icons :as i]
|
||||
|
@ -38,7 +39,6 @@
|
|||
[app.util.strings :refer [matches-search]]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def ^:private close-icon
|
||||
|
@ -53,25 +53,47 @@
|
|||
(def ^:private library-icon
|
||||
(i/icon-xref :library (stl/css :library-icon)))
|
||||
|
||||
(def ref:workspace-file
|
||||
(l/derived :workspace-file st/state))
|
||||
(defn- get-library-summary
|
||||
"Given a library data return a summary representation of this library"
|
||||
[data]
|
||||
(let [colors (count (:colors data))
|
||||
graphics 0
|
||||
typographies (count (:typographies data))
|
||||
components (count (ctkl/components-seq data))
|
||||
empty? (and (zero? components)
|
||||
(zero? graphics)
|
||||
(zero? colors)
|
||||
(zero? typographies))]
|
||||
|
||||
(defn create-file-library-ref
|
||||
[library-id]
|
||||
(letfn [(getter-fn [state]
|
||||
(let [fdata (let [{:keys [id] :as wfile} (:workspace-data state)]
|
||||
(if (= id library-id)
|
||||
wfile
|
||||
(dm/get-in state [:libraries library-id :data])))]
|
||||
{:colors (-> fdata :colors vals)
|
||||
:media (-> fdata :media vals)
|
||||
:components (ctkl/components-seq fdata)
|
||||
:typographies (-> fdata :typographies vals)}))]
|
||||
(l/derived getter-fn st/state =)))
|
||||
{:is-empty empty?
|
||||
:colors colors
|
||||
:graphics graphics
|
||||
:typographies typographies
|
||||
:components components}))
|
||||
|
||||
(defn- adapt-backend-summary
|
||||
[summary]
|
||||
(let [components (or (-> summary :components :count) 0)
|
||||
graphics (or (-> summary :media :count) 0)
|
||||
typographies (or (-> summary :typographies :count) 0)
|
||||
colors (or (-> summary :colors :count) 0)
|
||||
|
||||
empty? (and (zero? components)
|
||||
(zero? graphics)
|
||||
(zero? colors)
|
||||
(zero? typographies))]
|
||||
{:is-empty empty?
|
||||
:components components
|
||||
:graphics graphics
|
||||
:typographies typographies
|
||||
:colors colors}))
|
||||
|
||||
(defn- describe-library
|
||||
[components-count graphics-count colors-count typography-count]
|
||||
(let [all-zero? (and (zero? components-count) (zero? graphics-count) (zero? colors-count) (zero? typography-count))]
|
||||
(let [all-zero? (and (zero? components-count)
|
||||
(zero? graphics-count)
|
||||
(zero? colors-count)
|
||||
(zero? typography-count))]
|
||||
(str
|
||||
(str/join " · "
|
||||
(cond-> []
|
||||
|
@ -88,10 +110,15 @@
|
|||
(conj (tr "workspace.libraries.typography" typography-count))))
|
||||
"\u00A0")))
|
||||
|
||||
(mf/defc describe-library-blocks*
|
||||
(mf/defc library-description*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [components-count graphics-count colors-count typography-count]}]
|
||||
[{:keys [summary]}]
|
||||
(let [components-count (get summary :components)
|
||||
graphics-count (get summary :graphics)
|
||||
typography-count (get summary :typographies)
|
||||
colors-count (get summary :colors)]
|
||||
|
||||
[:*
|
||||
(when (pos? components-count)
|
||||
[:li {:class (stl/css :element-count)}
|
||||
|
@ -107,7 +134,7 @@
|
|||
|
||||
(when (pos? typography-count)
|
||||
[:li {:class (stl/css :element-count)}
|
||||
(tr "workspace.libraries.typography" typography-count)])])
|
||||
(tr "workspace.libraries.typography" typography-count)])]))
|
||||
|
||||
(mf/defc sample-library-entry*
|
||||
{::mf/props :obj
|
||||
|
@ -146,26 +173,35 @@
|
|||
:value (if (= importing? id) (tr "labels.adding") (tr "labels.add"))
|
||||
:on-click import-library}]]))
|
||||
|
||||
(defn- empty-library?
|
||||
"Check if currentt library summary has elements or not"
|
||||
[summary]
|
||||
(let [colors (or (-> summary :colors :count) 0)
|
||||
components (or (-> summary :components :count) 0)
|
||||
media (or (-> summary :media :count) 0)
|
||||
typographies (or (-> summary :typographies :count) 0)]
|
||||
|
||||
(and (zero? colors)
|
||||
(zero? components)
|
||||
(zero? media)
|
||||
(zero? typographies))))
|
||||
|
||||
(mf/defc libraries-tab*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [file-id is-shared linked-libraries shared-libraries]}]
|
||||
(let [search-term* (mf/use-state "")
|
||||
[{:keys [is-shared linked-libraries shared-libraries]}]
|
||||
(let [file-id (mf/use-ctx ctx/current-file-id)
|
||||
search-term* (mf/use-state "")
|
||||
search-term (deref search-term*)
|
||||
library-ref (mf/with-memo [file-id]
|
||||
(create-file-library-ref file-id))
|
||||
library (deref library-ref)
|
||||
colors (:colors library)
|
||||
components (:components library)
|
||||
media (:media library)
|
||||
typographies (:typographies library)
|
||||
|
||||
;; The summary of the current/local library
|
||||
;; NOTE: we only need a snapshot of current library
|
||||
local-library (deref refs/workspace-data)
|
||||
summary (get-library-summary local-library)
|
||||
empty-library? (empty-library? summary)
|
||||
|
||||
selected (h/use-shared-state mdc/colorpalette-selected-broadcast-key :recent)
|
||||
|
||||
empty-library? (and
|
||||
(zero? (count colors))
|
||||
(zero? (count components))
|
||||
(zero? (count media))
|
||||
(zero? (count typographies)))
|
||||
|
||||
shared-libraries
|
||||
(mf/with-memo [shared-libraries linked-libraries file-id search-term]
|
||||
|
@ -263,10 +299,8 @@
|
|||
[:div {:class (stl/css :item-content)}
|
||||
[:div {:class (stl/css :item-name)} (tr "workspace.libraries.file-library")]
|
||||
[:ul {:class (stl/css :item-contents)}
|
||||
[:> describe-library-blocks* {:components-count (count components)
|
||||
:graphics-count (count media)
|
||||
:colors-count (count colors)
|
||||
:typography-count (count typographies)}]]]
|
||||
[:> library-description* {:summary summary}]]]
|
||||
|
||||
(if ^boolean is-shared
|
||||
[:input {:class (stl/css :item-unpublish)
|
||||
:type "button"
|
||||
|
@ -277,21 +311,15 @@
|
|||
:value (tr "common.publish")
|
||||
:on-click publish}])]
|
||||
|
||||
(for [{:keys [id name] :as library} linked-libraries]
|
||||
(for [{:keys [id name data] :as library} linked-libraries]
|
||||
[:div {:class (stl/css :section-list-item)
|
||||
:key (dm/str id)
|
||||
:data-testid "library-item"}
|
||||
[:div {:class (stl/css :item-content)}
|
||||
[:div {:class (stl/css :item-name)} name]
|
||||
[:ul {:class (stl/css :item-contents)}
|
||||
(let [components-count (count (or (ctkl/components-seq (:data library)) []))
|
||||
graphics-count (count (dm/get-in library [:data :media] []))
|
||||
colors-count (count (dm/get-in library [:data :colors] []))
|
||||
typography-count (count (dm/get-in library [:data :typographies] []))]
|
||||
[:> describe-library-blocks* {:components-count components-count
|
||||
:graphics-count graphics-count
|
||||
:colors-count colors-count
|
||||
:typography-count typography-count}])]]
|
||||
(let [summary (get-library-summary data)]
|
||||
[:> library-description* {:summary summary}])]]
|
||||
|
||||
[:button {:class (stl/css :item-button)
|
||||
:type "button"
|
||||
|
@ -318,14 +346,10 @@
|
|||
[:div {:class (stl/css :item-content)}
|
||||
[:div {:class (stl/css :item-name)} name]
|
||||
[:ul {:class (stl/css :item-contents)}
|
||||
(let [components-count (dm/get-in library [:library-summary :components :count] 0)
|
||||
graphics-count (dm/get-in library [:library-summary :media :count] 0)
|
||||
colors-count (dm/get-in library [:library-summary :colors :count] 0)
|
||||
typography-count (dm/get-in library [:library-summary :typographies :count] 0)]
|
||||
[:> describe-library-blocks* {:components-count components-count
|
||||
:graphics-count graphics-count
|
||||
:colors-count colors-count
|
||||
:typography-count typography-count}])]]
|
||||
(let [summary (-> (:library-summary library)
|
||||
(adapt-backend-summary))]
|
||||
[:> library-description* {:summary summary}])]]
|
||||
|
||||
[:button {:class (stl/css :item-button-shared)
|
||||
:data-library-id (dm/str id)
|
||||
:title (tr "workspace.libraries.shared-library-btn")
|
||||
|
@ -414,11 +438,16 @@
|
|||
(mf/defc updates-tab*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [file-id file-data libraries]}]
|
||||
[{:keys [file-id libraries]}]
|
||||
;; FIXME: naming
|
||||
(let [summary?* (mf/use-state true)
|
||||
summary? (deref summary?*)
|
||||
updating? (mf/deref refs/updating-library)
|
||||
|
||||
;; NOTE: we don't want to react on file changes, we just want
|
||||
;; a snapshot of file on the momento of open the dialog
|
||||
file-data (deref refs/workspace-data)
|
||||
|
||||
see-all-assets
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
|
@ -544,22 +573,31 @@
|
|||
(when (or (pos? (:components exceeded))
|
||||
(pos? (:colors exceeded))
|
||||
(pos? (:typographies exceeded)))
|
||||
[:& lb/link-button {:on-click see-all-assets
|
||||
[:& lb/link-button
|
||||
{:on-click see-all-assets
|
||||
:class (stl/css :libraries-updates-see-all)
|
||||
:value (str "(" (tr "workspace.libraries.update.see-all-changes") ")")}])])]])]]))
|
||||
|
||||
(mf/defc libraries-dialog
|
||||
{::mf/register modal/components
|
||||
::mf/register-as :libraries-dialog}
|
||||
[{:keys [starting-tab] :as props :or {starting-tab :libraries}}]
|
||||
(let [file-data (mf/deref refs/workspace-data)
|
||||
file (mf/deref ref:workspace-file)
|
||||
(let [;; NOTE: we don't want to react on file changes, we just want
|
||||
;; a snapshot of file on the momento of open the dialog
|
||||
file (deref refs/file)
|
||||
|
||||
file-id (:id file)
|
||||
shared? (:is-shared file)
|
||||
|
||||
libraries (mf/deref refs/libraries)
|
||||
libraries (mf/with-memo [libraries]
|
||||
(d/removem (fn [[_ val]] (:is-indirect val)) libraries))
|
||||
linked-libraries
|
||||
(mf/deref refs/files)
|
||||
|
||||
linked-libraries
|
||||
(mf/with-memo [linked-libraries file-id]
|
||||
(d/removem (fn [[_ lib]]
|
||||
(or (:is-indirect lib)
|
||||
(= (:id lib) file-id)))
|
||||
linked-libraries))
|
||||
|
||||
shared-libraries
|
||||
(mf/deref refs/shared-files)
|
||||
|
@ -578,16 +616,14 @@
|
|||
|
||||
libraries-tab
|
||||
(mf/html [:> libraries-tab*
|
||||
{:file-id file-id
|
||||
:is-shared shared?
|
||||
:linked-libraries libraries
|
||||
{:is-shared shared?
|
||||
:linked-libraries linked-libraries
|
||||
:shared-libraries shared-libraries}])
|
||||
|
||||
updates-tab
|
||||
(mf/html [:> updates-tab*
|
||||
{:file-id file-id
|
||||
:file-data file-data
|
||||
:libraries libraries}])
|
||||
:libraries linked-libraries}])
|
||||
|
||||
tabs
|
||||
#js [#js {:label (tr "workspace.libraries.libraries")
|
||||
|
@ -600,7 +636,9 @@
|
|||
(mf/with-effect []
|
||||
(st/emit! (dtm/fetch-shared-files)))
|
||||
|
||||
[:div {:class (stl/css :modal-overlay) :on-click close-dialog-outside :data-testid "libraries-modal"}
|
||||
[:div {:class (stl/css :modal-overlay)
|
||||
:on-click close-dialog-outside
|
||||
:data-testid "libraries-modal"}
|
||||
[:div {:class (stl/css :modal-dialog)}
|
||||
[:button {:class (stl/css :close-btn)
|
||||
:on-click close-dialog
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[app.common.geom.shapes.bounds :as gsb]
|
||||
[app.common.math :as mth]
|
||||
[app.common.thumbnails :as thc]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.thumbnails :as dwt]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -70,7 +70,7 @@
|
|||
::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
objects (wsh/lookup-page-objects @st/state)
|
||||
objects (dsh/lookup-page-objects @st/state)
|
||||
|
||||
frame-id (dm/get-prop shape :id)
|
||||
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||
[app.main.ui.workspace.sidebar.assets.file-library :refer [file-library]]
|
||||
[app.main.ui.workspace.sidebar.assets.file-library :refer [file-library*]]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[cuerdas.core :as str]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc assets-libraries*
|
||||
|
@ -31,38 +32,39 @@
|
|||
::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [filters]}]
|
||||
(let [libraries (mf/deref refs/libraries)
|
||||
libraries (mf/with-memo [libraries]
|
||||
(let [file-id (mf/use-ctx ctx/current-file-id)
|
||||
|
||||
libraries (mf/deref refs/libraries)
|
||||
libraries (mf/with-memo [libraries file-id]
|
||||
(->> (vals libraries)
|
||||
(remove :is-indirect)
|
||||
(remove #(= file-id (:id %)))
|
||||
(map (fn [file]
|
||||
(update file :data dissoc :pages-index)))
|
||||
(sort-by #(str/lower (:name %)))))]
|
||||
|
||||
(for [file libraries]
|
||||
[:& file-library
|
||||
[:> file-library*
|
||||
{:key (dm/str (:id file))
|
||||
:file file
|
||||
:local? false
|
||||
:default-open? false
|
||||
:is-local false
|
||||
:is-default-open false
|
||||
:filters filters}])))
|
||||
|
||||
(def ^:private ref:local-library
|
||||
(l/derived (fn [file]
|
||||
(update file :data dissoc :pages-index))
|
||||
refs/file))
|
||||
|
||||
(mf/defc assets-local-library
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
[{:keys [filters]}]
|
||||
;; NOTE: as workspace-file is an incomplete view of file (it do not
|
||||
;; contain :data), we need to reconstruct it using workspace-data
|
||||
(let [file (mf/deref refs/workspace-file)
|
||||
data (mf/deref refs/workspace-data)
|
||||
data (mf/with-memo [data]
|
||||
(dissoc data :pages-index))
|
||||
file (mf/with-memo [file data]
|
||||
(assoc file :data data))]
|
||||
|
||||
[:& file-library
|
||||
(let [file (mf/deref ref:local-library)]
|
||||
[:> file-library*
|
||||
{:file file
|
||||
:local? true
|
||||
:default-open? true
|
||||
:is-local true
|
||||
:is-default-open true
|
||||
:filters filters}]))
|
||||
|
||||
(defn- toggle-values
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.config :as cf]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
|
@ -58,7 +59,10 @@
|
|||
(if reverse? "z" "a")
|
||||
path)]
|
||||
(str/lower (cfh/merge-path-item path name))))
|
||||
(if ^boolean reverse? > <)))))
|
||||
(if ^boolean reverse? > <))
|
||||
|
||||
:always
|
||||
(vec))))
|
||||
|
||||
(defn add-group
|
||||
[asset group-name]
|
||||
|
@ -315,10 +319,13 @@
|
|||
copies (filter ctk/in-component-copy? shapes)
|
||||
|
||||
current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
objects (deref refs/workspace-page-objects)
|
||||
workspace-data (deref refs/workspace-data)
|
||||
current-page-id (mf/use-ctx ctx/current-page-id)
|
||||
|
||||
libraries (deref refs/libraries)
|
||||
current-file {:id current-file-id :data workspace-data}
|
||||
current-file (get libraries current-file-id)
|
||||
|
||||
objects (-> (dsh/get-page (:data current-file) current-page-id)
|
||||
(get :objects))
|
||||
|
||||
find-component (fn [shape include-deleted?]
|
||||
(ctf/resolve-component
|
||||
|
|
|
@ -37,31 +37,23 @@
|
|||
[potok.v2.core :as ptk]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def drag-data* (atom {:local? false}))
|
||||
(def drag-data* (atom {:is-local false}))
|
||||
|
||||
(defn set-drag-data! [data]
|
||||
(reset! drag-data* data))
|
||||
|
||||
(defn- get-component-root-and-container
|
||||
[file-id component components-v2]
|
||||
(if (= file-id (:id @refs/workspace-file))
|
||||
(let [data @refs/workspace-data]
|
||||
[(ctf/get-component-root data component)
|
||||
(if components-v2
|
||||
(ctf/get-component-page data component)
|
||||
component)])
|
||||
[file-id component]
|
||||
(let [data (dm/get-in @refs/libraries [file-id :data])
|
||||
root-shape (ctf/get-component-root data component)
|
||||
container (if components-v2
|
||||
(ctf/get-component-page data component)
|
||||
component)]
|
||||
[root-shape container])))
|
||||
container (ctf/get-component-page data component)]
|
||||
[root-shape container]))
|
||||
|
||||
(mf/defc components-item
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [component renaming listing-thumbs? selected
|
||||
file-id on-asset-click on-context-menu on-drag-start do-rename
|
||||
cancel-rename selected-full selected-paths local]}]
|
||||
cancel-rename selected-full selected-paths is-local]}]
|
||||
|
||||
(let [item-ref (mf/use-ref)
|
||||
|
||||
|
@ -69,7 +61,6 @@
|
|||
dragging? (deref dragging*)
|
||||
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
component-id (:id component)
|
||||
|
||||
visible? (h/use-visible item-ref :once? true)
|
||||
|
@ -78,7 +69,7 @@
|
|||
;; really need rerender on any change on the file change. If
|
||||
;; the component changes, it will trigger rerender anyway.
|
||||
[root-shape container]
|
||||
(get-component-root-and-container file-id component components-v2)
|
||||
(get-component-root-and-container file-id component)
|
||||
|
||||
unselect-all
|
||||
(mf/use-fn
|
||||
|
@ -94,38 +85,38 @@
|
|||
|
||||
on-component-double-click
|
||||
(mf/use-fn
|
||||
(mf/deps file-id component local)
|
||||
(mf/deps file-id component is-local)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(if local
|
||||
(if is-local
|
||||
(st/emit! (dwl/go-to-local-component component-id))
|
||||
(st/emit! (dwl/go-to-component-file file-id component)))))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps component dragging* selected selected-full selected-paths local drag-data*)
|
||||
(mf/deps component dragging* selected selected-full selected-paths is-local drag-data*)
|
||||
(fn [event]
|
||||
(when (and local (:local? @drag-data*))
|
||||
(when (and is-local (:is-local @drag-data*))
|
||||
(cmm/on-drop-asset event component dragging* selected selected-full
|
||||
selected-paths dwl/rename-component-and-main-instance))))
|
||||
|
||||
on-drag-enter
|
||||
(mf/use-fn
|
||||
(mf/deps component dragging* selected selected-paths local drag-data*)
|
||||
(mf/deps component dragging* selected selected-paths is-local drag-data*)
|
||||
(fn [event]
|
||||
(when (and local (:local? @drag-data*))
|
||||
(when (and is-local (:is-local @drag-data*))
|
||||
(cmm/on-drag-enter-asset event component dragging* selected selected-paths))))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* local drag-data*)
|
||||
(mf/deps dragging* is-local drag-data*)
|
||||
(fn [event]
|
||||
(when (and local (:local? @drag-data*))
|
||||
(when (and is-local (:is-local @drag-data*))
|
||||
(cmm/on-drag-leave-asset event dragging*))))
|
||||
|
||||
on-component-drag-start
|
||||
(mf/use-fn
|
||||
(mf/deps file-id component selected item-ref on-drag-start read-only? local)
|
||||
(mf/deps file-id component selected item-ref on-drag-start read-only? is-local)
|
||||
(fn [event]
|
||||
(if read-only?
|
||||
(dom/prevent-default event)
|
||||
|
@ -183,7 +174,7 @@
|
|||
{::mf/wrap-props false}
|
||||
[{:keys [file-id prefix groups open-groups force-open? renaming listing-thumbs? selected on-asset-click
|
||||
on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu
|
||||
selected-full local]}]
|
||||
selected-full is-local]}]
|
||||
|
||||
(let [group-open? (if (false? (get open-groups prefix)) ;; if the user has closed it specifically, respect that
|
||||
false
|
||||
|
@ -199,23 +190,23 @@
|
|||
selected-full))
|
||||
on-drag-enter
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* prefix selected-paths local drag-data*)
|
||||
(mf/deps dragging* prefix selected-paths is-local drag-data*)
|
||||
(fn [event]
|
||||
(when (and local (:local? @drag-data*))
|
||||
(when (and is-local (:is-local @drag-data*))
|
||||
(cmm/on-drag-enter-asset-group event dragging* prefix selected-paths))))
|
||||
|
||||
on-drag-leave
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* local drag-data*)
|
||||
(mf/deps dragging* is-local drag-data*)
|
||||
(fn [event]
|
||||
(when (and local (:local? @drag-data*))
|
||||
(when (and is-local (:is-local @drag-data*))
|
||||
(cmm/on-drag-leave-asset event dragging*))))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
(mf/deps dragging* prefix selected-paths selected-full local drag-data*)
|
||||
(mf/deps dragging* prefix selected-paths selected-full is-local drag-data*)
|
||||
(fn [event]
|
||||
(when (and local (:local? @drag-data*))
|
||||
(when (and is-local (:is-local @drag-data*))
|
||||
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full dwl/rename-component-and-main-instance))))]
|
||||
|
||||
[:div {:class (stl/css :component-group)
|
||||
|
@ -248,7 +239,7 @@
|
|||
|
||||
(when (and (empty? components)
|
||||
(some? groups)
|
||||
local)
|
||||
is-local)
|
||||
[:div {:class (stl/css-case :drop-space true
|
||||
:drop-space-small (not dragging?))}])
|
||||
|
||||
|
@ -268,7 +259,7 @@
|
|||
:on-group on-group
|
||||
:do-rename do-rename
|
||||
:cancel-rename cancel-rename
|
||||
:local local}])])
|
||||
:is-local is-local}])])
|
||||
|
||||
(for [[path-item content] groups]
|
||||
(when-not (empty? path-item)
|
||||
|
@ -289,11 +280,11 @@
|
|||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full
|
||||
:local local}]))])]))
|
||||
:is-local is-local}]))])]))
|
||||
|
||||
(mf/defc components-section
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file-id local? components listing-thumbs? open? force-open?
|
||||
[{:keys [file-id is-local components listing-thumbs? open? force-open?
|
||||
reverse-sort? selected on-asset-click on-assets-delete
|
||||
on-clear-selection open-status-ref]}]
|
||||
|
||||
|
@ -466,7 +457,7 @@
|
|||
(fn [component event]
|
||||
|
||||
(let [file-data
|
||||
(d/nilv (dm/get-in @refs/libraries [file-id :data]) @refs/workspace-data)
|
||||
(dm/get-in @refs/libraries [file-id :data])
|
||||
|
||||
shape-main
|
||||
(ctf/get-component-root file-data component)]
|
||||
|
@ -476,7 +467,7 @@
|
|||
(set-drag-data! {:file-id file-id
|
||||
:component component
|
||||
:shape shape-main
|
||||
:local? local?})
|
||||
:is-local is-local})
|
||||
|
||||
(dnd/set-data! event "penpot/component" true)
|
||||
|
||||
|
@ -487,10 +478,10 @@
|
|||
|
||||
on-show-main
|
||||
(mf/use-fn
|
||||
(mf/deps current-component-id file-id local?)
|
||||
(mf/deps current-component-id file-id is-local)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(if local?
|
||||
(if is-local
|
||||
(st/emit! (dwl/go-to-local-component :id current-component-id))
|
||||
(let [component (d/seek #(= (:id %) current-component-id) components)]
|
||||
(st/emit! (dwl/go-to-component-file file-id component))))))
|
||||
|
@ -518,7 +509,7 @@
|
|||
:title (tr "workspace.assets.grid-view")
|
||||
:id "opt-grid"}]]])
|
||||
|
||||
(when (and components-v2 (not read-only?) local?)
|
||||
(when (and components-v2 (not read-only?) is-local)
|
||||
[:> icon-button* {:variant "ghost"
|
||||
:aria-label (tr "workspace.assets.components.add-component")
|
||||
:on-click add-component
|
||||
|
@ -547,27 +538,27 @@
|
|||
:on-ungroup on-ungroup
|
||||
:on-context-menu on-context-menu
|
||||
:selected-full selected-full
|
||||
:local ^boolean local?}])
|
||||
:local ^boolean is-local}])
|
||||
|
||||
[:& cmm/assets-context-menu
|
||||
{:on-close on-close-menu
|
||||
:state @menu-state
|
||||
:options [(when (and local? (not (or multi-components? multi-assets? read-only?)))
|
||||
:options [(when (and is-local (not (or multi-components? multi-assets? read-only?)))
|
||||
{:name (tr "workspace.assets.rename")
|
||||
:id "assets-rename-component"
|
||||
:handler on-rename})
|
||||
(when (and local? (not (or multi-assets? read-only?)))
|
||||
(when (and is-local (not (or multi-assets? read-only?)))
|
||||
{:name (if components-v2
|
||||
(tr "workspace.assets.duplicate-main")
|
||||
(tr "workspace.assets.duplicate"))
|
||||
:id "assets-duplicate-component"
|
||||
:handler on-duplicate})
|
||||
|
||||
(when (and local? (not read-only?))
|
||||
(when (and is-local (not read-only?))
|
||||
{:name (tr "workspace.assets.delete")
|
||||
:id "assets-delete-component"
|
||||
:handler on-delete})
|
||||
(when (and local? (not (or multi-assets? read-only?)))
|
||||
(when (and is-local (not (or multi-assets? read-only?)))
|
||||
{:name (tr "workspace.assets.group")
|
||||
:id "assets-group-component"
|
||||
:handler on-group})
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.main.data.event :as ev]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.libraries :as dwl]
|
||||
|
@ -19,7 +20,6 @@
|
|||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.libraries :refer [create-file-library-ref]]
|
||||
[app.main.ui.workspace.sidebar.assets.colors :refer [colors-section]]
|
||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||
[app.main.ui.workspace.sidebar.assets.components :refer [components-section]]
|
||||
|
@ -33,6 +33,10 @@
|
|||
[potok.v2.core :as ptk]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; REFS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(def ^:private ref:open-status
|
||||
(l/derived (l/in [:workspace-assets :open-status]) st/state))
|
||||
|
||||
|
@ -40,8 +44,37 @@
|
|||
(-> (l/in [:workspace-assets :selected])
|
||||
(l/derived st/state)))
|
||||
|
||||
(defn- create-file-ref
|
||||
[library-id]
|
||||
(l/derived (fn [state]
|
||||
(dm/get-in state [:files library-id :data]))
|
||||
st/state))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; LOCAL HELPER HOOKS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn- use-library-ref
|
||||
[file-id]
|
||||
(let [library-ref (mf/with-memo [file-id]
|
||||
(create-file-ref file-id))]
|
||||
(mf/deref library-ref)))
|
||||
|
||||
(defn- use-selected
|
||||
"Returns the currently selected assets set on the library"
|
||||
[file-id]
|
||||
(let [selected-ref
|
||||
(mf/with-memo [file-id]
|
||||
(-> (l/key file-id)
|
||||
(l/derived ref:selected)))]
|
||||
(mf/deref selected-ref)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; COMPONENTS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(mf/defc file-library-title*
|
||||
{::mf/props :obj}
|
||||
{::mf/private true}
|
||||
[{:keys [is-open is-local file-id page-id file-name]}]
|
||||
(let [router (mf/deref refs/router)
|
||||
team-id (mf/use-ctx ctx/current-team-id)
|
||||
|
@ -61,7 +94,8 @@
|
|||
(dom/stop-propagation ev)
|
||||
(st/emit! (ptk/data-event ::ev/event {::ev/name "navigate-to-library-file"}))))]
|
||||
|
||||
[:div {:class (stl/css-case :library-title true
|
||||
[:div {:class (stl/css-case
|
||||
:library-title true
|
||||
:open is-open)}
|
||||
[:& title-bar {:collapsable true
|
||||
:collapsed (not is-open)
|
||||
|
@ -71,10 +105,9 @@
|
|||
(mf/html [:div {:class (stl/css :special-title)}
|
||||
(tr "workspace.assets.local-library")])
|
||||
;; Do we need to add shared info here?
|
||||
|
||||
(mf/html [:div {:class (stl/css :special-title)}
|
||||
file-name]))}
|
||||
(when-not is-local
|
||||
(when-not ^boolean is-local
|
||||
[:span {:title (tr "workspace.assets.open-library")}
|
||||
[:a {:class (stl/css :file-link)
|
||||
:href (str "#" url)
|
||||
|
@ -82,74 +115,8 @@
|
|||
:on-click on-click}
|
||||
i/open-link]])]]))
|
||||
|
||||
(mf/defc file-library-content
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [file local? open-status-ref on-clear-selection filters]}]
|
||||
(let [components-v2 (mf/use-ctx ctx/components-v2)
|
||||
open-status (mf/deref open-status-ref)
|
||||
|
||||
file-id (:id file)
|
||||
project-id (:project-id file)
|
||||
|
||||
filters-section (:section filters)
|
||||
|
||||
filters-term (:term filters)
|
||||
filters-ordering (:ordering filters)
|
||||
filters-list-style (:list-style filters)
|
||||
|
||||
reverse-sort? (= :desc filters-ordering)
|
||||
listing-thumbs? (= :thumbs filters-list-style)
|
||||
|
||||
library-ref (mf/with-memo [file-id]
|
||||
(create-file-library-ref file-id))
|
||||
|
||||
library (mf/deref library-ref)
|
||||
colors (:colors library)
|
||||
components (:components library)
|
||||
media (:media library)
|
||||
typographies (:typographies library)
|
||||
|
||||
colors (mf/with-memo [filters colors]
|
||||
(cmm/apply-filters colors filters))
|
||||
components (mf/with-memo [filters components]
|
||||
(cmm/apply-filters components filters))
|
||||
media (mf/with-memo [filters media]
|
||||
(cmm/apply-filters media filters))
|
||||
typographies (mf/with-memo [filters typographies]
|
||||
(cmm/apply-filters typographies filters))
|
||||
|
||||
show-components? (and (or (= filters-section "all")
|
||||
(= filters-section "components"))
|
||||
(or (pos? (count components))
|
||||
(str/empty? filters-term)))
|
||||
show-graphics? (and (or (= filters-section "all")
|
||||
(= filters-section "graphics"))
|
||||
(or (pos? (count media))
|
||||
(and (str/empty? filters-term)
|
||||
(not components-v2))))
|
||||
show-colors? (and (or (= filters-section "all")
|
||||
(= filters-section "colors"))
|
||||
(or (> (count colors) 0)
|
||||
(str/empty? filters-term)))
|
||||
show-typography? (and (or (= filters-section "all")
|
||||
(= filters-section "typographies"))
|
||||
(or (pos? (count typographies))
|
||||
(str/empty? filters-term)))
|
||||
|
||||
selected-lens (mf/with-memo [file-id]
|
||||
(-> (l/key file-id)
|
||||
(l/derived ref:selected)))
|
||||
|
||||
selected (mf/deref selected-lens)
|
||||
|
||||
has-term? (not ^boolean (str/empty? filters-term))
|
||||
force-open-components? (when ^boolean has-term? (> 60 (count components)))
|
||||
force-open-colors? (when ^boolean has-term? (> 60 (count colors)))
|
||||
force-open-graphics? (when ^boolean has-term? (> 60 (count media)))
|
||||
force-open-typographies? (when ^boolean has-term? (> 60 (count typographies)))
|
||||
|
||||
extend-selected
|
||||
(fn [type asset-groups asset-id]
|
||||
(defn- extend-selected
|
||||
[selected type asset-groups asset-id file-id]
|
||||
(letfn [(flatten-groups [groups]
|
||||
(reduce concat [(get groups "" [])
|
||||
(into []
|
||||
|
@ -175,9 +142,60 @@
|
|||
|
||||
(st/emit! (dw/select-assets file-id ids type)))))))
|
||||
|
||||
(mf/defc file-library-content*
|
||||
{::mf/private true}
|
||||
[{:keys [file is-local open-status-ref on-clear-selection filters colors media typographies components]}]
|
||||
(let [open-status (mf/deref open-status-ref)
|
||||
|
||||
file-id (:id file)
|
||||
project-id (:project-id file)
|
||||
|
||||
filters-section (:section filters)
|
||||
has-filters-term? (not ^boolean (str/empty? (:term filters)))
|
||||
|
||||
reverse-sort? (= :desc (:ordering filters))
|
||||
listing-thumbs? (= :thumbs (:list-style filters))
|
||||
|
||||
selected (use-selected file-id)
|
||||
|
||||
show-components?
|
||||
(and (or (= filters-section "all")
|
||||
(= filters-section "components"))
|
||||
(or (pos? (count components))
|
||||
(not has-filters-term?)))
|
||||
|
||||
show-graphics?
|
||||
(and (or (= filters-section "all")
|
||||
(= filters-section "graphics"))
|
||||
(pos? (count media)))
|
||||
|
||||
show-colors?
|
||||
(and (or (= filters-section "all")
|
||||
(= filters-section "colors"))
|
||||
(or (> (count colors) 0)
|
||||
(not has-filters-term?)))
|
||||
|
||||
show-typography?
|
||||
(and (or (= filters-section "all")
|
||||
(= filters-section "typographies"))
|
||||
(or (pos? (count typographies))
|
||||
(not has-filters-term?)))
|
||||
|
||||
force-open-components?
|
||||
(when ^boolean has-filters-term? (> 60 (count components)))
|
||||
|
||||
force-open-colors?
|
||||
(when ^boolean has-filters-term? (> 60 (count colors)))
|
||||
|
||||
force-open-graphics?
|
||||
(when ^boolean has-filters-term? (> 60 (count media)))
|
||||
|
||||
force-open-typographies?
|
||||
(when ^boolean has-filters-term? (> 60 (count typographies)))
|
||||
|
||||
on-asset-click
|
||||
(mf/use-fn
|
||||
(mf/deps file-id extend-selected)
|
||||
(mf/deps file-id selected)
|
||||
(fn [asset-type asset-groups asset-id default-click event]
|
||||
(cond
|
||||
(kbd/mod? event)
|
||||
|
@ -188,7 +206,7 @@
|
|||
(kbd/shift? event)
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(extend-selected asset-type asset-groups asset-id))
|
||||
(extend-selected selected asset-type asset-groups asset-id file-id))
|
||||
|
||||
:else
|
||||
(when default-click
|
||||
|
@ -232,7 +250,7 @@
|
|||
(when ^boolean show-components?
|
||||
[:& components-section
|
||||
{:file-id file-id
|
||||
:local? local?
|
||||
:local? is-local
|
||||
:components components
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:open? (or ^boolean force-open-components?
|
||||
|
@ -249,7 +267,7 @@
|
|||
[:& graphics-section
|
||||
{:file-id file-id
|
||||
:project-id project-id
|
||||
:local? local?
|
||||
:local? is-local
|
||||
:objects media
|
||||
:listing-thumbs? listing-thumbs?
|
||||
:open? (or ^boolean force-open-graphics?
|
||||
|
@ -265,7 +283,7 @@
|
|||
(when ^boolean show-colors?
|
||||
[:& colors-section
|
||||
{:file-id file-id
|
||||
:local? local?
|
||||
:local? is-local
|
||||
:colors colors
|
||||
:open? (or ^boolean force-open-colors?
|
||||
^boolean (get open-status :colors false))
|
||||
|
@ -281,7 +299,7 @@
|
|||
[:& typographies-section
|
||||
{:file file
|
||||
:file-id (:id file)
|
||||
:local? local?
|
||||
:local? is-local
|
||||
:typographies typographies
|
||||
:open? (or ^boolean force-open-typographies?
|
||||
^boolean (get open-status :typographies false))
|
||||
|
@ -303,67 +321,90 @@
|
|||
[:span {:class (stl/css :no-found-text)}
|
||||
(tr "workspace.assets.not-found")]])]))
|
||||
|
||||
(defn- force-lib-open? [file-id filters]
|
||||
(let [library-ref (mf/with-memo [file-id]
|
||||
(create-file-library-ref file-id))
|
||||
library (mf/deref library-ref)
|
||||
|
||||
colors (:colors library)
|
||||
components (:components library)
|
||||
media (:media library)
|
||||
typographies (:typographies library)
|
||||
|
||||
filtered-colors (mf/with-memo [filters colors]
|
||||
(cmm/apply-filters colors filters))
|
||||
filtered-components (mf/with-memo [filters components]
|
||||
(cmm/apply-filters components filters))
|
||||
filtered-media (mf/with-memo [filters media]
|
||||
(cmm/apply-filters media filters))
|
||||
filtered-typographies (mf/with-memo [filters typographies]
|
||||
(cmm/apply-filters typographies filters))
|
||||
|
||||
filters-term (:term filters)
|
||||
has-term? (not (str/blank? filters-term))]
|
||||
(and has-term?
|
||||
(some pos? (map count [filtered-components filtered-colors filtered-media filtered-typographies]))
|
||||
(some #(> 60 (count %)) [filtered-components filtered-colors filtered-media filtered-typographies]))))
|
||||
|
||||
(mf/defc file-library
|
||||
{::mf/props :obj}
|
||||
[{:keys [file local? default-open? filters]}]
|
||||
(mf/defc file-library*
|
||||
[{:keys [file is-local is-default-open? filters]}]
|
||||
(let [file-id (:id file)
|
||||
file-name (:name file)
|
||||
page-id (dm/get-in file [:data :pages 0])
|
||||
|
||||
open-status-ref (mf/with-memo [file-id]
|
||||
library (use-library-ref file-id)
|
||||
|
||||
colors (:colors library)
|
||||
media (:media library)
|
||||
typographies (:typographies library)
|
||||
|
||||
filters-term (:term filters)
|
||||
|
||||
;; FIXME: maybe unused
|
||||
;; has-term? (not (str/blank? filters-term))
|
||||
|
||||
filtered-colors
|
||||
(mf/with-memo [filters colors]
|
||||
(-> (vals colors)
|
||||
(cmm/apply-filters filters)))
|
||||
|
||||
filtered-components
|
||||
(mf/with-memo [filters library]
|
||||
(-> (into [] (ctkl/components-seq library))
|
||||
(cmm/apply-filters filters)))
|
||||
|
||||
filtered-media
|
||||
(mf/with-memo [filters media]
|
||||
(-> (vals media)
|
||||
(cmm/apply-filters filters)))
|
||||
|
||||
filtered-typographies
|
||||
(mf/with-memo [filters typographies]
|
||||
(-> (vals typographies)
|
||||
(cmm/apply-filters filters)))
|
||||
|
||||
open-status-ref
|
||||
(mf/with-memo [file-id]
|
||||
(-> (l/key file-id)
|
||||
(l/derived ref:open-status)))
|
||||
open-status (mf/deref open-status-ref)
|
||||
force-open-lib? (force-lib-open? file-id filters)
|
||||
|
||||
open? (if (false? (:library open-status)) ;; if the user has closed it specifically, respect that
|
||||
open-status
|
||||
(mf/deref open-status-ref)
|
||||
|
||||
force-lib-open?
|
||||
(and (not (str/blank? filters-term))
|
||||
(or (> 60 (count filtered-colors))
|
||||
(> 60 (count filtered-components))
|
||||
(> 60 (count filtered-media))
|
||||
(> 60 (count filtered-typographies))))
|
||||
|
||||
open?
|
||||
(if (false? (:library open-status))
|
||||
;; if the user has closed it specifically, respect that
|
||||
false
|
||||
(or force-open-lib?
|
||||
(d/nilv (:library open-status) default-open?)))
|
||||
(or force-lib-open?
|
||||
(d/nilv (:library open-status) is-default-open?)))
|
||||
|
||||
unselect-all
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(fn []
|
||||
(st/emit! (dw/unselect-all-assets file-id))))]
|
||||
|
||||
[:div {:class (stl/css :tool-window)
|
||||
:on-context-menu dom/prevent-default
|
||||
:on-click unselect-all}
|
||||
|
||||
[:> file-library-title*
|
||||
{:file-id file-id
|
||||
:page-id page-id
|
||||
:file-name file-name
|
||||
:is-open open?
|
||||
:is-local local?}]
|
||||
:is-local is-local}]
|
||||
|
||||
(when ^boolean open?
|
||||
[:& file-library-content
|
||||
[:> file-library-content*
|
||||
{:file file
|
||||
:local? local?
|
||||
:is-local is-local
|
||||
:filters filters
|
||||
:colors filtered-colors
|
||||
:components filtered-components
|
||||
:media filtered-media
|
||||
:typographies filtered-typographies
|
||||
:on-clear-selection unselect-all
|
||||
:open-status-ref open-status-ref}])]))
|
||||
|
|
|
@ -249,6 +249,7 @@
|
|||
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
menu-state (mf/use-state cmm/initial-context-menu-state)
|
||||
|
||||
typographies (mf/with-memo [typographies]
|
||||
(mapv dwl/extract-path-if-missing typographies))
|
||||
|
||||
|
|
|
@ -169,11 +169,12 @@
|
|||
(defn use-search
|
||||
[page objects]
|
||||
(let [state* (mf/use-state
|
||||
{:show-search false
|
||||
#(do {:show-search false
|
||||
:show-menu false
|
||||
:search-text ""
|
||||
:filters #{}
|
||||
:num-items 100})
|
||||
:num-items 100}))
|
||||
|
||||
state (deref state*)
|
||||
current-filters (:filters state)
|
||||
current-items (:num-items state)
|
||||
|
|
|
@ -268,15 +268,6 @@
|
|||
[:span {:class (stl/css :arrow-icon)}
|
||||
i/arrow]]))
|
||||
|
||||
(def ^:private ref:swap-libraries
|
||||
(letfn [(get-libraries [state]
|
||||
(let [file (:workspace-file state)
|
||||
data (:workspace-data state)
|
||||
libs (:libraries state)]
|
||||
(assoc libs (:id file)
|
||||
(assoc file :data data))))]
|
||||
(l/derived get-libraries st/state)))
|
||||
|
||||
(defn- find-common-path
|
||||
([components]
|
||||
(let [paths (map (comp cfh/split-path :path) components)]
|
||||
|
@ -298,14 +289,13 @@
|
|||
(= (:component-id shape-a)
|
||||
(:component-id shape-b)))
|
||||
|
||||
|
||||
(mf/defc component-swap
|
||||
{::mf/props :obj}
|
||||
[{:keys [shapes]}]
|
||||
(let [single? (= 1 (count shapes))
|
||||
shape (first shapes)
|
||||
current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
libraries (mf/deref ref:swap-libraries)
|
||||
libraries (mf/deref refs/files)
|
||||
objects (mf/deref refs/workspace-page-objects)
|
||||
|
||||
^boolean
|
||||
|
@ -522,12 +512,13 @@
|
|||
{::mf/props :obj}
|
||||
[{:keys [shapes swap-opened?]}]
|
||||
(let [current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
workspace-data (deref refs/workspace-data)
|
||||
libraries (deref refs/libraries)
|
||||
|
||||
state* (mf/use-state {:show-content true
|
||||
:menu-open false})
|
||||
libraries (deref refs/libraries)
|
||||
current-file (get libraries current-file-id)
|
||||
|
||||
state* (mf/use-state
|
||||
#(do {:show-content true
|
||||
:menu-open false}))
|
||||
state (deref state*)
|
||||
open? (:show-content state)
|
||||
menu-open? (:menu-open state)
|
||||
|
@ -535,18 +526,18 @@
|
|||
shapes (filter ctk/instance-head? shapes)
|
||||
multi (> (count shapes) 1)
|
||||
copies (filter ctk/in-component-copy? shapes)
|
||||
can-swap? (and components-v2 (seq copies))
|
||||
can-swap? (boolean (seq copies))
|
||||
|
||||
;; For when it's only one shape
|
||||
shape (first shapes)
|
||||
id (:id shape)
|
||||
shape-name (:name shape)
|
||||
|
||||
component (ctf/resolve-component shape
|
||||
{:id current-file-id
|
||||
:data workspace-data}
|
||||
current-file
|
||||
libraries
|
||||
{:include-deleted? true})
|
||||
main-instance? (if components-v2 (ctk/main-instance? shape) true)
|
||||
main-instance? (ctk/main-instance? shape)
|
||||
|
||||
toggle-content
|
||||
(mf/use-fn #(swap! state* update :show-content not))
|
||||
|
@ -585,7 +576,7 @@
|
|||
(fn []
|
||||
(swap! state* update :render inc)))
|
||||
|
||||
menu-entries (cmm/generate-components-menu-entries shapes components-v2)
|
||||
menu-entries (cmm/generate-components-menu-entries shapes true)
|
||||
show-menu? (seq menu-entries)
|
||||
path (->> component (:path) (cfh/split-path) (cfh/join-path-with-dot))]
|
||||
|
||||
|
@ -650,7 +641,7 @@
|
|||
(when swap-opened?
|
||||
[:& component-swap {:shapes copies}])
|
||||
|
||||
(when (and (not swap-opened?) (not multi) components-v2)
|
||||
(when (and (not swap-opened?) (not multi))
|
||||
[:& component-annotation {:id id :shape shape :component component :rerender-fn rerender-fn}])
|
||||
(when (dbg/enabled? :display-touched)
|
||||
[:div ":touched " (str (:touched shape))])])])))
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.data.exports.assets :as de]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.select :refer [select]]
|
||||
|
@ -40,7 +40,7 @@
|
|||
state (mf/deref refs/export)
|
||||
in-progress? (:in-progress state)
|
||||
|
||||
shapes-with-exports (->> (wsh/lookup-shapes @st/state ids)
|
||||
shapes-with-exports (->> (dsh/lookup-shapes @st/state ids)
|
||||
(filter #(pos? (count (:exports %)))))
|
||||
|
||||
sname (when (seqable? exports)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
(:require
|
||||
[app.common.colors :as clr]
|
||||
[app.common.data :as d]
|
||||
[app.common.types.color :as ctc]
|
||||
[app.common.types.shape.attrs :refer [default-color]]
|
||||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.store :as st]
|
||||
|
@ -167,12 +168,7 @@
|
|||
(seq fills)
|
||||
[:& h/sortable-container {}
|
||||
(for [[index value] (d/enumerate (:fills values []))]
|
||||
[:& color-row {:color {:color (:fill-color value)
|
||||
:opacity (:fill-opacity value)
|
||||
:id (:fill-color-ref-id value)
|
||||
:file-id (:fill-color-ref-file value)
|
||||
:gradient (:fill-color-gradient value)
|
||||
:image (:fill-image value)}
|
||||
[:& color-row {:color (ctc/fill->color value)
|
||||
:key index
|
||||
:index index
|
||||
:title (tr "workspace.options.fill")
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.features :as features]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
||||
|
@ -56,7 +56,7 @@
|
|||
wasm-renderer-enabled? (features/use-feature "render-wasm/v1")
|
||||
|
||||
shapes (->
|
||||
(wsh/lookup-page-objects @st/state)
|
||||
(dsh/lookup-page-objects @st/state)
|
||||
(select-keys ids)
|
||||
vals)
|
||||
|
||||
|
|
|
@ -57,16 +57,16 @@
|
|||
(or next (peek fonts)))
|
||||
current))
|
||||
|
||||
(mf/defc font-item
|
||||
(mf/defc font-item*
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [font current? on-click style]}]
|
||||
[{:keys [font is-current on-click style]}]
|
||||
(let [item-ref (mf/use-ref)
|
||||
on-click (mf/use-fn (mf/deps font) #(on-click font))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps current?)
|
||||
(mf/deps is-current)
|
||||
(fn []
|
||||
(when current?
|
||||
(when is-current
|
||||
(let [element (mf/ref-val item-ref)]
|
||||
(when-not (dom/is-in-viewport? element)
|
||||
(dom/scroll-into-view! element))))))
|
||||
|
@ -76,9 +76,9 @@
|
|||
:ref item-ref
|
||||
:on-click on-click}
|
||||
[:div {:class (stl/css-case :font-item true
|
||||
:selected current?)}
|
||||
:selected is-current)}
|
||||
[:span {:class (stl/css :label)} (:name font)]
|
||||
[:span {:class (stl/css :icon)} (when current? i/tick)]]]))
|
||||
[:span {:class (stl/css :icon)} (when is-current i/tick)]]]))
|
||||
|
||||
(declare row-renderer)
|
||||
|
||||
|
@ -93,16 +93,21 @@
|
|||
(comp (filter #(contains? backends (:backend %)))))]
|
||||
(into [] xform fonts)))
|
||||
|
||||
(mf/defc font-selector
|
||||
[{:keys [on-select on-close current-font show-recent full-size] :as props}]
|
||||
(mf/defc font-selector*
|
||||
[{:keys [on-select on-close current-font show-recent full-size]}]
|
||||
(let [selected (mf/use-state current-font)
|
||||
state (mf/use-state {:term "" :backends #{}})
|
||||
state* (mf/use-state
|
||||
#(do {:term "" :backends #{}}))
|
||||
state (deref state*)
|
||||
|
||||
flist (mf/use-ref)
|
||||
input (mf/use-ref)
|
||||
|
||||
fonts (mf/use-memo (mf/deps @state) #(filter-fonts @state @fonts/fonts))
|
||||
recent-fonts (mf/deref refs/workspace-recent-fonts)
|
||||
fonts (mf/deref fonts/fonts)
|
||||
fonts (mf/with-memo [state fonts]
|
||||
(filter-fonts state fonts))
|
||||
|
||||
recent-fonts (mf/deref refs/recent-fonts)
|
||||
|
||||
full-size? (boolean (and full-size show-recent))
|
||||
|
||||
|
@ -136,7 +141,7 @@
|
|||
on-filter-change
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(swap! state assoc :term event)))
|
||||
(swap! state* assoc :term event)))
|
||||
|
||||
on-select-and-close
|
||||
(mf/use-fn
|
||||
|
@ -145,9 +150,6 @@
|
|||
(on-select font)
|
||||
(on-close)))]
|
||||
|
||||
(mf/with-effect [fonts]
|
||||
(st/emit! (fts/load-recent-fonts fonts)))
|
||||
|
||||
(mf/with-effect [fonts]
|
||||
(let [key (events/listen js/document "keydown" on-key-down)]
|
||||
#(events/unlistenByKey key)))
|
||||
|
@ -176,18 +178,18 @@
|
|||
[:div {:class (stl/css-case :font-selector-dropdown true :font-selector-dropdown-full-size full-size?)}
|
||||
[:div {:class (stl/css :header)}
|
||||
[:& search-bar {:on-change on-filter-change
|
||||
:value (:term @state)
|
||||
:value (:term state)
|
||||
:auto-focus true
|
||||
:placeholder (tr "workspace.options.search-font")}]
|
||||
(when (and recent-fonts show-recent)
|
||||
[:section {:class (stl/css :show-recent)}
|
||||
[:p {:class (stl/css :title)} (tr "workspace.options.recent-fonts")]
|
||||
(for [[idx font] (d/enumerate recent-fonts)]
|
||||
[:& font-item {:key (dm/str "font-" idx)
|
||||
[:> font-item* {:key (dm/str "font-" idx)
|
||||
:font font
|
||||
:style {}
|
||||
:on-click on-select-and-close
|
||||
:current? (= (:id font) (:id @selected))}])])]
|
||||
:is-current (= (:id font) (:id @selected))}])])]
|
||||
|
||||
[:div {:class (stl/css-case :fonts-list true
|
||||
:fonts-list-full-size full-size?)}
|
||||
|
@ -211,11 +213,11 @@
|
|||
style (unchecked-get props "style")
|
||||
font (nth fonts index)]
|
||||
(mf/html
|
||||
[:& font-item {:key key
|
||||
[:> font-item* {:key key
|
||||
:font font
|
||||
:style style
|
||||
:on-click on-select
|
||||
:current? (= (:id font) (:id selected))}])))
|
||||
:is-current (= (:id font) (:id selected))}])))
|
||||
|
||||
(mf/defc font-options
|
||||
{::mf/wrap-props false}
|
||||
|
@ -228,14 +230,14 @@
|
|||
|
||||
fonts (mf/deref fonts/fontsdb)
|
||||
font (get fonts font-id)
|
||||
recent-fonts (mf/deref refs/workspace-recent-fonts)
|
||||
|
||||
last-font (mf/use-ref nil)
|
||||
|
||||
open-selector? (mf/use-state false)
|
||||
|
||||
change-font
|
||||
(mf/use-fn
|
||||
(mf/deps on-change fonts recent-fonts)
|
||||
(mf/deps on-change fonts)
|
||||
(fn [new-font-id]
|
||||
(let [{:keys [family] :as font} (get fonts new-font-id)
|
||||
{:keys [id name weight style]} (fonts/get-default-variant font)]
|
||||
|
@ -286,7 +288,7 @@
|
|||
|
||||
[:*
|
||||
(when @open-selector?
|
||||
[:& font-selector
|
||||
[:> font-selector*
|
||||
{:current-font font
|
||||
:on-close on-font-selector-close
|
||||
:on-select on-font-select
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def lens:background-color
|
||||
(def ^:private ref:background-color
|
||||
(-> (l/key :background)
|
||||
(l/derived refs/workspace-page)))
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
|||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
[]
|
||||
(let [background (mf/deref lens:background-color)
|
||||
(let [background (mf/deref ref:background-color)
|
||||
on-change (mf/use-fn #(st/emit! (dw/change-canvas-color %)))
|
||||
on-open (mf/use-fn #(st/emit! (dwu/start-undo-transaction :options)))
|
||||
on-close (mf/use-fn #(st/emit! (dwu/commit-undo-transaction :options)))]
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.common :as dcm]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -27,6 +28,29 @@
|
|||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
;; FIXME: can we unify this two refs in one?
|
||||
|
||||
(def ^:private ref:file-with-pages
|
||||
"A derived state of the current file, without data with the
|
||||
exception of list of pages"
|
||||
(l/derived (fn [{:keys [data] :as file}]
|
||||
(-> file
|
||||
(dissoc :data)
|
||||
(assoc :pages (:pages data))))
|
||||
refs/file
|
||||
=))
|
||||
|
||||
(defn- make-page-ref
|
||||
"Create a derived state that poins to a page identified by `page-id`
|
||||
without including the page objects (mainly for avoid rerender on
|
||||
each object change)"
|
||||
[page-id]
|
||||
(l/derived (fn [fdata]
|
||||
(-> (dsh/get-page fdata page-id)
|
||||
(dissoc :objects)))
|
||||
refs/workspace-data
|
||||
=))
|
||||
|
||||
;; --- Page Item
|
||||
|
||||
(mf/defc page-item
|
||||
|
@ -155,17 +179,11 @@
|
|||
|
||||
;; --- Page Item Wrapper
|
||||
|
||||
(defn- make-page-ref
|
||||
[page-id]
|
||||
(l/derived (fn [state]
|
||||
(let [page (get-in state [:workspace-data :pages-index page-id])]
|
||||
(select-keys page [:id :name])))
|
||||
st/state =))
|
||||
|
||||
(mf/defc page-item-wrapper
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [page-id index deletable? selected? editing?]}]
|
||||
(let [page-ref (mf/use-memo (mf/deps page-id) #(make-page-ref page-id))
|
||||
(let [page-ref (mf/with-memo [page-id]
|
||||
(make-page-ref page-id))
|
||||
page (mf/deref page-ref)]
|
||||
[:& page-item {:page page
|
||||
:index index
|
||||
|
@ -198,7 +216,7 @@
|
|||
(mf/defc sitemap
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [size show-pages? toggle-pages]}]
|
||||
(let [file (mf/deref refs/workspace-file)
|
||||
(let [file (mf/deref ref:file-with-pages)
|
||||
file-id (get file :id)
|
||||
project-id (get file :project-id)
|
||||
|
||||
|
@ -207,6 +225,7 @@
|
|||
(fn [event]
|
||||
(st/emit! (dw/create-page {:file-id file-id :project-id project-id}))
|
||||
(-> event dom/get-current-target dom/blur!)))
|
||||
|
||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
permissions (mf/use-ctx ctx/permissions)]
|
||||
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
[app.common.types.shape.radius :as ctsr]
|
||||
[app.common.types.token :as ctt]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace :as udw]
|
||||
[app.main.data.workspace.colors :as wdc]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.store :as st]
|
||||
|
@ -36,7 +36,8 @@
|
|||
(ptk/reify ::apply-token
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when-let [tokens (some-> (get-in state [:workspace-data :tokens-lib])
|
||||
(when-let [tokens (some-> (dsh/lookup-file-data state)
|
||||
(get :tokens-lib)
|
||||
(ctob/get-active-themes-set-tokens))]
|
||||
(->> (rx/from (sd/resolve-tokens+ tokens))
|
||||
(rx/mapcat
|
||||
|
@ -179,7 +180,7 @@
|
|||
(ptk/reify ::update-layout-spacing
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [layout-shape-ids (->> (wsh/lookup-shapes state shape-ids)
|
||||
(let [layout-shape-ids (->> (dsh/lookup-shapes state shape-ids)
|
||||
(eduction
|
||||
(filter :layout)
|
||||
(map :id)))
|
||||
|
|
|
@ -1,17 +1,24 @@
|
|||
(ns app.main.ui.workspace.tokens.token-set
|
||||
(:require
|
||||
[app.common.types.tokens-lib :as ctob]))
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.main.data.helpers :as dsh]))
|
||||
|
||||
(defn get-workspace-tokens-lib [state]
|
||||
(get-in state [:workspace-data :tokens-lib]))
|
||||
(defn get-workspace-tokens-lib
|
||||
[state]
|
||||
(-> (dsh/lookup-file-data state)
|
||||
(get :tokens-lib)))
|
||||
|
||||
;; Themes ----------------------------------------------------------------------
|
||||
|
||||
(defn get-active-theme-ids [state]
|
||||
(get-in state [:workspace-data :token-active-themes] #{}))
|
||||
(defn get-active-theme-ids
|
||||
[state]
|
||||
(-> (dsh/lookup-file-data state)
|
||||
(get :token-active-themes #{})))
|
||||
|
||||
(defn get-temp-theme-id [state]
|
||||
(get-in state [:workspace-data :token-theme-temporary-id]))
|
||||
(defn get-temp-theme-id
|
||||
[state]
|
||||
(-> (dsh/lookup-file-data state)
|
||||
(get :token-theme-temporary-id)))
|
||||
|
||||
(defn update-theme-id
|
||||
[state]
|
||||
|
@ -22,8 +29,11 @@
|
|||
(= 1 (count active-themes)) (first active-themes)
|
||||
:else temporary-theme-id)))
|
||||
|
||||
(defn get-workspace-token-theme [id state]
|
||||
(get-in state [:workspace-data :token-themes-index id]))
|
||||
(defn get-workspace-token-theme
|
||||
[id state]
|
||||
(-> (dsh/lookup-file-data state)
|
||||
(get :token-themes-index)
|
||||
(get id)))
|
||||
|
||||
(defn add-token-set-to-token-theme [token-set-id token-theme]
|
||||
(update token-theme :sets conj token-set-id))
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
(ns app.main.ui.workspace.tokens.update
|
||||
(:require
|
||||
[app.common.types.token :as ctt]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.ui.workspace.tokens.changes :as wtch]
|
||||
[app.main.ui.workspace.tokens.style-dictionary :as wtsd]
|
||||
|
@ -107,7 +107,7 @@
|
|||
shapes-update-info))
|
||||
|
||||
(defn update-tokens [state resolved-tokens]
|
||||
(->> (wsh/lookup-page-objects state)
|
||||
(->> (dsh/lookup-page-objects state)
|
||||
(collect-shapes-update-info resolved-tokens)
|
||||
(actionize-shapes-update-info)))
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@
|
|||
objects
|
||||
selected))
|
||||
|
||||
(mf/defc viewport-classic
|
||||
[{:keys [selected wglobal wlocal layout file palete-size] :as props}]
|
||||
(mf/defc viewport-classic*
|
||||
[{:keys [selected wglobal wlocal layout file page palete-size]}]
|
||||
(let [;; When adding data from workspace-local revisit `app.main.ui.workspace` to check
|
||||
;; that the new parameter is sent
|
||||
{:keys [edit-path
|
||||
|
@ -100,13 +100,12 @@
|
|||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||
|
||||
;; DEREFS
|
||||
|
||||
drawing (mf/deref refs/workspace-drawing)
|
||||
focus (mf/deref refs/workspace-focus-selected)
|
||||
|
||||
page (mf/deref refs/workspace-page)
|
||||
objects (get page :objects)
|
||||
file-id (get file :id)
|
||||
page-id (get page :id)
|
||||
objects (get page :objects)
|
||||
background (get page :background clr/canvas)
|
||||
|
||||
base-objects (ui-hooks/with-focus-objects objects focus)
|
||||
|
@ -158,7 +157,6 @@
|
|||
drawing-tool (:tool drawing)
|
||||
drawing-obj (:object drawing)
|
||||
|
||||
|
||||
selected-frames (into #{} (map :frame-id) selected-shapes)
|
||||
|
||||
;; Only when we have all the selected shapes in one frame
|
||||
|
@ -302,12 +300,12 @@
|
|||
:edition edition}])]]]
|
||||
|
||||
(when show-comments?
|
||||
[:& comments/comments-layer {:vbox vbox
|
||||
[:> comments/comments-layer* {:vbox vbox
|
||||
:page-id page-id
|
||||
:file-id file-id
|
||||
:vport vport
|
||||
:zoom zoom
|
||||
:drawing drawing
|
||||
:page-id page-id
|
||||
:file-id (:id file)}])
|
||||
:drawing drawing}])
|
||||
|
||||
(when picking-color?
|
||||
[:& pixel-overlay/pixel-overlay {:vport vport
|
||||
|
@ -568,6 +566,7 @@
|
|||
[:> guides/viewport-guides*
|
||||
{:zoom zoom
|
||||
:vbox vbox
|
||||
:guides (:guides page)
|
||||
:hover-frame guide-frame
|
||||
:disabled-guides disabled-guides?
|
||||
:modifiers modifiers}])
|
||||
|
@ -648,6 +647,7 @@
|
|||
:modifiers modifiers
|
||||
:shape frame
|
||||
:view-only true}]))]
|
||||
|
||||
[:g.scrollbar-wrapper {:clipPath "url(#clip-handlers)"}
|
||||
[:& scroll-bars/viewport-scrollbars
|
||||
{:objects base-objects
|
||||
|
@ -655,9 +655,9 @@
|
|||
:vbox vbox
|
||||
:bottom-padding (when palete-size (+ palete-size 8))}]]]]]))
|
||||
|
||||
(mf/defc viewport
|
||||
(mf/defc viewport*
|
||||
[props]
|
||||
(let [wasm-renderer-enabled? (features/use-feature "render-wasm/v1")]
|
||||
(if ^boolean wasm-renderer-enabled?
|
||||
[:& viewport.wasm/viewport props]
|
||||
[:& viewport-classic props])))
|
||||
[:> viewport.wasm/viewport* props]
|
||||
[:> viewport-classic* props])))
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.comments :as dcm]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.comments :as dwcm]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
|
@ -24,9 +25,14 @@
|
|||
(assoc :frame-id (dm/get-in positions [id :frame-id])))
|
||||
thread))
|
||||
|
||||
(mf/defc comments-layer
|
||||
{::mf/props :obj}
|
||||
[{:keys [vbox vport zoom file-id page-id drawing] :as props}]
|
||||
(def ^:private ref:thread-positions
|
||||
(l/derived (fn [state]
|
||||
(-> (dsh/lookup-page state)
|
||||
(get :comment-thread-positions)))
|
||||
st/state))
|
||||
|
||||
(mf/defc comments-layer*
|
||||
[{:keys [vbox vport zoom drawing file-id page-id]}]
|
||||
(let [vbox-x (dm/get-prop vbox :x)
|
||||
vbox-y (dm/get-prop vbox :y)
|
||||
vport-w (dm/get-prop vport :width)
|
||||
|
@ -36,26 +42,26 @@
|
|||
pos-y (* (- vbox-y) zoom)
|
||||
|
||||
profile (mf/deref refs/profile)
|
||||
profiles (mf/deref refs/profiles)
|
||||
local (mf/deref refs/comments-local)
|
||||
|
||||
positions-ref
|
||||
(mf/with-memo [page-id]
|
||||
;; FIXME: use lookup helpers here
|
||||
(-> (l/in [:workspace-data :pages-index page-id :comment-thread-positions])
|
||||
(l/derived st/state)))
|
||||
positions (mf/deref ref:thread-positions)
|
||||
|
||||
positions (mf/deref positions-ref)
|
||||
threads-map (mf/deref refs/threads-ref)
|
||||
threads-map (mf/deref refs/threads)
|
||||
threads-map (mf/with-memo [threads-map page-id positions]
|
||||
(reduce-kv (fn [threads id thread]
|
||||
(if (= (:page-id thread) page-id)
|
||||
(assoc threads id (update-position positions thread))
|
||||
threads))
|
||||
{}
|
||||
threads-map))
|
||||
|
||||
threads
|
||||
(mf/with-memo [threads-map positions local profile]
|
||||
(mf/with-memo [threads-map local profile]
|
||||
(->> (vals threads-map)
|
||||
(filter #(= (:page-id %) page-id))
|
||||
(mapv (partial update-position positions))
|
||||
(dcm/apply-filters local profile)))
|
||||
|
||||
viewport (assoc vport :offset-x pos-x :offset-y pos-y)
|
||||
viewport
|
||||
(assoc vport :offset-x pos-x :offset-y pos-y)
|
||||
|
||||
on-draft-cancel
|
||||
(mf/use-fn #(st/emit! :interrupt))
|
||||
|
@ -78,7 +84,6 @@
|
|||
:style {:transform (dm/fmt "translate(%px, %px)" pos-x pos-y)}}
|
||||
(for [item threads]
|
||||
[:> cmt/comment-floating-bubble* {:thread item
|
||||
:profiles profiles
|
||||
:zoom zoom
|
||||
:is-open (= (:id item) (:open local))
|
||||
:key (:seqn item)}])
|
||||
|
@ -86,15 +91,14 @@
|
|||
(when-let [id (:open local)]
|
||||
(when-let [thread (get threads-map id)]
|
||||
(when (seq (dcm/apply-filters local profile [thread]))
|
||||
[:> cmt/comment-floating-thread* {:thread (update-position positions thread)
|
||||
:profiles profiles
|
||||
[:> cmt/comment-floating-thread*
|
||||
{:thread (update-position positions thread)
|
||||
:viewport viewport
|
||||
:zoom zoom}])))
|
||||
|
||||
(when-let [draft (:comment drawing)]
|
||||
[:> cmt/comment-floating-thread-draft* {:draft draft
|
||||
:profiles profiles
|
||||
[:> cmt/comment-floating-thread-draft*
|
||||
{:draft draft
|
||||
:on-cancel on-draft-cancel
|
||||
:on-submit on-draft-submit
|
||||
:zoom zoom}])]]]))
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.workspace.viewport.rulers :as rulers]
|
||||
[app.util.dom :as dom]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def guide-width 1)
|
||||
|
@ -448,16 +447,12 @@
|
|||
:is-hover true
|
||||
:hover-frame frame}])]))
|
||||
|
||||
(def ^:private lens:workspace-guides
|
||||
(-> (l/key :guides)
|
||||
(l/derived refs/workspace-page)))
|
||||
|
||||
(mf/defc viewport-guides*
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/props :obj}
|
||||
[{:keys [zoom vbox hover-frame disabled-guides modifiers]}]
|
||||
(let [guides (mf/deref lens:workspace-guides)
|
||||
guides (mf/with-memo [guides vbox]
|
||||
[{:keys [zoom vbox hover-frame disabled-guides modifiers guides]}]
|
||||
(let [guides
|
||||
(mf/with-memo [guides vbox]
|
||||
(->> (vals guides)
|
||||
(filter (partial guide-inside-vbox? zoom vbox))))
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@
|
|||
objects
|
||||
selected))
|
||||
|
||||
(mf/defc viewport
|
||||
[{:keys [selected wglobal wlocal layout file palete-size] :as props}]
|
||||
(mf/defc viewport*
|
||||
[{:keys [selected wglobal wlocal layout file page palete-size]}]
|
||||
(let [;; When adding data from workspace-local revisit `app.main.ui.workspace` to check
|
||||
;; that the new parameter is sent
|
||||
{:keys [edit-path
|
||||
|
@ -102,7 +102,6 @@
|
|||
drawing (mf/deref refs/workspace-drawing)
|
||||
focus (mf/deref refs/workspace-focus-selected)
|
||||
|
||||
page (mf/deref refs/workspace-page)
|
||||
objects (get page :objects)
|
||||
page-id (get page :id)
|
||||
background (get page :background clr/canvas)
|
||||
|
@ -341,12 +340,11 @@
|
|||
:edition edition}])]]]
|
||||
|
||||
(when show-comments?
|
||||
[:& comments/comments-layer {:vbox vbox
|
||||
[:> comments/comments-layer* {:vbox vbox
|
||||
:page-id page-id
|
||||
:vport vport
|
||||
:zoom zoom
|
||||
:drawing drawing
|
||||
:page-id page-id
|
||||
:file-id (:id file)}])
|
||||
:drawing drawing}])
|
||||
|
||||
(when picking-color?
|
||||
[:& pixel-overlay/pixel-overlay {:vport vport
|
||||
|
@ -571,6 +569,7 @@
|
|||
[:> guides/viewport-guides*
|
||||
{:zoom zoom
|
||||
:vbox vbox
|
||||
:guides (:guides page)
|
||||
:hover-frame guide-frame
|
||||
:disabled-guides disabled-guides?
|
||||
:modifiers modifiers}])
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
"RPC for plugins runtime."
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.changes-builder :as cb]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.geom.point :as gpt]
|
||||
|
@ -19,6 +18,7 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.main.data.changes :as ch]
|
||||
[app.main.data.common :as dcm]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.bool :as dwb]
|
||||
[app.main.data.workspace.colors :as dwc]
|
||||
|
@ -48,15 +48,17 @@
|
|||
;;
|
||||
(defn create-shape
|
||||
[plugin-id type]
|
||||
(let [page-id (:current-page-id @st/state)
|
||||
page (dm/get-in @st/state [:workspace-data :pages-index page-id])
|
||||
(let [page (dsh/lookup-page @st/state)
|
||||
shape (cts/setup-shape {:type type
|
||||
:x 0 :y 0 :width 100 :height 100})
|
||||
:x 0 :y 0
|
||||
:width 100
|
||||
:height 100})
|
||||
changes
|
||||
(-> (cb/empty-changes)
|
||||
(cb/with-page page)
|
||||
(cb/with-objects (:objects page))
|
||||
(cb/add-object shape))]
|
||||
|
||||
(st/emit! (ch/commit-changes changes))
|
||||
(shape/shape-proxy plugin-id (:id shape))))
|
||||
|
||||
|
@ -160,7 +162,7 @@
|
|||
(map #(obj/get % "$id"))
|
||||
(mapcat #(cfh/get-children-with-self objects %)))
|
||||
file-id (:current-file-id @st/state)
|
||||
shared-libs (:libraries @st/state)]
|
||||
shared-libs (:files @st/state)]
|
||||
|
||||
(->> (ctc/extract-all-colors shapes file-id shared-libs)
|
||||
(group-by :attrs)
|
||||
|
@ -182,7 +184,7 @@
|
|||
|
||||
:else
|
||||
(let [file-id (:current-file-id @st/state)
|
||||
shared-libs (:libraries @st/state)
|
||||
shared-libs (:files @st/state)
|
||||
objects (u/locate-objects)
|
||||
shapes
|
||||
(->> shapes
|
||||
|
@ -295,8 +297,7 @@
|
|||
|
||||
:createPath
|
||||
(fn []
|
||||
(let [page-id (:current-page-id @st/state)
|
||||
page (dm/get-in @st/state [:workspace-data :pages-index page-id])
|
||||
(let [page (dsh/lookup-page @st/state)
|
||||
shape (cts/setup-shape
|
||||
{:type :path
|
||||
:content [{:command :move-to :params {:x 0 :y 0}}
|
||||
|
@ -306,6 +307,7 @@
|
|||
(cb/with-page page)
|
||||
(cb/with-objects (:objects page))
|
||||
(cb/add-object shape))]
|
||||
|
||||
(st/emit! (ch/commit-changes changes))
|
||||
(shape/shape-proxy plugin-id (:id shape))))
|
||||
|
||||
|
@ -316,9 +318,7 @@
|
|||
(u/display-not-valid :createText text)
|
||||
|
||||
:else
|
||||
(let [file-id (:current-file-id @st/state)
|
||||
page-id (:current-page-id @st/state)
|
||||
page (dm/get-in @st/state [:workspace-data :pages-index page-id])
|
||||
(let [page (dsh/lookup-page @st/state)
|
||||
shape (-> (cts/setup-shape {:type :text :x 0 :y 0 :grow-type :auto-width})
|
||||
(txt/change-text text)
|
||||
(assoc :position-data nil))
|
||||
|
@ -327,8 +327,9 @@
|
|||
(cb/with-page page)
|
||||
(cb/with-objects (:objects page))
|
||||
(cb/add-object shape))]
|
||||
|
||||
(st/emit! (ch/commit-changes changes))
|
||||
(shape/shape-proxy plugin-id file-id page-id (:id shape)))))
|
||||
(shape/shape-proxy plugin-id (:id shape)))))
|
||||
|
||||
:createShapeFromSvg
|
||||
(fn [svg-string]
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.comments :as dc]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.comments :as dwc]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
|
@ -25,7 +26,7 @@
|
|||
(obj/type-of? p "CommentProxy"))
|
||||
|
||||
(defn comment-proxy
|
||||
[plugin-id file-id page-id thread-id users data]
|
||||
[plugin-id file-id page-id thread-id data]
|
||||
(let [data* (atom data)]
|
||||
(obj/reify {:name "CommentProxy"}
|
||||
;; Private properties
|
||||
|
@ -36,9 +37,15 @@
|
|||
:$id {:enumerable false :get (fn [] (:id data))}
|
||||
|
||||
;; Public properties
|
||||
|
||||
;; FIXME: inconsistent with comment-thread: owner
|
||||
:user
|
||||
{:get
|
||||
(fn [] (user/user-proxy plugin-id (get users (:owner-id data))))}
|
||||
{:get #(->> (dc/get-owner data)
|
||||
(user/user-proxy plugin-id))}
|
||||
|
||||
:owner
|
||||
{:get #(->> (dc/get-owner data)
|
||||
(user/user-proxy plugin-id))}
|
||||
|
||||
:date
|
||||
{:get
|
||||
|
@ -86,20 +93,22 @@
|
|||
(obj/type-of? p "CommentThreadProxy"))
|
||||
|
||||
(defn comment-thread-proxy
|
||||
[plugin-id file-id page-id users data]
|
||||
[plugin-id file-id page-id data]
|
||||
(let [data* (atom data)]
|
||||
(obj/reify {:name "CommentThreadProxy"}
|
||||
:$plugin {:enumerable false :get (fn [] plugin-id)}
|
||||
:$file {:enumerable false :get (fn [] file-id)}
|
||||
:$page {:enumerable false :get (fn [] page-id)}
|
||||
:$id {:enumerable false :get (fn [] (:id data))}
|
||||
:$users {:enumerable false :get (fn [] users)}
|
||||
|
||||
:page {:enumerable false :get #(u/locate-page file-id page-id)}
|
||||
:seqNumber {:get #(:seqn 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))}
|
||||
|
||||
:owner
|
||||
{:get #(->> (dc/get-owner data)
|
||||
(user/user-proxy plugin-id))}
|
||||
|
||||
:position
|
||||
{:get
|
||||
(fn []
|
||||
|
@ -152,7 +161,7 @@
|
|||
(fn [comments]
|
||||
(resolve
|
||||
(format/format-array
|
||||
#(comment-proxy plugin-id file-id page-id (:id data) users %) comments)))
|
||||
#(comment-proxy plugin-id file-id page-id (:id data) %) comments)))
|
||||
reject))))))
|
||||
|
||||
:reply
|
||||
|
@ -168,12 +177,12 @@
|
|||
(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))))))
|
||||
(rx/subs! #(resolve (comment-proxy plugin-id file-id page-id (:id data) %)) reject))))))
|
||||
|
||||
:remove
|
||||
(fn []
|
||||
(let [profile (:profile @st/state)
|
||||
owner (get users (:owner-id data))]
|
||||
owner (dsh/lookup-profile @st/state (:owner-id data))]
|
||||
(cond
|
||||
(not (r/check-permission plugin-id "comment:write"))
|
||||
(u/display-not-valid :remove "Plugin doesn't have 'comment:write' permission")
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
(ns app.plugins.events
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.store :as st]
|
||||
[app.plugins.file :as file]
|
||||
[app.plugins.page :as page]
|
||||
|
@ -63,8 +63,8 @@
|
|||
(defmethod handle-state-change "shapechange"
|
||||
[_ plugin-id old-val new-val props]
|
||||
(if-let [shape-id (-> (obj/get props "shapeId") parser/parse-id)]
|
||||
(let [old-shape (wsh/lookup-shape old-val shape-id)
|
||||
new-shape (wsh/lookup-shape new-val shape-id)
|
||||
(let [old-shape (dsh/lookup-shape old-val shape-id)
|
||||
new-shape (dsh/lookup-shape new-val shape-id)
|
||||
|
||||
file-id (:current-file-id new-val)
|
||||
page-id (:current-page-id new-val)]
|
||||
|
|
|
@ -929,7 +929,7 @@
|
|||
:connected
|
||||
{:get
|
||||
(fn []
|
||||
(let [libraries (get @st/state :libraries)]
|
||||
(let [libraries (get @st/state :files)]
|
||||
(apply array (->> libraries keys (map (partial library-proxy plugin-id))))))}
|
||||
|
||||
:availableLibraries
|
||||
|
@ -937,7 +937,7 @@
|
|||
(let [team-id (:current-team-id @st/state)]
|
||||
(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(let [current-libs (into #{} (map first) (get @st/state :libraries))]
|
||||
(let [current-libs (into #{} (map first) (get @st/state :files))]
|
||||
(->> (rp/cmd! :get-team-shared-files {:team-id team-id})
|
||||
(rx/map (fn [result]
|
||||
(->> result
|
||||
|
|
|
@ -369,11 +369,7 @@
|
|||
:content content}
|
||||
|
||||
(fn [data]
|
||||
(->> (rp/cmd! :get-team-users {:file-id file-id})
|
||||
(rx/subs!
|
||||
(fn [users]
|
||||
(let [users (d/index-by :id users)]
|
||||
(resolve (pc/comment-thread-proxy plugin-id file-id id users data)))))))
|
||||
(resolve (pc/comment-thread-proxy plugin-id file-id id data)))
|
||||
false))))))))
|
||||
|
||||
:removeCommentThread
|
||||
|
@ -396,7 +392,7 @@
|
|||
(fn [criteria]
|
||||
(let [only-yours (boolean (obj/get criteria "onlyYours" false))
|
||||
show-resolved (boolean (obj/get criteria "showResolved" true))
|
||||
user-id (-> @st/state :profile :id)]
|
||||
user-id (:profile-id @st/state)]
|
||||
(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(cond
|
||||
|
@ -406,14 +402,11 @@
|
|||
(reject "Plugin doesn't have 'comment:read' permission"))
|
||||
|
||||
:else
|
||||
(->> (rx/zip (rp/cmd! :get-team-users {:file-id file-id})
|
||||
(rp/cmd! :get-comment-threads {:file-id file-id}))
|
||||
(rx/take 1)
|
||||
(->> (rp/cmd! :get-comment-threads {:file-id file-id})
|
||||
(rx/subs!
|
||||
(fn [[users comments]]
|
||||
(let [users (d/index-by :id users)
|
||||
comments
|
||||
(cond->> comments
|
||||
(fn [threads]
|
||||
(let [threads
|
||||
(cond->> threads
|
||||
(not show-resolved)
|
||||
(filter (comp not :is-resolved))
|
||||
|
||||
|
@ -421,5 +414,5 @@
|
|||
(filter #(contains? (:participants %) user-id)))]
|
||||
(resolve
|
||||
(format/format-array
|
||||
#(pc/comment-thread-proxy plugin-id file-id id users %) comments))))
|
||||
#(pc/comment-thread-proxy plugin-id file-id id %) threads))))
|
||||
reject)))))))))
|
||||
|
|
|
@ -11,21 +11,20 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.store :as st]
|
||||
[app.util.object :as obj]))
|
||||
|
||||
(defn locate-file
|
||||
[id]
|
||||
(assert (uuid? id) "File not valid uuid")
|
||||
(if (= id (:current-file-id @st/state))
|
||||
(-> (:workspace-file @st/state)
|
||||
(assoc :data (:workspace-data @st/state)))
|
||||
(dm/get-in @st/state [:libraries id])))
|
||||
(dsh/lookup-file @st/state id))
|
||||
|
||||
(defn locate-page
|
||||
[file-id id]
|
||||
(assert (uuid? id) "Page not valid uuid")
|
||||
(dm/get-in (locate-file file-id) [:data :pages-index id]))
|
||||
(-> (dsh/lookup-file-data @st/state file-id)
|
||||
(dsh/get-page id)))
|
||||
|
||||
(defn locate-objects
|
||||
([]
|
||||
|
@ -62,13 +61,15 @@
|
|||
(let [{:keys [profile-id]} (locate-presence session-id)]
|
||||
(dm/get-in @st/state [:users profile-id])))
|
||||
|
||||
;; FIXME: the impl looks strange: objects is passed by parameters but
|
||||
;; then the rest of the file is looked up directly from state.... (?)
|
||||
(defn locate-component
|
||||
[objects shape]
|
||||
(let [current-file-id (:current-file-id @st/state)
|
||||
workspace-data (:workspace-data @st/state)
|
||||
libraries (:libraries @st/state)
|
||||
(let [state (deref st/state)
|
||||
file (dsh/lookup-file state)
|
||||
libraries (dsh/lookup-libraries state)
|
||||
root (ctn/get-instance-root objects shape)]
|
||||
[root (ctf/resolve-component root {:id current-file-id :data workspace-data} libraries {:include-deleted? true})]))
|
||||
[root (ctf/resolve-component root file libraries {:include-deleted? true})]))
|
||||
|
||||
(defn proxy->file
|
||||
[proxy]
|
||||
|
@ -168,8 +169,11 @@
|
|||
(defn get-state
|
||||
([self attr]
|
||||
(let [id (get-data self :id)
|
||||
page-id (d/nilv (get-data self :page-id) (:current-page-id @st/state))]
|
||||
(dm/get-in @st/state [:workspace-data :pages-index page-id :objects id attr])))
|
||||
page-id (or (get-data self :page-id)
|
||||
(:current-page-id @st/state))]
|
||||
(-> (dsh/lookup-page-objects @st/state page-id)
|
||||
(dm/get-in [:objects id attr]))))
|
||||
|
||||
([self attr mapfn]
|
||||
(-> (get-state self attr)
|
||||
(mapfn))))
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
[app.main.data.changes :as dwc]
|
||||
[app.main.data.common :as dcm]
|
||||
[app.main.data.dashboard.shortcuts]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.preview :as dp]
|
||||
[app.main.data.viewer.shortcuts]
|
||||
[app.main.data.workspace :as dw]
|
||||
|
@ -149,8 +150,10 @@
|
|||
nil)
|
||||
|
||||
(defn ^:export dump-data []
|
||||
(logjs "workspace-data" (get @st/state :workspace-data))
|
||||
nil)
|
||||
(let [fdata (-> (dsh/lookup-file @st/state)
|
||||
(get :data))]
|
||||
(logjs "file-data" fdata)
|
||||
nil))
|
||||
|
||||
(defn ^:export dump-buffer []
|
||||
(logjs "last-events" @st/last-events)
|
||||
|
@ -165,8 +168,7 @@
|
|||
|
||||
(defn dump-objects'
|
||||
[state]
|
||||
(let [page-id (get state :current-page-id)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])]
|
||||
(let [objects (dsh/lookup-page-objects state)]
|
||||
(logjs "objects" objects)
|
||||
nil))
|
||||
|
||||
|
@ -174,33 +176,25 @@
|
|||
[]
|
||||
(dump-objects' @st/state))
|
||||
|
||||
(defn dump-object'
|
||||
(defn get-object
|
||||
[state name]
|
||||
(let [page-id (get state :current-page-id)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
result (or (d/seek (fn [shape] (= name (:name shape))) (vals objects))
|
||||
(get objects (uuid/uuid name)))]
|
||||
#_(logjs name result)
|
||||
result
|
||||
|
||||
#_nil))
|
||||
result))
|
||||
|
||||
(defn ^:export dump-object
|
||||
[name]
|
||||
(dump-object' @st/state name))
|
||||
(get-object @st/state name))
|
||||
|
||||
(defn dump-selected'
|
||||
(defn get-selected
|
||||
[state]
|
||||
(let [page-id (get state :current-page-id)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
selected (get-in state [:workspace-local :selected])
|
||||
result (->> selected (map (d/getf objects)))]
|
||||
(logjs "selected" result)
|
||||
nil))
|
||||
(dsh/lookup-selected state))
|
||||
|
||||
(defn ^:export dump-selected
|
||||
[]
|
||||
(dump-selected' @st/state))
|
||||
(logjs "selected" (get-selected @st/state))
|
||||
nil)
|
||||
|
||||
(defn ^:export preview-selected
|
||||
[]
|
||||
|
@ -208,26 +202,20 @@
|
|||
|
||||
(defn ^:export parent
|
||||
[]
|
||||
(let [state @st/state
|
||||
page-id (get state :current-page-id)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
selected (first (get-in state [:workspace-local :selected]))
|
||||
parent-id (get-in objects [selected :parent-id])
|
||||
parent (get objects parent-id)]
|
||||
(when parent
|
||||
(prn (str (:name parent) " - " (:id parent))))
|
||||
(let [objects (dsh/lookup-page-objects @st/state)
|
||||
selected-id (first (dsh/get-selected-ids @st/state))
|
||||
parent-id (dm/get-in objects [selected-id :parent-id])]
|
||||
(when-let [parent (get objects parent-id)]
|
||||
(js/console.log (str (:name parent) " - " (:id parent))))
|
||||
nil))
|
||||
|
||||
(defn ^:export frame
|
||||
[]
|
||||
(let [state @st/state
|
||||
page-id (get state :current-page-id)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
selected (first (get-in state [:workspace-local :selected]))
|
||||
frame-id (get-in objects [selected :frame-id])
|
||||
frame (get objects frame-id)]
|
||||
(when frame
|
||||
(prn (str (:name frame) " - " (:id frame))))
|
||||
(let [objects (dsh/lookup-page-objects @st/state)
|
||||
selected-id (first (dsh/get-selected-ids @st/state))
|
||||
frame-id (dm/get-in objects [selected-id :frame-id])]
|
||||
(when-let [frame (get objects frame-id)]
|
||||
(js/console.log (str (:name frame) " - " (:id frame))))
|
||||
nil))
|
||||
|
||||
(defn ^:export select-by-object-id
|
||||
|
@ -246,9 +234,8 @@
|
|||
([state show-ids show-touched] (dump-tree' state show-ids show-touched false))
|
||||
([state show-ids show-touched show-modified]
|
||||
(let [page-id (get state :current-page-id)
|
||||
file (assoc (get state :workspace-file)
|
||||
:data (get state :workspace-data))
|
||||
libraries (get state :libraries)]
|
||||
file (dsh/lookup-file state)
|
||||
libraries (get state :files)]
|
||||
(ctf/dump-tree file page-id libraries {:show-ids show-ids
|
||||
:show-touched show-touched
|
||||
:show-modified show-modified}))))
|
||||
|
@ -264,14 +251,11 @@
|
|||
([state shape-id show-ids show-touched] (dump-subtree' state shape-id show-ids show-touched false))
|
||||
([state shape-id show-ids show-touched show-modified]
|
||||
(let [page-id (get state :current-page-id)
|
||||
file (assoc (get state :workspace-file)
|
||||
:data (get state :workspace-data))
|
||||
libraries (get state :libraries)
|
||||
file (dsh/lookup-file state)
|
||||
libraries (get state :files)
|
||||
shape-id (if (some? shape-id)
|
||||
(uuid/uuid shape-id)
|
||||
(let [objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
selected (get-in state [:workspace-local :selected])]
|
||||
(->> selected (map (d/getf objects)) first :id)))]
|
||||
(first (dsh/lookup-selected state)))]
|
||||
(if (some? shape-id)
|
||||
(ctf/dump-subtree file page-id shape-id libraries {:show-ids show-ids
|
||||
:show-touched show-touched
|
||||
|
@ -363,10 +347,10 @@
|
|||
|
||||
(defn ^:export dump-modifiers
|
||||
[]
|
||||
(let [page-id (get @st/state :current-page-id)
|
||||
objects (get-in @st/state [:workspace-data :pages-index page-id :objects])]
|
||||
(.log js/console (modif->js (:workspace-modifiers @st/state) objects)))
|
||||
nil)
|
||||
(let [objects (dsh/lookup-page-objects @st/state)
|
||||
modifiers (:workspace-modifiers @st/state)]
|
||||
(js/console.log (modif->js modifiers objects))
|
||||
nil))
|
||||
|
||||
(defn ^:export set-workspace-read-only
|
||||
[read-only?]
|
||||
|
@ -381,10 +365,8 @@
|
|||
(defn ^:export validate
|
||||
([] (validate nil))
|
||||
([shape-id]
|
||||
(let [file (assoc (get @st/state :workspace-file)
|
||||
:data (get @st/state :workspace-data))
|
||||
libraries (get @st/state :libraries)]
|
||||
|
||||
(let [file (dsh/lookup-file @st/state)
|
||||
libraries (get @st/state :files)]
|
||||
(try
|
||||
(->> (if-let [shape-id (some-> shape-id parse-uuid)]
|
||||
(let [page (dm/get-in file [:data :pages-index (get @st/state :current-page-id)])]
|
||||
|
@ -398,9 +380,8 @@
|
|||
(defn ^:export validate-schema
|
||||
[]
|
||||
(try
|
||||
(-> (get @st/state :workspace-file)
|
||||
(assoc :data (get @st/state :workspace-data))
|
||||
(cfv/validate-file-schema!))
|
||||
(let [file (dsh/lookup-file @st/state)]
|
||||
(cfv/validate-file-schema! file))
|
||||
(catch :default cause
|
||||
(errors/print-error! cause))))
|
||||
|
||||
|
@ -413,11 +394,8 @@
|
|||
(let [features (features/get-team-enabled-features state)
|
||||
sid (:session-id state)
|
||||
|
||||
file (get state :workspace-file)
|
||||
fdata (get state :workspace-data)
|
||||
|
||||
file (assoc file :data fdata)
|
||||
libs (get state :libraries)
|
||||
file (dsh/lookup-file state)
|
||||
libs (get state :files)
|
||||
|
||||
errors (cfv/validate-file file libs)
|
||||
_ (l/dbg :hint "repair current file" :errors (count errors))
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[app.common.test-helpers.files :as cthf]
|
||||
[app.common.test-helpers.ids-map :as cthi]
|
||||
[app.common.test-helpers.shapes :as cths]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.data.workspace.shapes :as dwsh]
|
||||
[cljs.test :as t :include-macros true]
|
||||
|
@ -34,11 +35,8 @@
|
|||
store done events
|
||||
(fn [new-state]
|
||||
(let [;; ==== Get
|
||||
shape1' (get-in new-state [:workspace-data
|
||||
:pages-index
|
||||
(cthi/id :page1)
|
||||
:objects
|
||||
(cthi/id :shape1)])
|
||||
objects (dsh/lookup-page-objects new-state)
|
||||
shape1' (get objects (cthi/id :shape1))
|
||||
fills' (:fills shape1')
|
||||
fill' (first fills')]
|
||||
|
||||
|
@ -68,13 +66,9 @@
|
|||
store done events
|
||||
(fn [new-state]
|
||||
(let [;; ==== Get
|
||||
shape1' (get-in new-state [:workspace-data
|
||||
:pages-index
|
||||
(cthi/id :page1)
|
||||
:objects
|
||||
(cthi/id :shape1)])
|
||||
stroke' (-> (:strokes shape1')
|
||||
first)]
|
||||
objects (dsh/lookup-page-objects new-state)
|
||||
shape1' (get objects (cthi/id :shape1))
|
||||
stroke' (first (:strokes shape1'))]
|
||||
|
||||
;; ==== Check
|
||||
;; (println stroke')
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
[app.common.files.helpers :as cfh]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[cljs.test :as t :include-macros true]
|
||||
[frontend-tests.helpers.pages :as thp]))
|
||||
|
||||
|
@ -111,7 +111,7 @@
|
|||
root-inst (ctn/get-shape page root-inst-id)
|
||||
main-instance? (:main-instance root-inst)
|
||||
|
||||
libs (wsh/get-libraries state)
|
||||
libs (dsh/lookup-libraries state)
|
||||
component (ctf/get-component libs (:component-file root-inst) (:component-id root-inst))
|
||||
library (ctf/get-component-library libs root-inst)
|
||||
|
||||
|
@ -151,7 +151,7 @@
|
|||
(let [page (thp/current-page state)
|
||||
root-inst (ctn/get-shape page root-inst-id)
|
||||
|
||||
libs (wsh/get-libraries state)
|
||||
libs (dsh/lookup-libraries state)
|
||||
component (ctf/get-component libs (:component-file root-inst) (:component-id root-inst))
|
||||
library (ctf/get-component-library libs root-inst)
|
||||
|
||||
|
@ -166,7 +166,7 @@
|
|||
(defn resolve-component
|
||||
"Get the component with the given id and all its shapes."
|
||||
[state component-file component-id]
|
||||
(let [libs (wsh/get-libraries state)
|
||||
(let [libs (dsh/lookup-libraries state)
|
||||
component (ctf/get-component libs component-file component-id)
|
||||
library (ctf/get-component-library libs component)
|
||||
shapes-main (ctf/get-component-shapes (:data library) component)]
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.data.workspace.groups :as dwg]
|
||||
[app.main.data.workspace.layout :as layout]
|
||||
[app.main.data.workspace.state-helpers :as wsh]))
|
||||
[app.main.data.workspace.layout :as layout]))
|
||||
|
||||
;; ---- Helpers to manage pages and objects
|
||||
|
||||
|
@ -33,12 +33,15 @@
|
|||
:current-page-id nil
|
||||
:workspace-layout layout/default-layout
|
||||
:workspace-global layout/default-global
|
||||
:workspace-data {:id current-file-id
|
||||
|
||||
:files
|
||||
{current-file-id
|
||||
{:id current-file-id
|
||||
:data {:id current-file-id
|
||||
:options {:components-v2 true}
|
||||
:components {}
|
||||
:pages []
|
||||
:pages-index {}}
|
||||
:workspace-libraries {}
|
||||
:pages-index {}}}}
|
||||
:features-team #{"components/v2"}})
|
||||
|
||||
(def ^:private idmap (atom {}))
|
||||
|
@ -48,8 +51,9 @@
|
|||
|
||||
(defn current-page
|
||||
[state]
|
||||
(let [page-id (:current-page-id state)]
|
||||
(get-in state [:workspace-data :pages-index page-id])))
|
||||
(let [page-id (:current-page-id state)
|
||||
file-id (:current-file-id state)]
|
||||
(get-in state [:files file-id :data :pages-index page-id])))
|
||||
|
||||
(defn id
|
||||
[label]
|
||||
|
@ -65,18 +69,20 @@
|
|||
(let [page (current-page state)]
|
||||
(cfh/get-children (:objects page) (id label))))
|
||||
|
||||
(defn apply-changes
|
||||
[state changes]
|
||||
(let [file-id (:current-file-id state)]
|
||||
(update-in state [:files file-id :data] cp/process-changes changes)))
|
||||
|
||||
(defn sample-page
|
||||
([state] (sample-page state {}))
|
||||
([state {:keys [id name] :as props
|
||||
:or {id (uuid/next)
|
||||
name "page1"}}]
|
||||
|
||||
(swap! idmap assoc :page id)
|
||||
(-> state
|
||||
(assoc :current-page-id id)
|
||||
(update :workspace-data
|
||||
cp/process-changes
|
||||
[{:type :add-page
|
||||
(apply-changes [{:type :add-page
|
||||
:id id
|
||||
:name name}]))))
|
||||
|
||||
|
@ -87,8 +93,7 @@
|
|||
frame (cfh/get-frame (:objects page))
|
||||
shape (cts/setup-shape (merge {:type type :x 0 :y 0 :width 1 :height 1} props))]
|
||||
(swap! idmap assoc label (:id shape))
|
||||
(update state :workspace-data
|
||||
cp/process-changes
|
||||
(apply-changes state
|
||||
[{:type :add-obj
|
||||
:id (:id shape)
|
||||
:page-id (:id page)
|
||||
|
@ -106,8 +111,7 @@
|
|||
(dwg/prepare-create-group (pcb/empty-changes) nil (:objects page) (:id page) shapes prefix true)]
|
||||
|
||||
(swap! idmap assoc label (:id group))
|
||||
(update state :workspace-data
|
||||
cp/process-changes (:redo-changes changes)))))))
|
||||
(apply-changes state (:redo-changes changes)))))))
|
||||
|
||||
(defn frame-shapes
|
||||
([state label ids] (frame-shapes state label ids "Board"))
|
||||
|
@ -128,13 +132,12 @@
|
|||
true)]
|
||||
|
||||
(swap! idmap assoc label (:id frame))
|
||||
(update state :workspace-data
|
||||
cp/process-changes (:redo-changes changes)))))))
|
||||
(apply-changes state (:redo-changes changes)))))))
|
||||
|
||||
(defn make-component
|
||||
[state instance-label component-label shape-ids]
|
||||
(let [page (current-page state)
|
||||
objects (wsh/lookup-page-objects state (:id page))
|
||||
objects (dsh/lookup-page-objects state (:id page))
|
||||
shapes (dwg/shapes-for-grouping objects shape-ids)
|
||||
|
||||
[group component-id changes]
|
||||
|
@ -149,15 +152,14 @@
|
|||
|
||||
(swap! idmap assoc instance-label (:id group)
|
||||
component-label component-id)
|
||||
(update state :workspace-data
|
||||
cp/process-changes (:redo-changes changes))))
|
||||
(apply-changes state (:redo-changes changes))))
|
||||
|
||||
(defn instantiate-component
|
||||
([state label component-id]
|
||||
(instantiate-component state label component-id current-file-id))
|
||||
([state label component-id file-id]
|
||||
(let [page (current-page state)
|
||||
libraries (wsh/get-libraries state)
|
||||
libraries (dsh/lookup-libraries state)
|
||||
objects (:objects page)
|
||||
|
||||
changes (-> (pcb/empty-changes nil (:id page))
|
||||
|
@ -173,26 +175,27 @@
|
|||
libraries)]
|
||||
|
||||
(swap! idmap assoc label (:id new-shape))
|
||||
(update state :workspace-data
|
||||
cp/process-changes (:redo-changes changes)))))
|
||||
(apply-changes state (:redo-changes changes)))))
|
||||
|
||||
(defn move-to-library
|
||||
[state label name]
|
||||
(let [library-id (uuid/next)
|
||||
data (get state :workspace-data)]
|
||||
file-id (:current-file-id state)
|
||||
data (get-in state [:files file-id :data])]
|
||||
(swap! idmap assoc label library-id)
|
||||
(-> state
|
||||
(update :workspace-libraries
|
||||
assoc library-id {:id library-id
|
||||
(update :files assoc library-id
|
||||
{:id library-id
|
||||
:name name
|
||||
:data {:id library-id
|
||||
:options (:options data)
|
||||
:pages (:pages data)
|
||||
:pages-index (:pages-index data)
|
||||
:components (:components data)}})
|
||||
(update :workspace-data
|
||||
assoc :components {} :pages [] :pages-index {}))))
|
||||
|
||||
(update-in [:files file-id :data] assoc
|
||||
:components {}
|
||||
:pages []
|
||||
:pages-index {}))))
|
||||
|
||||
(defn simulate-copy-shape
|
||||
[selected objects libraries page file features version]
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
:workspace-global layout/default-global
|
||||
:current-file-id nil
|
||||
:current-page-id nil
|
||||
:workspace-data nil
|
||||
:workspace-libraries {}
|
||||
:features-team #{"components/v2"}})
|
||||
|
||||
(defn- on-error
|
||||
|
@ -34,8 +32,7 @@
|
|||
(assoc :current-file-id (:id file)
|
||||
:current-page-id (cthf/current-page-id file)
|
||||
:permissions {:can-edit true}
|
||||
:workspace-file (dissoc file :data)
|
||||
:workspace-data (:data file)))
|
||||
:files {(:id file) file}))
|
||||
store (ptk/store {:state state :on-error on-error})]
|
||||
store))
|
||||
|
||||
|
@ -64,7 +61,7 @@
|
|||
|
||||
(ptk/emit! store :the/end))))
|
||||
|
||||
(defn get-file-from-store
|
||||
[store]
|
||||
(-> (:workspace-file store)
|
||||
(assoc :data (:workspace-data store))))
|
||||
(defn get-file-from-state
|
||||
[state]
|
||||
(let [file-id (:current-file-id state)]
|
||||
(get-in state [:files file-id])))
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue