mirror of
https://github.com/penpot/penpot.git
synced 2026-05-03 15:18:59 +00:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
5983b9cd54
@ -31,10 +31,33 @@ jobs:
|
||||
- run: cat .cljfmt.edn
|
||||
- run: clj-kondo --version
|
||||
|
||||
# - run:
|
||||
# name: "fmt check [clj]"
|
||||
# command: |
|
||||
# yarn run fmt:clj:check
|
||||
- run:
|
||||
name: "fmt check backend [clj]"
|
||||
working_directory: "./backend"
|
||||
command: |
|
||||
yarn install
|
||||
yarn run fmt:clj:check
|
||||
|
||||
- run:
|
||||
name: "fmt check exporter [clj]"
|
||||
working_directory: "./exporter"
|
||||
command: |
|
||||
yarn install
|
||||
yarn run fmt:clj:check
|
||||
|
||||
- run:
|
||||
name: "fmt check common [clj]"
|
||||
working_directory: "./common"
|
||||
command: |
|
||||
yarn install
|
||||
yarn run fmt:clj:check
|
||||
|
||||
- run:
|
||||
name: "fmt check frontend [clj]"
|
||||
working_directory: "./frontend"
|
||||
command: |
|
||||
yarn install
|
||||
yarn run fmt:clj:check
|
||||
|
||||
- run:
|
||||
name: common lint
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
:remove-surrounding-whitespace? true
|
||||
:remove-consecutive-blank-lines? false
|
||||
:extra-indents {rumext.v2/fnc [[:inner 0]]
|
||||
cljs.test/async [[:inner 0]]
|
||||
promesa.exec/thread [[:inner 0]]
|
||||
specify! [[:inner 0] [:inner 1]]}
|
||||
}
|
||||
|
||||
@ -383,12 +383,12 @@
|
||||
(defn- migrate-components
|
||||
"If there is any component in the file library, add a new 'Library
|
||||
backup', generate main instances for all components there and remove
|
||||
shapes from library components. Mark the file with
|
||||
the :components-v2 option."
|
||||
shapes from library components. Mark the file with the :components-v2 option."
|
||||
[file-data libraries]
|
||||
(sse/tap {:type :migration-progress
|
||||
:section :components})
|
||||
(let [components (ctkl/components-seq file-data)]
|
||||
(let [file-data (prepare-file-data file-data libraries)
|
||||
components (ctkl/components-seq file-data)]
|
||||
(if (empty? components)
|
||||
(assoc-in file-data [:options :components-v2] true)
|
||||
(let [[file-data page-id start-pos]
|
||||
@ -503,9 +503,7 @@
|
||||
(some-> *team-stats* (swap! update :processed/components (fnil + 0) total))
|
||||
(some-> *file-stats* (swap! assoc :processed/components total)))
|
||||
|
||||
(-> file-data
|
||||
(prepare-file-data libraries)
|
||||
(add-instance-grids))))))
|
||||
(add-instance-grids file-data)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; GRAPHICS MIGRATION
|
||||
|
||||
@ -201,9 +201,9 @@
|
||||
;; because of the timestamp precission (two concurrent requests), in
|
||||
;; this case we just retry the operation.
|
||||
(let [cfg (-> cfg
|
||||
(assoc ::rtry/when rtry/conflict-exception?)
|
||||
(assoc ::rtry/max-retries 6)
|
||||
(assoc ::rtry/label "persist-audit-log"))
|
||||
(assoc ::rtry/when rtry/conflict-exception?)
|
||||
(assoc ::rtry/max-retries 6)
|
||||
(assoc ::rtry/label "persist-audit-log"))
|
||||
params (-> params
|
||||
(update :props db/tjson)
|
||||
(update :context db/tjson)
|
||||
|
||||
@ -816,16 +816,16 @@
|
||||
(update :features #(db/create-array conn "text" %))
|
||||
(update :data blob/encode))]
|
||||
|
||||
(l/dbg :hint "create file" :id (str file-id') ::l/sync? true)
|
||||
(l/dbg :hint "create file" :id (str file-id') ::l/sync? true)
|
||||
|
||||
(if overwrite?
|
||||
(create-or-update-file! conn file)
|
||||
(db/insert! conn :file file))
|
||||
(if overwrite?
|
||||
(create-or-update-file! conn file)
|
||||
(db/insert! conn :file file))
|
||||
|
||||
(when overwrite?
|
||||
(db/delete! conn :file-thumbnail {:file-id file-id'}))
|
||||
(when overwrite?
|
||||
(db/delete! conn :file-thumbnail {:file-id file-id'}))
|
||||
|
||||
file-id'))))
|
||||
file-id'))))
|
||||
|
||||
(defmethod read-section :v1/rels
|
||||
[{:keys [::db/conn ::input ::timestamp]}]
|
||||
@ -1008,8 +1008,8 @@
|
||||
(if (:image v)
|
||||
(update-in res [k :image :id] lookup-index)
|
||||
res))
|
||||
colors
|
||||
colors))
|
||||
colors
|
||||
colors))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; HIGH LEVEL API
|
||||
|
||||
@ -312,7 +312,7 @@
|
||||
(teams/check-read-permissions! conn profile-id team-id))
|
||||
|
||||
(let [projs (db/query conn :project
|
||||
{:team-id team-id})
|
||||
{:team-id team-id})
|
||||
|
||||
files (let [sql (str "SELECT f.id "
|
||||
" FROM file AS f "
|
||||
|
||||
@ -157,7 +157,7 @@
|
||||
:or {rollback? true
|
||||
skip-on-error true
|
||||
validate? false
|
||||
max-procs 1 }
|
||||
max-procs 1}
|
||||
:as opts}]
|
||||
|
||||
(l/dbg :hint "migrate:start" :rollback rollback?)
|
||||
@ -256,20 +256,20 @@
|
||||
|
||||
:else
|
||||
(px/submit! scope (fn []
|
||||
(try
|
||||
(mark-team-migration! system id)
|
||||
(-> (assoc system ::db/rollback rollback?)
|
||||
(feat/migrate-team! id
|
||||
:max-procs max-procs
|
||||
:validate? validate?
|
||||
:throw-on-validate? (not skip-on-error)))
|
||||
(catch Throwable cause
|
||||
(l/err :hint "unexpected error on processing team"
|
||||
:team-id (str id)
|
||||
:cause cause))
|
||||
(finally
|
||||
(ps/release! sjobs)
|
||||
(unmark-team-migration! system id))))))))]
|
||||
(try
|
||||
(mark-team-migration! system id)
|
||||
(-> (assoc system ::db/rollback rollback?)
|
||||
(feat/migrate-team! id
|
||||
:max-procs max-procs
|
||||
:validate? validate?
|
||||
:throw-on-validate? (not skip-on-error)))
|
||||
(catch Throwable cause
|
||||
(l/err :hint "unexpected error on processing team"
|
||||
:team-id (str id)
|
||||
:cause cause))
|
||||
(finally
|
||||
(ps/release! sjobs)
|
||||
(unmark-team-migration! system id))))))))]
|
||||
|
||||
(l/dbg :hint "migrate:start"
|
||||
:rollback rollback?
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
[app.db :as db]
|
||||
[app.db.sql :as sql]
|
||||
[app.features.fdata :as feat.fdata]
|
||||
[app.main :refer [system]]
|
||||
[app.main :as main]
|
||||
[app.rpc.commands.files :as files]
|
||||
[app.rpc.commands.files-update :as files-update]
|
||||
[app.util.blob :as blob]
|
||||
@ -55,16 +55,17 @@
|
||||
|
||||
(defn reset-file-data!
|
||||
"Hardcode replace of the data of one file."
|
||||
[system id data]
|
||||
(db/tx-run! system (fn [system]
|
||||
(db/update! system :file
|
||||
{:data data}
|
||||
{:id id}))))
|
||||
[id data]
|
||||
(db/tx-run! main/system
|
||||
(fn [system]
|
||||
(db/update! system :file
|
||||
{:data data}
|
||||
{:id id}))))
|
||||
|
||||
(defn get-file
|
||||
"Get the migrated data of one file."
|
||||
[system id & {:keys [migrate?] :or {migrate? true}}]
|
||||
(db/run! system
|
||||
[id & {:keys [migrate?] :or {migrate? true}}]
|
||||
(db/run! main/system
|
||||
(fn [system]
|
||||
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer system id)]
|
||||
(-> (files/get-file system id :migrate? migrate?)
|
||||
@ -73,8 +74,8 @@
|
||||
(defn validate
|
||||
"Validate structure, referencial integrity and semantic coherence of
|
||||
all contents of a file. Returns a list of errors."
|
||||
[system id]
|
||||
(db/tx-run! system
|
||||
[id]
|
||||
(db/tx-run! main/system
|
||||
(fn [{:keys [::db/conn] :as system}]
|
||||
(binding [pmap/*load-fn* (partial feat.fdata/load-pointer system id)]
|
||||
(let [id (if (string? id) (parse-uuid id) id)
|
||||
@ -90,8 +91,8 @@
|
||||
|
||||
(defn repair!
|
||||
"Repair the list of errors detected by validation."
|
||||
[system id]
|
||||
(db/tx-run! system
|
||||
[id]
|
||||
(db/tx-run! main/system
|
||||
(fn [{:keys [::db/conn] :as system}]
|
||||
(binding [pmap/*tracked* (pmap/create-tracked)
|
||||
pmap/*load-fn* (partial feat.fdata/load-pointer system id)]
|
||||
@ -127,8 +128,8 @@
|
||||
(defn update-file!
|
||||
"Apply a function to the data of one file. Optionally save the changes or not.
|
||||
The function receives the decoded and migrated file data."
|
||||
[system & {:keys [update-fn id rollback? migrate? inc-revn?]
|
||||
:or {rollback? true migrate? true inc-revn? true}}]
|
||||
[& {:keys [update-fn id rollback? migrate? inc-revn?]
|
||||
:or {rollback? true migrate? true inc-revn? true}}]
|
||||
(letfn [(process-file [{:keys [::db/conn] :as system} {:keys [features] :as file}]
|
||||
(binding [pmap/*tracked* (pmap/create-tracked)
|
||||
pmap/*load-fn* (partial feat.fdata/load-pointer system id)
|
||||
@ -153,7 +154,7 @@
|
||||
|
||||
(dissoc file :data)))]
|
||||
|
||||
(db/tx-run! system
|
||||
(db/tx-run! main/system
|
||||
(fn [system]
|
||||
(binding [*system* system]
|
||||
(try
|
||||
@ -163,6 +164,12 @@
|
||||
(when rollback?
|
||||
(db/rollback! system)))))))))
|
||||
|
||||
|
||||
(def ^:private sql:get-file-ids
|
||||
"SELECT id FROM file
|
||||
WHERE created_at < ? AND deleted_at is NULL
|
||||
ORDER BY created_at DESC")
|
||||
|
||||
(defn analyze-files
|
||||
"Apply a function to all files in the database, reading them in
|
||||
batches. Do not change data.
|
||||
@ -171,21 +178,11 @@
|
||||
and the previous state and returns the new state.
|
||||
|
||||
Emits rollback at the end of operation."
|
||||
[system & {:keys [chunk-size max-items start-at on-file on-error on-end on-init with-libraries?]
|
||||
:or {chunk-size 10 max-items Long/MAX_VALUE}}]
|
||||
(letfn [(get-chunk [conn cursor]
|
||||
(let [sql (str "SELECT id, created_at FROM file "
|
||||
" WHERE created_at < ? AND deleted_at is NULL "
|
||||
" ORDER BY created_at desc LIMIT ?")
|
||||
rows (db/exec! conn [sql cursor chunk-size])]
|
||||
[(some->> rows peek :created-at) (map :id rows)]))
|
||||
|
||||
(get-candidates [conn]
|
||||
(->> (d/iteration (partial get-chunk conn)
|
||||
:vf second
|
||||
:kf first
|
||||
:initk (or start-at (dt/now)))
|
||||
(take max-items)))
|
||||
[& {:keys [max-items start-at on-file on-error on-end on-init with-libraries?]}]
|
||||
(letfn [(get-candidates [conn]
|
||||
(cond->> (db/cursor conn [sql:get-file-ids (or start-at (dt/now))])
|
||||
(some? max-items)
|
||||
(take max-items)))
|
||||
|
||||
(on-error* [cause file]
|
||||
(println "unexpected exception happened on processing file: " (:id file))
|
||||
@ -210,12 +207,13 @@
|
||||
(catch Throwable cause
|
||||
((or on-error on-error*) cause file)))))]
|
||||
|
||||
(db/tx-run! system
|
||||
(db/tx-run! main/system
|
||||
(fn [{:keys [::db/conn] :as system}]
|
||||
(try
|
||||
(binding [*system* system]
|
||||
(when (fn? on-init) (on-init))
|
||||
(run! (partial process-file system) (get-candidates conn)))
|
||||
(run! (partial process-file system)
|
||||
(get-candidates conn)))
|
||||
(finally
|
||||
(when (fn? on-end)
|
||||
(ex/ignoring (on-end)))
|
||||
@ -224,33 +222,20 @@
|
||||
(defn process-files!
|
||||
"Apply a function to all files in the database, reading them in
|
||||
batches."
|
||||
|
||||
[system & {:keys [chunk-size
|
||||
max-items
|
||||
workers
|
||||
start-at
|
||||
on-file
|
||||
on-error
|
||||
on-end
|
||||
on-init
|
||||
rollback?]
|
||||
:or {chunk-size 10
|
||||
max-items Long/MAX_VALUE
|
||||
workers 1
|
||||
rollback? true}}]
|
||||
(letfn [(get-chunk [conn cursor]
|
||||
(let [sql (str "SELECT id, created_at FROM file "
|
||||
" WHERE created_at < ? AND deleted_at is NULL "
|
||||
" ORDER BY created_at desc LIMIT ?")
|
||||
rows (db/exec! conn [sql cursor chunk-size])]
|
||||
[(some->> rows peek :created-at) (map :id rows)]))
|
||||
|
||||
(get-candidates [conn]
|
||||
(->> (d/iteration (partial get-chunk conn)
|
||||
:vf second
|
||||
:kf first
|
||||
:initk (or start-at (dt/now)))
|
||||
(take max-items)))
|
||||
[& {:keys [max-items
|
||||
workers
|
||||
start-at
|
||||
on-file
|
||||
on-error
|
||||
on-end
|
||||
on-init
|
||||
rollback?]
|
||||
:or {workers 1
|
||||
rollback? true}}]
|
||||
(letfn [(get-candidates [conn]
|
||||
(cond->> (db/cursor conn [sql:get-file-ids (or start-at (dt/now))])
|
||||
(some? max-items)
|
||||
(take max-items)))
|
||||
|
||||
(on-error* [cause file]
|
||||
(println! "unexpected exception happened on processing file: " (:id file))
|
||||
@ -275,7 +260,7 @@
|
||||
((or on-error on-error*) cause file-id))))
|
||||
|
||||
(run-worker [in index]
|
||||
(db/tx-run! system
|
||||
(db/tx-run! main/system
|
||||
(fn [system]
|
||||
(binding [*system* system]
|
||||
(loop [i 0]
|
||||
@ -288,15 +273,16 @@
|
||||
(db/rollback! system)))))
|
||||
|
||||
(run-producer [input]
|
||||
(db/tx-run! system (fn [{:keys [::db/conn]}]
|
||||
(doseq [file-id (get-candidates conn)]
|
||||
(println! "=> producer:" file-id "|" (px/get-name))
|
||||
(sp/put! input file-id))
|
||||
(sp/close! input))))]
|
||||
(db/tx-run! main/system
|
||||
(fn [{:keys [::db/conn]}]
|
||||
(doseq [file-id (get-candidates conn)]
|
||||
(println! "=> producer:" file-id "|" (px/get-name))
|
||||
(sp/put! input file-id))
|
||||
(sp/close! input))))]
|
||||
|
||||
(when (fn? on-init) (on-init))
|
||||
|
||||
(let [input (sp/chan :buf chunk-size)
|
||||
(let [input (sp/chan :buf 25)
|
||||
producer (px/thread
|
||||
{:name "penpot/srepl/producer"}
|
||||
(run-producer input))
|
||||
|
||||
@ -38,52 +38,45 @@
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(defn print-available-tasks
|
||||
[system]
|
||||
(let [tasks (:app.worker/registry system)]
|
||||
[]
|
||||
(let [tasks (:app.worker/registry main/system)]
|
||||
(p/pprint (keys tasks) :level 200)))
|
||||
|
||||
(defn run-task!
|
||||
([system name]
|
||||
(run-task! system name {}))
|
||||
([system name params]
|
||||
(let [tasks (:app.worker/registry system)]
|
||||
(if-let [task-fn (get tasks name)]
|
||||
([tname]
|
||||
(run-task! tname {}))
|
||||
([tname params]
|
||||
(let [tasks (:app.worker/registry main/system)
|
||||
tname (if (keyword? tname) (name tname) name)]
|
||||
(if-let [task-fn (get tasks tname)]
|
||||
(task-fn params)
|
||||
(println (format "no task '%s' found" name))))))
|
||||
(println (format "no task '%s' found" tname))))))
|
||||
|
||||
(defn schedule-task!
|
||||
([system name]
|
||||
(schedule-task! system name {}))
|
||||
([system name props]
|
||||
(let [pool (:app.db/pool system)]
|
||||
([name]
|
||||
(schedule-task! name {}))
|
||||
([name props]
|
||||
(let [pool (:app.db/pool main/system)]
|
||||
(wrk/submit!
|
||||
::wrk/conn pool
|
||||
::wrk/task name
|
||||
::wrk/props props))))
|
||||
|
||||
(defn send-test-email!
|
||||
[system destination]
|
||||
(us/verify!
|
||||
:expr (some? system)
|
||||
:hint "system should be provided")
|
||||
|
||||
[destination]
|
||||
(us/verify!
|
||||
:expr (string? destination)
|
||||
:hint "destination should be provided")
|
||||
|
||||
(let [handler (:app.email/sendmail system)]
|
||||
(let [handler (:app.email/sendmail main/system)]
|
||||
(handler {:body "test email"
|
||||
:subject "test email"
|
||||
:to [destination]})))
|
||||
|
||||
(defn resend-email-verification-email!
|
||||
[system email]
|
||||
(us/verify!
|
||||
:expr (some? system)
|
||||
:hint "system should be provided")
|
||||
|
||||
(let [sprops (:app.setup/props system)
|
||||
pool (:app.db/pool system)
|
||||
[email]
|
||||
(let [sprops (:app.setup/props main/system)
|
||||
pool (:app.db/pool main/system)
|
||||
profile (profile/get-profile-by-email pool email)]
|
||||
|
||||
(auth/send-email-verification! pool sprops profile)
|
||||
@ -92,8 +85,8 @@
|
||||
(defn mark-profile-as-active!
|
||||
"Mark the profile blocked and removes all the http sessiones
|
||||
associated with the profile-id."
|
||||
[system email]
|
||||
(db/with-atomic [conn (:app.db/pool system)]
|
||||
[email]
|
||||
(db/with-atomic [conn (:app.db/pool main/system)]
|
||||
(when-let [profile (db/get* conn :profile
|
||||
{:email (str/lower email)}
|
||||
{:columns [:id :email]})]
|
||||
@ -104,8 +97,8 @@
|
||||
(defn mark-profile-as-blocked!
|
||||
"Mark the profile blocked and removes all the http sessiones
|
||||
associated with the profile-id."
|
||||
[system email]
|
||||
(db/with-atomic [conn (:app.db/pool system)]
|
||||
[email]
|
||||
(db/with-atomic [conn (:app.db/pool main/system)]
|
||||
(when-let [profile (db/get* conn :profile
|
||||
{:email (str/lower email)}
|
||||
{:columns [:id :email]})]
|
||||
@ -117,9 +110,9 @@
|
||||
(defn reset-password!
|
||||
"Reset a password to a specific one for a concrete user or all users
|
||||
if email is `:all` keyword."
|
||||
[system & {:keys [email password] :or {password "123123"} :as params}]
|
||||
[& {:keys [email password] :or {password "123123"} :as params}]
|
||||
(us/verify! (contains? params :email) "`email` parameter is mandatory")
|
||||
(db/with-atomic [conn (:app.db/pool system)]
|
||||
(db/with-atomic [conn (:app.db/pool main/system)]
|
||||
(let [password (derive-password password)]
|
||||
(if (= email :all)
|
||||
(db/exec! conn ["update profile set password=?" password])
|
||||
@ -127,21 +120,21 @@
|
||||
(db/exec! conn ["update profile set password=? where email=?" password email]))))))
|
||||
|
||||
(defn enable-objects-map-feature-on-file!
|
||||
[system & {:keys [save? id]}]
|
||||
(h/update-file! system
|
||||
[& {:keys [save? id]}]
|
||||
(h/update-file! main/system
|
||||
:id id
|
||||
:update-fn features.fdata/enable-objects-map
|
||||
:save? save?))
|
||||
|
||||
(defn enable-pointer-map-feature-on-file!
|
||||
[system & {:keys [save? id]}]
|
||||
(h/update-file! system
|
||||
[& {:keys [save? id]}]
|
||||
(h/update-file! main/system
|
||||
:id id
|
||||
:update-fn features.fdata/enable-pointer-map
|
||||
:save? save?))
|
||||
|
||||
(defn enable-team-feature!
|
||||
[system team-id feature]
|
||||
[team-id feature]
|
||||
(dm/verify!
|
||||
"feature should be supported"
|
||||
(contains? cfeat/supported-features feature))
|
||||
@ -149,7 +142,7 @@
|
||||
(let [team-id (if (string? team-id)
|
||||
(parse-uuid team-id)
|
||||
team-id)]
|
||||
(db/tx-run! system
|
||||
(db/tx-run! main/system
|
||||
(fn [{:keys [::db/conn]}]
|
||||
(let [team (-> (db/get conn :team {:id team-id})
|
||||
(update :features db/decode-pgarray #{}))
|
||||
@ -161,7 +154,7 @@
|
||||
:enabled))))))
|
||||
|
||||
(defn disable-team-feature!
|
||||
[system team-id feature]
|
||||
[team-id feature]
|
||||
(dm/verify!
|
||||
"feature should be supported"
|
||||
(contains? cfeat/supported-features feature))
|
||||
@ -169,7 +162,7 @@
|
||||
(let [team-id (if (string? team-id)
|
||||
(parse-uuid team-id)
|
||||
team-id)]
|
||||
(db/tx-run! system
|
||||
(db/tx-run! main/system
|
||||
(fn [{:keys [::db/conn]}]
|
||||
(let [team (-> (db/get conn :team {:id team-id})
|
||||
(update :features db/decode-pgarray #{}))
|
||||
@ -181,9 +174,9 @@
|
||||
:disabled))))))
|
||||
|
||||
(defn enable-storage-features-on-file!
|
||||
[system & {:as params}]
|
||||
(enable-objects-map-feature-on-file! system params)
|
||||
(enable-pointer-map-feature-on-file! system params))
|
||||
[& {:as params}]
|
||||
(enable-objects-map-feature-on-file! main/system params)
|
||||
(enable-pointer-map-feature-on-file! main/system params))
|
||||
|
||||
(defn instrument-var
|
||||
[var]
|
||||
@ -207,13 +200,13 @@
|
||||
(defn take-file-snapshot!
|
||||
"An internal helper that persist the file snapshot using non-gc
|
||||
collectable file-changes entry."
|
||||
[system & {:keys [file-id label]}]
|
||||
[& {:keys [file-id label]}]
|
||||
(let [file-id (h/parse-uuid file-id)]
|
||||
(db/tx-run! system fsnap/take-file-snapshot! {:file-id file-id :label label})))
|
||||
(db/tx-run! main/system fsnap/take-file-snapshot! {:file-id file-id :label label})))
|
||||
|
||||
(defn restore-file-snapshot!
|
||||
[system & {:keys [file-id id]}]
|
||||
(db/tx-run! system
|
||||
[& {:keys [file-id id]}]
|
||||
(db/tx-run! main/system
|
||||
(fn [cfg]
|
||||
(let [file-id (h/parse-uuid file-id)
|
||||
id (h/parse-uuid id)]
|
||||
@ -224,12 +217,13 @@
|
||||
|
||||
|
||||
(defn list-file-snapshots!
|
||||
[system & {:keys [file-id limit]}]
|
||||
(db/tx-run! system (fn [system]
|
||||
(let [params {:file-id (h/parse-uuid file-id)
|
||||
:limit limit}]
|
||||
(->> (fsnap/get-file-snapshots system (d/without-nils params))
|
||||
(print-table [:id :revn :created-at :label]))))))
|
||||
[& {:keys [file-id limit]}]
|
||||
(db/tx-run! main/system
|
||||
(fn [system]
|
||||
(let [params {:file-id (h/parse-uuid file-id)
|
||||
:limit limit}]
|
||||
(->> (fsnap/get-file-snapshots system (d/without-nils params))
|
||||
(print-table [:id :revn :created-at :label]))))))
|
||||
|
||||
(defn notify!
|
||||
[{:keys [::mbus/msgbus ::db/pool]} & {:keys [dest code message level]
|
||||
@ -334,12 +328,12 @@
|
||||
(into #{})
|
||||
(run! send))))
|
||||
|
||||
|
||||
(defn duplicate-team
|
||||
[system team-id & {:keys [name]}]
|
||||
[team-id & {:keys [name]}]
|
||||
(let [team-id (if (string? team-id) (parse-uuid team-id) team-id)
|
||||
name (or name (fn [prev-name]
|
||||
(str/ffmt "Cloned: % (%)" prev-name (dt/format-instant (dt/now)))))]
|
||||
(db/tx-run! system (fn [cfg]
|
||||
(db/exec-one! cfg ["SET CONSTRAINTS ALL DEFERRED"])
|
||||
(mgmt/duplicate-team cfg :team-id team-id :name name)))))
|
||||
(db/tx-run! main/system
|
||||
(fn [cfg]
|
||||
(db/exec-one! cfg ["SET CONSTRAINTS ALL DEFERRED"])
|
||||
(mgmt/duplicate-team cfg :team-id team-id :name name)))))
|
||||
|
||||
@ -113,13 +113,13 @@
|
||||
(fn [params]
|
||||
(let [min-age (dt/duration (or (:min-age params) min-age))]
|
||||
(db/tx-run! cfg (fn [cfg]
|
||||
(let [cfg (assoc cfg ::min-age min-age)
|
||||
total (clean-deleted! cfg)]
|
||||
(let [cfg (assoc cfg ::min-age min-age)
|
||||
total (clean-deleted! cfg)]
|
||||
|
||||
(l/inf :hint "task finished"
|
||||
:min-age (dt/format-duration min-age)
|
||||
:total total)
|
||||
(l/inf :hint "task finished"
|
||||
:min-age (dt/format-duration min-age)
|
||||
:total total)
|
||||
|
||||
{:deleted total}))))))
|
||||
{:deleted total}))))))
|
||||
|
||||
|
||||
|
||||
@ -20,8 +20,8 @@
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.main :as main]
|
||||
[app.media :as-alias mtx]
|
||||
[app.media]
|
||||
[app.media :as-alias mtx]
|
||||
[app.migrations]
|
||||
[app.msgbus :as-alias mbus]
|
||||
[app.rpc :as-alias rpc]
|
||||
|
||||
@ -233,8 +233,7 @@
|
||||
(t/is (= 1 (:processed res))))
|
||||
|
||||
(let [rows (th/db-query :file-data-fragment {:file-id (:id file)})]
|
||||
(t/is (= 2 (count rows))))
|
||||
)))
|
||||
(t/is (= 2 (count rows)))))))
|
||||
|
||||
|
||||
|
||||
@ -904,8 +903,7 @@
|
||||
(let [error (:error out)
|
||||
error-data (ex-data error)]
|
||||
(t/is (th/ex-info? error))
|
||||
(t/is (= (:type error-data) :not-found))))
|
||||
))
|
||||
(t/is (= (:type error-data) :not-found))))))
|
||||
|
||||
|
||||
(t/deftest object-thumbnails-ops
|
||||
|
||||
@ -248,9 +248,7 @@
|
||||
(let [result (th/run-task! :storage-gc-deleted {:min-age 0})]
|
||||
(t/is (= 1 (:deleted result))))
|
||||
|
||||
(t/is (some? (sto/get-object storage (:media-id row2))))
|
||||
|
||||
)))
|
||||
(t/is (some? (sto/get-object storage (:media-id row2)))))))
|
||||
|
||||
(t/deftest error-on-direct-storage-obj-deletion
|
||||
(let [storage (::sto/storage th/*system*)
|
||||
|
||||
@ -153,8 +153,7 @@
|
||||
|
||||
(let [res (th/run-task! :storage-gc-touched {:min-age 0})]
|
||||
(t/is (= 0 (:freeze res)))
|
||||
(t/is (= 6 (:delete res))))
|
||||
))
|
||||
(t/is (= 6 (:delete res))))))
|
||||
|
||||
(t/deftest font-deletion-2
|
||||
(let [prof (th/create-profile* 1 {:is-active true})
|
||||
@ -216,8 +215,7 @@
|
||||
|
||||
(let [res (th/run-task! :storage-gc-touched {:min-age 0})]
|
||||
(t/is (= 0 (:freeze res)))
|
||||
(t/is (= 3 (:delete res))))
|
||||
))
|
||||
(t/is (= 3 (:delete res))))))
|
||||
|
||||
(t/deftest font-deletion-3
|
||||
(let [prof (th/create-profile* 1 {:is-active true})
|
||||
@ -278,6 +276,4 @@
|
||||
|
||||
(let [res (th/run-task! :storage-gc-touched {:min-age 0})]
|
||||
(t/is (= 0 (:freeze res)))
|
||||
(t/is (= 3 (:delete res))))
|
||||
|
||||
))
|
||||
(t/is (= 3 (:delete res))))))
|
||||
|
||||
@ -166,9 +166,7 @@
|
||||
out (th/command! params)]
|
||||
;; (th/print-result! out)
|
||||
(let [result (:result out)]
|
||||
(t/is (= uuid/zero (:id result)))))
|
||||
|
||||
))
|
||||
(t/is (= uuid/zero (:id result)))))))
|
||||
|
||||
(t/deftest registration-domain-whitelist
|
||||
(let [whitelist #{"gmail.com" "hey.com" "ya.ru"}]
|
||||
|
||||
@ -462,5 +462,4 @@
|
||||
(t/is (dt/instant? (:deleted-at (first rows)))))
|
||||
|
||||
(let [result (th/run-task! :objects-gc {:min-age 0})]
|
||||
(t/is (= 5 (:processed result))))
|
||||
))
|
||||
(t/is (= 5 (:processed result))))))
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
|
||||
(ns app.common.attrs
|
||||
(:require
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]))
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]))
|
||||
|
||||
(defn- get-attr
|
||||
[obj attr]
|
||||
|
||||
@ -14,10 +14,10 @@
|
||||
(:require-macros [app.common.data]))
|
||||
|
||||
(:require
|
||||
#?(:cljs [cljs.reader :as r]
|
||||
:clj [clojure.edn :as r])
|
||||
#?(:cljs [cljs.core :as c]
|
||||
:clj [clojure.core :as c])
|
||||
#?(:cljs [cljs.reader :as r]
|
||||
:clj [clojure.edn :as r])
|
||||
#?(:cljs [goog.array :as garray])
|
||||
[app.common.math :as mth]
|
||||
[clojure.set :as set]
|
||||
@ -589,8 +589,8 @@
|
||||
(defn num-string? [v]
|
||||
;; https://stackoverflow.com/questions/175739/built-in-way-in-javascript-to-check-if-a-string-is-a-valid-number
|
||||
#?(:cljs (and (string? v)
|
||||
(not (js/isNaN v))
|
||||
(not (js/isNaN (parse-double v))))
|
||||
(not (js/isNaN v))
|
||||
(not (js/isNaN (parse-double v))))
|
||||
|
||||
:clj (not= (parse-double v :nan) :nan)))
|
||||
|
||||
@ -846,26 +846,26 @@
|
||||
(def ^:const trail-zeros-regex-2 #"(\.\d*[^0])0+$")
|
||||
|
||||
#?(:cljs
|
||||
(defn format-precision
|
||||
"Creates a number with predetermined precision and then removes the trailing 0.
|
||||
(defn format-precision
|
||||
"Creates a number with predetermined precision and then removes the trailing 0.
|
||||
Examples:
|
||||
12.0123, 0 => 12
|
||||
12.0123, 1 => 12
|
||||
12.0123, 2 => 12.01"
|
||||
[num precision]
|
||||
[num precision]
|
||||
|
||||
(if (number? num)
|
||||
(try
|
||||
(let [num-str (mth/to-fixed num precision)
|
||||
;; Remove all trailing zeros after the comma 100.00000
|
||||
num-str (str/replace num-str trail-zeros-regex-1 "")]
|
||||
;; Remove trailing zeros after a decimal number: 0.001|00|
|
||||
(if-let [m (re-find trail-zeros-regex-2 num-str)]
|
||||
(str/replace num-str (first m) (second m))
|
||||
num-str))
|
||||
(catch :default _
|
||||
(str num)))
|
||||
(str num))))
|
||||
(if (number? num)
|
||||
(try
|
||||
(let [num-str (mth/to-fixed num precision)
|
||||
;; Remove all trailing zeros after the comma 100.00000
|
||||
num-str (str/replace num-str trail-zeros-regex-1 "")]
|
||||
;; Remove trailing zeros after a decimal number: 0.001|00|
|
||||
(if-let [m (re-find trail-zeros-regex-2 num-str)]
|
||||
(str/replace num-str (first m) (second m))
|
||||
num-str))
|
||||
(catch :default _
|
||||
(str num)))
|
||||
(str num))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Util protocols
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
keys in contrast to clojure.core/select-keys"
|
||||
[target keys]
|
||||
(assert (vector? keys) "keys expected to be a vector")
|
||||
`{ ~@(mapcat (fn [key] [key (list `c/get target key)]) keys) ~@[] })
|
||||
`{~@(mapcat (fn [key] [key (list `c/get target key)]) keys) ~@[]})
|
||||
|
||||
(defmacro get-in
|
||||
"A macro version of `get-in`. Useful when the keys vector is known at
|
||||
@ -121,7 +121,7 @@
|
||||
directly on CLJS, on CLJ works as get."
|
||||
[obj prop]
|
||||
(if (:ns &env)
|
||||
(list 'js* (c/str "(~{}?." (str/snake prop) ")") obj)
|
||||
(list 'js* (c/str "(~{}?." (str/snake prop) "?? ~{})") obj (list 'cljs.core/get obj prop))
|
||||
(list `c/get obj prop)))
|
||||
|
||||
(def ^:dynamic *assert-context* nil)
|
||||
|
||||
@ -83,113 +83,112 @@
|
||||
(sm/humanize-explain (::sm/explain data) opts)))
|
||||
|
||||
#?(:clj
|
||||
(defn format-throwable
|
||||
[^Throwable cause & {:keys [summary? detail? header? data? explain? chain? data-level data-length trace-length]
|
||||
:or {summary? true
|
||||
detail? true
|
||||
header? true
|
||||
data? true
|
||||
explain? true
|
||||
chain? true
|
||||
data-length 8
|
||||
data-level 5}}]
|
||||
(defn format-throwable
|
||||
[^Throwable cause & {:keys [summary? detail? header? data? explain? chain? data-level data-length trace-length]
|
||||
:or {summary? true
|
||||
detail? true
|
||||
header? true
|
||||
data? true
|
||||
explain? true
|
||||
chain? true
|
||||
data-length 8
|
||||
data-level 5}}]
|
||||
|
||||
(letfn [(print-trace-element [^StackTraceElement e]
|
||||
(let [class (.getClassName e)
|
||||
method (.getMethodName e)]
|
||||
(let [match (re-matches #"^([A-Za-z0-9_.-]+)\$(\w+)__\d+$" (str class))]
|
||||
(if (and match (= "invoke" method))
|
||||
(apply printf "%s/%s" (rest match))
|
||||
(printf "%s.%s" class method))))
|
||||
(printf "(%s:%d)" (or (.getFileName e) "") (.getLineNumber e)))
|
||||
(letfn [(print-trace-element [^StackTraceElement e]
|
||||
(let [class (.getClassName e)
|
||||
method (.getMethodName e)]
|
||||
(let [match (re-matches #"^([A-Za-z0-9_.-]+)\$(\w+)__\d+$" (str class))]
|
||||
(if (and match (= "invoke" method))
|
||||
(apply printf "%s/%s" (rest match))
|
||||
(printf "%s.%s" class method))))
|
||||
(printf "(%s:%d)" (or (.getFileName e) "") (.getLineNumber e)))
|
||||
|
||||
(print-explain [explain]
|
||||
(print " xp: ")
|
||||
(let [[line & lines] (str/lines explain)]
|
||||
(print line)
|
||||
(newline)
|
||||
(doseq [line lines]
|
||||
(println " " line))))
|
||||
(print-explain [explain]
|
||||
(print " xp: ")
|
||||
(let [[line & lines] (str/lines explain)]
|
||||
(print line)
|
||||
(newline)
|
||||
(doseq [line lines]
|
||||
(println " " line))))
|
||||
|
||||
(print-data [data]
|
||||
(when (seq data)
|
||||
(print " dt: ")
|
||||
(let [[line & lines] (str/lines (pp/pprint-str data :level data-level :length data-length))]
|
||||
(print line)
|
||||
(newline)
|
||||
(doseq [line lines]
|
||||
(println " " line)))))
|
||||
(print-data [data]
|
||||
(when (seq data)
|
||||
(print " dt: ")
|
||||
(let [[line & lines] (str/lines (pp/pprint-str data :level data-level :length data-length))]
|
||||
(print line)
|
||||
(newline)
|
||||
(doseq [line lines]
|
||||
(println " " line)))))
|
||||
|
||||
(print-trace-title [^Throwable cause]
|
||||
(print " → ")
|
||||
(printf "%s: %s" (.getName (class cause))
|
||||
(-> (ex-message cause)
|
||||
(str/lines)
|
||||
(first)
|
||||
(str/prune 130)))
|
||||
(print-trace-title [^Throwable cause]
|
||||
(print " → ")
|
||||
(printf "%s: %s" (.getName (class cause))
|
||||
(-> (ex-message cause)
|
||||
(str/lines)
|
||||
(first)
|
||||
(str/prune 130)))
|
||||
|
||||
(when-let [^StackTraceElement e (first (.getStackTrace ^Throwable cause))]
|
||||
(printf " (%s:%d)" (or (.getFileName e) "") (.getLineNumber e)))
|
||||
(when-let [^StackTraceElement e (first (.getStackTrace ^Throwable cause))]
|
||||
(printf " (%s:%d)" (or (.getFileName e) "") (.getLineNumber e)))
|
||||
|
||||
(newline))
|
||||
(newline))
|
||||
|
||||
(print-summary [^Throwable cause]
|
||||
(let [causes (loop [cause (ex-cause cause)
|
||||
result []]
|
||||
(if cause
|
||||
(recur (ex-cause cause)
|
||||
(conj result cause))
|
||||
result))]
|
||||
(when header?
|
||||
(println "SUMMARY:"))
|
||||
(print-trace-title cause)
|
||||
(doseq [cause causes]
|
||||
(print-trace-title cause))))
|
||||
(print-summary [^Throwable cause]
|
||||
(let [causes (loop [cause (ex-cause cause)
|
||||
result []]
|
||||
(if cause
|
||||
(recur (ex-cause cause)
|
||||
(conj result cause))
|
||||
result))]
|
||||
(when header?
|
||||
(println "SUMMARY:"))
|
||||
(print-trace-title cause)
|
||||
(doseq [cause causes]
|
||||
(print-trace-title cause))))
|
||||
|
||||
(print-trace [^Throwable cause]
|
||||
(print-trace-title cause)
|
||||
(let [st (.getStackTrace cause)]
|
||||
(print " at: ")
|
||||
(if-let [e (first st)]
|
||||
(print-trace-element e)
|
||||
(print "[empty stack trace]"))
|
||||
(newline)
|
||||
(print-trace [^Throwable cause]
|
||||
(print-trace-title cause)
|
||||
(let [st (.getStackTrace cause)]
|
||||
(print " at: ")
|
||||
(if-let [e (first st)]
|
||||
(print-trace-element e)
|
||||
(print "[empty stack trace]"))
|
||||
(newline)
|
||||
|
||||
(doseq [e (if (nil? trace-length) (rest st) (take (dec trace-length) (rest st)))]
|
||||
(print " ")
|
||||
(print-trace-element e)
|
||||
(newline))))
|
||||
(doseq [e (if (nil? trace-length) (rest st) (take (dec trace-length) (rest st)))]
|
||||
(print " ")
|
||||
(print-trace-element e)
|
||||
(newline))))
|
||||
|
||||
(print-detail [^Throwable cause]
|
||||
(print-trace cause)
|
||||
(when-let [data (ex-data cause)]
|
||||
(when data?
|
||||
(print-data (dissoc data ::s/problems ::s/spec ::s/value ::sm/explain)))
|
||||
(when explain?
|
||||
(if-let [explain (explain data {:length data-length :level data-level})]
|
||||
(print-explain explain)))))
|
||||
(print-detail [^Throwable cause]
|
||||
(print-trace cause)
|
||||
(when-let [data (ex-data cause)]
|
||||
(when data?
|
||||
(print-data (dissoc data ::s/problems ::s/spec ::s/value ::sm/explain)))
|
||||
(when explain?
|
||||
(if-let [explain (explain data {:length data-length :level data-level})]
|
||||
(print-explain explain)))))
|
||||
|
||||
(print-all [^Throwable cause]
|
||||
(when summary?
|
||||
(print-summary cause))
|
||||
(print-all [^Throwable cause]
|
||||
(when summary?
|
||||
(print-summary cause))
|
||||
|
||||
(when detail?
|
||||
(when header?
|
||||
(println "DETAIL:"))
|
||||
(when detail?
|
||||
(when header?
|
||||
(println "DETAIL:"))
|
||||
|
||||
(print-detail cause)
|
||||
(when chain?
|
||||
(loop [cause cause]
|
||||
(when-let [cause (ex-cause cause)]
|
||||
(newline)
|
||||
(print-detail cause)
|
||||
(recur cause))))))
|
||||
]
|
||||
(print-detail cause)
|
||||
(when chain?
|
||||
(loop [cause cause]
|
||||
(when-let [cause (ex-cause cause)]
|
||||
(newline)
|
||||
(print-detail cause)
|
||||
(recur cause))))))]
|
||||
|
||||
(with-out-str
|
||||
(print-all cause)))))
|
||||
(with-out-str
|
||||
(print-all cause)))))
|
||||
|
||||
#?(:clj
|
||||
(defn print-throwable
|
||||
[cause & {:as opts}]
|
||||
(println (format-throwable cause opts))))
|
||||
(defn print-throwable
|
||||
[cause & {:as opts}]
|
||||
(println (format-throwable cause opts))))
|
||||
|
||||
@ -93,7 +93,6 @@
|
||||
[flag]
|
||||
(case flag
|
||||
:feature-components-v2 "components/v2"
|
||||
:feature-new-css-system "styles/v2"
|
||||
:feature-styles-v2 "styles/v2"
|
||||
:feature-grid-layout "layout/grid"
|
||||
:feature-fdata-objects-map "fdata/objects-map"
|
||||
|
||||
@ -814,8 +814,8 @@
|
||||
(defn- parents-frames
|
||||
"Go trough the parents and get all of them that are a frame."
|
||||
[id objects]
|
||||
(->> (cfh/get-parents-with-self objects id)
|
||||
(filter cfh/frame-shape?)))
|
||||
(->> (cfh/get-parents-with-self objects id)
|
||||
(filter cfh/frame-shape?)))
|
||||
|
||||
(defmulti frames-changed (fn [_ change] (:type change)))
|
||||
|
||||
|
||||
@ -58,8 +58,8 @@
|
||||
(defn set-undo-group
|
||||
[changes undo-group]
|
||||
(cond-> changes
|
||||
(some? undo-group)
|
||||
(assoc :undo-group undo-group)))
|
||||
(some? undo-group)
|
||||
(assoc :undo-group undo-group)))
|
||||
|
||||
(defn with-page
|
||||
[changes page]
|
||||
@ -166,12 +166,12 @@
|
||||
new-changes (if (< index (count redo-changes))
|
||||
(->> (subvec (:redo-changes changes) index)
|
||||
(map #(-> %
|
||||
(assoc :page-id uuid/zero)
|
||||
(dissoc :component-id))))
|
||||
(assoc :page-id uuid/zero)
|
||||
(dissoc :component-id))))
|
||||
[])
|
||||
new-file-data (cfc/process-changes file-data new-changes)]
|
||||
(vary-meta changes assoc ::file-data new-file-data
|
||||
::applied-changes-count (count redo-changes)))
|
||||
::applied-changes-count (count redo-changes)))
|
||||
changes))
|
||||
|
||||
;; Page changes
|
||||
@ -224,9 +224,9 @@
|
||||
:option option-key
|
||||
:value option-val})
|
||||
(update :undo-changes conj {:type :set-option
|
||||
:page-id page-id
|
||||
:option option-key
|
||||
:value old-val})
|
||||
:page-id page-id
|
||||
:option option-key
|
||||
:value old-val})
|
||||
(apply-changes-local))))
|
||||
|
||||
(defn update-page-option
|
||||
@ -243,9 +243,9 @@
|
||||
:option option-key
|
||||
:value new-val})
|
||||
(update :undo-changes conj {:type :set-option
|
||||
:page-id page-id
|
||||
:option option-key
|
||||
:value old-val})
|
||||
:page-id page-id
|
||||
:option option-key
|
||||
:value old-val})
|
||||
(apply-changes-local))))
|
||||
|
||||
;; Shape tree changes
|
||||
@ -292,7 +292,7 @@
|
||||
(-> changes
|
||||
(update :redo-changes conj add-change)
|
||||
(cond->
|
||||
(and (ctk/in-component-copy? parent) (not ignore-touched))
|
||||
(and (ctk/in-component-copy? parent) (not ignore-touched))
|
||||
(update :undo-changes conj restore-touched-change))
|
||||
(update :undo-changes conj del-change)
|
||||
(apply-changes-local)))))
|
||||
@ -333,13 +333,13 @@
|
||||
mk-undo-change
|
||||
(fn [undo-changes shape]
|
||||
(let [prev-sibling (cfh/get-prev-sibling objects (:id shape))]
|
||||
(conj undo-changes
|
||||
{:type :mov-objects
|
||||
:page-id (::page-id (meta changes))
|
||||
:parent-id (:parent-id shape)
|
||||
:shapes [(:id shape)]
|
||||
:after-shape prev-sibling
|
||||
:index 0}))) ; index is used in case there is no after-shape (moving bottom shapes)
|
||||
(conj undo-changes
|
||||
{:type :mov-objects
|
||||
:page-id (::page-id (meta changes))
|
||||
:parent-id (:parent-id shape)
|
||||
:shapes [(:id shape)]
|
||||
:after-shape prev-sibling
|
||||
:index 0}))) ; index is used in case there is no after-shape (moving bottom shapes)
|
||||
|
||||
restore-touched-change
|
||||
{:type :mod-obj
|
||||
@ -351,7 +351,7 @@
|
||||
(-> changes
|
||||
(update :redo-changes conj set-parent-change)
|
||||
(cond->
|
||||
(ctk/in-component-copy? parent)
|
||||
(ctk/in-component-copy? parent)
|
||||
(update :undo-changes conj restore-touched-change))
|
||||
(update :undo-changes #(reduce mk-undo-change % shapes))
|
||||
(apply-changes-local)))))
|
||||
@ -501,10 +501,10 @@
|
||||
|
||||
objects (lookup-objects changes)
|
||||
xform (comp
|
||||
(mapcat #(cons % (cfh/get-parent-ids objects %)))
|
||||
(map (d/getf objects))
|
||||
(filter #(contains? #{:group :bool} (:type %)))
|
||||
(distinct))
|
||||
(mapcat #(cons % (cfh/get-parent-ids objects %)))
|
||||
(map (d/getf objects))
|
||||
(filter #(contains? #{:group :bool} (:type %)))
|
||||
(distinct))
|
||||
all-parents (sequence xform ids)
|
||||
|
||||
generate-operation
|
||||
@ -661,59 +661,59 @@
|
||||
([changes id path name new-shapes updated-shapes main-instance-id main-instance-page]
|
||||
(add-component changes id path name new-shapes updated-shapes main-instance-id main-instance-page nil))
|
||||
([changes id path name new-shapes updated-shapes main-instance-id main-instance-page annotation]
|
||||
(assert-page-id! changes)
|
||||
(assert-objects! changes)
|
||||
(let [page-id (::page-id (meta changes))
|
||||
objects (lookup-objects changes)
|
||||
lookupf (d/getf objects)
|
||||
(assert-page-id! changes)
|
||||
(assert-objects! changes)
|
||||
(let [page-id (::page-id (meta changes))
|
||||
objects (lookup-objects changes)
|
||||
lookupf (d/getf objects)
|
||||
|
||||
mk-change (fn [shape]
|
||||
{:type :mod-obj
|
||||
:page-id page-id
|
||||
:id (:id shape)
|
||||
:operations [{:type :set
|
||||
:attr :component-id
|
||||
:val (:component-id shape)}
|
||||
{:type :set
|
||||
:attr :component-file
|
||||
:val (:component-file shape)}
|
||||
{:type :set
|
||||
:attr :component-root
|
||||
:val (:component-root shape)}
|
||||
{:type :set
|
||||
:attr :main-instance
|
||||
:val (:main-instance shape)}
|
||||
{:type :set
|
||||
:attr :shape-ref
|
||||
:val (:shape-ref shape)}
|
||||
{:type :set
|
||||
:attr :touched
|
||||
:val (:touched shape)}]}) ]
|
||||
(-> changes
|
||||
(update :redo-changes
|
||||
(fn [redo-changes]
|
||||
(-> redo-changes
|
||||
(conj (cond-> {:type :add-component
|
||||
:id id
|
||||
:path path
|
||||
:name name
|
||||
:main-instance-id main-instance-id
|
||||
:main-instance-page main-instance-page
|
||||
:annotation annotation}
|
||||
(some? new-shapes) ;; this will be null in components-v2
|
||||
(assoc :shapes (vec new-shapes))))
|
||||
(into (map mk-change) updated-shapes))))
|
||||
(update :undo-changes
|
||||
(fn [undo-changes]
|
||||
(-> undo-changes
|
||||
(conj {:type :del-component
|
||||
:id id
|
||||
:skip-undelete? true})
|
||||
(into (comp (map :id)
|
||||
(map lookupf)
|
||||
(map mk-change))
|
||||
updated-shapes))))
|
||||
(apply-changes-local)))))
|
||||
mk-change (fn [shape]
|
||||
{:type :mod-obj
|
||||
:page-id page-id
|
||||
:id (:id shape)
|
||||
:operations [{:type :set
|
||||
:attr :component-id
|
||||
:val (:component-id shape)}
|
||||
{:type :set
|
||||
:attr :component-file
|
||||
:val (:component-file shape)}
|
||||
{:type :set
|
||||
:attr :component-root
|
||||
:val (:component-root shape)}
|
||||
{:type :set
|
||||
:attr :main-instance
|
||||
:val (:main-instance shape)}
|
||||
{:type :set
|
||||
:attr :shape-ref
|
||||
:val (:shape-ref shape)}
|
||||
{:type :set
|
||||
:attr :touched
|
||||
:val (:touched shape)}]})]
|
||||
(-> changes
|
||||
(update :redo-changes
|
||||
(fn [redo-changes]
|
||||
(-> redo-changes
|
||||
(conj (cond-> {:type :add-component
|
||||
:id id
|
||||
:path path
|
||||
:name name
|
||||
:main-instance-id main-instance-id
|
||||
:main-instance-page main-instance-page
|
||||
:annotation annotation}
|
||||
(some? new-shapes) ;; this will be null in components-v2
|
||||
(assoc :shapes (vec new-shapes))))
|
||||
(into (map mk-change) updated-shapes))))
|
||||
(update :undo-changes
|
||||
(fn [undo-changes]
|
||||
(-> undo-changes
|
||||
(conj {:type :del-component
|
||||
:id id
|
||||
:skip-undelete? true})
|
||||
(into (comp (map :id)
|
||||
(map lookupf)
|
||||
(map mk-change))
|
||||
updated-shapes))))
|
||||
(apply-changes-local)))))
|
||||
|
||||
(defn update-component
|
||||
[changes id update-fn]
|
||||
@ -748,7 +748,7 @@
|
||||
(update :redo-changes conj {:type :del-component
|
||||
:id id})
|
||||
(update :undo-changes conj {:type :restore-component
|
||||
:id id})))
|
||||
:id id})))
|
||||
|
||||
(defn restore-component
|
||||
([changes id]
|
||||
@ -760,7 +760,7 @@
|
||||
:id id
|
||||
:page-id page-id})
|
||||
(update :undo-changes conj {:type :del-component
|
||||
:id id}))))
|
||||
:id id}))))
|
||||
|
||||
(defn ignore-remote
|
||||
[changes]
|
||||
|
||||
@ -603,7 +603,7 @@
|
||||
(defn last-path
|
||||
"Returns the last item of the path."
|
||||
[path]
|
||||
(last (split-path path)))
|
||||
(last (split-path path)))
|
||||
|
||||
(defn compact-name
|
||||
"Append the first item of the path and the name."
|
||||
|
||||
@ -621,13 +621,13 @@
|
||||
(defmethod migrate 33
|
||||
[data]
|
||||
(letfn [(update-object [object]
|
||||
; Ensure all root objects are well formed shapes.
|
||||
(if (= (:id object) uuid/zero)
|
||||
(-> object
|
||||
(assoc :parent-id uuid/zero
|
||||
:frame-id uuid/zero)
|
||||
(cts/setup-shape))
|
||||
object))
|
||||
;; Ensure all root objects are well formed shapes.
|
||||
(if (= (:id object) uuid/zero)
|
||||
(-> object
|
||||
(assoc :parent-id uuid/zero
|
||||
:frame-id uuid/zero)
|
||||
(cts/setup-shape))
|
||||
object))
|
||||
|
||||
(update-container [container]
|
||||
(update container :objects update-vals update-object))]
|
||||
|
||||
@ -400,10 +400,10 @@
|
||||
; Convert the shape in a frame.
|
||||
(log/debug :hint " -> set :type :frame")
|
||||
(assoc shape :type :frame
|
||||
:fills []
|
||||
:hide-in-viewer true
|
||||
:rx 0
|
||||
:ry 0))]
|
||||
:fills []
|
||||
:hide-in-viewer true
|
||||
:rx 0
|
||||
:ry 0))]
|
||||
|
||||
(log/dbg :hint "repairing shape :instance-head-not-frame" :id (:id shape) :name (:name shape) :page-id page-id)
|
||||
(-> (pcb/empty-changes nil page-id)
|
||||
|
||||
@ -46,8 +46,8 @@
|
||||
:y (:y wrapper-rect)})
|
||||
|
||||
:vtop (let [top (:y rect)]
|
||||
{:x (:x wrapper-rect)
|
||||
:y top})
|
||||
{:x (:x wrapper-rect)
|
||||
:y top})
|
||||
|
||||
:vcenter (let [center (+ (:y rect) (/ (:height rect) 2))]
|
||||
{:x (:x wrapper-rect)
|
||||
|
||||
@ -31,13 +31,13 @@
|
||||
(create-bounds shape bounds-map objects modif-tree nil))
|
||||
|
||||
([{:keys [id] :as shape} bounds-map objects modif-tree current-ref]
|
||||
(cond
|
||||
(and (cfh/mask-shape? shape) (d/not-empty? (:shapes shape)))
|
||||
(create-bounds (get objects (first (:shapes shape))) bounds-map objects modif-tree)
|
||||
|
||||
(cfh/group-shape? shape)
|
||||
(if (cfh/group-shape? shape)
|
||||
(let [modifiers (dm/get-in modif-tree [id :modifiers])
|
||||
children (cfh/get-immediate-children objects id)
|
||||
|
||||
children
|
||||
(cond->> (cfh/get-immediate-children objects id)
|
||||
(cfh/mask-shape? shape)
|
||||
(take 1))
|
||||
shape-bounds (if current-ref @current-ref @(get bounds-map id))
|
||||
current-bounds
|
||||
(cond-> shape-bounds
|
||||
@ -49,7 +49,7 @@
|
||||
(mapv #(deref (get bounds-map (:id %)))))]
|
||||
(gpo/merge-parent-coords-bounds children-bounds current-bounds))
|
||||
|
||||
:else
|
||||
;; Shape
|
||||
(let [modifiers (dm/get-in modif-tree [id :modifiers])
|
||||
shape-bounds (if current-ref @current-ref @(get bounds-map id))]
|
||||
(cond-> shape-bounds
|
||||
|
||||
@ -6,9 +6,9 @@
|
||||
|
||||
(ns app.common.geom.matrix
|
||||
(:require
|
||||
#?(:clj [app.common.fressian :as fres])
|
||||
#?(:cljs [cljs.pprint :as pp]
|
||||
:clj [clojure.pprint :as pp])
|
||||
#?(:clj [app.common.fressian :as fres])
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
@ -100,7 +100,7 @@
|
||||
(sg/small-double)
|
||||
(sg/small-double)
|
||||
(sg/small-double)
|
||||
(sg/small-double) )
|
||||
(sg/small-double))
|
||||
(sg/fmap #(apply pos->Matrix %)))
|
||||
::oapi/type "string"
|
||||
::oapi/format "matrix"
|
||||
@ -248,8 +248,8 @@
|
||||
([pt]
|
||||
(dm/assert! (gpt/point? pt))
|
||||
(pos->Matrix 1 0 0 1
|
||||
(- (dm/get-prop pt :x))
|
||||
(- (dm/get-prop pt :y))))
|
||||
(- (dm/get-prop pt :x))
|
||||
(- (dm/get-prop pt :y))))
|
||||
|
||||
([x y]
|
||||
(pos->Matrix 1 0 0 1 (- x) (- y))))
|
||||
|
||||
@ -7,11 +7,11 @@
|
||||
(ns app.common.geom.point
|
||||
(:refer-clojure :exclude [divide min max abs])
|
||||
(:require
|
||||
#?(:cljs [cljs.pprint :as pp]
|
||||
:clj [clojure.pprint :as pp])
|
||||
#?(:clj [app.common.fressian :as fres])
|
||||
#?(:cljs [cljs.core :as c]
|
||||
:clj [clojure.core :as c])
|
||||
#?(:clj [app.common.fressian :as fres])
|
||||
#?(:cljs [cljs.pprint :as pp]
|
||||
:clj [clojure.pprint :as pp])
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
|
||||
@ -363,9 +363,9 @@
|
||||
(cond-> bounds
|
||||
(> target-height height)
|
||||
(-> (assoc :height target-height)
|
||||
(update :y - (/ (- target-height height ) 2)))
|
||||
(update :y - (/ (- target-height height) 2)))
|
||||
|
||||
(< target-height height)
|
||||
(-> (assoc :width target-width)
|
||||
(update :x - (/ (- target-width width ) 2)))))
|
||||
(update :x - (/ (- target-width width) 2)))))
|
||||
bounds))
|
||||
|
||||
@ -171,9 +171,9 @@
|
||||
layout-gap-row
|
||||
0)
|
||||
|
||||
col-pad (if (or(and row? space-evenly?)
|
||||
(and row? space-around?)
|
||||
(and col? content-evenly?))
|
||||
col-pad (if (or (and row? space-evenly?)
|
||||
(and row? space-around?)
|
||||
(and col? content-evenly?))
|
||||
layout-gap-col
|
||||
0)
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
(<= (+ b-y b-height) (+ a-y a-height))))
|
||||
|
||||
(defn intersects?
|
||||
[[a-x a-y a-width a-height ]
|
||||
[[a-x a-y a-width a-height]
|
||||
[b-x b-y b-width b-height]]
|
||||
(not (or (<= (+ b-x b-width) a-x)
|
||||
(<= (+ b-y b-height) a-y)
|
||||
@ -76,11 +76,9 @@
|
||||
y2 (min ra-y rb-y)
|
||||
height (- y2 y1)
|
||||
rb-x (+ b-x b-width)
|
||||
width (- a-width (- rb-x a-x))
|
||||
]
|
||||
width (- a-width (- rb-x a-x))]
|
||||
(when (and (> width 0) (> height 0))
|
||||
(make-area rb-x y1 width height)))
|
||||
)
|
||||
(make-area rb-x y1 width height))))
|
||||
|
||||
(defn difference
|
||||
[area-a area-b]
|
||||
@ -92,4 +90,4 @@
|
||||
(into []
|
||||
(keep #(% area-a area-b))
|
||||
[top-rect left-rect right-rect bottom-rect])))
|
||||
|
||||
|
||||
|
||||
@ -30,13 +30,13 @@
|
||||
|
||||
(let [parent-id (:id parent)
|
||||
parent-bounds @(get bounds parent-id)
|
||||
|
||||
|
||||
{pad-top :p1 pad-right :p2 pad-bottom :p3 pad-left :p4} layout-padding
|
||||
pad-top (or pad-top 0)
|
||||
pad-right (or pad-right 0)
|
||||
pad-bottom (or pad-bottom 0)
|
||||
pad-left (or pad-left 0)
|
||||
|
||||
|
||||
layout-points (layout-content-points bounds parent layout-data)]
|
||||
|
||||
(if (d/not-empty? layout-points)
|
||||
|
||||
@ -62,14 +62,14 @@
|
||||
(defn child-min-width
|
||||
[child child-bounds bounds objects]
|
||||
(+ (ctl/child-width-margin child)
|
||||
(-child-min-width child child-bounds bounds objects)))
|
||||
(-child-min-width child child-bounds bounds objects true)))
|
||||
|
||||
(def -child-min-height nil)
|
||||
|
||||
(defn child-min-height
|
||||
[child child-bounds bounds objects]
|
||||
(+ (ctl/child-height-margin child)
|
||||
(-child-min-height child child-bounds bounds objects)))
|
||||
(-child-min-height child child-bounds bounds objects true)))
|
||||
|
||||
(defn layout-bounds
|
||||
[parent shape-bounds]
|
||||
@ -82,7 +82,7 @@
|
||||
(let [[size max-size]
|
||||
(case type
|
||||
:percent
|
||||
(let [value (/ (* total-value value) 100) ]
|
||||
(let [value (/ (* total-value value) 100)]
|
||||
[value value])
|
||||
|
||||
:fixed
|
||||
@ -190,7 +190,7 @@
|
||||
;; Apply assign-fr to the track-list
|
||||
track-list
|
||||
(reduce
|
||||
(fn [track-list [idx assignment] ]
|
||||
(fn [track-list [idx assignment]]
|
||||
(-> track-list
|
||||
(update-in [idx :size] max assignment)))
|
||||
track-list
|
||||
|
||||
@ -54,13 +54,13 @@
|
||||
current-range nil]
|
||||
(if pending
|
||||
(let [[next-shape rect :as next-shape+rects] (first pending)]
|
||||
|
||||
|
||||
(if (or (not current-range) (overlaps-range? axis current-range rect))
|
||||
;; Add shape to current row
|
||||
(let [current-track (conj current-track (:id next-shape))
|
||||
current-range (join-range axis current-range rect)]
|
||||
(recur (next pending) result index current-track current-range))
|
||||
|
||||
|
||||
;; New row
|
||||
(recur (next pending)
|
||||
(conj result {:index index
|
||||
|
||||
@ -176,7 +176,7 @@
|
||||
[shape rect include-content?]
|
||||
|
||||
(when (d/not-empty? (:content shape))
|
||||
(let [ ;; If paths are too complex the intersection is too expensive
|
||||
(let [;; If paths are too complex the intersection is too expensive
|
||||
;; we fallback to check its bounding box otherwise the performance penalty
|
||||
;; is too big
|
||||
;; TODO: Look for ways to optimize this operation
|
||||
@ -190,10 +190,10 @@
|
||||
start-point (-> shape :content (first) :params (gpt/point))]
|
||||
|
||||
(or (intersects-lines? rect-lines path-lines)
|
||||
(if include-content?
|
||||
(or (is-point-inside-nonzero? (first rect-points) path-lines)
|
||||
(is-point-inside-nonzero? start-point rect-lines))
|
||||
false)))))
|
||||
(if include-content?
|
||||
(or (is-point-inside-nonzero? (first rect-points) path-lines)
|
||||
(is-point-inside-nonzero? start-point rect-lines))
|
||||
false)))))
|
||||
|
||||
(defn is-point-inside-ellipse?
|
||||
"checks if a point is inside an ellipse"
|
||||
|
||||
@ -16,54 +16,60 @@
|
||||
[app.common.types.shape.layout :as ctl]))
|
||||
|
||||
(defn child-min-width
|
||||
[child child-bounds bounds objects]
|
||||
(cond
|
||||
(and (ctl/fill-width? child) (ctl/flex-layout? child))
|
||||
(ctl/child-min-width child)
|
||||
;; Uncomment this to activate "auto" as min size
|
||||
#_(let [children (cfh/get-immediate-children objects (dm/get-prop child :id) {:remove-hidden true})]
|
||||
(max (ctl/child-min-width child)
|
||||
(gpo/width-points (fb/layout-content-bounds bounds child children objects))))
|
||||
([child child-bounds bounds objects]
|
||||
(child-min-width child child-bounds bounds objects false))
|
||||
([child child-bounds bounds objects strict?]
|
||||
(cond
|
||||
(and (not strict?) (ctl/fill-width? child) (ctl/flex-layout? child))
|
||||
(ctl/child-min-width child)
|
||||
|
||||
(and (ctl/fill-width? child)
|
||||
(ctl/grid-layout? child))
|
||||
(let [children
|
||||
(->> (cfh/get-immediate-children objects (:id child) {:remove-hidden true})
|
||||
(map #(vector @(get bounds (:id %)) %)))
|
||||
layout-data (gd/calc-layout-data child @(get bounds (:id child)) children bounds objects true)]
|
||||
(max (ctl/child-min-width child)
|
||||
(gpo/width-points (gb/layout-content-bounds bounds child layout-data))))
|
||||
(and strict? (ctl/fill-width? child) (ctl/flex-layout? child))
|
||||
(let [children (cfh/get-immediate-children objects (dm/get-prop child :id) {:remove-hidden true})]
|
||||
(max (ctl/child-min-width child)
|
||||
(gpo/width-points (fb/layout-content-bounds bounds child children objects))))
|
||||
|
||||
(ctl/fill-width? child)
|
||||
(ctl/child-min-width child)
|
||||
(and (ctl/fill-width? child)
|
||||
(ctl/grid-layout? child))
|
||||
(let [children
|
||||
(->> (cfh/get-immediate-children objects (:id child) {:remove-hidden true})
|
||||
(map #(vector @(get bounds (:id %)) %)))
|
||||
layout-data (gd/calc-layout-data child @(get bounds (:id child)) children bounds objects true)]
|
||||
(max (ctl/child-min-width child)
|
||||
(gpo/width-points (gb/layout-content-bounds bounds child layout-data))))
|
||||
|
||||
:else
|
||||
(gpo/width-points child-bounds)))
|
||||
(ctl/fill-width? child)
|
||||
(ctl/child-min-width child)
|
||||
|
||||
:else
|
||||
(gpo/width-points child-bounds))))
|
||||
|
||||
(defn child-min-height
|
||||
[child child-bounds bounds objects]
|
||||
(cond
|
||||
(and (ctl/fill-height? child) (ctl/flex-layout? child))
|
||||
;; Uncomment this to activate "auto" as min size
|
||||
(ctl/child-min-height child)
|
||||
#_(let [children (cfh/get-immediate-children objects (dm/get-prop child :id) {:remove-hidden true})]
|
||||
(max (ctl/child-min-height child)
|
||||
(gpo/height-points (fb/layout-content-bounds bounds child children objects))))
|
||||
([child child-bounds bounds objects]
|
||||
(child-min-height child child-bounds bounds objects false))
|
||||
([child child-bounds bounds objects strict?]
|
||||
(cond
|
||||
(and (not strict?) (ctl/fill-height? child) (ctl/flex-layout? child))
|
||||
(ctl/child-min-height child)
|
||||
|
||||
(and (ctl/fill-height? child) (ctl/grid-layout? child))
|
||||
(let [children
|
||||
(->> (cfh/get-immediate-children objects (dm/get-prop child :id) {:remove-hidden true})
|
||||
(map (fn [child] [@(get bounds (:id child)) child])))
|
||||
layout-data (gd/calc-layout-data child (:points child) children bounds objects true)
|
||||
auto-bounds (gb/layout-content-bounds bounds child layout-data)]
|
||||
(max (ctl/child-min-height child)
|
||||
(gpo/height-points auto-bounds)))
|
||||
(and strict? (ctl/fill-height? child) (ctl/flex-layout? child))
|
||||
(let [children (cfh/get-immediate-children objects (dm/get-prop child :id) {:remove-hidden true})]
|
||||
(max (ctl/child-min-height child)
|
||||
(gpo/height-points (fb/layout-content-bounds bounds child children objects))))
|
||||
|
||||
(ctl/fill-height? child)
|
||||
(ctl/child-min-height child)
|
||||
(and (ctl/fill-height? child) (ctl/grid-layout? child))
|
||||
(let [children
|
||||
(->> (cfh/get-immediate-children objects (dm/get-prop child :id) {:remove-hidden true})
|
||||
(map (fn [child] [@(get bounds (:id child)) child])))
|
||||
layout-data (gd/calc-layout-data child (:points child) children bounds objects true)
|
||||
auto-bounds (gb/layout-content-bounds bounds child layout-data)]
|
||||
(max (ctl/child-min-height child)
|
||||
(gpo/height-points auto-bounds)))
|
||||
|
||||
:else
|
||||
(gpo/height-points child-bounds)))
|
||||
(ctl/fill-height? child)
|
||||
(ctl/child-min-height child)
|
||||
|
||||
:else
|
||||
(gpo/height-points child-bounds))))
|
||||
|
||||
#?(:cljs
|
||||
(do (set! fd/-child-min-width child-min-width)
|
||||
|
||||
@ -477,8 +477,7 @@
|
||||
result)
|
||||
last-start (if (= :move-to command)
|
||||
point
|
||||
last-start)
|
||||
]
|
||||
last-start)]
|
||||
(recur (first pending)
|
||||
(rest pending)
|
||||
result
|
||||
@ -523,7 +522,7 @@
|
||||
"Point on line"
|
||||
[position from-p to-p]
|
||||
|
||||
(let [e1 (gpt/to-vec from-p to-p )
|
||||
(let [e1 (gpt/to-vec from-p to-p)
|
||||
e2 (gpt/to-vec from-p position)
|
||||
|
||||
len2 (+ (mth/sq (:x e1)) (mth/sq (:y e1)))
|
||||
@ -730,7 +729,7 @@
|
||||
ray-t (get-line-tval ray-line curve-v)]
|
||||
(and (> ray-t 0)
|
||||
(> (mth/abs (- curve-tg-angle 180)) 0.01)
|
||||
(> (mth/abs (- curve-tg-angle 0)) 0.01)) )))]
|
||||
(> (mth/abs (- curve-tg-angle 0)) 0.01)))))]
|
||||
(->> curve-ts
|
||||
(mapv #(vector (curve-values curve %)
|
||||
(curve-windup curve %))))))
|
||||
|
||||
@ -74,7 +74,7 @@
|
||||
points
|
||||
(if has-resize?
|
||||
(-> (:points shape)
|
||||
(gco/transform-points (ctm/modifiers->transform modifiers)) )
|
||||
(gco/transform-points (ctm/modifiers->transform modifiers)))
|
||||
points)]
|
||||
[modifiers points])]
|
||||
(position-pixel-precision modifiers shape points precision ignore-axis)))
|
||||
|
||||
@ -6,6 +6,6 @@
|
||||
|
||||
(defn update-strokes-width
|
||||
[shape scale]
|
||||
(update shape :strokes
|
||||
(fn [strokes]
|
||||
(mapv #(update-stroke-width % scale) strokes))))
|
||||
(update shape :strokes
|
||||
(fn [strokes]
|
||||
(mapv #(update-stroke-width % scale) strokes))))
|
||||
|
||||
@ -61,8 +61,8 @@
|
||||
dy (dm/get-prop delta :y)]
|
||||
(if (d/num? dx dy)
|
||||
(mapv #(-> %
|
||||
(update :x + dx)
|
||||
(update :y + dy))
|
||||
(update :x + dx)
|
||||
(update :y + dy))
|
||||
position-data)
|
||||
position-data))))
|
||||
|
||||
@ -162,8 +162,8 @@
|
||||
(-> (gmt/matrix)
|
||||
(gmt/translate center)
|
||||
(cond->
|
||||
flip-x (gmt/scale (gpt/point -1 1))
|
||||
flip-y (gmt/scale (gpt/point 1 -1)))
|
||||
flip-x (gmt/scale (gpt/point -1 1))
|
||||
flip-y (gmt/scale (gpt/point 1 -1)))
|
||||
(gmt/multiply (:transform-inverse shape (gmt/matrix)))
|
||||
(gmt/translate (gpt/negate center)))))
|
||||
|
||||
@ -207,24 +207,24 @@
|
||||
mb7 (/ (- x2 x1) det)
|
||||
mb8 (/ (- (* x1 y1) (* x2 y1)) det)]
|
||||
|
||||
(gmt/matrix (+ (* ma0 mb0)
|
||||
(* ma1 mb3)
|
||||
(* ma2 mb6))
|
||||
(+ (* ma3 mb0)
|
||||
(* ma4 mb3)
|
||||
(* ma5 mb6))
|
||||
(+ (* ma0 mb1)
|
||||
(* ma1 mb4)
|
||||
(* ma2 mb7))
|
||||
(+ (* ma3 mb1)
|
||||
(* ma4 mb4)
|
||||
(* ma5 mb7))
|
||||
(+ (* ma0 mb2)
|
||||
(* ma1 mb5)
|
||||
(* ma2 mb8))
|
||||
(+ (* ma3 mb2)
|
||||
(* ma4 mb5)
|
||||
(* ma5 mb8)))))))
|
||||
(gmt/matrix (+ (* ma0 mb0)
|
||||
(* ma1 mb3)
|
||||
(* ma2 mb6))
|
||||
(+ (* ma3 mb0)
|
||||
(* ma4 mb3)
|
||||
(* ma5 mb6))
|
||||
(+ (* ma0 mb1)
|
||||
(* ma1 mb4)
|
||||
(* ma2 mb7))
|
||||
(+ (* ma3 mb1)
|
||||
(* ma4 mb4)
|
||||
(* ma5 mb7))
|
||||
(+ (* ma0 mb2)
|
||||
(* ma1 mb5)
|
||||
(* ma2 mb8))
|
||||
(+ (* ma3 mb2)
|
||||
(* ma4 mb5)
|
||||
(* ma5 mb8)))))))
|
||||
|
||||
(defn calculate-selrect
|
||||
[points center]
|
||||
|
||||
@ -239,7 +239,7 @@
|
||||
#?(:clj
|
||||
(defn slf4j-log-handler
|
||||
{:no-doc true}
|
||||
[_ _ _ {:keys [::logger ::level ::trace ::message] }]
|
||||
[_ _ _ {:keys [::logger ::level ::trace ::message]}]
|
||||
(when-let [logger (enabled? logger level)]
|
||||
(let [message (cond-> @message
|
||||
(some? trace)
|
||||
@ -312,8 +312,8 @@
|
||||
(let [cljs? (:ns &env)]
|
||||
`(do
|
||||
(~(if cljs?
|
||||
`(partial console-log-handler nil nil nil)
|
||||
`(partial slf4j-log-handler nil nil nil))
|
||||
`(partial console-log-handler nil nil nil)
|
||||
`(partial slf4j-log-handler nil nil nil))
|
||||
{::logger ~(str *ns*)
|
||||
::level ~level
|
||||
::message (delay ~message)})
|
||||
|
||||
@ -44,11 +44,11 @@
|
||||
"Determine a scale factor and unit for displaying a time."
|
||||
[measurement]
|
||||
(cond
|
||||
(> measurement 60) [(/ 60) "min"]
|
||||
(< measurement 1e-6) [1e9 "ns"]
|
||||
(< measurement 1e-3) [1e6 "µs"]
|
||||
(< measurement 1) [1e3 "ms"]
|
||||
:else [1 "sec"]))
|
||||
(> measurement 60) [(/ 60) "min"]
|
||||
(< measurement 1e-6) [1e9 "ns"]
|
||||
(< measurement 1e-3) [1e6 "µs"]
|
||||
(< measurement 1) [1e3 "ms"]
|
||||
:else [1 "sec"]))
|
||||
|
||||
(defn format-time
|
||||
[value]
|
||||
|
||||
@ -51,52 +51,52 @@
|
||||
['cljs.core/IRecord
|
||||
'cljs.core/ICloneable
|
||||
`(~'-clone [~this-sym]
|
||||
(new ~tagname ~@(generate-field-access this-sym val-sym fields)))
|
||||
(new ~tagname ~@(generate-field-access this-sym val-sym fields)))
|
||||
|
||||
'cljs.core/IHash
|
||||
`(~'-hash [~this-sym]
|
||||
(caching-hash ~this-sym
|
||||
(fn [coll#]
|
||||
(bit-xor
|
||||
~(hash (str tagname))
|
||||
(cljs.core/hash-unordered-coll coll#)))
|
||||
(. ~this-sym ~'-$hash)))
|
||||
(caching-hash ~this-sym
|
||||
(fn [coll#]
|
||||
(bit-xor
|
||||
~(hash (str tagname))
|
||||
(cljs.core/hash-unordered-coll coll#)))
|
||||
(. ~this-sym ~'-$hash)))
|
||||
|
||||
'cljs.core/IEquiv
|
||||
`(~'-equiv [~this-sym ~othr-sym]
|
||||
(or (identical? ~this-sym ~othr-sym)
|
||||
(and (some? ~othr-sym)
|
||||
(identical? (.-constructor ~this-sym)
|
||||
(.-constructor ~othr-sym))
|
||||
~@(map (fn [field]
|
||||
`(= (.. ~this-sym ~(property-symbol field))
|
||||
(.. ~(with-meta othr-sym {:tag tagname}) ~(property-symbol field))))
|
||||
base-fields)
|
||||
(or (identical? ~this-sym ~othr-sym)
|
||||
(and (some? ~othr-sym)
|
||||
(identical? (.-constructor ~this-sym)
|
||||
(.-constructor ~othr-sym))
|
||||
~@(map (fn [field]
|
||||
`(= (.. ~this-sym ~(property-symbol field))
|
||||
(.. ~(with-meta othr-sym {:tag tagname}) ~(property-symbol field))))
|
||||
base-fields)
|
||||
|
||||
(= (. ~this-sym ~'-$extmap)
|
||||
(. ~(with-meta othr-sym {:tag tagname}) ~'-$extmap)))))
|
||||
(= (. ~this-sym ~'-$extmap)
|
||||
(. ~(with-meta othr-sym {:tag tagname}) ~'-$extmap)))))
|
||||
|
||||
`ICustomRecordEquiv
|
||||
`(~'-equiv-with-exceptions [~this-sym ~othr-sym ~'exceptions]
|
||||
(or (identical? ~this-sym ~othr-sym)
|
||||
(and (some? ~othr-sym)
|
||||
(identical? (.-constructor ~this-sym)
|
||||
(.-constructor ~othr-sym))
|
||||
(and ~@(->> base-fields
|
||||
(map (fn [field]
|
||||
`(= (.. ~this-sym ~(property-symbol field))
|
||||
(.. ~(with-meta othr-sym {:tag tagname}) ~(property-symbol field))))))
|
||||
(== (count (. ~this-sym ~'-$extmap))
|
||||
(count (. ~othr-sym ~'-$extmap))))
|
||||
(or (identical? ~this-sym ~othr-sym)
|
||||
(and (some? ~othr-sym)
|
||||
(identical? (.-constructor ~this-sym)
|
||||
(.-constructor ~othr-sym))
|
||||
(and ~@(->> base-fields
|
||||
(map (fn [field]
|
||||
`(= (.. ~this-sym ~(property-symbol field))
|
||||
(.. ~(with-meta othr-sym {:tag tagname}) ~(property-symbol field))))))
|
||||
(== (count (. ~this-sym ~'-$extmap))
|
||||
(count (. ~othr-sym ~'-$extmap))))
|
||||
|
||||
(reduce-kv (fn [~'_ ~'k ~'v]
|
||||
(if (contains? ~'exceptions ~'k)
|
||||
true
|
||||
(if (= (get (. ~this-sym ~'-$extmap) ~'k ::not-exists) ~'v)
|
||||
true
|
||||
(reduced false))))
|
||||
true
|
||||
(. ~othr-sym ~'-$extmap)))))
|
||||
(reduce-kv (fn [~'_ ~'k ~'v]
|
||||
(if (contains? ~'exceptions ~'k)
|
||||
true
|
||||
(if (= (get (. ~this-sym ~'-$extmap) ~'k ::not-exists) ~'v)
|
||||
true
|
||||
(reduced false))))
|
||||
true
|
||||
(. ~othr-sym ~'-$extmap)))))
|
||||
|
||||
|
||||
'cljs.core/IMeta
|
||||
@ -104,98 +104,98 @@
|
||||
|
||||
'cljs.core/IWithMeta
|
||||
`(~'-with-meta [~this-sym ~val-sym]
|
||||
(new ~tagname ~@(->> (replace {'$meta val-sym} fields)
|
||||
(generate-field-access this-sym val-sym))))
|
||||
(new ~tagname ~@(->> (replace {'$meta val-sym} fields)
|
||||
(generate-field-access this-sym val-sym))))
|
||||
|
||||
'cljs.core/ILookup
|
||||
`(~'-lookup [~this-sym k#]
|
||||
(cljs.core/-lookup ~this-sym k# nil))
|
||||
(cljs.core/-lookup ~this-sym k# nil))
|
||||
|
||||
`(~'-lookup [~this-sym ~key-sym else#]
|
||||
(case ~key-sym
|
||||
~@(mapcat (fn [f] [(keyword f) `(. ~this-sym ~(property-symbol f))])
|
||||
base-fields)
|
||||
(cljs.core/get (. ~this-sym ~'-$extmap) ~key-sym else#)))
|
||||
(case ~key-sym
|
||||
~@(mapcat (fn [f] [(keyword f) `(. ~this-sym ~(property-symbol f))])
|
||||
base-fields)
|
||||
(cljs.core/get (. ~this-sym ~'-$extmap) ~key-sym else#)))
|
||||
|
||||
'cljs.core/ICounted
|
||||
`(~'-count [~this-sym]
|
||||
(+ ~(count base-fields) (count (. ~this-sym ~'-$extmap))))
|
||||
(+ ~(count base-fields) (count (. ~this-sym ~'-$extmap))))
|
||||
|
||||
'cljs.core/ICollection
|
||||
`(~'-conj [~this-sym ~val-sym]
|
||||
(if (vector? ~val-sym)
|
||||
(cljs.core/-assoc ~this-sym (cljs.core/-nth ~val-sym 0) (cljs.core/-nth ~val-sym 1))
|
||||
(reduce cljs.core/-conj ~this-sym ~val-sym)))
|
||||
(if (vector? ~val-sym)
|
||||
(cljs.core/-assoc ~this-sym (cljs.core/-nth ~val-sym 0) (cljs.core/-nth ~val-sym 1))
|
||||
(reduce cljs.core/-conj ~this-sym ~val-sym)))
|
||||
|
||||
'cljs.core/IAssociative
|
||||
`(~'-contains-key? [~this-sym ~key-sym]
|
||||
~(if (seq base-fields)
|
||||
`(case ~key-sym
|
||||
(~@(map keyword base-fields)) true
|
||||
(contains? (. ~this-sym ~'-$extmap) ~key-sym))
|
||||
`(contains? (. ~this-sym ~'-$extmap) ~key-sym)))
|
||||
~(if (seq base-fields)
|
||||
`(case ~key-sym
|
||||
(~@(map keyword base-fields)) true
|
||||
(contains? (. ~this-sym ~'-$extmap) ~key-sym))
|
||||
`(contains? (. ~this-sym ~'-$extmap) ~key-sym)))
|
||||
|
||||
`(~'-assoc [~this-sym ~key-sym ~val-sym]
|
||||
(case ~key-sym
|
||||
~@(mapcat (fn [fld]
|
||||
[(keyword fld) `(new ~tagname ~@(->> (replace {fld val-sym '$hash nil} fields)
|
||||
(generate-field-access this-sym val-sym)))])
|
||||
base-fields)
|
||||
(new ~tagname ~@(->> (remove #{'$extmap '$hash} fields)
|
||||
(generate-field-access this-sym val-sym))
|
||||
(assoc (. ~this-sym ~'-$extmap) ~key-sym ~val-sym) nil)))
|
||||
(case ~key-sym
|
||||
~@(mapcat (fn [fld]
|
||||
[(keyword fld) `(new ~tagname ~@(->> (replace {fld val-sym '$hash nil} fields)
|
||||
(generate-field-access this-sym val-sym)))])
|
||||
base-fields)
|
||||
(new ~tagname ~@(->> (remove #{'$extmap '$hash} fields)
|
||||
(generate-field-access this-sym val-sym))
|
||||
(assoc (. ~this-sym ~'-$extmap) ~key-sym ~val-sym) nil)))
|
||||
|
||||
'cljs.core/ITransientAssociative
|
||||
`(~'-assoc! [~this-sym ~key-sym ~val-sym]
|
||||
(let [key# (if (keyword? ~key-sym)
|
||||
(.-fqn ~(with-meta key-sym {:tag `cljs.core/Keyword}))
|
||||
~key-sym)]
|
||||
(case ~key-sym
|
||||
~@(mapcat
|
||||
(fn [f]
|
||||
[(keyword f) `(set! (. ~this-sym ~(property-symbol f)) ~val-sym)])
|
||||
base-fields)
|
||||
(let [key# (if (keyword? ~key-sym)
|
||||
(.-fqn ~(with-meta key-sym {:tag `cljs.core/Keyword}))
|
||||
~key-sym)]
|
||||
(case ~key-sym
|
||||
~@(mapcat
|
||||
(fn [f]
|
||||
[(keyword f) `(set! (. ~this-sym ~(property-symbol f)) ~val-sym)])
|
||||
base-fields)
|
||||
|
||||
(set! (. ~this-sym ~'-$extmap) (cljs.core/assoc (. ~this-sym ~'-$extmap) ~key-sym ~val-sym)))
|
||||
(set! (. ~this-sym ~'-$extmap) (cljs.core/assoc (. ~this-sym ~'-$extmap) ~key-sym ~val-sym)))
|
||||
|
||||
~this-sym))
|
||||
~this-sym))
|
||||
|
||||
'cljs.core/IMap
|
||||
`(~'-dissoc [~this-sym ~key-sym]
|
||||
(case ~key-sym
|
||||
(~@(map keyword base-fields))
|
||||
(cljs.core/-assoc ~this-sym ~key-sym nil)
|
||||
(case ~key-sym
|
||||
(~@(map keyword base-fields))
|
||||
(cljs.core/-assoc ~this-sym ~key-sym nil)
|
||||
|
||||
(let [extmap1# (. ~this-sym ~'-$extmap)
|
||||
extmap2# (dissoc extmap1# ~key-sym)]
|
||||
(if (identical? extmap1# extmap2#)
|
||||
~this-sym
|
||||
(new ~tagname ~@(->> (remove #{'$extmap '$hash} fields)
|
||||
(generate-field-access this-sym val-sym))
|
||||
(not-empty extmap2#)
|
||||
nil)))))
|
||||
(let [extmap1# (. ~this-sym ~'-$extmap)
|
||||
extmap2# (dissoc extmap1# ~key-sym)]
|
||||
(if (identical? extmap1# extmap2#)
|
||||
~this-sym
|
||||
(new ~tagname ~@(->> (remove #{'$extmap '$hash} fields)
|
||||
(generate-field-access this-sym val-sym))
|
||||
(not-empty extmap2#)
|
||||
nil)))))
|
||||
|
||||
'cljs.core/ISeqable
|
||||
`(~'-seq [~this-sym]
|
||||
(seq (concat [~@(map (fn [f]
|
||||
`(cljs.core/MapEntry.
|
||||
~(keyword f)
|
||||
(. ~this-sym ~(property-symbol f))
|
||||
nil))
|
||||
base-fields)]
|
||||
(. ~this-sym ~'-$extmap))))
|
||||
(seq (concat [~@(map (fn [f]
|
||||
`(cljs.core/MapEntry.
|
||||
~(keyword f)
|
||||
(. ~this-sym ~(property-symbol f))
|
||||
nil))
|
||||
base-fields)]
|
||||
(. ~this-sym ~'-$extmap))))
|
||||
|
||||
'cljs.core/IIterable
|
||||
`(~'-iterator [~this-sym]
|
||||
(cljs.core/RecordIter. 0 ~this-sym ~(count base-fields)
|
||||
[~@(map keyword base-fields)]
|
||||
(if (. ~this-sym ~'-$extmap)
|
||||
(cljs.core/-iterator (. ~this-sym ~'-$extmap))
|
||||
(cljs.core/nil-iter))))
|
||||
(cljs.core/RecordIter. 0 ~this-sym ~(count base-fields)
|
||||
[~@(map keyword base-fields)]
|
||||
(if (. ~this-sym ~'-$extmap)
|
||||
(cljs.core/-iterator (. ~this-sym ~'-$extmap))
|
||||
(cljs.core/nil-iter))))
|
||||
|
||||
'cljs.core/IKVReduce
|
||||
`(~'-kv-reduce [~this-sym f# init#]
|
||||
(reduce (fn [ret# [~key-sym v#]] (f# ret# ~key-sym v#)) init# ~this-sym))])))
|
||||
(reduce (fn [ret# [~key-sym v#]] (f# ret# ~key-sym v#)) init# ~this-sym))])))
|
||||
|
||||
#?(:clj
|
||||
(defn emit-impl-jvm
|
||||
@ -208,144 +208,143 @@
|
||||
['clojure.lang.IRecord
|
||||
'clojure.lang.IPersistentMap
|
||||
`(~'equiv [~this-sym ~val-sym]
|
||||
(and (some? ~val-sym)
|
||||
(instance? ~tagname ~val-sym)
|
||||
~@(map (fn [field]
|
||||
`(= (.. ~this-sym ~(property-symbol field))
|
||||
(.. ~(with-meta val-sym {:tag tagname}) ~(property-symbol field))))
|
||||
base-fields)
|
||||
(= (. ~this-sym ~'-$extmap)
|
||||
(. ~(with-meta val-sym {:tag tagname}) ~'-$extmap))))
|
||||
(and (some? ~val-sym)
|
||||
(instance? ~tagname ~val-sym)
|
||||
~@(map (fn [field]
|
||||
`(= (.. ~this-sym ~(property-symbol field))
|
||||
(.. ~(with-meta val-sym {:tag tagname}) ~(property-symbol field))))
|
||||
base-fields)
|
||||
(= (. ~this-sym ~'-$extmap)
|
||||
(. ~(with-meta val-sym {:tag tagname}) ~'-$extmap))))
|
||||
|
||||
`(~'entryAt [~this-sym ~key-sym]
|
||||
(let [v# (.valAt ~this-sym ~key-sym ::not-found)]
|
||||
(when (not= v# ::not-found)
|
||||
(clojure.lang.MapEntry. ~key-sym v#))))
|
||||
(let [v# (.valAt ~this-sym ~key-sym ::not-found)]
|
||||
(when (not= v# ::not-found)
|
||||
(clojure.lang.MapEntry. ~key-sym v#))))
|
||||
|
||||
`(~'valAt [~this-sym ~key-sym]
|
||||
(.valAt ~this-sym ~key-sym nil))
|
||||
(.valAt ~this-sym ~key-sym nil))
|
||||
|
||||
`(~'valAt [~this-sym ~key-sym ~'not-found]
|
||||
(case ~key-sym
|
||||
~@(mapcat (fn [f] [(keyword f) `(. ~this-sym ~(property-symbol f))]) base-fields)
|
||||
(clojure.core/get (. ~this-sym ~'-$extmap) ~key-sym ~'not-found)))
|
||||
(case ~key-sym
|
||||
~@(mapcat (fn [f] [(keyword f) `(. ~this-sym ~(property-symbol f))]) base-fields)
|
||||
(clojure.core/get (. ~this-sym ~'-$extmap) ~key-sym ~'not-found)))
|
||||
|
||||
`(~'count [~this-sym]
|
||||
(+ ~(count base-fields) (count (. ~this-sym ~'-$extmap))))
|
||||
(+ ~(count base-fields) (count (. ~this-sym ~'-$extmap))))
|
||||
|
||||
|
||||
`(~'empty [~this-sym]
|
||||
(new ~tagname ~@(->> (remove #{'$extmap '$hash} fields)
|
||||
(generate-field-access this-sym nil))
|
||||
nil nil))
|
||||
(new ~tagname ~@(->> (remove #{'$extmap '$hash} fields)
|
||||
(generate-field-access this-sym nil))
|
||||
nil nil))
|
||||
|
||||
`(~'cons [~this-sym ~val-sym]
|
||||
(if (instance? java.util.Map$Entry ~val-sym)
|
||||
(let [^Map$Entry e# ~val-sym]
|
||||
(.assoc ~this-sym (.getKey e#) (.getValue e#)))
|
||||
(if (instance? clojure.lang.IPersistentVector ~val-sym)
|
||||
(if (= 2 (count ~val-sym))
|
||||
(.assoc ~this-sym (nth ~val-sym 0) (nth ~val-sym 1))
|
||||
(throw (IllegalArgumentException.
|
||||
"Vector arg to map conj must be a pair")))
|
||||
(reduce (fn [^clojure.lang.IPersistentMap m#
|
||||
^java.util.Map$Entry e#]
|
||||
(.assoc m# (.getKey e#) (.getValue e#)))
|
||||
~this-sym
|
||||
~val-sym))))
|
||||
(if (instance? java.util.Map$Entry ~val-sym)
|
||||
(let [^Map$Entry e# ~val-sym]
|
||||
(.assoc ~this-sym (.getKey e#) (.getValue e#)))
|
||||
(if (instance? clojure.lang.IPersistentVector ~val-sym)
|
||||
(if (= 2 (count ~val-sym))
|
||||
(.assoc ~this-sym (nth ~val-sym 0) (nth ~val-sym 1))
|
||||
(throw (IllegalArgumentException.
|
||||
"Vector arg to map conj must be a pair")))
|
||||
(reduce (fn [^clojure.lang.IPersistentMap m#
|
||||
^java.util.Map$Entry e#]
|
||||
(.assoc m# (.getKey e#) (.getValue e#)))
|
||||
~this-sym
|
||||
~val-sym))))
|
||||
|
||||
`(~'assoc [~this-sym ~key-sym ~val-sym]
|
||||
(case ~key-sym
|
||||
~@(mapcat (fn [fld]
|
||||
[(keyword fld) `(new ~tagname ~@(->> (replace {fld val-sym '$hash nil} fields)
|
||||
(generate-field-access this-sym val-sym)))])
|
||||
base-fields)
|
||||
(new ~tagname ~@(->> (remove #{'$extmap '$hash} fields)
|
||||
(generate-field-access this-sym val-sym))
|
||||
(assoc (. ~this-sym ~'-$extmap) ~key-sym ~val-sym)
|
||||
nil)))
|
||||
(case ~key-sym
|
||||
~@(mapcat (fn [fld]
|
||||
[(keyword fld) `(new ~tagname ~@(->> (replace {fld val-sym '$hash nil} fields)
|
||||
(generate-field-access this-sym val-sym)))])
|
||||
base-fields)
|
||||
(new ~tagname ~@(->> (remove #{'$extmap '$hash} fields)
|
||||
(generate-field-access this-sym val-sym))
|
||||
(assoc (. ~this-sym ~'-$extmap) ~key-sym ~val-sym)
|
||||
nil)))
|
||||
|
||||
`(~'without [~this-sym ~key-sym]
|
||||
(case ~key-sym
|
||||
(~@(map keyword base-fields))
|
||||
(.assoc ~this-sym ~key-sym nil)
|
||||
(case ~key-sym
|
||||
(~@(map keyword base-fields))
|
||||
(.assoc ~this-sym ~key-sym nil)
|
||||
|
||||
(if-let [extmap1# (. ~this-sym ~'-$extmap)]
|
||||
(let [extmap2# (.without ^clojure.lang.IPersistentMap extmap1# ~key-sym)]
|
||||
(if (identical? extmap1# extmap2#)
|
||||
~this-sym
|
||||
(new ~tagname ~@(->> (remove #{'$extmap '$hash} fields)
|
||||
(generate-field-access this-sym val-sym))
|
||||
(not-empty extmap2#)
|
||||
nil)))
|
||||
~this-sym)))
|
||||
(if-let [extmap1# (. ~this-sym ~'-$extmap)]
|
||||
(let [extmap2# (.without ^clojure.lang.IPersistentMap extmap1# ~key-sym)]
|
||||
(if (identical? extmap1# extmap2#)
|
||||
~this-sym
|
||||
(new ~tagname ~@(->> (remove #{'$extmap '$hash} fields)
|
||||
(generate-field-access this-sym val-sym))
|
||||
(not-empty extmap2#)
|
||||
nil)))
|
||||
~this-sym)))
|
||||
|
||||
`(~'seq [~this-sym]
|
||||
(seq (concat [~@(map (fn [f]
|
||||
`(clojure.lang.MapEntry/create
|
||||
~(keyword f)
|
||||
(. ~this-sym ~(property-symbol f))))
|
||||
base-fields)]
|
||||
(. ~this-sym ~'-$extmap))))
|
||||
(seq (concat [~@(map (fn [f]
|
||||
`(clojure.lang.MapEntry/create
|
||||
~(keyword f)
|
||||
(. ~this-sym ~(property-symbol f))))
|
||||
base-fields)]
|
||||
(. ~this-sym ~'-$extmap))))
|
||||
|
||||
`(~'iterator [~this-sym]
|
||||
(clojure.lang.SeqIterator. (.seq ~this-sym)))
|
||||
(clojure.lang.SeqIterator. (.seq ~this-sym)))
|
||||
|
||||
'clojure.lang.IFn
|
||||
`(~'invoke [~this-sym ~key-sym]
|
||||
(.valAt ~this-sym ~key-sym))
|
||||
(.valAt ~this-sym ~key-sym))
|
||||
|
||||
`(~'invoke [~this-sym ~key-sym ~'not-found]
|
||||
(.valAt ~this-sym ~key-sym ~'not-found))
|
||||
(.valAt ~this-sym ~key-sym ~'not-found))
|
||||
|
||||
'java.util.Map
|
||||
`(~'size [~this-sym]
|
||||
(clojure.core/count ~this-sym))
|
||||
(clojure.core/count ~this-sym))
|
||||
|
||||
`(~'containsKey [~this-sym ~key-sym]
|
||||
~(if (seq base-fields)
|
||||
`(case ~key-sym
|
||||
(~@(map keyword base-fields)) true
|
||||
(contains? (. ~this-sym ~'-$extmap) ~key-sym))
|
||||
`(contains? (. ~this-sym ~'-$extmap) ~key-sym)))
|
||||
~(if (seq base-fields)
|
||||
`(case ~key-sym
|
||||
(~@(map keyword base-fields)) true
|
||||
(contains? (. ~this-sym ~'-$extmap) ~key-sym))
|
||||
`(contains? (. ~this-sym ~'-$extmap) ~key-sym)))
|
||||
|
||||
`(~'isEmpty [~this-sym]
|
||||
(zero? (count ~this-sym)))
|
||||
(zero? (count ~this-sym)))
|
||||
|
||||
`(~'keySet [~this-sym]
|
||||
(throw (UnsupportedOperationException. "not implemented")))
|
||||
(throw (UnsupportedOperationException. "not implemented")))
|
||||
|
||||
`(~'entrySet [~this-sym]
|
||||
(throw (UnsupportedOperationException. "not implemented")))
|
||||
(throw (UnsupportedOperationException. "not implemented")))
|
||||
|
||||
`(~'get [~this-sym ~key-sym]
|
||||
(.valAt ~this-sym ~key-sym))
|
||||
(.valAt ~this-sym ~key-sym))
|
||||
|
||||
`(~'containsValue [~this-sym ~val-sym]
|
||||
(throw (UnsupportedOperationException. "not implemented")))
|
||||
(throw (UnsupportedOperationException. "not implemented")))
|
||||
|
||||
`(~'values [~this-sym]
|
||||
(map val (.seq ~this-sym)))
|
||||
(map val (.seq ~this-sym)))
|
||||
|
||||
'java.lang.Object
|
||||
`(~'equals [~this-sym other#]
|
||||
(.equiv ~this-sym other#))
|
||||
(.equiv ~this-sym other#))
|
||||
|
||||
`(~'hashCode [~this-sym]
|
||||
(clojure.lang.APersistentMap/mapHash ~this-sym))
|
||||
(clojure.lang.APersistentMap/mapHash ~this-sym))
|
||||
|
||||
'clojure.lang.IHashEq
|
||||
`(~'hasheq [~this-sym]
|
||||
(clojure.core/hash-unordered-coll ~this-sym))
|
||||
(clojure.core/hash-unordered-coll ~this-sym))
|
||||
|
||||
'clojure.lang.IObj
|
||||
`(~'meta [~this-sym]
|
||||
(. ~this-sym ~'-$meta))
|
||||
(. ~this-sym ~'-$meta))
|
||||
|
||||
`(~'withMeta [~this-sym ~val-sym]
|
||||
(new ~tagname ~@(->> (replace {'$meta val-sym} fields)
|
||||
(generate-field-access this-sym val-sym))))
|
||||
])))
|
||||
(new ~tagname ~@(->> (replace {'$meta val-sym} fields)
|
||||
(generate-field-access this-sym val-sym))))])))
|
||||
|
||||
(defmacro defrecord
|
||||
[rsym fields & impls]
|
||||
@ -367,14 +366,14 @@
|
||||
~@(when (:ns &env)
|
||||
['cljs.core/IPrintWithWriter
|
||||
`(~'-pr-writer [~'this writer# opts#]
|
||||
(let [pr-pair# (fn [keyval#]
|
||||
(cljs.core/pr-sequential-writer writer# (~'js* "cljs.core.pr_writer")
|
||||
"" " " "" opts# keyval#))]
|
||||
(cljs.core/pr-sequential-writer
|
||||
writer# pr-pair# ~(str ident "{") ", " "}" opts#
|
||||
(concat [~@(for [f fields']
|
||||
`(vector ~(keyword f) (. ~'this ~(property-symbol f))))]
|
||||
(. ~'this ~'-$extmap)))))]))
|
||||
(let [pr-pair# (fn [keyval#]
|
||||
(cljs.core/pr-sequential-writer writer# (~'js* "cljs.core.pr_writer")
|
||||
"" " " "" opts# keyval#))]
|
||||
(cljs.core/pr-sequential-writer
|
||||
writer# pr-pair# ~(str ident "{") ", " "}" opts#
|
||||
(concat [~@(for [f fields']
|
||||
`(vector ~(keyword f) (. ~'this ~(property-symbol f))))]
|
||||
(. ~'this ~'-$extmap)))))]))
|
||||
|
||||
~@(when-not (:ns &env)
|
||||
[`(defmethod print-method ~rsym [o# ^java.io.Writer w#]
|
||||
|
||||
@ -122,9 +122,7 @@
|
||||
:encoders (mt/-string-encoders)}
|
||||
{:name :collections
|
||||
:decoders coders
|
||||
:encoders coders}
|
||||
|
||||
)))
|
||||
:encoders coders})))
|
||||
|
||||
(defn validator
|
||||
[s]
|
||||
@ -304,7 +302,7 @@
|
||||
options (into {:type :validation
|
||||
:code :data-validation
|
||||
::explain explain}
|
||||
options)
|
||||
options)
|
||||
hint (get options :hint "schema validation error")]
|
||||
(throw (ex-info hint options)))))))
|
||||
|
||||
|
||||
@ -169,15 +169,14 @@
|
||||
(map (fn [[k _ s]]
|
||||
(str (pad " " level) (str/camel k)
|
||||
(when (contains? optional k) "?")
|
||||
": " s )))
|
||||
": " s)))
|
||||
(str/join ",\n"))
|
||||
|
||||
header (cond-> (if (zero? level)
|
||||
(str "type " title)
|
||||
(str title))
|
||||
closed? (str "!")
|
||||
(some? title) (str " ")
|
||||
)]
|
||||
(some? title) (str " "))]
|
||||
|
||||
(str header "{\n" entries "\n" (pad "}" level))))))
|
||||
|
||||
|
||||
@ -74,17 +74,17 @@
|
||||
(defn word-string
|
||||
[]
|
||||
(->> (tg/such-that #(re-matches #"\w+" %)
|
||||
tg/string-alphanumeric
|
||||
50)
|
||||
tg/string-alphanumeric
|
||||
50)
|
||||
(tg/such-that (complement str/blank?))))
|
||||
|
||||
(defn uri
|
||||
[]
|
||||
(tg/let [scheme (tg/elements ["http" "https"])
|
||||
domain (as-> (word-string) $
|
||||
(tg/such-that (fn [x] (> (count x) 5)) $ 100)
|
||||
(tg/fmap str/lower $))
|
||||
ext (tg/elements ["net" "com" "org" "app" "io"])]
|
||||
domain (as-> (word-string) $
|
||||
(tg/such-that (fn [x] (> (count x) 5)) $ 100)
|
||||
(tg/fmap str/lower $))
|
||||
ext (tg/elements ["net" "com" "org" "app" "io"])]
|
||||
(u/uri (str scheme "://" domain "." ext))))
|
||||
|
||||
(defn uuid
|
||||
@ -102,11 +102,11 @@
|
||||
([dest elements]
|
||||
(->> (apply tg/tuple (repeat (count elements) tg/boolean))
|
||||
(tg/fmap (fn [bools]
|
||||
(into dest
|
||||
(comp
|
||||
(c/filter first)
|
||||
(c/map second))
|
||||
(c/map list bools elements)))))))
|
||||
(into dest
|
||||
(comp
|
||||
(c/filter first)
|
||||
(c/map second))
|
||||
(c/map list bools elements)))))))
|
||||
|
||||
(defn set
|
||||
[g]
|
||||
|
||||
@ -6,9 +6,9 @@
|
||||
|
||||
(ns app.common.svg
|
||||
(:require
|
||||
#?(:cljs ["./svg/optimizer.js" :as svgo])
|
||||
#?(:clj [clojure.xml :as xml]
|
||||
:cljs [tubax.core :as tubax])
|
||||
#?(:cljs ["./svg/optimizer.js" :as svgo])
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
@ -115,8 +115,7 @@
|
||||
:tspan
|
||||
:use
|
||||
:view
|
||||
:vkern
|
||||
})
|
||||
:vkern})
|
||||
|
||||
;; https://www.w3.org/TR/SVG11/attindex.html
|
||||
(def svg-attr-list
|
||||
@ -680,7 +679,7 @@
|
||||
;; Removed this warning because slows a lot rendering with big svgs
|
||||
#_(let [filtered-props (->> attrs (remove known-property?) (map first))]
|
||||
(when (seq filtered-props)
|
||||
(.warn js/console "Unknown properties: " (str/join ", " filtered-props ))))
|
||||
(.warn js/console "Unknown properties: " (str/join ", " filtered-props))))
|
||||
|
||||
(into {}
|
||||
(comp (filter known-property?)
|
||||
@ -740,7 +739,7 @@
|
||||
|
||||
node-defs (->> rec-result (map first) (reduce merge current-node-defs))]
|
||||
|
||||
[ node-defs node ])))
|
||||
[node-defs node])))
|
||||
|
||||
(defn find-attr-references [attrs]
|
||||
(->> attrs
|
||||
@ -1048,7 +1047,7 @@
|
||||
(conj {:href (or (:href attrs) (:xlink:href attrs))
|
||||
:width (d/parse-integer (:width attrs) 0)
|
||||
:height (d/parse-integer (:height attrs) 0)})))]
|
||||
(reduce-nodes redfn [] svg-data )))
|
||||
(reduce-nodes redfn [] svg-data)))
|
||||
|
||||
#?(:clj
|
||||
(defn- secure-parser-factory
|
||||
|
||||
@ -292,8 +292,8 @@
|
||||
(let [;; We need to reverse the second path when making a difference/intersection/exclude
|
||||
;; and both shapes are in the same direction
|
||||
should-reverse? (and (not= :union bool-type)
|
||||
(= (ups/clockwise? content-b)
|
||||
(ups/clockwise? content-a)))
|
||||
(= (ups/clockwise? content-b)
|
||||
(ups/clockwise? content-a)))
|
||||
|
||||
content-a (-> content-a
|
||||
(close-paths)
|
||||
|
||||
@ -159,8 +159,8 @@
|
||||
point->handlers (content->handlers content)
|
||||
|
||||
handlers (->> point
|
||||
(point->handlers )
|
||||
(filter (fn [[ci cp]] (and (not= index ci) (not= prefix cp)) )))]
|
||||
(point->handlers)
|
||||
(filter (fn [[ci cp]] (and (not= index ci) (not= prefix cp)))))]
|
||||
|
||||
(cond
|
||||
(= (count handlers) 1)
|
||||
|
||||
@ -107,8 +107,7 @@
|
||||
[:c2x :number]
|
||||
[:c2y :number]
|
||||
[:x :number]
|
||||
[:y :number]])
|
||||
]
|
||||
[:y :number]])]
|
||||
(for [params param-list]
|
||||
{:command :curve-to
|
||||
:relative relative
|
||||
@ -228,7 +227,7 @@
|
||||
(d/update-in-when [:params :y] + (:y prev-pos))
|
||||
|
||||
(cond->
|
||||
(= :line-to-horizontal (:command command))
|
||||
(= :line-to-horizontal (:command command))
|
||||
(d/update-in-when [:params :value] + (:x prev-pos))
|
||||
|
||||
(= :line-to-vertical (:command command))
|
||||
|
||||
@ -132,8 +132,7 @@
|
||||
[:c2x :number]
|
||||
[:c2y :number]
|
||||
[:x :number]
|
||||
[:y :number]])
|
||||
]
|
||||
[:y :number]])]
|
||||
(for [params param-list]
|
||||
{:command :curve-to
|
||||
:relative relative
|
||||
@ -254,8 +253,7 @@
|
||||
|
||||
dtheta (unit-vector-angle v1x v1y v2x v2y)
|
||||
dtheta (if (and (= fs 0) (> dtheta 0)) (- dtheta (* mth/PI 2)) dtheta)
|
||||
dtheta (if (and (= fs 1) (< dtheta 0)) (+ dtheta (* mth/PI 2)) dtheta)
|
||||
]
|
||||
dtheta (if (and (= fs 1) (< dtheta 0)) (+ dtheta (* mth/PI 2)) dtheta)]
|
||||
|
||||
[cx cy theta1 dtheta]))
|
||||
|
||||
@ -302,8 +300,7 @@
|
||||
(and (zero? rx)
|
||||
(zero? ry)))
|
||||
[]
|
||||
(let [
|
||||
rx (mth/abs rx)
|
||||
(let [rx (mth/abs rx)
|
||||
ry (mth/abs ry)
|
||||
lambda (+ (/ (* x1p x1p) (* rx rx))
|
||||
(/ (* y1p y1p) (* ry ry)))
|
||||
@ -380,7 +377,7 @@
|
||||
(d/update-in-when [:params :y] + (:y prev-pos))
|
||||
|
||||
(cond->
|
||||
(= :line-to-horizontal (:command command))
|
||||
(= :line-to-horizontal (:command command))
|
||||
(d/update-in-when [:params :value] + (:x prev-pos))
|
||||
|
||||
(= :line-to-vertical (:command command))
|
||||
|
||||
@ -273,29 +273,29 @@
|
||||
"Given a root node of a text content extracts the texts with its associated styles"
|
||||
[node]
|
||||
(letfn
|
||||
[(rec-style-text-map [acc node style]
|
||||
(let [node-style (merge style (select-keys node text-attrs))
|
||||
head (or (-> acc first) [{} ""])
|
||||
[head-style head-text] head
|
||||
[(rec-style-text-map [acc node style]
|
||||
(let [node-style (merge style (select-keys node text-attrs))
|
||||
head (or (-> acc first) [{} ""])
|
||||
[head-style head-text] head
|
||||
|
||||
new-acc
|
||||
(cond
|
||||
(:children node)
|
||||
(reduce #(rec-style-text-map %1 %2 node-style) acc (:children node))
|
||||
new-acc
|
||||
(cond
|
||||
(:children node)
|
||||
(reduce #(rec-style-text-map %1 %2 node-style) acc (:children node))
|
||||
|
||||
(not= head-style node-style)
|
||||
(cons [node-style (:text node "")] acc)
|
||||
(not= head-style node-style)
|
||||
(cons [node-style (:text node "")] acc)
|
||||
|
||||
:else
|
||||
(cons [node-style (dm/str head-text "" (:text node))] (rest acc)))
|
||||
:else
|
||||
(cons [node-style (dm/str head-text "" (:text node))] (rest acc)))
|
||||
|
||||
;; We add an end-of-line when finish a paragraph
|
||||
new-acc
|
||||
(if (= (:type node) "paragraph")
|
||||
(let [[hs ht] (first new-acc)]
|
||||
(cons [hs (dm/str ht "\n")] (rest new-acc)))
|
||||
new-acc)]
|
||||
new-acc))]
|
||||
new-acc
|
||||
(if (= (:type node) "paragraph")
|
||||
(let [[hs ht] (first new-acc)]
|
||||
(cons [hs (dm/str ht "\n")] (rest new-acc)))
|
||||
new-acc)]
|
||||
new-acc))]
|
||||
|
||||
(-> (rec-style-text-map [] node {})
|
||||
reverse)))
|
||||
|
||||
@ -6,14 +6,14 @@
|
||||
|
||||
(ns app.common.transit
|
||||
(:require
|
||||
#?(:clj [datoteka.fs :as fs])
|
||||
#?(:cljs ["luxon" :as lxn])
|
||||
[app.common.data :as d]
|
||||
[app.common.uri :as uri]
|
||||
[cognitect.transit :as t]
|
||||
[lambdaisland.uri :as luri]
|
||||
[linked.core :as lk]
|
||||
[linked.set :as lks]
|
||||
#?(:clj [datoteka.fs :as fs])
|
||||
#?(:cljs ["luxon" :as lxn]))
|
||||
[linked.set :as lks])
|
||||
#?(:clj
|
||||
(:import
|
||||
java.io.ByteArrayInputStream
|
||||
|
||||
@ -6,14 +6,14 @@
|
||||
|
||||
(ns app.common.types.color
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.openapi :as-alias oapi]
|
||||
[app.common.text :as txt]
|
||||
[app.common.types.color.generic :as-alias color-generic]
|
||||
[app.common.types.color.gradient :as-alias color-gradient]
|
||||
[app.common.types.color.gradient.stop :as-alias color-gradient-stop]
|
||||
[clojure.test.check.generators :as tgen]))
|
||||
[app.common.data :as d]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.openapi :as-alias oapi]
|
||||
[app.common.text :as txt]
|
||||
[app.common.types.color.generic :as-alias color-generic]
|
||||
[app.common.types.color.gradient :as-alias color-gradient]
|
||||
[app.common.types.color.gradient.stop :as-alias color-gradient-stop]
|
||||
[clojure.test.check.generators :as tgen]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; SCHEMAS
|
||||
|
||||
@ -87,10 +87,10 @@
|
||||
(get-component file-data component-id false))
|
||||
|
||||
([file-data component-id include-deleted?]
|
||||
(let [component (get-in file-data [:components component-id])]
|
||||
(when (or include-deleted?
|
||||
(not (:deleted component)))
|
||||
component))))
|
||||
(let [component (get-in file-data [:components component-id])]
|
||||
(when (or include-deleted?
|
||||
(not (:deleted component)))
|
||||
component))))
|
||||
|
||||
(defn get-deleted-component
|
||||
[file-data component-id]
|
||||
|
||||
@ -270,7 +270,7 @@
|
||||
(ctkl/update-component component-id #(dissoc % :objects))
|
||||
(ctkl/mark-component-undeleted component-id)
|
||||
(cond-> update-page?
|
||||
(ctkl/update-component component-id #(assoc % :main-instance-page page-id))))))
|
||||
(ctkl/update-component component-id #(assoc % :main-instance-page page-id))))))
|
||||
|
||||
(defn purge-component
|
||||
"Remove permanently a component."
|
||||
|
||||
@ -42,27 +42,27 @@
|
||||
;; * change-properties
|
||||
|
||||
(defrecord Modifiers
|
||||
[last-order ;; Last `order` attribute in the geometry list
|
||||
geometry-parent
|
||||
geometry-child
|
||||
structure-parent
|
||||
structure-child])
|
||||
[last-order ;; Last `order` attribute in the geometry list
|
||||
geometry-parent
|
||||
geometry-child
|
||||
structure-parent
|
||||
structure-child])
|
||||
|
||||
(defrecord GeometricOperation
|
||||
[order ;; Need the order to keep consistent between geometry-parent and geometry-child
|
||||
type
|
||||
vector
|
||||
origin
|
||||
transform
|
||||
transform-inverse
|
||||
rotation
|
||||
center])
|
||||
[order ;; Need the order to keep consistent between geometry-parent and geometry-child
|
||||
type
|
||||
vector
|
||||
origin
|
||||
transform
|
||||
transform-inverse
|
||||
rotation
|
||||
center])
|
||||
|
||||
(defrecord StructureOperation
|
||||
[type
|
||||
property
|
||||
value
|
||||
index])
|
||||
[type
|
||||
property
|
||||
value
|
||||
index])
|
||||
|
||||
;; Record constructors
|
||||
|
||||
@ -599,8 +599,8 @@
|
||||
"Transforms a matrix by the translation modifier"
|
||||
[matrix modifier]
|
||||
(-> (dm/get-prop modifier :vector)
|
||||
(gmt/translate-matrix)
|
||||
(gmt/multiply! matrix)))
|
||||
(gmt/translate-matrix)
|
||||
(gmt/multiply! matrix)))
|
||||
|
||||
|
||||
(defn transform-resize!
|
||||
@ -656,8 +656,7 @@
|
||||
[modifiers]
|
||||
(let [modifiers (concat (dm/get-prop modifiers :geometry-parent)
|
||||
(dm/get-prop modifiers :geometry-child))
|
||||
modifiers (sort-by #(dm/get-prop % :order) modifiers)
|
||||
]
|
||||
modifiers (sort-by #(dm/get-prop % :order) modifiers)]
|
||||
(modifiers->transform1 modifiers)))
|
||||
|
||||
(defn modifiers->transform-old
|
||||
|
||||
@ -194,8 +194,7 @@
|
||||
[:vector {:gen/max 1} ::ctss/shadow]]
|
||||
[:blur {:optional true} ::ctsb/blur]
|
||||
[:grow-type {:optional true}
|
||||
[::sm/one-of #{:auto-width :auto-height :fixed}]]
|
||||
])
|
||||
[::sm/one-of #{:auto-width :auto-height :fixed}]]])
|
||||
|
||||
(sm/define! ::group-attrs
|
||||
[:map {:title "GroupAttrs"}
|
||||
@ -351,8 +350,8 @@
|
||||
(defn has-images?
|
||||
[{:keys [fills strokes]}]
|
||||
(or
|
||||
(some :fill-image fills)
|
||||
(some :stroke-image strokes)))
|
||||
(some :fill-image fills)
|
||||
(some :stroke-image strokes)))
|
||||
|
||||
;; --- Initialization
|
||||
|
||||
|
||||
@ -270,7 +270,7 @@
|
||||
(defn has-destination
|
||||
[interaction]
|
||||
(#{:navigate :open-overlay :toggle-overlay :close-overlay}
|
||||
(:action-type interaction)))
|
||||
(:action-type interaction)))
|
||||
|
||||
(defn destination?
|
||||
[interaction]
|
||||
|
||||
@ -1054,7 +1054,7 @@
|
||||
(->> (cells-seq parent :sort? true)
|
||||
(reduce
|
||||
(fn [[parent auto?] cell]
|
||||
|
||||
|
||||
(let [[cell auto?]
|
||||
(cond
|
||||
(and (empty? (:shapes cell))
|
||||
@ -1067,7 +1067,7 @@
|
||||
(not= (:column-span cell) 1))
|
||||
(= :auto (:position cell)))
|
||||
[(assoc cell :position :manual) false]
|
||||
|
||||
|
||||
(empty? (:shapes cell))
|
||||
[cell false]
|
||||
|
||||
@ -1129,9 +1129,7 @@
|
||||
(defn assign-cells
|
||||
[parent objects]
|
||||
(prn ">assign-cells")
|
||||
(let [
|
||||
|
||||
parent (assign-cell-positions parent objects)
|
||||
(let [parent (assign-cell-positions parent objects)
|
||||
|
||||
shape-has-cell?
|
||||
(into #{} (mapcat (comp :shapes second)) (:layout-grid-cells parent))
|
||||
|
||||
@ -193,7 +193,7 @@
|
||||
|
||||
[base-id idx-a idx-b]))
|
||||
|
||||
(defn is-shape-over-shape?
|
||||
(defn- is-shape-over-shape?
|
||||
[objects base-shape-id over-shape-id bottom-frames?]
|
||||
|
||||
(let [[base-id index-a index-b] (get-base objects base-shape-id over-shape-id)]
|
||||
@ -211,14 +211,21 @@
|
||||
;; Check which index is lower
|
||||
:else
|
||||
;; If the base is a layout we should check if the z-index property is set
|
||||
(let [[z-index-a z-index-b]
|
||||
(if (ctl/any-layout? objects base-id)
|
||||
(let [layer-order? (ctl/any-layout? objects base-id)
|
||||
[z-index-a z-index-b]
|
||||
(if layer-order?
|
||||
[(ctl/layout-z-index objects (dm/get-in objects [base-id :shapes index-a]))
|
||||
(ctl/layout-z-index objects (dm/get-in objects [base-id :shapes index-b]))]
|
||||
[0 0])]
|
||||
|
||||
(if (= z-index-a z-index-b)
|
||||
(cond
|
||||
(and (= z-index-a z-index-b) (not layer-order?))
|
||||
(< index-a index-b)
|
||||
|
||||
(and (= z-index-a z-index-b) layer-order?)
|
||||
(> index-a index-b)
|
||||
|
||||
:else
|
||||
(< z-index-a z-index-b))))))
|
||||
|
||||
(defn sort-z-index
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
|
||||
(ns app.common.types.typography
|
||||
(:require
|
||||
[app.common.schema :as sm]
|
||||
[app.common.text :as txt]))
|
||||
[app.common.schema :as sm]
|
||||
[app.common.text :as txt]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; SCHEMA
|
||||
@ -44,8 +44,8 @@
|
||||
:content
|
||||
;; Check if any node in the content has a reference for the library
|
||||
(txt/node-seq
|
||||
#(and (some? (:typography-ref-id %))
|
||||
(= (:typography-ref-file %) library-id))))))
|
||||
#(and (some? (:typography-ref-id %))
|
||||
(= (:typography-ref-file %) library-id))))))
|
||||
|
||||
(defn uses-library-typography?
|
||||
"Check if the shape uses the given library typography."
|
||||
@ -55,8 +55,8 @@
|
||||
:content
|
||||
;; Check if any node in the content has a reference for the library
|
||||
(txt/node-seq
|
||||
#(and (= (:typography-ref-id %) typography-id)
|
||||
(= (:typography-ref-file %) library-id))))))
|
||||
#(and (= (:typography-ref-id %) typography-id)
|
||||
(= (:typography-ref-file %) library-id))))))
|
||||
|
||||
(defn remap-typographies
|
||||
"Change the shape so that any use of the given typography now points to
|
||||
|
||||
@ -8,10 +8,10 @@
|
||||
(ns app.common.uuid
|
||||
(:refer-clojure :exclude [next uuid zero? short])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
#?(:clj [clojure.core :as c])
|
||||
#?(:cljs [app.common.uuid-impl :as impl])
|
||||
#?(:cljs [cljs.core :as c]))
|
||||
#?(:cljs [cljs.core :as c])
|
||||
[app.common.data.macros :as dm])
|
||||
#?(:clj (:import
|
||||
app.common.UUIDv8
|
||||
java.util.UUID
|
||||
|
||||
@ -6,10 +6,10 @@
|
||||
|
||||
(ns common-tests.colors-test
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
#?(:cljs [goog.color :as gcolors])
|
||||
[app.common.colors :as colors]
|
||||
[clojure.test :as t]
|
||||
#?(:cljs [goog.color :as gcolors])))
|
||||
[app.common.data :as d]
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/deftest valid-hex-color
|
||||
(t/is (false? (colors/valid-hex-color? nil)))
|
||||
@ -18,16 +18,14 @@
|
||||
(t/is (false? (colors/valid-hex-color? "#qqqqqq")))
|
||||
(t/is (true? (colors/valid-hex-color? "#aaa")))
|
||||
(t/is (false? (colors/valid-hex-color? "#aaaa")))
|
||||
(t/is (true? (colors/valid-hex-color? "#fabada")))
|
||||
)
|
||||
(t/is (true? (colors/valid-hex-color? "#fabada"))))
|
||||
|
||||
(t/deftest valid-rgb-color
|
||||
(t/is (false? (colors/valid-rgb-color? nil)))
|
||||
(t/is (false? (colors/valid-rgb-color? "")))
|
||||
(t/is (false? (colors/valid-rgb-color? "()")))
|
||||
(t/is (true? (colors/valid-rgb-color? "(255, 30, 30)")))
|
||||
(t/is (true? (colors/valid-rgb-color? "rgb(255, 30, 30)")))
|
||||
)
|
||||
(t/is (true? (colors/valid-rgb-color? "rgb(255, 30, 30)"))))
|
||||
|
||||
(t/deftest rgb-to-str
|
||||
(t/is (= "rgb(1,2,3)" (colors/rgb->str [1 2 3])))
|
||||
@ -37,16 +35,14 @@
|
||||
;; (prn (colors/rgb->hsv [1 2 3]))
|
||||
;; (prn (gcolors/rgbToHsv 1 2 3))
|
||||
(t/is (= [210.0 0.6666666666666666 3.0] (colors/rgb->hsv [1.0 2.0 3.0])))
|
||||
#?(:cljs (t/is (= (colors/rgb->hsv [1 2 3]) (vec (gcolors/rgbToHsv 1 2 3)))))
|
||||
)
|
||||
#?(:cljs (t/is (= (colors/rgb->hsv [1 2 3]) (vec (gcolors/rgbToHsv 1 2 3))))))
|
||||
|
||||
(t/deftest hsv-to-rgb
|
||||
(t/is (= [1 2 3]
|
||||
(colors/hsv->rgb [210 0.6666666666666666 3])))
|
||||
#?(:cljs
|
||||
(t/is (= (colors/hsv->rgb [210 0.6666666666666666 3])
|
||||
(vec (gcolors/hsvToRgb 210 0.6666666666666666 3)))))
|
||||
)
|
||||
(vec (gcolors/hsvToRgb 210 0.6666666666666666 3))))))
|
||||
|
||||
(t/deftest rgb-to-hex
|
||||
(t/is (= "#010203" (colors/rgb->hex [1 2 3]))))
|
||||
@ -68,9 +64,7 @@
|
||||
(t/is (= [1 2 3] (colors/hsl->rgb [210.0 0.5 0.00784313725490196])))
|
||||
(t/is (= [210.0 0.5 0.00784313725490196] (colors/rgb->hsl [1 2 3])))
|
||||
#?(:cljs (t/is (= (colors/hsl->rgb [210 0.5 0.00784313725490196])
|
||||
(vec (gcolors/hslToRgb 210 0.5 0.00784313725490196)))))
|
||||
|
||||
)
|
||||
(vec (gcolors/hslToRgb 210 0.5 0.00784313725490196))))))
|
||||
|
||||
(t/deftest expand-hex
|
||||
(t/is (= "aaaaaa" (colors/expand-hex "a")))
|
||||
@ -93,8 +87,5 @@
|
||||
(t/is (true? (colors/color-string? "magenta")))
|
||||
(t/is (false? (colors/color-string? nil)))
|
||||
(t/is (false? (colors/color-string? "")))
|
||||
(t/is (false? (colors/color-string? "kkkkkk")))
|
||||
|
||||
|
||||
)
|
||||
(t/is (false? (colors/color-string? "kkkkkk"))))
|
||||
|
||||
|
||||
@ -30,8 +30,7 @@
|
||||
(d/remove-at-index [5 1 2 3 4] 0)))
|
||||
|
||||
(t/is (= [1 2 3 4]
|
||||
(d/remove-at-index [1 5 2 3 4] 1)))
|
||||
)
|
||||
(d/remove-at-index [1 5 2 3 4] 1))))
|
||||
|
||||
(t/deftest with-next
|
||||
(t/is (= [[0 1] [1 2] [2 3] [3 4] [4 nil]]
|
||||
|
||||
@ -71,14 +71,14 @@
|
||||
:version 7}
|
||||
|
||||
expect (-> data
|
||||
(update-in [:pages-index page-id :objects] dissoc
|
||||
(uuid/custom 1 2)
|
||||
(uuid/custom 1 3)
|
||||
(uuid/custom 1 4))
|
||||
(update-in [:pages-index page-id :objects (uuid/custom 1 1) :shapes]
|
||||
(fn [shapes]
|
||||
(let [id (uuid/custom 1 2)]
|
||||
(into [] (remove #(= id %)) shapes)))))
|
||||
(update-in [:pages-index page-id :objects] dissoc
|
||||
(uuid/custom 1 2)
|
||||
(uuid/custom 1 3)
|
||||
(uuid/custom 1 4))
|
||||
(update-in [:pages-index page-id :objects (uuid/custom 1 1) :shapes]
|
||||
(fn [shapes]
|
||||
(let [id (uuid/custom 1 2)]
|
||||
(into [] (remove #(= id %)) shapes)))))
|
||||
|
||||
res (cpm/migrate-data data 8)]
|
||||
|
||||
@ -86,5 +86,4 @@
|
||||
;; (pprint expect)
|
||||
|
||||
(t/is (= (dissoc expect :version)
|
||||
(dissoc res :version)))
|
||||
))
|
||||
(dissoc res :version)))))
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
|
||||
(ns common-tests.geom-point-test
|
||||
(:require
|
||||
[app.common.math :as mth]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.math :as mth]
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/deftest add-points
|
||||
@ -62,8 +62,7 @@
|
||||
(t/is (gpt/close? rs p1)))
|
||||
|
||||
(let [rs (gpt/min p2 p1)]
|
||||
(t/is (gpt/close? rs p1)))
|
||||
))
|
||||
(t/is (gpt/close? rs p1)))))
|
||||
|
||||
(t/deftest max-point
|
||||
(let [p1 (gpt/point 1 2)
|
||||
@ -85,8 +84,7 @@
|
||||
(t/is (gpt/close? rs p2)))
|
||||
|
||||
(let [rs (gpt/max p2 p1)]
|
||||
(t/is (gpt/close? rs p2)))
|
||||
))
|
||||
(t/is (gpt/close? rs p2)))))
|
||||
|
||||
(t/deftest inverse-point
|
||||
(let [p1 (gpt/point 1 2)
|
||||
@ -154,8 +152,7 @@
|
||||
p2 (gpt/point 1 5)
|
||||
rs (gpt/angle-sign p1 p2)]
|
||||
(t/is (number? rs))
|
||||
(t/is (mth/close? -1 rs)))
|
||||
)
|
||||
(t/is (mth/close? -1 rs))))
|
||||
|
||||
(t/deftest update-angle
|
||||
(let [p1 (gpt/point 1 3)
|
||||
@ -184,8 +181,7 @@
|
||||
(let [p1 (gpt/point -1 -3)
|
||||
rs (gpt/quadrant p1)]
|
||||
(t/is (number? rs))
|
||||
(t/is (mth/close? 3 rs)))
|
||||
)
|
||||
(t/is (mth/close? 3 rs))))
|
||||
|
||||
(t/deftest round-point
|
||||
(let [p1 (gpt/point 1.34567 3.34567)
|
||||
@ -198,8 +194,7 @@
|
||||
rs (gpt/round p1 2)]
|
||||
(t/is (gpt/point? rs))
|
||||
(t/is (mth/close? 1.35 (:x rs)))
|
||||
(t/is (mth/close? 3.35 (:y rs))))
|
||||
)
|
||||
(t/is (mth/close? 3.35 (:y rs)))))
|
||||
|
||||
(t/deftest halft-round-point
|
||||
(let [p1 (gpt/point 1.34567 3.34567)
|
||||
|
||||
@ -41,9 +41,9 @@
|
||||
(t/deftest transform-shapes
|
||||
(t/testing "Shape without modifiers should stay the same"
|
||||
(t/are [type]
|
||||
(let [shape-before (create-test-shape type)
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(= shape-before shape-after))
|
||||
(let [shape-before (create-test-shape type)
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(= shape-before shape-after))
|
||||
|
||||
:rect :path))
|
||||
|
||||
@ -65,49 +65,48 @@
|
||||
(get-in shape-after [:selrect :width])))
|
||||
|
||||
(t/is (close? (get-in shape-before [:selrect :height])
|
||||
(get-in shape-after [:selrect :height])))
|
||||
)))
|
||||
(get-in shape-after [:selrect :height]))))))
|
||||
|
||||
(t/testing "Transform with empty translation"
|
||||
(t/are [type]
|
||||
(let [modifiers {:displacement (gmt/matrix)}
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(t/are [prop]
|
||||
(t/is (close? (get-in shape-before [:selrect prop])
|
||||
(get-in shape-after [:selrect prop])))
|
||||
:x :y :width :height :x1 :y1 :x2 :y2))
|
||||
(let [modifiers {:displacement (gmt/matrix)}
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(t/are [prop]
|
||||
(t/is (close? (get-in shape-before [:selrect prop])
|
||||
(get-in shape-after [:selrect prop])))
|
||||
:x :y :width :height :x1 :y1 :x2 :y2))
|
||||
:rect :path))
|
||||
|
||||
(t/testing "Transform shape with resize modifiers"
|
||||
(t/are [type]
|
||||
(let [modifiers (ctm/resize-modifiers (gpt/point 2 2) (gpt/point 0 0))
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(t/is (not= shape-before shape-after))
|
||||
(let [modifiers (ctm/resize-modifiers (gpt/point 2 2) (gpt/point 0 0))
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(t/is (not= shape-before shape-after))
|
||||
|
||||
(t/is (close? (get-in shape-before [:selrect :x])
|
||||
(get-in shape-after [:selrect :x])))
|
||||
(t/is (close? (get-in shape-before [:selrect :x])
|
||||
(get-in shape-after [:selrect :x])))
|
||||
|
||||
(t/is (close? (get-in shape-before [:selrect :y])
|
||||
(get-in shape-after [:selrect :y])))
|
||||
(t/is (close? (get-in shape-before [:selrect :y])
|
||||
(get-in shape-after [:selrect :y])))
|
||||
|
||||
(t/is (close? (* 2 (get-in shape-before [:selrect :width]))
|
||||
(get-in shape-after [:selrect :width])))
|
||||
(t/is (close? (* 2 (get-in shape-before [:selrect :width]))
|
||||
(get-in shape-after [:selrect :width])))
|
||||
|
||||
(t/is (close? (* 2 (get-in shape-before [:selrect :height]))
|
||||
(get-in shape-after [:selrect :height]))))
|
||||
(t/is (close? (* 2 (get-in shape-before [:selrect :height]))
|
||||
(get-in shape-after [:selrect :height]))))
|
||||
:rect :path))
|
||||
|
||||
(t/testing "Transform with empty resize"
|
||||
(t/are [type]
|
||||
(let [modifiers (ctm/resize-modifiers (gpt/point 1 1) (gpt/point 0 0))
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(t/are [prop]
|
||||
(t/is (close? (get-in shape-before [:selrect prop])
|
||||
(get-in shape-after [:selrect prop])))
|
||||
:x :y :width :height :x1 :y1 :x2 :y2))
|
||||
(let [modifiers (ctm/resize-modifiers (gpt/point 1 1) (gpt/point 0 0))
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(t/are [prop]
|
||||
(t/is (close? (get-in shape-before [:selrect prop])
|
||||
(get-in shape-after [:selrect prop])))
|
||||
:x :y :width :height :x1 :y1 :x2 :y2))
|
||||
:rect :path))
|
||||
|
||||
(t/testing "Transform with resize=0"
|
||||
@ -118,54 +117,52 @@
|
||||
(t/is (close? (get-in shape-before [:selrect :width])
|
||||
(get-in shape-after [:selrect :width])))
|
||||
(t/is (close? (get-in shape-before [:selrect :height])
|
||||
(get-in shape-after [:selrect :height])))))
|
||||
(get-in shape-after [:selrect :height])))))
|
||||
|
||||
(t/testing "Transform shape with rotation modifiers"
|
||||
(t/are [type]
|
||||
(let [shape-before (create-test-shape type)
|
||||
modifiers (ctm/rotation-modifiers shape-before (gsh/shape->center shape-before) 30)
|
||||
shape-before (assoc shape-before :modifiers modifiers)
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
(let [shape-before (create-test-shape type)
|
||||
modifiers (ctm/rotation-modifiers shape-before (gsh/shape->center shape-before) 30)
|
||||
shape-before (assoc shape-before :modifiers modifiers)
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
|
||||
(t/is (close? (get-in shape-before [:selrect :x])
|
||||
(get-in shape-after [:selrect :x])))
|
||||
(t/is (close? (get-in shape-before [:selrect :x])
|
||||
(get-in shape-after [:selrect :x])))
|
||||
|
||||
(t/is (close? (get-in shape-before [:selrect :y])
|
||||
(get-in shape-after [:selrect :y])))
|
||||
(t/is (close? (get-in shape-before [:selrect :y])
|
||||
(get-in shape-after [:selrect :y])))
|
||||
|
||||
(t/is (= (count (:points shape-before)) (count (:points shape-after))))
|
||||
(t/is (= (count (:points shape-before)) (count (:points shape-after))))
|
||||
|
||||
(for [idx (range 0 (count (:point shape-before)))]
|
||||
(do (t/is (not (close? (get-in shape-before [:points idx :x])
|
||||
(get-in shape-after [:points idx :x]))))
|
||||
(t/is (not (close? (get-in shape-before [:points idx :y])
|
||||
(get-in shape-after [:points idx :y])))))))
|
||||
(for [idx (range 0 (count (:point shape-before)))]
|
||||
(do (t/is (not (close? (get-in shape-before [:points idx :x])
|
||||
(get-in shape-after [:points idx :x]))))
|
||||
(t/is (not (close? (get-in shape-before [:points idx :y])
|
||||
(get-in shape-after [:points idx :y])))))))
|
||||
:rect :path))
|
||||
|
||||
(t/testing "Transform shape with rotation = 0 should leave equal selrect"
|
||||
(t/are [type]
|
||||
(let [shape-before (create-test-shape type)
|
||||
modifiers (ctm/rotation-modifiers shape-before (gsh/shape->center shape-before) 0)
|
||||
shape-after (gsh/transform-shape (assoc shape-before :modifiers modifiers))]
|
||||
(t/are [prop]
|
||||
(t/is (close? (get-in shape-before [:selrect prop])
|
||||
(get-in shape-after [:selrect prop])))
|
||||
:x :y :width :height :x1 :y1 :x2 :y2))
|
||||
(let [shape-before (create-test-shape type)
|
||||
modifiers (ctm/rotation-modifiers shape-before (gsh/shape->center shape-before) 0)
|
||||
shape-after (gsh/transform-shape (assoc shape-before :modifiers modifiers))]
|
||||
(t/are [prop]
|
||||
(t/is (close? (get-in shape-before [:selrect prop])
|
||||
(get-in shape-after [:selrect prop])))
|
||||
:x :y :width :height :x1 :y1 :x2 :y2))
|
||||
:rect :path))
|
||||
|
||||
(t/testing "Transform shape with invalid selrect fails gracefully"
|
||||
(t/are [type selrect]
|
||||
(let [modifiers (ctm/move-modifiers 0 0)
|
||||
shape-before (create-test-shape type {:selrect selrect})
|
||||
shape-after (gsh/transform-shape shape-before modifiers)]
|
||||
(let [modifiers (ctm/move-modifiers 0 0)
|
||||
shape-before (create-test-shape type {:selrect selrect})
|
||||
shape-after (gsh/transform-shape shape-before modifiers)]
|
||||
|
||||
(t/is (grc/close-rect? (:selrect shape-before)
|
||||
(:selrect shape-after))))
|
||||
(t/is (grc/close-rect? (:selrect shape-before)
|
||||
(:selrect shape-after))))
|
||||
|
||||
:rect (grc/make-rect 0 0 ##Inf ##Inf)
|
||||
:path (grc/make-rect 0 0 ##Inf ##Inf)
|
||||
))
|
||||
)
|
||||
:path (grc/make-rect 0 0 ##Inf ##Inf))))
|
||||
|
||||
(t/deftest points-to-selrect
|
||||
(let [points [(gpt/point 0.5 0.5)
|
||||
@ -185,8 +182,8 @@
|
||||
(t/deftest points-transform-matrix
|
||||
(t/testing "Transform matrix"
|
||||
(t/are [selrect points expected]
|
||||
(let [result (gsht/transform-points-matrix selrect points)]
|
||||
(t/is (gmt/close? expected result)))
|
||||
(let [result (gsht/transform-points-matrix selrect points)]
|
||||
(t/is (gmt/close? expected result)))
|
||||
|
||||
;; No transformation
|
||||
(grc/make-rect 0 0 10 10)
|
||||
@ -197,7 +194,7 @@
|
||||
;; Displacement
|
||||
(grc/make-rect 0 0 10 10)
|
||||
(-> (grc/make-rect 20 20 10 10)
|
||||
(grc/rect->points ))
|
||||
(grc/rect->points))
|
||||
(gmt/matrix 1 0 0 1 20 20)
|
||||
|
||||
;; Resize
|
||||
@ -234,5 +231,4 @@
|
||||
(t/is (true? (gsin/fast-has-point? shape point1)))
|
||||
(t/is (true? (gsin/slow-has-point? shape point1)))
|
||||
(t/is (false? (gsin/fast-has-point? shape point2)))
|
||||
(t/is (false? (gsin/fast-has-point? shape point2)))
|
||||
))
|
||||
(t/is (false? (gsin/fast-has-point? shape point2)))))
|
||||
|
||||
@ -6,10 +6,10 @@
|
||||
|
||||
(ns common-tests.geom-test
|
||||
(:require
|
||||
[clojure.test :as t]
|
||||
[app.common.math :as mth]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.matrix :as gmt]))
|
||||
[app.common.math :as mth]
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/deftest point-constructors-test
|
||||
(t/testing "Create point with both coordinates"
|
||||
|
||||
@ -6,11 +6,11 @@
|
||||
|
||||
(ns common-tests.helpers.components
|
||||
(:require
|
||||
[clojure.test :as t]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.file :as ctf]))
|
||||
[app.common.types.file :as ctf]
|
||||
[clojure.test :as t]))
|
||||
|
||||
;; ---- Helpers to manage libraries and synchronization
|
||||
|
||||
@ -99,7 +99,7 @@
|
||||
main-shape
|
||||
(ctn/get-shape component (:shape-ref shape))]
|
||||
|
||||
(t/is (some? main-shape))))]
|
||||
(t/is (some? main-shape))))]
|
||||
|
||||
;; Validate that the instance tree is well constructed
|
||||
(check-instance-root (first shapes-inst))
|
||||
@ -135,7 +135,7 @@
|
||||
main-shape
|
||||
(ctn/get-shape component (:shape-ref shape))]
|
||||
|
||||
(t/is (some? main-shape))))]
|
||||
(t/is (some? main-shape))))]
|
||||
|
||||
;; Validate that the instance tree is well constructed
|
||||
(check-instance-root (first shapes-inst))
|
||||
|
||||
@ -45,111 +45,111 @@
|
||||
(defn sample-shape
|
||||
[file label type page-id props]
|
||||
(ctf/update-file-data
|
||||
file
|
||||
(fn [file-data]
|
||||
(let [frame-id (get props :frame-id uuid/zero)
|
||||
parent-id (get props :parent-id uuid/zero)
|
||||
shape (cts/setup-shape
|
||||
(-> {:type type
|
||||
:width 1
|
||||
:height 1}
|
||||
(merge props)))]
|
||||
file
|
||||
(fn [file-data]
|
||||
(let [frame-id (get props :frame-id uuid/zero)
|
||||
parent-id (get props :parent-id uuid/zero)
|
||||
shape (cts/setup-shape
|
||||
(-> {:type type
|
||||
:width 1
|
||||
:height 1}
|
||||
(merge props)))]
|
||||
|
||||
(swap! idmap assoc label (:id shape))
|
||||
(ctpl/update-page file-data
|
||||
page-id
|
||||
#(ctst/add-shape (:id shape)
|
||||
shape
|
||||
%
|
||||
frame-id
|
||||
parent-id
|
||||
0
|
||||
true))))))
|
||||
(swap! idmap assoc label (:id shape))
|
||||
(ctpl/update-page file-data
|
||||
page-id
|
||||
#(ctst/add-shape (:id shape)
|
||||
shape
|
||||
%
|
||||
frame-id
|
||||
parent-id
|
||||
0
|
||||
true))))))
|
||||
|
||||
(defn sample-component
|
||||
[file label page-id shape-id]
|
||||
(ctf/update-file-data
|
||||
file
|
||||
(fn [file-data]
|
||||
(let [page (ctpl/get-page file-data page-id)
|
||||
file
|
||||
(fn [file-data]
|
||||
(let [page (ctpl/get-page file-data page-id)
|
||||
|
||||
[component-shape component-shapes updated-shapes]
|
||||
(ctn/make-component-shape (ctn/get-shape page shape-id)
|
||||
(:objects page)
|
||||
(:id file)
|
||||
true)]
|
||||
[component-shape component-shapes updated-shapes]
|
||||
(ctn/make-component-shape (ctn/get-shape page shape-id)
|
||||
(:objects page)
|
||||
(:id file)
|
||||
true)]
|
||||
|
||||
(swap! idmap assoc label (:id component-shape))
|
||||
(-> file-data
|
||||
(ctpl/update-page page-id
|
||||
#(reduce (fn [page shape] (ctst/set-shape page shape))
|
||||
%
|
||||
updated-shapes))
|
||||
(ctkl/add-component {:id (:id component-shape)
|
||||
:name (:name component-shape)
|
||||
:path ""
|
||||
:main-instance-id shape-id
|
||||
:main-instance-page page-id
|
||||
:shapes component-shapes}))))))
|
||||
(swap! idmap assoc label (:id component-shape))
|
||||
(-> file-data
|
||||
(ctpl/update-page page-id
|
||||
#(reduce (fn [page shape] (ctst/set-shape page shape))
|
||||
%
|
||||
updated-shapes))
|
||||
(ctkl/add-component {:id (:id component-shape)
|
||||
:name (:name component-shape)
|
||||
:path ""
|
||||
:main-instance-id shape-id
|
||||
:main-instance-page page-id
|
||||
:shapes component-shapes}))))))
|
||||
|
||||
(defn sample-instance
|
||||
[file label page-id library component-id]
|
||||
(ctf/update-file-data
|
||||
file
|
||||
(fn [file-data]
|
||||
(let [[instance-shape instance-shapes]
|
||||
(ctn/make-component-instance (ctpl/get-page file-data page-id)
|
||||
(ctkl/get-component (:data library) component-id)
|
||||
(:data library)
|
||||
(gpt/point 0 0)
|
||||
true)]
|
||||
file
|
||||
(fn [file-data]
|
||||
(let [[instance-shape instance-shapes]
|
||||
(ctn/make-component-instance (ctpl/get-page file-data page-id)
|
||||
(ctkl/get-component (:data library) component-id)
|
||||
(:data library)
|
||||
(gpt/point 0 0)
|
||||
true)]
|
||||
|
||||
(swap! idmap assoc label (:id instance-shape))
|
||||
(-> file-data
|
||||
(ctpl/update-page page-id
|
||||
#(reduce (fn [page shape]
|
||||
(ctst/add-shape (:id shape)
|
||||
shape
|
||||
page
|
||||
uuid/zero
|
||||
(:parent-id shape)
|
||||
0
|
||||
true))
|
||||
%
|
||||
instance-shapes)))))))
|
||||
(swap! idmap assoc label (:id instance-shape))
|
||||
(-> file-data
|
||||
(ctpl/update-page page-id
|
||||
#(reduce (fn [page shape]
|
||||
(ctst/add-shape (:id shape)
|
||||
shape
|
||||
page
|
||||
uuid/zero
|
||||
(:parent-id shape)
|
||||
0
|
||||
true))
|
||||
%
|
||||
instance-shapes)))))))
|
||||
|
||||
(defn sample-color
|
||||
[file label props]
|
||||
(ctf/update-file-data
|
||||
file
|
||||
(fn [file-data]
|
||||
(let [id (uuid/next)
|
||||
props (merge {:id id
|
||||
:name "Color 1"
|
||||
:color "#000000"
|
||||
:opacity 1}
|
||||
props)]
|
||||
(swap! idmap assoc label id)
|
||||
(ctcl/add-color file-data props)))))
|
||||
file
|
||||
(fn [file-data]
|
||||
(let [id (uuid/next)
|
||||
props (merge {:id id
|
||||
:name "Color 1"
|
||||
:color "#000000"
|
||||
:opacity 1}
|
||||
props)]
|
||||
(swap! idmap assoc label id)
|
||||
(ctcl/add-color file-data props)))))
|
||||
|
||||
(defn sample-typography
|
||||
[file label props]
|
||||
(ctf/update-file-data
|
||||
file
|
||||
(fn [file-data]
|
||||
(let [id (uuid/next)
|
||||
props (merge {:id id
|
||||
:name "Typography 1"
|
||||
:font-id "sourcesanspro"
|
||||
:font-family "sourcesanspro"
|
||||
:font-size "14"
|
||||
:font-style "normal"
|
||||
:font-variant-id "regular"
|
||||
:font-weight "400"
|
||||
:line-height "1.2"
|
||||
:letter-spacing "0"
|
||||
:text-transform "none"}
|
||||
props)]
|
||||
(swap! idmap assoc label id)
|
||||
(ctyl/add-typography file-data props)))))
|
||||
file
|
||||
(fn [file-data]
|
||||
(let [id (uuid/next)
|
||||
props (merge {:id id
|
||||
:name "Typography 1"
|
||||
:font-id "sourcesanspro"
|
||||
:font-family "sourcesanspro"
|
||||
:font-size "14"
|
||||
:font-style "normal"
|
||||
:font-variant-id "regular"
|
||||
:font-weight "400"
|
||||
:line-height "1.2"
|
||||
:letter-spacing "0"
|
||||
:text-transform "none"}
|
||||
props)]
|
||||
(swap! idmap assoc label id)
|
||||
(ctyl/add-typography file-data props)))))
|
||||
|
||||
|
||||
@ -6,9 +6,9 @@
|
||||
|
||||
(ns common-tests.pages-helpers-test
|
||||
(:require
|
||||
[clojure.test :as t]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[clojure.pprint :refer [pprint]]
|
||||
[app.common.files.helpers :as cfh]))
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/deftest parse-path-name
|
||||
(t/is (= ["foo" "bar"] (cfh/parse-path-name "foo/bar")))
|
||||
|
||||
@ -82,8 +82,7 @@
|
||||
:option [:values :test2]
|
||||
:value nil}]
|
||||
res (ch/process-changes data chgs)]
|
||||
(t/is (= [:test1] (keys (get-in res [:pages-index page-id :options :values]))))))
|
||||
))
|
||||
(t/is (= [:test1] (keys (get-in res [:pages-index page-id :options :values]))))))))
|
||||
|
||||
(t/deftest process-change-add-obj
|
||||
(let [file-id (uuid/custom 2 2)
|
||||
@ -137,8 +136,7 @@
|
||||
(t/is (not (nil? (get objects id-a))))
|
||||
(t/is (not (nil? (get objects id-b))))
|
||||
(t/is (not (nil? (get objects id-c))))
|
||||
(t/is (= [id-b id-c id-a] (get-in objects [uuid/zero :shapes]))))))
|
||||
))
|
||||
(t/is (= [id-b id-c id-a] (get-in objects [uuid/zero :shapes]))))))))
|
||||
|
||||
(t/deftest process-change-mod-obj
|
||||
(let [file-id (uuid/custom 2 2)
|
||||
@ -164,9 +162,7 @@
|
||||
:attr :name
|
||||
:val "foobar"}]}
|
||||
res (ch/process-changes data [chg])]
|
||||
(t/is (= res data))))
|
||||
|
||||
))
|
||||
(t/is (= res data))))))
|
||||
|
||||
|
||||
;; (t/deftest process-change-del-obj
|
||||
|
||||
@ -50,6 +50,5 @@
|
||||
(t/is (= 10 (dm/get-prop u :a)))
|
||||
(t/is (= 20 (dm/get-prop u :b)))
|
||||
(t/is (= 124 (:c u)))
|
||||
(t/is (not= u o)))))
|
||||
))
|
||||
(t/is (not= u o)))))))
|
||||
|
||||
|
||||
@ -6,13 +6,13 @@
|
||||
|
||||
(ns common-tests.svg-path-test
|
||||
(:require
|
||||
#?(:cljs [app.common.svg.path.legacy-parser2 :as svg.path.legacy1])
|
||||
[app.common.data :as d]
|
||||
[app.common.pprint :as pp]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pprint :as pp]
|
||||
[app.common.svg.path :as svg.path]
|
||||
[app.common.svg.path.legacy-parser2 :as svg.path.legacy2]
|
||||
[clojure.test :as t]
|
||||
#?(:cljs [app.common.svg.path.legacy-parser2 :as svg.path.legacy1])))
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/deftest parse-test-1
|
||||
(let [data (str "m -994.563 4564.1423 149.3086 -52.8821 30.1828 "
|
||||
@ -25,7 +25,7 @@
|
||||
(update entry :params #(into (sorted-map) %)))))
|
||||
result2 (->> (svg.path.legacy2/parse data)
|
||||
(mapv (fn [entry]
|
||||
(update entry :params #(into (sorted-map) %)))))
|
||||
(update entry :params #(into (sorted-map) %)))))
|
||||
|
||||
result3 #?(:cljs (->> (svg.path.legacy1/parse data)
|
||||
(mapv (fn [entry]
|
||||
@ -113,7 +113,7 @@
|
||||
(update entry :params #(into (sorted-map) %)))))
|
||||
result2 (->> (svg.path.legacy2/parse data)
|
||||
(mapv (fn [entry]
|
||||
(update entry :params #(into (sorted-map) %)))))]
|
||||
(update entry :params #(into (sorted-map) %)))))]
|
||||
|
||||
(t/is (= 165
|
||||
(count result1)
|
||||
@ -144,7 +144,7 @@
|
||||
(update entry :params #(into (sorted-map) %)))))
|
||||
result2 (->> (svg.path.legacy2/parse data)
|
||||
(mapv (fn [entry]
|
||||
(update entry :params #(into (sorted-map) %)))))]
|
||||
(update entry :params #(into (sorted-map) %)))))]
|
||||
|
||||
(t/is (= 6
|
||||
(count result1)
|
||||
@ -223,7 +223,7 @@
|
||||
(update entry :params #(into (sorted-map) %)))))
|
||||
result2 (->> (svg.path.legacy2/parse data)
|
||||
(mapv (fn [entry]
|
||||
(update entry :params #(into (sorted-map) %)))))]
|
||||
(update entry :params #(into (sorted-map) %)))))]
|
||||
|
||||
(t/is (= 41
|
||||
(count result1)
|
||||
@ -242,8 +242,7 @@
|
||||
|
||||
(doseq [[k v] (:params item1)]
|
||||
(t/is (mth/close? v (get-in item2 [:params k]) 0.000000001))
|
||||
(t/is (mth/close? v (get-in item3 [:params k]) 0.000000001))
|
||||
)))))
|
||||
(t/is (mth/close? v (get-in item3 [:params k]) 0.000000001)))))))
|
||||
|
||||
(t/deftest parse-test-5
|
||||
(let [data (str "M363 826"
|
||||
@ -268,15 +267,14 @@
|
||||
"8.5 8.676 8.5 21.5 0 12.825-8.675 21.325-8.676 8.5-21.5 8.5Zm120 0Q747 886 "
|
||||
"738.5 877.325q-8.5-8.676-8.5-21.5 0-12.825 8.675-21.325 8.676-8.5 21.5-8.5 "
|
||||
"12.825 0 21.325 8.675 8.5 8.676 8.5 21.5 0 12.825-8.675 21.325-8.676 8.5-21.5 "
|
||||
"8.5Z"
|
||||
)
|
||||
"8.5Z")
|
||||
|
||||
result1 (->> (svg.path/parse data)
|
||||
(mapv (fn [entry]
|
||||
(update entry :params #(into (sorted-map) %)))))
|
||||
result2 (->> (svg.path.legacy2/parse data)
|
||||
(mapv (fn [entry]
|
||||
(update entry :params #(into (sorted-map) %)))))]
|
||||
(update entry :params #(into (sorted-map) %)))))]
|
||||
|
||||
(t/is (= 76
|
||||
(count result1)
|
||||
@ -287,15 +285,13 @@
|
||||
|
||||
(dotimes [i (count result1)]
|
||||
(let [item1 (nth result1 i)
|
||||
item2 (nth result2 i)
|
||||
]
|
||||
item2 (nth result2 i)]
|
||||
|
||||
(t/is (= (:command item1)
|
||||
(:command item2)))
|
||||
|
||||
(doseq [[k v] (:params item1)]
|
||||
(t/is (mth/close? v (get-in item2 [:params k]) 0.000000001))
|
||||
)))))
|
||||
(t/is (mth/close? v (get-in item2 [:params k]) 0.000000001)))))))
|
||||
|
||||
(t/deftest parse-test-6
|
||||
(let [data (str "M3.078 3.548v16.9a.5.5 0 0 0 1 0v-16.9a.5.5 0 0 0-1 0ZM18.422 11.5"
|
||||
@ -314,7 +310,7 @@
|
||||
(update entry :params #(into (sorted-map) %)))))
|
||||
result2 (->> (svg.path.legacy2/parse data)
|
||||
(mapv (fn [entry]
|
||||
(update entry :params #(into (sorted-map) %)))))]
|
||||
(update entry :params #(into (sorted-map) %)))))]
|
||||
|
||||
(t/is (= 47
|
||||
(count result1)
|
||||
@ -325,15 +321,13 @@
|
||||
|
||||
(dotimes [i (count result1)]
|
||||
(let [item1 (nth result1 i)
|
||||
item2 (nth result2 i)
|
||||
]
|
||||
item2 (nth result2 i)]
|
||||
|
||||
(t/is (= (:command item1)
|
||||
(:command item2)))
|
||||
|
||||
(doseq [[k v] (:params item1)]
|
||||
(t/is (mth/close? v (get-in item2 [:params k]) 0.000000001))
|
||||
)))
|
||||
(t/is (mth/close? v (get-in item2 [:params k]) 0.000000001)))))
|
||||
|
||||
#?(:cljs
|
||||
(let [result3 (svg.path.legacy1/parse data)]
|
||||
@ -346,7 +340,7 @@
|
||||
item3 (nth result2 i)]
|
||||
|
||||
(t/is (= (:command item1)
|
||||
(:command item3)))
|
||||
(:command item3)))
|
||||
|
||||
(t/is (= (:params item1)
|
||||
(:params item3)))))))))
|
||||
@ -414,9 +408,7 @@
|
||||
(dotimes [i (count result2)]
|
||||
(t/is (mth/close? (nth result2 i)
|
||||
(nth expected2 i)
|
||||
0.000000000001)))))
|
||||
|
||||
))
|
||||
0.000000000001)))))))
|
||||
|
||||
(t/deftest arc-to-bezier-2
|
||||
(let [expected1 [3.0779999999999994,
|
||||
@ -486,9 +478,7 @@
|
||||
(dotimes [i (count result2)]
|
||||
(t/is (mth/close? (nth result2 i)
|
||||
(nth expected2 i)
|
||||
0.000000000001)))))
|
||||
|
||||
))
|
||||
0.000000000001)))))))
|
||||
|
||||
|
||||
|
||||
@ -553,8 +543,7 @@
|
||||
(t/is (= (nth result 2)
|
||||
(nth expected 2)))
|
||||
(t/is (= (nth result 3)
|
||||
(nth expected 3)))
|
||||
))
|
||||
(nth expected 3)))))
|
||||
|
||||
;; FOR POSSIBLE FUTURE TEST CASES
|
||||
;; (str "M259.958 89.134c-6.88-.354-10.484-1.241-12.44-3.064-1.871-1.743-6.937-3.098-15.793-4.226-7.171-.913-17.179-2.279-22.24-3.034-5.06-.755-15.252-2.016-22.648-2.8-18.685-1.985-35.63-4.223-38.572-5.096-3.655-1.084-3.016-3.548.708-2.726 1.751.387 13.376 1.701 25.833 2.922 12.456 1.22 29.018 3.114 36.803 4.208 29.94 4.206 29.433 4.204 34.267.136 3.787-3.186 5.669-3.669 14.303-3.669 14.338 0 17.18 1.681 12.182 7.205-2.053 2.268-1.994 2.719.707 5.42 3.828 3.827 3.74 5.846-.238 5.5-1.752-.153-7.544-.502-12.872-.776zm7.563-3.194c0-.778-1.751-1.352-3.892-1.274l-3.893.141 3.539 1.133c1.946.624 3.698 1.197 3.893 1.275.194.077.354-.496.354-1.275zm-15.899-8.493c1.43-2.29 1.414-2.83-.084-2.83-2.05 0-5.25 2.76-5.25 4.529 0 2.226 3.599 1.08 5.334-1.699zm8.114 0c2.486-2.746 2.473-2.83-.438-2.83-1.65 0-3.683 1.273-4.516 2.83-1.175 2.196-1.077 2.831.438 2.831 1.075 0 3.107-1.274 4.516-2.83zm7.814.674c2.858-3.444.476-4.085-3.033-.816-2.451 2.284-2.677 2.973-.975 2.973 1.22 0 3.023-.97 4.008-2.157zm-49.571-4.509c-1.168-.43-3.294-1.802-4.725-3.051-2.112-1.843-9.304-2.595-38.219-3.994-46.474-2.25-63-4.077-60.27-6.665.324-.308 9.507.261 20.406 1.264 10.9 1.003 31.16 2.258 45.024 2.789l25.207.964 4.625-3.527c4.313-3.29 5.41-3.474 16.24-2.732 6.389.438 11.981 1.388 12.428 2.111.447.723-.517 2.73-2.141 4.46l-2.954 3.144c1.607 1.697 3.308 3.289 5.049 4.845 3.248 2.189-5.438 1.289-8.678 1.284-5.428-.061-10.825-.463-11.992-.892zm12.74-3.242c-1.123-.694-2.36-.943-2.75-.554-.389.39.21 1.275 1.334 1.97 1.122.693 2.36.942 2.749.553.389-.39-.21-1.275-1.334-1.97zm-5.663 0a1.42 1.42 0 00-1.415-1.416 1.42 1.42 0 00-1.416 1.416 1.42 1.42 0 001.416 1.415 1.42 1.42 0 001.415-1.415zm-8.464-6.404c.984-1.187 1.35-2.598.813-3.135-1.181-1.18-5.408 1.297-6.184 3.624-.806 2.42 3.265 2.048 5.37-.49zm6.863.258c.867-1.045 1.163-2.313.658-2.819-1.063-1.062-4.719 1.631-4.719 3.476 0 1.864 2.274 1.496 4.061-.657zm8.792-.36c1.637-1.972 1.448-2.197-1.486-1.77-1.848.27-3.622 1.287-3.943 2.26-.838 2.547 3.212 2.181 5.429-.49zm32.443-4.11c-6.156-2.228-67.1-6.138-119.124-7.642-39.208-1.134-72.072-.928-94.618.593-6.617.446-19.681 1.16-29.03 1.587-15.798.72-17.183.573-19.588-2.085-4.498-4.97-2.544-7.857 6.39-9.44 4.394-.778 9.164-2.436 10.6-3.685 5.44-4.729 20.332-14.06 31.14-19.509C65.717 11.88 78.955 7.79 103.837 3.08 121.686-.3 125.552-.642 129.318.82c2.44.948 12.4 1.948 22.132 2.221 15.37.432 20.004 1.18 35.294 5.698 22.36 6.606 39.732 15.1 56.55 27.653 7.307 5.452 14.086 9.913 15.066 9.913.98 0 2.148.956 2.596 2.124.55 1.432 2.798 2.123 6.914 2.123 6.213 0 12.4 3.046 12.38 6.096-.012 1.75-6.502 5.353-9.118 5.063-.818-.09-3.717-.972-6.442-1.958zm-16.986-7.436c0-1.575-33.326-18.118-43.173-21.43-23.008-7.739-54.084-12.922-77.136-12.866-16.863.041-37.877 3.628-52.465 8.956-18.062 6.596-26.563 10.384-29.181 13.002-1.205 1.205-5.306 3.769-9.112 5.698-7.754 3.929-8.841 5.482-3.029 4.325 13.494-2.685 66.794-3.773 110.913-2.264 38.005 1.3 96.812 4.435 102.122 5.443.584.111 1.061-.277 1.061-.864zm-236.39-3.18c0-.78-1.592-1.416-3.539-1.416-1.946 0-3.538.637-3.538 1.415 0 .779 1.592 1.416 3.538 1.416 1.947 0 3.54-.637 3.54-1.416zm7.078-1.416c0-.779-.956-1.416-2.124-1.416-1.167 0-2.123.637-2.123 1.416 0 .778.956 1.415 2.123 1.415 1.168 0 2.124-.637 2.124-1.415zm11.734-4.437c3.278-1.661 6.278-3.483 6.667-4.048 1.366-1.98 20.645-11.231 32.557-15.622 11.862-4.372 36.546-9.865 44.327-9.865 3.485 0 3.867-.404 3.012-3.185-.538-1.752-1.177-3.41-1.42-3.685-.907-1.026-36.72 7.16-45.065 10.302-17.226 6.484-47.566 24.27-47.566 27.886 0 1.786.845 1.585 7.488-1.783zm206.254-5.577c-12.298-10.518-53.842-27.166-70.896-28.41-5.526-.404-6.3-.097-6.695 2.655-.33 2.307.402 3.275 2.831 3.742 32.436 6.237 52.205 12.315 66.975 20.594 11.904 6.673 14.477 7.141 7.785 1.419zM150.1 11.04c-1.949-3.64-7.568-4.078-6.886-.538.256 1.329 2.054 2.817 3.997 3.309 4.498 1.137 4.816.832 2.888-2.771zm6.756.94c-.248-1.752-1.026-3.185-1.727-3.185-.7 0-1.493 1.433-1.76 3.185-.328 2.152.232 3.185 1.727 3.185 1.485 0 2.064-1.047 1.76-3.185zm-30.178-2.458c0-2.303-.908-3.694-2.627-4.025-3.6-.694-5.23 1.301-4.22 5.166 1.216 4.647 6.847 3.709 6.847-1.14zm12.544 2.104c-.448-1.168-1.224-2.132-1.725-2.142-.5-.013-2.343-.404-4.095-.873-2.569-.689-3.185-.274-3.185 2.142 0 2.476.854 2.996 4.91 2.996 3.783 0 4.723-.487 4.095-2.123z")
|
||||
|
||||
@ -8,8 +8,8 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.text :as txt]
|
||||
[clojure.test :as t :include-macros true]
|
||||
[clojure.pprint :refer [pprint]]))
|
||||
[clojure.pprint :refer [pprint]]
|
||||
[clojure.test :as t :include-macros true]))
|
||||
|
||||
(t/deftest test-basic-conversion-roundtrip
|
||||
(let [text "qwqw 🠒"
|
||||
|
||||
@ -28,51 +28,51 @@
|
||||
(t/use-fixtures :each thf/reset-idmap!)
|
||||
|
||||
#_(t/deftest test-absorb-components
|
||||
(let [library-id (uuid/custom 1 1)
|
||||
library-page-id (uuid/custom 2 2)
|
||||
file-id (uuid/custom 3 3)
|
||||
file-page-id (uuid/custom 4 4)
|
||||
(let [library-id (uuid/custom 1 1)
|
||||
library-page-id (uuid/custom 2 2)
|
||||
file-id (uuid/custom 3 3)
|
||||
file-page-id (uuid/custom 4 4)
|
||||
|
||||
library (-> (thf/sample-file library-id library-page-id {:is-shared true})
|
||||
(thf/sample-shape :group1
|
||||
:group
|
||||
library-page-id
|
||||
{:name "Group1"})
|
||||
(thf/sample-shape :shape1
|
||||
:rect
|
||||
library-page-id
|
||||
{:name "Rect1"
|
||||
:parent-id (thf/id :group1)})
|
||||
(thf/sample-component :component1
|
||||
library-page-id
|
||||
(thf/id :group1)))
|
||||
library (-> (thf/sample-file library-id library-page-id {:is-shared true})
|
||||
(thf/sample-shape :group1
|
||||
:group
|
||||
library-page-id
|
||||
{:name "Group1"})
|
||||
(thf/sample-shape :shape1
|
||||
:rect
|
||||
library-page-id
|
||||
{:name "Rect1"
|
||||
:parent-id (thf/id :group1)})
|
||||
(thf/sample-component :component1
|
||||
library-page-id
|
||||
(thf/id :group1)))
|
||||
|
||||
file (-> (thf/sample-file file-id file-page-id)
|
||||
(thf/sample-instance :instance1
|
||||
file-page-id
|
||||
library
|
||||
(thf/id :component1)))
|
||||
file (-> (thf/sample-file file-id file-page-id)
|
||||
(thf/sample-instance :instance1
|
||||
file-page-id
|
||||
library
|
||||
(thf/id :component1)))
|
||||
|
||||
absorbed-file (ctf/update-file-data
|
||||
file
|
||||
#(ctf/absorb-assets % (:data library)))
|
||||
absorbed-file (ctf/update-file-data
|
||||
file
|
||||
#(ctf/absorb-assets % (:data library)))
|
||||
|
||||
pages (ctpl/pages-seq (ctf/file-data absorbed-file))
|
||||
components (ctkl/components-seq (ctf/file-data absorbed-file))
|
||||
shapes-1 (ctn/shapes-seq (first pages))
|
||||
shapes-2 (ctn/shapes-seq (second pages))
|
||||
pages (ctpl/pages-seq (ctf/file-data absorbed-file))
|
||||
components (ctkl/components-seq (ctf/file-data absorbed-file))
|
||||
shapes-1 (ctn/shapes-seq (first pages))
|
||||
shapes-2 (ctn/shapes-seq (second pages))
|
||||
|
||||
[[p-group p-shape] [c-group1 c-shape1] component1]
|
||||
(thk/resolve-instance-and-main
|
||||
(first pages)
|
||||
(:id (second shapes-1))
|
||||
{file-id absorbed-file})
|
||||
[[p-group p-shape] [c-group1 c-shape1] component1]
|
||||
(thk/resolve-instance-and-main
|
||||
(first pages)
|
||||
(:id (second shapes-1))
|
||||
{file-id absorbed-file})
|
||||
|
||||
[[lp-group lp-shape] [c-group2 c-shape2] component2]
|
||||
(thk/resolve-instance-and-main
|
||||
(second pages)
|
||||
(:id (second shapes-2))
|
||||
{file-id absorbed-file})]
|
||||
[[lp-group lp-shape] [c-group2 c-shape2] component2]
|
||||
(thk/resolve-instance-and-main
|
||||
(second pages)
|
||||
(:id (second shapes-2))
|
||||
{file-id absorbed-file})]
|
||||
|
||||
;; Uncomment to debug
|
||||
|
||||
@ -100,20 +100,20 @@
|
||||
;; {file-id absorbed-file}
|
||||
;; false)
|
||||
|
||||
(t/is (= (count pages) 2))
|
||||
(t/is (= (:name (first pages)) "Page 1"))
|
||||
(t/is (= (:name (second pages)) "Library backup"))
|
||||
(t/is (= (count pages) 2))
|
||||
(t/is (= (:name (first pages)) "Page 1"))
|
||||
(t/is (= (:name (second pages)) "Library backup"))
|
||||
|
||||
(t/is (= (count components) 1))
|
||||
(t/is (= (count components) 1))
|
||||
|
||||
(t/is (= (:name p-group) "Group1"))
|
||||
(t/is (ctk/instance-of? p-group file-id (:id component1)))
|
||||
(t/is (not (:main-instance? p-group)))
|
||||
(t/is (not (ctk/main-instance-of? (:id p-group) file-page-id component1)))
|
||||
(t/is (ctk/is-main-of? c-group1 p-group))
|
||||
(t/is (= (:name p-group) "Group1"))
|
||||
(t/is (ctk/instance-of? p-group file-id (:id component1)))
|
||||
(t/is (not (:main-instance? p-group)))
|
||||
(t/is (not (ctk/main-instance-of? (:id p-group) file-page-id component1)))
|
||||
(t/is (ctk/is-main-of? c-group1 p-group))
|
||||
|
||||
(t/is (= (:name p-shape) "Rect1"))
|
||||
(t/is (ctk/is-main-of? c-shape1 p-shape))))
|
||||
(t/is (= (:name p-shape) "Rect1"))
|
||||
(t/is (ctk/is-main-of? c-shape1 p-shape))))
|
||||
|
||||
|
||||
(t/deftest test-absorb-colors
|
||||
@ -137,8 +137,8 @@
|
||||
:fill-color-ref-file library-id}]}))
|
||||
|
||||
absorbed-file (ctf/update-file-data
|
||||
file
|
||||
#(ctf/absorb-assets % (:data library)))
|
||||
file
|
||||
#(ctf/absorb-assets % (:data library)))
|
||||
|
||||
colors (ctcl/colors-seq (ctf/file-data absorbed-file))
|
||||
page (ctpl/get-page (ctf/file-data absorbed-file) file-page-id)
|
||||
@ -187,11 +187,10 @@
|
||||
:text-decoration "none"
|
||||
:letter-spacing "0"
|
||||
:fills [{:fill-color "#000000"
|
||||
:fill-opacity 1}]}]
|
||||
}]}]}}))
|
||||
:fill-opacity 1}]}]}]}]}}))
|
||||
absorbed-file (ctf/update-file-data
|
||||
file
|
||||
#(ctf/absorb-assets % (:data library)))
|
||||
file
|
||||
#(ctf/absorb-assets % (:data library)))
|
||||
|
||||
typographies (ctyl/typographies-seq (ctf/file-data absorbed-file))
|
||||
page (ctpl/get-page (ctf/file-data absorbed-file) file-page-id)
|
||||
|
||||
@ -6,10 +6,10 @@
|
||||
|
||||
(ns common-tests.types-modifiers-test
|
||||
(:require
|
||||
[clojure.test :as t]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.types.modifiers :as ctm]))
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/deftest test-modifiers->transform
|
||||
(let [modifiers
|
||||
|
||||
@ -6,11 +6,11 @@
|
||||
|
||||
(ns common-tests.types-shape-interactions-test
|
||||
(:require
|
||||
[app.common.math :as mth]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.rect :as grc]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
[app.common.uuid :as uuid]
|
||||
@ -48,8 +48,7 @@
|
||||
new-interaction
|
||||
(ctsi/set-event-type interaction :after-delay frame)]
|
||||
(t/is (= :after-delay (:event-type new-interaction)))
|
||||
(t/is (= 300 (:delay new-interaction)))))
|
||||
))
|
||||
(t/is (= 300 (:delay new-interaction)))))))
|
||||
|
||||
|
||||
(t/deftest set-action-type
|
||||
|
||||
@ -6,13 +6,13 @@
|
||||
|
||||
(ns common-tests.types-test
|
||||
(:require
|
||||
[clojure.test :as t]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.generators :as sg]
|
||||
[app.common.transit :as transit]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.file :as ctf]))
|
||||
[app.common.types.shape :as cts]
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/deftest transit-encode-decode-with-shape
|
||||
(sg/check!
|
||||
|
||||
@ -90,6 +90,7 @@ function readLocales() {
|
||||
["ja_jp", "jpn_JP"],
|
||||
// ["fi", "fin_FI"],
|
||||
["uk", "ukr_UA"],
|
||||
"ha"
|
||||
];
|
||||
const result = {};
|
||||
|
||||
|
||||
@ -408,6 +408,8 @@
|
||||
border-radius: $br-4;
|
||||
box-shadow: inset 0 0 0px 2px rgb(255 255 255 / 20%);
|
||||
svg {
|
||||
width: $s-16;
|
||||
height: $s-16;
|
||||
display: none;
|
||||
stroke: var(--input-checkbox-inactive-foreground-color);
|
||||
}
|
||||
|
||||
@ -207,6 +207,8 @@
|
||||
--assets-component-background-color-disabled: var(
|
||||
--off-white
|
||||
); // We don't want this color to change with palette
|
||||
--assets-component-border-color: var(--color-background-tertiary);
|
||||
--assets-component-border-selected: var(--color-select);
|
||||
|
||||
--radio-btns-background-color: var(--color-background-tertiary);
|
||||
--radio-btn-background-color-selected: var(--color-background-quaternary);
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
--color-foreground-primary: var(--black);
|
||||
--color-foreground-secondary: var(--off-black);
|
||||
--color-foreground-tertiary: var(--pink);
|
||||
--color-foreground-disabled: var(--light-gray-1);
|
||||
--color-foreground-disabled: var(--off-black-30);
|
||||
--color-accent-primary: var(--purple);
|
||||
--color-accent-primary-muted: var(--purple-30);
|
||||
--color-accent-secondary: var(--blue);
|
||||
|
||||
@ -53,9 +53,6 @@
|
||||
// Partials
|
||||
//#################################################
|
||||
|
||||
@import "main/partials/viewer";
|
||||
@import "main/partials/viewer-header";
|
||||
@import "main/partials/viewer-thumbnails";
|
||||
@import "main/partials/activity-bar";
|
||||
@import "main/partials/debug-icons-preview";
|
||||
@import "main/partials/editable-label";
|
||||
@ -67,6 +64,5 @@
|
||||
@import "main/partials/user-settings";
|
||||
@import "main/partials/workspace";
|
||||
@import "main/partials/color-bullet";
|
||||
@import "main/partials/inspect";
|
||||
@import "main/partials/exception-page";
|
||||
@import "main/partials/signup-questions";
|
||||
|
||||
@ -1,487 +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
|
||||
|
||||
.inspect-svg-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.expand-button,
|
||||
.copy-button {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
position: absolute;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.code-block & {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
fill: $color-gray-20;
|
||||
transition: fill 0.3s;
|
||||
|
||||
&:hover {
|
||||
fill: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.expand-button {
|
||||
right: 24px;
|
||||
top: -1px;
|
||||
|
||||
svg {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
.copy-button {
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.attributes-block {
|
||||
user-select: text;
|
||||
|
||||
border-bottom: 1px solid $color-gray-60;
|
||||
padding-bottom: 0.5rem;
|
||||
font-size: $fs12;
|
||||
|
||||
.attributes-text-block {
|
||||
border-bottom: 1px solid $color-gray-60;
|
||||
}
|
||||
|
||||
& :last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.attributes-label {
|
||||
color: $color-gray-20;
|
||||
}
|
||||
|
||||
.attributes-value {
|
||||
color: $color-white;
|
||||
}
|
||||
|
||||
.attributes-block-title {
|
||||
position: relative;
|
||||
color: $color-gray-10;
|
||||
padding: 0.5rem;
|
||||
font-size: $fs14;
|
||||
|
||||
.copy-button {
|
||||
padding: 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-unit-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0.6rem 1.6rem 0.6rem 0.5rem;
|
||||
|
||||
.attributes-label,
|
||||
.attributes-value {
|
||||
margin-right: 0.5rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 50%;
|
||||
.items {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
.copy-button {
|
||||
padding: 0.6rem 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-color-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem 0;
|
||||
position: relative;
|
||||
|
||||
.attributes-color-id {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > * {
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.attributes-color-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > * {
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
|
||||
& :last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.color-text {
|
||||
width: 3rem;
|
||||
text-transform: uppercase;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.attributes-color-display {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.color-bullet {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid $color-gray-30;
|
||||
}
|
||||
|
||||
.hide-color .color-bullet {
|
||||
visibility: hidden;
|
||||
}
|
||||
.copy-button {
|
||||
padding: 1rem 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
select {
|
||||
font-size: $fs12;
|
||||
margin: 0;
|
||||
background: none;
|
||||
color: $color-gray-20;
|
||||
border: none;
|
||||
border-bottom: 1px solid $color-gray-30;
|
||||
padding: 0 1rem 0.25rem 0.25rem;
|
||||
margin-top: 2px;
|
||||
background-image: url("/images/icons/arrow-down-white.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 95% 48%;
|
||||
background-size: 10px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
&:focus,
|
||||
&:focus-within {
|
||||
border: 1px solid $color-primary;
|
||||
}
|
||||
|
||||
option {
|
||||
padding: 1rem;
|
||||
background-color: $color-gray-50;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-content-row {
|
||||
position: relative;
|
||||
margin: 0.5rem;
|
||||
width: calc(100% - 1rem);
|
||||
|
||||
.attributes-content {
|
||||
overflow-y: auto;
|
||||
max-height: 5rem;
|
||||
background: $color-gray-60;
|
||||
border-radius: $br4;
|
||||
padding: 1rem 0.5rem;
|
||||
color: $color-gray-10;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
padding: 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-image-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 0.25rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0.5rem;
|
||||
background: $color-gray-60;
|
||||
border-radius: $br4;
|
||||
|
||||
width: calc(100% - 1rem);
|
||||
min-height: 5rem;
|
||||
|
||||
img {
|
||||
max-height: 8rem;
|
||||
max-width: 100%;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-shadow-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
margin: 0.5rem;
|
||||
padding-right: 2rem;
|
||||
justify-content: space-between;
|
||||
|
||||
& > :first-child {
|
||||
color: $color-gray-10;
|
||||
}
|
||||
|
||||
.attributes-shadow {
|
||||
display: flex;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-stroke-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
margin: 0.5rem;
|
||||
padding-right: 2rem;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.attributes-typography-name-row {
|
||||
position: relative;
|
||||
margin-top: 0.5rem;
|
||||
border: 1px solid $color-black;
|
||||
border-radius: $br4;
|
||||
margin: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.copy-button {
|
||||
padding: 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-typography-row {
|
||||
position: relative;
|
||||
margin: 0.5rem;
|
||||
padding-right: 2rem;
|
||||
|
||||
.typography-sample {
|
||||
font-size: $fs16;
|
||||
}
|
||||
}
|
||||
|
||||
.download-button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
border: 1px solid $color-gray-60;
|
||||
background-color: $color-gray-60;
|
||||
padding: 0.5rem 1rem;
|
||||
color: $color-gray-10;
|
||||
width: calc(100% - 1rem);
|
||||
border-radius: $br4;
|
||||
margin: 0.5rem;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-primary;
|
||||
color: $color-black;
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-block-title,
|
||||
.attributes-unit-row,
|
||||
.attributes-color-row,
|
||||
.attributes-shadow-row,
|
||||
.attributes-stroke-row,
|
||||
.attributes-typography-row,
|
||||
.attributes-content-row,
|
||||
.attributes-typography-name-row {
|
||||
&:hover {
|
||||
.expand-button,
|
||||
.copy-button {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.attributes-shadow-block,
|
||||
.attributes-stroke-block,
|
||||
.attributes-fill-block {
|
||||
border-top: 1px solid $color-gray-60;
|
||||
}
|
||||
|
||||
.attributes-shadow-blocks :first-child,
|
||||
.attributes-stroke-blocks :first-child,
|
||||
.attributes-fill-blocks :first-child {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
.code-block {
|
||||
position: relative;
|
||||
margin-top: 0.5rem;
|
||||
border-top: 1px solid $color-gray-60;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.code-row-lang {
|
||||
.expand-button,
|
||||
.copy-button {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.code-row-lang {
|
||||
color: $color-gray-10;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: $fs14;
|
||||
margin: 0.5rem;
|
||||
|
||||
.expand-button,
|
||||
.copy-button {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.custom-select {
|
||||
border: 1px solid $color-gray-40;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
padding: 0.25rem 1.5rem 0.25rem 0.25rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.dropdown-button {
|
||||
position: absolute;
|
||||
right: 0.25rem;
|
||||
top: 7px;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-40;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-select-dropdown {
|
||||
background-color: $color-white;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
|
||||
left: 0;
|
||||
max-height: 30rem;
|
||||
min-width: 7rem;
|
||||
position: absolute;
|
||||
overflow-y: auto;
|
||||
top: 30px;
|
||||
z-index: 12;
|
||||
|
||||
li {
|
||||
color: $color-gray-60;
|
||||
cursor: pointer;
|
||||
font-size: 0.875rem;
|
||||
display: flex;
|
||||
gap: 0 10px;
|
||||
justify-content: flex-start;
|
||||
padding: 0.5rem;
|
||||
|
||||
.checked-element {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
visibility: hidden;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: none;
|
||||
margin: 0.25rem;
|
||||
fill: $color-black;
|
||||
}
|
||||
|
||||
.is-selected svg {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.code-row-display {
|
||||
line-height: 1;
|
||||
margin: 0.5rem;
|
||||
font-size: $fs14;
|
||||
max-height: var(--code-height, 400px);
|
||||
overflow: auto;
|
||||
|
||||
.code-display {
|
||||
font-family: monospace;
|
||||
border-radius: $br4;
|
||||
padding: 0.5rem 1rem;
|
||||
overflow: hidden;
|
||||
white-space: pre;
|
||||
min-width: fit-content;
|
||||
background: $color-gray-60;
|
||||
user-select: text;
|
||||
|
||||
.hljs-attr {
|
||||
color: #a6e22e;
|
||||
}
|
||||
.hljs-comment {
|
||||
color: $color-gray-30;
|
||||
}
|
||||
.hljs-string {
|
||||
color: #66d9ef;
|
||||
}
|
||||
}
|
||||
}
|
||||
.resize-area {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: -15px;
|
||||
left: 0;
|
||||
height: 18px;
|
||||
z-index: 1;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
}
|
||||
|
||||
.element-options > :first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.inspect-annotation {
|
||||
.content {
|
||||
background-color: $color-gray-60;
|
||||
color: $color-white;
|
||||
margin: 0 10px;
|
||||
padding: 10px;
|
||||
font-size: $fs14;
|
||||
overflow-wrap: anywhere;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
@ -1,234 +0,0 @@
|
||||
.viewer-header {
|
||||
align-items: center;
|
||||
background-color: $color-gray-50;
|
||||
border-bottom: 1px solid $color-gray-60;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 130px 1fr;
|
||||
height: 48px;
|
||||
padding: 0 $size-4 0 55px;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
justify-content: space-between;
|
||||
width: 100vw;
|
||||
|
||||
a {
|
||||
font-size: $fs12;
|
||||
}
|
||||
|
||||
.nav-zone {
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.main-icon {
|
||||
align-items: center;
|
||||
background-color: $color-gray-60;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 48px;
|
||||
|
||||
a {
|
||||
height: 30px;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-30;
|
||||
height: 30px;
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
svg {
|
||||
fill: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.options-zone {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
|
||||
> * {
|
||||
margin-left: $size-5;
|
||||
@media only screen and (max-width: 1366px) {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
flex-shrink: 0;
|
||||
svg {
|
||||
display: none;
|
||||
}
|
||||
@media only screen and (max-width: 1366px) {
|
||||
padding: 0 0.5rem;
|
||||
svg {
|
||||
display: inline-block;
|
||||
}
|
||||
span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
svg {
|
||||
fill: $color-gray-20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.view-options {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
> span {
|
||||
color: $color-gray-10;
|
||||
font-size: $fs14;
|
||||
margin-right: $size-1;
|
||||
}
|
||||
|
||||
> .icon {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-10;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
> svg {
|
||||
fill: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
min-width: 295px;
|
||||
top: 45px;
|
||||
left: -25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sitemap-zone {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
padding: $size-1;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.icon {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-20;
|
||||
height: 12px;
|
||||
margin-right: $size-2;
|
||||
width: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
display: grid;
|
||||
grid-template-columns: auto 10px auto 10px auto;
|
||||
}
|
||||
|
||||
.breadcrumb,
|
||||
.current-frame {
|
||||
position: relative;
|
||||
|
||||
> span {
|
||||
color: $color-gray-20;
|
||||
margin-right: $size-1;
|
||||
font-size: $fs14;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
> .dropdown {
|
||||
top: 45px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.current-frame {
|
||||
display: grid;
|
||||
grid-template-columns: 14px 1fr;
|
||||
span {
|
||||
color: $color-white;
|
||||
margin-right: $size-1;
|
||||
}
|
||||
|
||||
.counters {
|
||||
color: $color-gray-20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mode-zone {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
|
||||
.mode-zone-button {
|
||||
background: inherit;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
height: 100%;
|
||||
width: 48px;
|
||||
|
||||
svg {
|
||||
fill: $color-gray-20;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: $color-gray-60;
|
||||
svg {
|
||||
fill: $color-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.users-zone {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
margin-left: $size-2;
|
||||
position: relative;
|
||||
|
||||
img {
|
||||
border: 3px solid #f3dd14;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,192 +0,0 @@
|
||||
.viewer-thumbnails {
|
||||
grid-row: 1 / span 1;
|
||||
grid-column: 1 / span 1;
|
||||
|
||||
background-color: $color-gray-50;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 11;
|
||||
|
||||
&.invisible {
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
grid-row: 1 / span 2;
|
||||
|
||||
.btn-expand svg {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnails-summary {
|
||||
padding: 0.5rem 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 50px;
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: $color-gray-30;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
|
||||
&:hover {
|
||||
fill: $color-white;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-close {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
|
||||
.counter {
|
||||
color: $color-gray-10;
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnails-content {
|
||||
display: grid;
|
||||
grid-template-columns: 40px auto 40px;
|
||||
grid-template-rows: auto;
|
||||
}
|
||||
|
||||
.left-scroll-handler {
|
||||
grid-column: 1 / span 1;
|
||||
grid-row: 1 / span 1;
|
||||
|
||||
background-color: $color-gray-50;
|
||||
opacity: 0;
|
||||
display: flex;
|
||||
z-index: 12;
|
||||
cursor: pointer;
|
||||
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
svg {
|
||||
transform: rotate(180deg);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.right-scroll-handler {
|
||||
grid-column: 3 / span 1;
|
||||
grid-row: 1 / span 1;
|
||||
|
||||
background-color: $color-gray-50;
|
||||
opacity: 0;
|
||||
display: flex;
|
||||
z-index: 12;
|
||||
cursor: pointer;
|
||||
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnails-list {
|
||||
grid-column: 1 / span 3;
|
||||
grid-row: 1 / span 1;
|
||||
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
.thumbnails-list-inside {
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnails-list-expanded {
|
||||
grid-column: 1 / span 3;
|
||||
grid-row: 1 / span 1;
|
||||
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.thumbnail-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.thumbnail-preview {
|
||||
background-color: $color-gray-40;
|
||||
width: 120px;
|
||||
min-height: 120px;
|
||||
height: 120px;
|
||||
border: 1px solid $color-gray-20;
|
||||
border-radius: $br2;
|
||||
padding: 4px;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
border-color: $color-primary;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: $color-primary;
|
||||
outline: 2px solid $color-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnail-info {
|
||||
padding: 0.5rem 0;
|
||||
width: 120px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
span {
|
||||
font-size: $fs12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.thumbnail-close {
|
||||
grid-row: 1 / span 2;
|
||||
grid-column: 1 / span 1;
|
||||
z-index: 11;
|
||||
|
||||
&.invisible {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@ -1,214 +0,0 @@
|
||||
.viewer-content {
|
||||
background-color: black;
|
||||
display: grid;
|
||||
grid-template-rows: 232px auto;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.fullscreen.viewer-layout {
|
||||
.viewer-section {
|
||||
& .viewer-go-prev,
|
||||
& .viewer-go-next {
|
||||
.arrow {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.fullscreen.viewer-layout.force-visible {
|
||||
.viewer-section {
|
||||
& .viewer-go-prev,
|
||||
& .viewer-go-next {
|
||||
.arrow {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.viewer-loader {
|
||||
svg#loader-pencil {
|
||||
fill: $color-gray-50;
|
||||
}
|
||||
}
|
||||
|
||||
.viewer-section {
|
||||
height: calc(100vh - 48px);
|
||||
grid-row: 1 / span 2;
|
||||
grid-column: 1 / span 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-flow: wrap;
|
||||
overflow: auto;
|
||||
|
||||
&.fullscreen {
|
||||
height: 100vh;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
& .viewer-go-prev,
|
||||
& .viewer-go-next {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 53px;
|
||||
z-index: 2;
|
||||
.arrow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: $br12;
|
||||
background: $color-gray-50;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
fill: $color-gray-30;
|
||||
|
||||
svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $color-primary;
|
||||
fill: $color-black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& .viewer-go-next {
|
||||
right: 8px;
|
||||
width: 46px;
|
||||
svg {
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
& .viewer-go-next.right-bar {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
& .viewer-go-prev {
|
||||
left: 0;
|
||||
padding-left: 29px;
|
||||
svg {
|
||||
margin-right: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
& .viewer-go-prev.left-bar {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
& .viewer-bottom {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
height: 30px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
|
||||
&.left-bar {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.reset {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: $br12;
|
||||
background: $color-gray-50;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
cursor: pointer;
|
||||
fill: $color-gray-30;
|
||||
margin-left: 29px;
|
||||
|
||||
svg {
|
||||
margin-left: 4px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $color-primary;
|
||||
fill: $color-black;
|
||||
}
|
||||
}
|
||||
|
||||
.counter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: $br12;
|
||||
background: $color-gray-50;
|
||||
width: 67px;
|
||||
height: 25px;
|
||||
fill: $color-gray-20;
|
||||
}
|
||||
}
|
||||
|
||||
& .viewer-wrapper {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
& .viewer-clipper {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr;
|
||||
grid-template-columns: 1fr;
|
||||
justify-items: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
|
||||
svg {
|
||||
transform-origin: center;
|
||||
}
|
||||
}
|
||||
|
||||
& .viewer-wrapper-out {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
& .comments-right-sidebar {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50px;
|
||||
width: 256px;
|
||||
height: calc(100vh - 48px);
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.viewport-container {
|
||||
clip-path: inset(0 0 0 0);
|
||||
grid-column: 1 / 1;
|
||||
grid-row: 1 / 1;
|
||||
|
||||
.not-fixed {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.fixed {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
|
||||
.frame-children g {
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,8 +133,8 @@
|
||||
(rx/reduce conj [])
|
||||
(rx/with-latest-from files-stream)
|
||||
(rx/merge-map (fn [[data _]]
|
||||
(->> (uz/compress-files data)
|
||||
(rx/map #(vector file %)))))))))
|
||||
(->> (uz/compress-files data)
|
||||
(rx/map #(vector file %)))))))))
|
||||
|
||||
(deftype File [^:mutable file]
|
||||
Object
|
||||
@ -263,4 +263,4 @@
|
||||
(File. (fb/create-file name)))
|
||||
|
||||
(defn exports []
|
||||
#js { :createFile create-file-export })
|
||||
#js {:createFile create-file-export})
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
(fn [resolve reject]
|
||||
(->> (r/render-page data)
|
||||
(rx/take 1)
|
||||
(rx/subs! resolve reject))) )))
|
||||
(rx/subs! resolve reject))))))
|
||||
|
||||
(defn exports []
|
||||
#js {:renderPage render-page-export})
|
||||
|
||||
@ -171,14 +171,14 @@
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/cmd! :update-comment-thread {:id id :is-resolved is-resolved :share-id share-id})
|
||||
(rx/catch (fn [{:keys [type code] :as cause}]
|
||||
(if (and (= type :restriction)
|
||||
(= code :max-quote-reached))
|
||||
(rx/throw cause)
|
||||
(rx/throw {:type :comment-error}))))
|
||||
(rx/ignore))))))
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(->> (rp/cmd! :update-comment-thread {:id id :is-resolved is-resolved :share-id share-id})
|
||||
(rx/catch (fn [{:keys [type code] :as cause}]
|
||||
(if (and (= type :restriction)
|
||||
(= code :max-quote-reached))
|
||||
(rx/throw cause)
|
||||
(rx/throw {:type :comment-error}))))
|
||||
(rx/ignore))))))
|
||||
|
||||
(defn add-comment
|
||||
[thread content]
|
||||
@ -196,16 +196,16 @@
|
||||
(ptk/reify ::create-comment
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(rx/concat
|
||||
(->> (rp/cmd! :create-comment {:thread-id (:id thread) :content content :share-id share-id})
|
||||
(rx/map #(partial created %))
|
||||
(rx/catch (fn [{:keys [type code] :as cause}]
|
||||
(if (and (= type :restriction)
|
||||
(= code :max-quote-reached))
|
||||
(rx/throw cause)
|
||||
(rx/throw {:type :comment-error})))))
|
||||
(rx/of (refresh-comment-thread thread))))))))
|
||||
(let [share-id (-> state :viewer-local :share-id)]
|
||||
(rx/concat
|
||||
(->> (rp/cmd! :create-comment {:thread-id (:id thread) :content content :share-id share-id})
|
||||
(rx/map #(partial created %))
|
||||
(rx/catch (fn [{:keys [type code] :as cause}]
|
||||
(if (and (= type :restriction)
|
||||
(= code :max-quote-reached))
|
||||
(rx/throw cause)
|
||||
(rx/throw {:type :comment-error})))))
|
||||
(rx/of (refresh-comment-thread thread))))))))
|
||||
|
||||
(defn update-comment
|
||||
[{:keys [id content thread-id] :as comment}]
|
||||
@ -309,14 +309,14 @@
|
||||
(->
|
||||
(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)))]
|
||||
(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
|
||||
@ -491,23 +491,23 @@
|
||||
([thread]
|
||||
(update-comment-thread-frame thread uuid/zero))
|
||||
|
||||
([thread frame-id]
|
||||
(dm/assert!
|
||||
"expected valid comment thread"
|
||||
(check-comment-thread! thread))
|
||||
([thread frame-id]
|
||||
(dm/assert!
|
||||
"expected valid comment thread"
|
||||
(check-comment-thread! thread))
|
||||
|
||||
(ptk/reify ::update-comment-thread-frame
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [thread-id (:id thread)]
|
||||
(assoc-in state [:comment-threads thread-id :frame-id] frame-id)))
|
||||
(ptk/reify ::update-comment-thread-frame
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [thread-id (:id thread)]
|
||||
(assoc-in state [:comment-threads thread-id :frame-id] frame-id)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [thread-id (:id thread)]
|
||||
(->> (rp/cmd! :update-comment-thread-frame {:id thread-id :frame-id frame-id})
|
||||
(rx/catch #(rx/throw {:type :comment-error :code :update-comment-thread-frame}))
|
||||
(rx/ignore)))))))
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [thread-id (:id thread)]
|
||||
(->> (rp/cmd! :update-comment-thread-frame {:id thread-id :frame-id frame-id})
|
||||
(rx/catch #(rx/throw {:type :comment-error :code :update-comment-thread-frame}))
|
||||
(rx/ignore)))))))
|
||||
|
||||
(defn detach-comment-thread
|
||||
"Detach comment threads that are inside a frame when that frame is deleted"
|
||||
|
||||
@ -306,8 +306,8 @@
|
||||
(ptk/reify ::fetch-builtin-templates
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rp/cmd! :get-builtin-templates)
|
||||
(rx/map builtin-templates-fetched)))))
|
||||
(->> (rp/cmd! :get-builtin-templates)
|
||||
(rx/map builtin-templates-fetched)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Data Selection
|
||||
@ -320,7 +320,7 @@
|
||||
(update [_ state]
|
||||
(update state :dashboard-local
|
||||
assoc :selected-files #{}
|
||||
:selected-project nil))))
|
||||
:selected-project nil))))
|
||||
|
||||
(defn toggle-file-select
|
||||
[{:keys [id project-id] :as file}]
|
||||
@ -377,10 +377,10 @@
|
||||
:or {on-success identity
|
||||
on-error rx/throw}} (meta params)
|
||||
features (features/get-enabled-features state)]
|
||||
params {:name name
|
||||
:emails #{emails}
|
||||
:role role
|
||||
:features features}
|
||||
params {:name name
|
||||
:emails #{emails}
|
||||
:role role
|
||||
:features features}
|
||||
(->> (rp/cmd! :create-team-with-invitations params)
|
||||
(rx/tap on-success)
|
||||
(rx/map team-created)
|
||||
@ -817,7 +817,7 @@
|
||||
(d/update-in-when [:dashboard-files id :is-shared] (constantly is-shared))
|
||||
(d/update-in-when [:dashboard-recent-files id :is-shared] (constantly is-shared))
|
||||
(cond->
|
||||
(not is-shared)
|
||||
(not is-shared)
|
||||
(d/update-when :dashboard-shared-files dissoc id))))
|
||||
|
||||
ptk/WatchEvent
|
||||
@ -1010,9 +1010,9 @@
|
||||
(let [team-id (:current-team-id state)]
|
||||
(if (empty? term)
|
||||
(do
|
||||
(dom/focus! (dom/get-element "search-input"))
|
||||
(rx/of (rt/nav :dashboard-search
|
||||
{:team-id team-id})))
|
||||
(dom/focus! (dom/get-element "search-input"))
|
||||
(rx/of (rt/nav :dashboard-search
|
||||
{:team-id team-id})))
|
||||
(rx/of (rt/nav :dashboard-search
|
||||
{:team-id team-id}
|
||||
{:search-term term})))))
|
||||
|
||||
@ -59,16 +59,16 @@
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ stream]
|
||||
(rx/merge
|
||||
(let [stoper (rx/filter (ptk/type? ::hide) stream)]
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? :app.util.router/navigate))
|
||||
(rx/map (constantly hide))
|
||||
(rx/take-until stoper)))
|
||||
(when (:timeout data)
|
||||
(let [stoper (rx/filter (ptk/type? ::show) stream)]
|
||||
(->> (rx/of hide)
|
||||
(rx/delay (:timeout data))
|
||||
(rx/take-until stoper))))))))
|
||||
(let [stoper (rx/filter (ptk/type? ::hide) stream)]
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? :app.util.router/navigate))
|
||||
(rx/map (constantly hide))
|
||||
(rx/take-until stoper)))
|
||||
(when (:timeout data)
|
||||
(let [stoper (rx/filter (ptk/type? ::show) stream)]
|
||||
(->> (rx/of hide)
|
||||
(rx/delay (:timeout data))
|
||||
(rx/take-until stoper))))))))
|
||||
|
||||
(def hide
|
||||
(ptk/reify ::hide
|
||||
|
||||
@ -131,8 +131,8 @@
|
||||
(when profile
|
||||
(swap! storage assoc :profile profile)
|
||||
(i18n/set-locale! (:lang profile))
|
||||
(when (not= previous-email email)
|
||||
(swap! storage dissoc ::current-team-id)))))))
|
||||
(when (not= previous-email email)
|
||||
(swap! storage dissoc ::current-team-id)))))))
|
||||
|
||||
(defn fetch-profile
|
||||
[]
|
||||
|
||||
@ -66,10 +66,10 @@
|
||||
(-> state
|
||||
(assoc :current-file-id file-id)
|
||||
(update :viewer-local
|
||||
(fn [lstate]
|
||||
(if (nil? lstate)
|
||||
default-local-state
|
||||
lstate)))
|
||||
(fn [lstate]
|
||||
(if (nil? lstate)
|
||||
default-local-state
|
||||
lstate)))
|
||||
(assoc-in [:viewer-local :share-id] share-id)
|
||||
(assoc-in [:viewer-local :interactions-show?] interactions-show?)))
|
||||
|
||||
@ -202,10 +202,10 @@
|
||||
"fill" zoom-to-fill
|
||||
nil))
|
||||
(rx/of
|
||||
(cond
|
||||
(some? frame-id) (go-to-frame (uuid frame-id))
|
||||
(some? index) (go-to-frame-by-index index)
|
||||
:else (go-to-frame-auto)))))))))
|
||||
(cond
|
||||
(some? frame-id) (go-to-frame (uuid frame-id))
|
||||
(some? index) (go-to-frame-by-index index)
|
||||
:else (go-to-frame-auto)))))))))
|
||||
|
||||
(defn fetch-comment-threads
|
||||
[{:keys [file-id page-id share-id] :as params}]
|
||||
@ -297,9 +297,9 @@
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [srect (as-> (get-in state [:route :query-params :page-id]) %
|
||||
(get-in state [:viewer :pages % :frames])
|
||||
(nth % (get-in state [:route :query-params :index]))
|
||||
(get % :selrect))
|
||||
(get-in state [:viewer :pages % :frames])
|
||||
(nth % (get-in state [:route :query-params :index]))
|
||||
(get % :selrect))
|
||||
orig-size (get-in state [:viewer-local :viewport-size])
|
||||
wdiff (/ (:width orig-size) (:width srect))
|
||||
hdiff (/ (:height orig-size) (:height srect))
|
||||
@ -514,9 +514,9 @@
|
||||
|
||||
(some? animation)
|
||||
(assoc-in [:viewer-animations (:id frame)]
|
||||
{:kind :go-to-frame
|
||||
:orig-frame-id (:id frame)
|
||||
:animation animation}))))
|
||||
{:kind :go-to-frame
|
||||
:orig-frame-id (:id frame)
|
||||
:animation animation}))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
|
||||
@ -316,8 +316,8 @@
|
||||
(rx/take 1)
|
||||
(rx/map #(go-to-component (uuid/uuid component-id))))))
|
||||
|
||||
(rx/take-until
|
||||
(rx/filter (ptk/type? ::fetch-bundle) stream))))))
|
||||
(rx/take-until
|
||||
(rx/filter (ptk/type? ::fetch-bundle) stream))))))
|
||||
|
||||
(defn initialize-file
|
||||
[project-id file-id]
|
||||
@ -1038,12 +1038,12 @@
|
||||
shapes-to-select
|
||||
(->> selected
|
||||
(reduce
|
||||
(fn [result shape-id]
|
||||
(let [parent-id (dm/get-in objects [shape-id :parent-id])]
|
||||
(if (and (some? parent-id) (not= parent-id uuid/zero))
|
||||
(conj result parent-id)
|
||||
(conj result shape-id))))
|
||||
(d/ordered-set)))]
|
||||
(fn [result shape-id]
|
||||
(let [parent-id (dm/get-in objects [shape-id :parent-id])]
|
||||
(if (and (some? parent-id) (not= parent-id uuid/zero))
|
||||
(conj result parent-id)
|
||||
(conj result shape-id))))
|
||||
(d/ordered-set)))]
|
||||
(rx/of (dws/select-shapes shapes-to-select))))))
|
||||
|
||||
;; --- Change Page Order (D&D Ordering)
|
||||
@ -1470,17 +1470,17 @@
|
||||
|
||||
no-bool-shapes? (->> all-selected (some (comp #{:frame :text} :type)))]
|
||||
|
||||
(if (and (some? shape) (not (contains? selected (:id shape))))
|
||||
(rx/concat
|
||||
(rx/of (dws/select-shape (:id shape)))
|
||||
(rx/of (show-shape-context-menu params)))
|
||||
(rx/of (show-context-menu
|
||||
(-> params
|
||||
(assoc
|
||||
:kind :shape
|
||||
:disable-booleans? (or no-bool-shapes? not-group-like?)
|
||||
:disable-flatten? no-bool-shapes?
|
||||
:selected (conj selected (:id shape)))))))))))
|
||||
(if (and (some? shape) (not (contains? selected (:id shape))))
|
||||
(rx/concat
|
||||
(rx/of (dws/select-shape (:id shape)))
|
||||
(rx/of (show-shape-context-menu params)))
|
||||
(rx/of (show-context-menu
|
||||
(-> params
|
||||
(assoc
|
||||
:kind :shape
|
||||
:disable-booleans? (or no-bool-shapes? not-group-like?)
|
||||
:disable-flatten? no-bool-shapes?
|
||||
:selected (conj selected (:id shape)))))))))))
|
||||
|
||||
(defn show-page-item-context-menu
|
||||
[{:keys [position page] :as params}]
|
||||
@ -1488,8 +1488,8 @@
|
||||
(ptk/reify ::show-page-item-context-menu
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (show-context-menu
|
||||
(-> params (assoc :kind :page :selected (:id page))))))))
|
||||
(rx/of (show-context-menu
|
||||
(-> params (assoc :kind :page :selected (:id page))))))))
|
||||
|
||||
(defn show-track-context-menu
|
||||
[{:keys [grid-id type index] :as params}]
|
||||
@ -1902,7 +1902,7 @@
|
||||
;; - Align it to the limits on the x and y axis
|
||||
;; - Respect the distance of the object to the right and bottom in the original frame
|
||||
(gpt/point paste-x paste-y))]
|
||||
[frame-id frame-id delta (dec (count (:shapes selected-frame-obj )))]))
|
||||
[frame-id frame-id delta (dec (count (:shapes selected-frame-obj)))]))
|
||||
|
||||
(empty? page-selected)
|
||||
(let [frame-id (ctst/top-nested-frame page-objects position)
|
||||
@ -1953,8 +1953,7 @@
|
||||
(ptk/reify ::paste-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [
|
||||
file-id (:current-file-id state)
|
||||
(let [file-id (:current-file-id state)
|
||||
page (wsh/lookup-page state)
|
||||
|
||||
media-idx (->> (:media pdata)
|
||||
@ -2216,23 +2215,23 @@
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
|
||||
(let [data (get state :workspace-data)
|
||||
(let [data (get state :workspace-data)
|
||||
|
||||
update-fn
|
||||
(fn [component]
|
||||
update-fn
|
||||
(fn [component]
|
||||
;; NOTE: we need to ensure the component exists,
|
||||
;; because there are small possibilities of race
|
||||
;; conditions with component deletion.
|
||||
(when component
|
||||
(if (nil? annotation)
|
||||
(dissoc component :annotation)
|
||||
(assoc component :annotation annotation))))
|
||||
(when component
|
||||
(if (nil? annotation)
|
||||
(dissoc component :annotation)
|
||||
(assoc component :annotation annotation))))
|
||||
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/update-component id update-fn))]
|
||||
changes (-> (pcb/empty-changes it)
|
||||
(pcb/with-library-data data)
|
||||
(pcb/update-component id update-fn))]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
(defn set-annotations-expanded
|
||||
[expanded?]
|
||||
|
||||
@ -19,12 +19,12 @@
|
||||
(update [_ state]
|
||||
(let [expand-fn (fn [expanded]
|
||||
(merge expanded
|
||||
(->> ids
|
||||
(map #(cfh/get-parent-ids objects %))
|
||||
flatten
|
||||
(remove #(= % uuid/zero))
|
||||
(map (fn [id] {id true}))
|
||||
(into {}))))]
|
||||
(->> ids
|
||||
(map #(cfh/get-parent-ids objects %))
|
||||
flatten
|
||||
(remove #(= % uuid/zero))
|
||||
(map (fn [id] {id true}))
|
||||
(into {}))))]
|
||||
(update-in state [:workspace-local :expanded] expand-fn)))))
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user